sklearn:想扩展 CountVectorizer 以模糊匹配词汇表

sklearn: Would like to extend CountVectorizer to fuzzy match against vocabulary

我打算尝试使用 fuzzywuzzy 和一个调整后的可接受的分数参数 本质上,它会检查单词是否按原样出现在词汇表中,如果不在,它会要求 fuzzywuzzy 选择最佳模糊匹配,如果它至少达到一定分数,则将其接受到标记列表中。

如果这不是处理大量拼写错误和拼写略有不同但相似的单词的最佳方法,我愿意接受建议。

问题是子类一直抱怨它有一个空的词汇表,这没有任何意义,因为当我在代码的同一部分使用常规计数矢量化器时它工作正常。

它会吐出很多这样的错误:ValueError: empty vocabulary;也许文档只包含停用词

我错过了什么?我还没有让它做任何特别的事情。它应该像正常一样工作:

class FuzzyCountVectorizer(CountVectorizer):
    def __init__(self, input='content', encoding='utf-8', decode_error='strict',
                 strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, stop_words=None,
                 token_pattern="(?u)\b\w\w+\b", ngram_range=(1, 1), analyzer='word',
                 max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False,
                 dtype=numpy.int64, min_fuzzy_score=80):
        super().__init__(
            input=input, encoding=encoding, decode_error=decode_error, strip_accents=strip_accents,
            lowercase=lowercase, preprocessor=preprocessor, tokenizer=tokenizer, stop_words=stop_words,
            token_pattern=token_pattern, ngram_range=ngram_range, analyzer=analyzer, max_df=max_df,
            min_df=min_df, max_features=max_features, vocabulary=vocabulary, binary=binary, dtype=dtype)
        # self._trained = False
        self.min_fuzzy_score = min_fuzzy_score

    @staticmethod
    def remove_non_alphanumeric_chars(s: str) -> 'str':
        pass

    @staticmethod
    def tokenize_text(s: str) -> 'List[str]':
        pass

    def fuzzy_repair(self, sl: 'List[str]') -> 'List[str]':
        pass

    def fit(self, raw_documents, y=None):
        print('Running FuzzyTokenizer Fit')
        #TODO clean up input
        super().fit(raw_documents=raw_documents, y=y)
        self._trained = True
        return self

    def transform(self, raw_documents):
        print('Running Transform')
        #TODO clean up input
        #TODO fuzzyrepair
        return super().transform(raw_documents=raw_documents)

scikit-learn 的 CountVectorizer 的原始函数定义有

token_pattern=r"(?u)\b\w\w+\b"

而在您的子类中您不使用转义 r 字符串前缀,因此出现了这个问题。另外,与其复制所有 __init__ 个参数,不如直接使用

可能更容易
def __init__(self, *args, **kwargs):
     self.min_fuzzy_score = kwargs.pop('min_fuzzy_score', 80)
     super().__init__(*args, **kwargs)

至于这是否是最佳方法,这取决于您的数据集的大小。对于总共 N_words 和词汇量 N_vocab_size 的文档集,此方法需要 O(N_words*N_vocab_size) 繁琐的单词比较。如果您使用标准 CountVectorizer 向量化您的数据集,然后通过模糊匹配减少计算的词汇表(和 bag od 词矩阵),则需要 "only" O(N_vocab_size**2) 比较。

对于超过 10,000 个单词的词汇量,这可能仍然无法很好地扩展。如果您打算在生成的稀疏数组上应用一些机器学习算法,您可能还想尝试字符 n-gram,它在印刷错误方面也有一定的鲁棒性。