Как должен работать TFIDFVectorizer в scikit-learn?
Я пытаюсь получить слова, которые отличаются от определенных документов, используя класс TfIDFVectorizer в scikit-learn. Он создает матрицу tfidf со всеми словами и их оценками во всех документах, но затем, похоже, также учитывает общие слова. Это часть кода, который я запускаю:
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(contents)
feature_names = vectorizer.get_feature_names()
dense = tfidf_matrix.todense()
denselist = dense.tolist()
df = pd.DataFrame(denselist, columns=feature_names, index=characters)
s = pd.Series(df.loc['Adam'])
s[s > 0].sort_values(ascending=False)[:10]
Я ожидал, что это вернет список отличительных слов для документа "Адам", но то, что он делает, возвращает список общих слов:
and 0.497077
to 0.387147
the 0.316648
of 0.298724
in 0.186404
with 0.144583
his 0.140998
Я, возможно, не совсем понимаю это, но, как я понимаю, tf-idf должен найти слова, которые отличаются от одного документа в корпусе, и найти слова, которые часто появляются в одном документе, но не в других документах. Здесь and
часто появляется в других документах, поэтому я не знаю, почему он возвращает здесь высокое значение.
Полный код, который я использую для его создания, находится в этом ноутбуке Jupyter.
Когда я вычисляю tf/idfs полу-вручную, используя NLTK и вычислительные оценки для каждого слова, я получаю соответствующие результаты. Для документа "Адам":
fresh 0.000813
prime 0.000813
bone 0.000677
relate 0.000677
blame 0.000677
enough 0.000677
Это выглядит правильно, поскольку это слова, которые появляются в документе "Адам", но не так много в других документах в корпусе. Полный код, используемый для его создания, находится в этом ноутбуке Jupyter.
Я что-то делаю с кодом scikit? Есть ли другой способ инициализировать этот класс, где он возвращает правильные результаты? Конечно, я могу игнорировать стоп-слова, передавая stop_words = 'english'
, но это на самом деле не решает проблему, поскольку общие слова любого рода не должны иметь высоких оценок здесь.
Ответы
Ответ 1
Из документации scikit-learn:
Поскольку tf-idf очень часто используется для текстовых функций, есть еще один класс под названием TfidfVectorizer, который объединяет все опции CountVectorizer и TfidfTransformer в одной модели.
Как вы можете видеть, TfidfVectorizer - это CountVectorizer, за которым следует TfidfTransformer.
То, что вы, вероятно, ищете, это TfidfTransformer, а не TfidfVectorizer
Ответ 2
Я считаю, что ваша проблема заключается в использовании разных списков заметок. Scikit-learn и NLTK по умолчанию используют разные списки заметок. Для scikit-learn обычно рекомендуется иметь собственный список stop_words, переданный TfidfVectorizer, например:
my_stopword_list = ['and','to','the','of']
my_vectorizer = TfidfVectorizer(stop_words=my_stopword_list)
Страница Doc для класса TfidfVectorizer: [ http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html][1]
Ответ 3
Я не уверен, почему это не значение по умолчанию, но вы, вероятно, хотите sublinear_tf=True
в инициализации для TfidfVectorizer. Я разветкил ваше репо и отправил вам PR с примером, который, вероятно, больше походит на то, что вы хотите.
Ответ 4
используя ниже код, я получаю гораздо лучшие результаты
vectorizer = TfidfVectorizer(sublinear_tf=True, stop_words='english')
Вывод
sustain 0.045090
bone 0.045090
thou 0.044417
thee 0.043673
timely 0.043269
thy 0.042731
prime 0.041628
absence 0.041234
rib 0.041234
feel 0.040259
Name: Adam, dtype: float64
а также
thee 0.071188
thy 0.070549
forbids 0.069358
thou 0.068068
early 0.064642
earliest 0.062229
dreamed 0.062229
firmness 0.062229
glistering 0.062229
sweet 0.060770
Name: Eve, dtype: float64