如何在scikit-learn中使用TFIDFVectorizer?

时间:2016-04-22 18:09:43

标签: 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]

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

and     0.497077
to      0.387147
the     0.316648
of      0.298724
in      0.186404
with    0.144583
his     0.140998

我可能不完全理解它,但据我所知,tf-idf应该在语料库中找到与一个文档不同的单词,找到在一个文档中经常出现的单词,而不是在其他文档中出现的单词。在这里,and经常出现在其他文档中,因此我不知道为什么它会在这里返回高价值。

我用来生成此代码的完整代码是in this Jupyter notebook

当我半手动计算tf / idfs时,使用NLTK和每个单词的计算分数,我得到了合适的结果。对于'亚当'文件:

fresh        0.000813
prime        0.000813
bone         0.000677
relate       0.000677
blame        0.000677
enough       0.000677

这看起来是正确的,因为这些是出现在“亚当”中的词语。文档,但在语料库中的其他文档中没有那么多。用于生成此内容的完整代码位于this Jupyter notebook

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

5 个答案:

答案 0 :(得分:5)

来自scikit-learn文档:

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

如您所见,TfidfVectorizerCountVectorizer,后跟TfidfTransformer

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

答案 1 :(得分:5)

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

my_stopword_list = ['and','to','the','of']
my_vectorizer = TfidfVectorizer(stop_words=my_stopword_list)

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

答案 2 :(得分:2)

我不确定为什么它不是默认设置,但您可能需要在{TfidfVectorizer的初始化中sublinear_tf=True。我分叉你的回购并给你发了一个PR,其中有一个可能看起来更像你想要的例子。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

您的问题的答案可能取决于您的语料库大小和用于不同实现的源代码。我没有详细研究nltk代码,但是3-8个文档(在scikit代码中)可能不足以构成主体。构建语料库时;新闻档案库中包含数十万篇文章或数千本书籍。也许在8个文档中,像'the'这样的单词的出现频率总体上并不大,无法说明这些单词在这些文档中的通用性。

如果您查看源代码,无论它们遵循不同的归一化步骤还是频率分布(https://nlp.stanford.edu/IR-book/html/htmledition/document-and-query-weighting-schemes-1.html都有常见的tfidf变体),您都可以发现实现上的差异

另一种可能有用的方法是查看频率一词(scikit中的CountVectorizer),并确保在所有文档中都过度使用“ the”一词。