scikit-learn CountVectorizer中的词频是如何计算的
我不太明白CountVectorizer是怎么计算词频的。我需要了解这个,以便在过滤语料库中的词汇时,能合理选择max_df
参数。下面是一个示例代码:
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df = 1, max_df = 0.9)
X = vectorizer.fit_transform(['afr bdf dssd','afr bdf c','afr'])
word_freq_df = pd.DataFrame({'term': vectorizer.get_feature_names(), 'occurrences':np.asarray(X.sum(axis=0)).ravel().tolist()})
word_freq_df['frequency'] = word_freq_df['occurrences']/np.sum(word_freq_df['occurrences'])
print word_freq_df.sort('occurrences',ascending = False).head()
occurrences term frequency
0 3 afr 0.500000
1 2 bdf 0.333333
2 1 dssd 0.166667
看起来'afr'在我的语料库中出现了一半的次数,这和我观察到的情况一致。然而,当我在CountVectorizer
中设置max_df = 0.8
时,'afr'这个词却被过滤掉了。经过一些尝试,我发现对于我这个示例中的语料库,CountVectorizer给'afr'的频率大约是0.833。有人能提供一下计算max_df
所用的词频的公式吗?
谢谢
1 个回答
6
这个问题看起来不是频率计算的方式有问题,而是max_df
这个阈值的应用方式有问题。CountVectorizer
的代码是这样处理的:
max_doc_count = (max_df
if isinstance(max_df, numbers.Integral)
else int(round(max_df * n_doc))
)
也就是说,最大文档数是通过将文档比例乘以文档总数后进行四舍五入得到的。这意味着,在一个有3个文档的语料库中,任何大于2.5个文档的max_df
阈值实际上都和3个文档的阈值是一样的。你看到的“频率”是2.5/3=0.8333,也就是说,一个词在大约83.3%的3个文档中出现,实际上是出现在2.5个文档中,但因为四舍五入,这个数字被算作3,意味着它在所有文档中都出现了。
简单来说,“afr”被正确地认为在3个文档中出现,但最大文档频率却错误地被认为是3(0.9*3=2.7,四舍五入为3)。
我认为这是scikit中的一个bug。最大文档频率应该是向下四舍五入,而不是向上。如果阈值是0.9,那么一个在所有文档中都出现的词就超过了这个阈值,应该被排除。