如何在scikit-learn中使用TFIDFVectorizer?

Jon*_*han 27 python nlp scikit-learn

我正在尝试使用scikit-learn中的TfIDFVectorizer类来获取与某些文档不同的单词.它创建了一个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]
Run Code Online (Sandbox Code Playgroud)

我希望这能为文档'Adam'返回一个独特单词列表,但它的作用是返回一个常用单词列表:

and     0.497077
to      0.387147
the     0.316648
of      0.298724
in      0.186404
with    0.144583
his     0.140998
Run Code Online (Sandbox Code Playgroud)

我可能不完全理解它,但据我所知,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
Run Code Online (Sandbox Code Playgroud)

这看起来是正确的,因为这些是出现在"亚当"文档中的单词,但在语料库中的其他文档中却没有那么多.用于生成此代码的完整代码位于此Jupyter笔记本中.

我是否在使用scikit代码做错了什么?有没有其他方法来初始化这个类,它返回正确的结果?当然,我可以通过传递来忽略停用词stop_words = 'english',但这并不能真正解决问题,因为任何类型的常用词在这里都不应该有高分.

小智 7

从scikit-learn文档中:

由于tf–idf通常用于文本功能,因此还有另一个名为TfidfVectorizer的类,它将CountVectorizer和TfidfTransformer的所有选项组合在一个模型中。

如您所见,TfidfVectorizerCountVectorizer,后跟TfidfTransformer

您可能正在寻找的是TfidfTransformer而不是TfidfVectorizer

  • TfidfTransformer将转换CountVectorizer的输出,因此我可以运行CountVectorizer,然后运行TfidfTransformer,但这与运行TfidfVectorizer相同。因此,即使我必须首先运行CountVectorizer,我也不相信我需要TfidfTransformer。它不会返回相同的结果吗? (2认同)

Rab*_*bit 7

我相信您的问题在于使用不同的停用词列表。默认情况下,Scikit-learn和NLTK使用不同的停用词列表。对于scikit-learn,通常最好将自定义stop_words列表传递给TfidfVectorizer,例如:

my_stopword_list = ['and','to','the','of']
my_vectorizer = TfidfVectorizer(stop_words=my_stopword_list)
Run Code Online (Sandbox Code Playgroud)

TfidfVectorizer类的文档页面:[ http://scikit-learn.org/stable/modules/generation/sklearn.feature_extraction.text.TfidfVectorizer.html] [1 ]

  • 知道这很好,但我想我对为什么需要删除停用词一开始感到困惑。如果 'and' 或 'the' 在所有文档中频繁出现,比方说,那么为什么它的 tf-idf 值会很高?在我看来,tf-idf 的目的是调整所有文档中术语的频率,以便在整个语料库中频繁出现的术语不会出现在列表的顶部。 (4认同)
  • @Jono,我想您的直觉是TFIDF应该受益于稀有条款。这是正确的一半。TFIDF考虑了两个主要方面:TF,它是文档中的术语频率; IDF,它是整个文档集中的反向术语频率。TF使频繁条款受益,而IDF使罕见条款受益。这两个几乎是相反的措施,这使TFIDF成为一个平衡的指标。 (2认同)

mic*_*lew 6

使用下面的代码我得到了更好的结果

vectorizer = TfidfVectorizer(sublinear_tf=True, stop_words='english')
Run Code Online (Sandbox Code Playgroud)

输出

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)