使用scikit-learn计算文本TF-IDF值

一、TF-IDF介绍

(一)术语介绍

TF-IDF(Term Frequency-InversDocument Frequency)是一种常用于信息处理和数据挖掘的加权技术。该技术采用一种统计方法,根据字词的在文本中出现的次数和在整个语料中出现的文档频率来计算一个字词在整个语料中的重要程度。它的优点是能过滤掉一些常见的却无关紧要本的词语,同时保留影响整个文本的重要字词。计算方法如下面公式所示。

formula1.png

其中,式中tfidfi,j 表示词频tfi,j和倒文本词频idfi的乘积。TF-IDF值越大表示该特征词对这个文本的重要性越大。
TF(Term Frequency)表示某个关键词在整篇文章中出现的频率。
IDF(InversDocument Frequency)表示计算倒文本频率。文本频率是指某个关键词在整个语料所有文章中出现的次数。倒文档频率又称为逆文档频率,它是文档频率的倒数,主要用于降低所有文档中一些常见却对文档影响不大的词语的作用。

下面公式是TF词频的计算公式:

formula2.png

其中,ni,j为特征词ti在文本dj中出现的次数,是文本dj中所有特征词的个数。计算的结果即为某个特征词的词频。

下面公式是IDF的计算公式:

formula3.png

其中,|D|表示语料中文本的总数,|Dti|表示文本中包含特征词ti的数量。分母+1是为了防止该词语在语料库中不存在,即分母为0,

关于这部分的介绍,也可参考 阮一峰的博客http://www.ruanyifeng.com/blog/2013/03/tf-idf.html

(二)例子

假设有一篇文章包含了10000个词组,其中“中国”、“石油”、出现100次,“开采”出现200次,“的”出现500次(假设没有去除停用词)
语料库中共有1000篇文档,其中包含“中国”的文档有99篇,包含“石油”的文档59篇,包含“开采”的文档有19篇,包含“的”的文档有999篇

1 计算词频

根据公式:词频 = 某个词组在文章中出现次数/该文章总词组数

TF(中国)= 100/10000 = 0.01
TF(石油)= 100/10000 = 0.01
TF(开采)= 200/10000 = 0.02
TF(的)= 500/10000 = 0.05

2 计算逆文档频率

根据公式:逆文档频率 = log[语料库中文档总数/(包含该词组的文档数 + 1)]
这里的log表示以10为底

IDF(中国)= log(1000/100) = 1
IDF(石油)= log(1000/60) = 1.221
IDF(开采)= log(1000/20) = 1.7
IDF(开采)= log(1000/1000) = 0

由上述结果可以发现,当某个词在语料库中各个文档出现的次数越多,它的IDF值越低,当它在所有文档中都出现时,其IDF计算结果为0,而通常这些出现次数非常多的词或字为“的”、“我”、“吗”等,它对文章的权重计算起不到较大的作用。

3 计算TF-IDF值

根据公式:TF-IDF = 词频 * 逆文档频率
TF-IDF(中国) = 0.01 * 1 = 0.01
TF-IDF(石油) = 0.01 * 1.221 = 0.01221
TF-IDF(开采) = 0.02 * 1.7 = 0.0034
TF-IDF(的) = 0.05 * 0 = 0

通过计算结果可以发现,如果只选取一个关键词,则整篇文章是关于“开采”的;如果选取两个关键词,则整篇文章是关于“开采”、“石油”的。

二、用scikit-learn计算TF-IDF值

(一)例1

from sklearn import feature_extraction
from sklearn.feature_extraction.text import CountVectorizer 
from sklearn.feature_extraction.text import TfidfTransformer  

corpus = ['aaa ccc aaa aaa', 
          'aaa aaa', 
          'aaa aaa aaa', 
          'aaa aaa aaa aaa',
          'aaa bbb aaa bbb aaa',
          'ccc aaa aaa ccc aaa'
         ]

vectorizer = CountVectorizer() 

X = vectorizer.fit_transform(corpus)

# 获取词袋模型中的所有词语   
word = vectorizer.get_feature_names()  
print(word) 

# 获取每个词在该行(文档)中出现的次数
counts =  X.toarray()
print (counts)

transformer = TfidfTransformer()
tfidf = transformer.fit_transform(X)
#tfidf = transformer.fit_transform(counts) #与上一行的效果完全一样
#print(tfidf)
print(tfidf.toarray())

运行结果:

['aaa', 'bbb', 'ccc']
[[3 0 1]
 [2 0 0]
 [3 0 0]
 [4 0 0]
 [3 2 0]
 [3 0 2]]
[[0.85151335 0.         0.52433293]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [0.55422893 0.83236428 0.        ]
 [0.63035731 0.         0.77630514]]

分析:

1.CountVectorizer

CountVectorizer类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素a[i][j],它表示j词在i篇文档中出现的频次。它通过fit_transform函数计算各个词语出现的次数,通过get_feature_names()可获取词袋中所有文本的关键字(英语是按字母顺序排列的),通过toarray()可看到词频矩阵的结果。
从结果可以看出,总共出现了三个词:
[‘aaa’, ‘bbb’, ‘ccc’]

同时在输出每个句子中包含特征词的个数。例如,第一句“aaa ccc aaa aaa”,它对应的词频为[3, 0, 1],即’aaa’出现了3次,’bbb’出现了0次,’ccc’出现了1次。

2.TfidfTransformer

TfidfTransformer用于统计vectorizer中每个词语的TF-IDF值。

具体计算过程可以参考sklearn的官方文档
http://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction
中的4.2.3.4部分。

sklearn的计算过程有两点要注意:
一是sklean计算对数log时,底数是e,不是10
二是参数smooth_idf默认值为True,若改为False,即

transformer = TfidfTransformer(smooth_idf = False)

则计算方法略有不同,导致结果也有所差异:

[[0.81940995 0.         0.57320793]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [0.47330339 0.88089948 0.        ]
 [0.58149261 0.         0.81355169]]

(二)例2

这个例子旨在演示从文档里读入中文内容,并输出关键词和TF-IDF值

1 新建test.txt文件,内容如下

新春 备 年货 , 新年 联欢晚会
新春 节目单 , 春节 联欢晚会 红火
大盘 下跌 股市 散户
下跌 股市 赚钱
金猴 新春 红火 新年
新车 新年 年货 新春
股市 反弹 下跌
股市 散户 赚钱
新年 , 看 春节 联欢晚会
大盘 下跌 散户 散户

2 程序

from sklearn import feature_extraction    
from sklearn.feature_extraction.text import TfidfTransformer    
from sklearn.feature_extraction.text import CountVectorizer


if __name__ == "__main__": 
    corpus = []

    #读取预料 一行预料为一个文档 
    for line in open('test.txt', 'r').readlines():
        #print line
        corpus.append(line.strip())
    #print (corpus)#将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频  

    vectorizer = CountVectorizer()  

    #该类会统计每个词语的tf-idf权值  
    transformer = TfidfTransformer()  
    #print(transformer)

    #第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵  
    tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)) 
    #print(tfidf)

    #获取词袋模型中的所有词语   
    word = vectorizer.get_feature_names()  
    print(word)
    weight = tfidf.toarray()  
    print(weight)

运行结果:

['下跌', '反弹', '大盘', '年货', '散户', '新年', '新春', '新车', '春节', '红火', '联欢晚会', '股市', '节目单', '赚钱', '金猴']

[[0.         0.         0.         0.57972569 0.         0.45092956
  0.45092956 0.         0.         0.         0.50719147 0.
  0.         0.         0.        ]
 [0.         0.         0.         0.         0.         0.
  0.35673538 0.         0.45862743 0.45862743 0.40124481 0.
  0.53950369 0.         0.        ]
 [0.45092956 0.         0.57972569 0.         0.50719147 0.
  0.         0.         0.         0.         0.         0.45092956
  0.         0.         0.        ]
 [0.52322127 0.         0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.52322127
  0.         0.6726656  0.        ]
 [0.         0.         0.         0.         0.         0.4103054
  0.4103054  0.         0.         0.5274983  0.         0.
  0.         0.         0.62051954]
 [0.         0.         0.         0.5274983  0.         0.4103054
  0.4103054  0.62051954 0.         0.         0.         0.
  0.         0.         0.        ]
 [0.48296446 0.73040445 0.         0.         0.         0.
  0.         0.         0.         0.         0.         0.48296446
  0.         0.         0.        ]
 [0.         0.         0.         0.         0.56824385 0.
  0.         0.         0.         0.         0.         0.5052095
  0.         0.64950926 0.        ]
 [0.         0.         0.         0.         0.         0.5052095
  0.         0.         0.64950926 0.         0.56824385 0.
  0.         0.         0.        ]
 [0.3600654  0.         0.46290857 0.         0.8099806  0.
  0.         0.         0.         0.         0.         0.
  0.         0.         0.        ]]

三、参考

(1) http://www.ruanyifeng.com/blog/2013/03/tf-idf.html
(2) https://blog.csdn.net/eastmount/article/details/50323063
(3) http://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction


TopCoder & Codeforces & AtCoder交流QQ群:648202993
更多内容请关注微信公众号
wechat_public_header.jpg

猜你喜欢

转载自blog.csdn.net/haishu_zheng/article/details/80516906