使用 TfidfVectorizer 类求 TF-IDF
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/12828493.html
什么是 TF-IDF 值
在多项式朴素贝叶斯中提到了“词的 TF-IDF 值”,TF-IDF 是一个统计方法,用来评估某个词语对于一个文件集或文档库中的其中一份文件的重要程度。
TF-IDF 实际上是两个词组 Term Frequency 和 Inverse Document Frequency 的总称,两者缩写为 TF 和 IDF,分别代表了词频和逆向文档频率。
词频 TF 计算了一个单词在文档中出现的次数,它认为一个单词的重要性和它在文档中出现的次数呈正比。
逆向文档频率 IDF,是指一个单词在文档中的区分度。它认为一个单词出现在的文档数越少,就越能通过这个单词把该文档和其他文档区分开。IDF 越大就代表该单词的区分度越大。
所以 TF-IDF 实际上是词频 TF 和逆向文档频率 IDF 的乘积。这样我们倾向于找到 TF 和 IDF 取值都高的单词作为区分,即这个单词在一个文档中出现的次数多,同时又很少出现在其他文档中。这样的单词适合用于分类。
TF-IDF 如何计算
首先看下词频 TF 和逆向文档概率 IDF 的公式。
IDF 的分母中,单词出现的文档数要加 1,是因为有些单词可能不会存在文档中,为了避免分母为 0,统一给单词出现的文档数都加 1。
TF-IDF=TF*IDF
TF-IDF 值就是 TF 与 IDF 的乘积,这样可以更准确地对文档进行分类。比如“我”这样的高频单词,虽然 TF 词频高,但是 IDF 值很低,整体的 TF-IDF 也不高。
举个具体的例子
假设一个文件夹里一共有 10 篇文档,其中一篇文档有 1000 个单词,“this”这个单词出现 20 次,“bayes”出现了 5 次。“this”在所有文档中均出现过,而“bayes”只在 2 篇文档中出现过。计算一下这两个词语的 TF-IDF 值。
针对“this”,计算 TF-IDF 值:
所以 TF-IDF=0.02*(-0.0414)=-8.28e-4。
针对“bayes”,计算 TF-IDF 值:
所以 TF-IDF=0.005*0.5229=2.61e-3。
很明显“bayes”的 TF-IDF 值要大于“this”的 TF-IDF 值。这就说明用“bayes”这个单词做区分比单词“this”要好。
如何求 TF-IDF
在 sklearn 中直接使用 TfidfVectorizer 类,它可以计算单词 TF-IDF 向量的值。在这个类中,取 sklearn 计算的对数 log 时,底数是 e,不是 10。
from sklearn.feature_extraction.text import TfidfVectorizer stop_words = ['is', 'the', 'and'] tfidf_vec = TfidfVectorizer(stop_words=stop_words) # TfidfVectorizer(analyzer='word', binary=False, decode_error='strict', # dtype=<class 'numpy.float64'>, encoding='utf-8', # input='content', lowercase=True, max_df=1.0, max_features=None, # min_df=1, ngram_range=(1, 1), norm='l2', preprocessor=None, # smooth_idf=True, stop_words=['is', 'the', 'and'], # strip_accents=None, sublinear_tf=False, # token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None, use_idf=True, # vocabulary=None) print(tfidf_vec) documents = [ 'this is the bayes document', 'this is the second second document', 'and the third one', 'is this the document' ] # 使用 fit_transform 计算,返回文本矩阵,该矩阵表示了每个单词在每个文档中的 TF-IDF 值 tfidf_matrix = tfidf_vec.fit_transform(documents) # 不重复的词: ['bayes', 'document', 'one', 'second', 'third', 'this'] print('不重复的词:', tfidf_vec.get_feature_names()) # 停用词表: frozenset({'and', 'the', 'is'}) print('停用词表:', tfidf_vec.get_stop_words()) # 每个单词的ID: {'this': 5, 'bayes': 0, 'document': 1, 'second': 3, 'third': 4, 'one': 2} print('每个单词的ID:', tfidf_vec.vocabulary_) # 每个单词的tfidf值: # [[0.74230628 0.47380449 0. 0. 0. 0.47380449] # [0. 0.29088811 0. 0.91146487 0. 0.29088811] # [0. 0. 0.70710678 0. 0.70710678 0. ] # [0. 0.70710678 0. 0. 0. 0.70710678]] print('每个单词的tfidf值:\n', tfidf_matrix.toarray())
Note:
停用词就是在分类中没有用的词,这些词一般词频 TF 高,但是 IDF 很低,起不到分类的作用。为了节省空间和计算时间,把这些词作为停用词 stop words,告诉机器这些词不需要计算。停用词 stop_words 是一个列表 List 类型。
Reference
https://time.geekbang.org/column/article/79762