sklearn: хотел бы расширить CountVectorizer для нечеткого сопоставления со словарем.

Я собирался попробовать использовать fuzzywuzzy с настроенным параметром приемлемой оценки, по сути, он проверял бы, находится ли слово в словаре как есть, а если нет, то просил бы fuzzywuzzy выбрать наилучшее нечеткое совпадение и принять его для списка. жетонов, если это был хотя бы определенный балл.

Если это не лучший подход к изрядному количеству опечаток и немного по-разному написанных, но похожих слов, я открыт для предложений.

Проблема в том, что подкласс продолжает жаловаться, что у него пустой словарь, что не имеет никакого смысла, поскольку, когда я использую обычный векторизатор счета в той же части моего кода, он работает нормально.

он выдает много ошибок, таких как: ValueError: пустой словарь; возможно, документы содержат только стоп-слова

Что мне не хватает? Я пока ничего особенного не делаю. Это должно работать как обычно:

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)

person KotoroShinoto    schedule 15.09.2017    source источник


Ответы (1)


Исходное определение функции для scikit-learn CountVectorizer имеет

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

в то время как в вашем подклассе вы не используете префикс строки escape 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, а затем уменьшили вычисленный словарь (и матрицу пакетов слов) с помощью нечеткого сопоставления, это потребовало бы «всего» O(N_vocab_size**2) сравнений.

Это, вероятно, все еще не будет хорошо масштабироваться для словарного запаса, превышающего несколько 10 000 слов. Если вы собираетесь применить какой-либо алгоритм машинного обучения к результирующему разреженному массиву, вы также можете попробовать символьные n-граммы, которые также будут несколько устойчивы к типографским ошибкам.

person rth    schedule 18.09.2017