1. TF-IDF 是什么
TF-IDF简言之,就是对一篇文章提取关键词的算法。不论怎么将其复杂化定义,其本质都是计算特征词在文章中的重要程度。
第一步:想要考察一个词的重要程度,最简单的思路就是考察起出现的频率,即TF(Term Frequency)词频。可以通过统计特征词在文章中出现的次数来计算,比如本文“TF-IDF,词语,SK-learn,的,是…”。
第二步:显然第一步有一个漏洞,比如类似“的”,“是”,“因此”等词语在一篇文章中很常用,我们称其为“停用词”,那么必须考虑过滤掉这些词语,这些词语可以通过一个停用词库手动过滤。
第三步:过滤掉“停用词”后,只考虑有意义的词"TF-IDF,词语,sk-learn",它们中的关键词顺序应该是“TF-IDF,SK-learn”排序比较靠前,“词语”排序比较靠后。显然“词语”比较多,那么怎么来调整其系数呢。这就引入了另外一个思想IDF(Inverse Document Frequency)逆文档频率,其思想是“如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性,正是我们所需要的关键词。”
第四步:将TF和IDF相乘结合后,就可以得到一个特征词的TF-IDF值,作为重要程度的参考。
2. TF-IDF 公式计算
参考《TF-IDF详解》,描述了TF-IDF的几个变体。这里我们介绍最常用的公式:
T
F
=
特
征
词
在
文
章
中
出
现
次
数
/
文
章
中
的
总
词
数
TF = 特征词在文章中出现次数/文章中的总词数
TF=特征词在文章中出现次数/文章中的总词数
注意,TF的定义里包含了标准化的思想,不是直接使用次数。
I
D
F
=
l
o
g
(
语
料
库
文
档
总
数
/
(
包
含
该
词
的
文
档
数
+
1
)
)
IDF = log(语料库文档总数/(包含该词的文档数+1))
IDF=log(语料库文档总数/(包含该词的文档数+1))
注意,这里避免除0,所以+1,同时通过Log对数变换,防止线性增长,从而导致重要性变化太大。
T F − I D F = T F ∗ I D F TF-IDF = TF * IDF TF−IDF=TF∗IDF
3. TF-IDF的应用
3.1 余弦相似度
用来计算两篇文章的相似程度,最简单的想法:
- 将两篇文章有意义的分词合并组成词向量。
- 每篇文章分别计算分词词频TF,产生不同的词向量, A = [ A 1 , A 2 , … , A n ] , B = [ B 1 , B 2 , … , B n ] A=[A 1, A 2, \ldots, A n], B=[B 1, B 2, \ldots, B n] A=[A1,A2,…,An],B=[B1,B2,…,Bn]
- 计算两篇文章的余弦相似度,
cos
θ
=
∑
i
=
1
n
(
A
i
×
B
i
)
∑
i
=
1
n
(
A
i
)
2
×
∑
i
=
1
n
(
B
i
)
2
=
A
⋅
B
∣
A
∣
×
∣
B
∣
\begin{aligned} \cos \theta &=\frac{\sum_{i=1}^{n}\left(A_{i} \times B_{i}\right)}{\sqrt{\sum_{i=1}^{n}\left(A_{i}\right)^{2}} \times \sqrt{\sum_{i=1}^{n}\left(B_{i}\right)^{2}}} =\frac{A \cdot B}{|A| \times|B|} \end{aligned}
cosθ=∑i=1n(Ai)2×∑i=1n(Bi)2∑i=1n(Ai×Bi)=∣A∣×∣B∣A⋅B
值越大,表示越相似。
3.2 提取文章摘要
参考《自动摘要》
4. TF-IDF 优缺点
优点:简单快速,可解释性强
缺点:不够全面,有些重要词汇出现并不多,无法体现上下文信息。可以考虑word2Vec
5. SK-learn实战TF-IDF
- CountVectorizer
CountVectorizer类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素 a [ i ] [ j ] a[i][j] a[i][j],它表示 j j j词在 i i i篇文档中出现的频次。
fit_transform函数:计算各个词语出现的次数。
get_feature_names函数:可获取词袋中所有文本的关键字(英语是按字母顺序排列的)。
toarray函数:看到词频矩阵的结果。 - TfidfTransformer
TfidfTransformer用于统计vectorizer中每个词语的TF-IDF值。参考sk-learn文档《TF-IDF Text feature extraction》
参考代码如下所示:
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())
执行结果如下图: