TF-IDF 原理及sklearn中的tf-idf实例分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sty945/article/details/81813496

背景介绍

在一个大的文本语料库中,一些单词将出现很多次(例如 “the”, “a”, “is” 是英文),因此对文档的实际内容没有什么有意义的信息。 如果我们将直接计数数据直接提供给分类器,那么这些频繁词组会掩盖住那些我们关注但很少出现的词。
为了为了重新计算特征权重,并将其转化为适合分类器使用的浮点值,因此使用 tf-idf 变换是非常常见的。
Tf表示术语频率,而 tf-idf 表示术语频率乘以转制文档频率:
t f i d f ( t , d ) = t f ( t , d ) i d f ( d , t )

通俗的理解

字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降

公式解释:

在书本上面的通用的公式是:
t f ( t , d ) = t f i , j = n i , j k n k , j
其中 n i , j 表示术语 t i d j 中出现的次数, k n k , j 表示所有的 d j 中的单词个数之和

i d f ( d , t ) = l o g [ n d d f ( d , t ) + 1 ]
其中 n d 是文档的总数, d f ( d , t ) 是包含术语 t 的文档数,其中分母加1是为了防止除数为0

sklearn中tf-idf解释

在sklearn中的 t f i d f 中计算过程和上述的公式是有些区别的,在sklearn中,使用 TfidfTransformer的默认设置TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False) 术语频率,一个术语在给定文档中出现的次数乘以 idf组件, 计算为

t f ( t , d ) = n i , j
其中 n i , j 表示术语 t i d j 中出现的次数

idf ( d , t ) = l o g 1 + n d 1 + df ( d , t ) + 1
其中 n d 是文档的总数, d f ( d , t ) 是包含术语 t 的文档数

但是当smooth_idf=False
idf ( d , t ) = l o g n d df ( d , t ) + 1

然后,所得到的 tf-idf 向量通过欧几里得范数归一化:
v n o r m = v | | v | | 2 = v v 1 2 + v 2 2 + + v n 2

现在我们实现如下代码:

from sklearn.feature_extraction.text import TfidfTransformer
transformer = TfidfTransformer(smooth_idf=False)
counts = [[3, 0, 1],
          [2, 0, 0],
          [3, 0, 0],
          [4, 0, 0],
          [3, 2, 0],
          [3, 0, 2]]
tfidf = transformer.fit_transform(counts)
print(tfidf.toarray())

#output:
[[ 0.81940995,  0.        ,  0.57320793],
 [ 1.        ,  0.        ,  0.        ],
 [ 1.        ,  0.        ,  0.        ],
 [ 1.        ,  0.        ,  0.        ],
 [ 0.47330339,  0.88089948,  0.        ],
 [ 0.58149261,  0.        ,  0.81355169]]

例如,我们可以计算计数数组中第一个文档中第一个项的 tf-idf ,如下所示:

n d , term1 = 6

df ( d , t ) term1 = 6

idf ( d , t ) term1 = l o g n d df ( d , t ) + 1 = l o g ( 1 ) + 1 = 1

tf-idf term1 = tf × idf = 3 × 1 = 3

现在,如果我们对文档中剩下的2个术语重复这个计算,我们得到:
tf-idf term2 = 0 × ( l o g ( 6 / 1 ) + 1 ) = 0

tf-idf term3 = 1 × ( l o g ( 6 / 2 ) + 1 ) 2.0986

所以原始向量为:
tf-idf raw = [ 3 , 0 , 2.0986 ]

然后,应用欧几里德(L2)规范,我们获得文档1的以下 tf-idfs:
[ 3 , 0 , 2.0986 ] ( 3 2 + 0 2 + 2.0986 2 ) = [ 0.819 , 0 , 0.573 ]

此外,默认参数 smooth_idf=True 将 “1” 添加到分子和分母,就好像一个额外的文档被看做包含集合中的每个术语,这样可以避免零分割:

idf ( t ) = l o g 1 + n d 1 + df ( d , t ) + 1

使用此修改,文档1中第三项的 tf-idf 更改为 1.8473:
tf-idf term3 = 1 × l o g ( 7 / 3 ) + 1 1.8473

而 L2 标准化的 tf-idf 变为:
[ 3 , 0 , 1.8473 ] ( 3 2 + 0 2 + 1.8473 2 ) = [ 0.8515 , 0 , 0.5243 ] :

通过以下代码可以验证:

transformer = TfidfTransformer()
transformer.fit_transform(counts).toarray()

array([[ 0.85151335,  0.        ,  0.52433293],
       [ 1.        ,  0.        ,  0.        ],
       [ 1.        ,  0.        ,  0.        ],
       [ 1.        ,  0.        ,  0.        ],
       [ 0.55422893,  0.83236428,  0.        ],
       [ 0.63035731,  0.        ,  0.77630514]])

参考:

http://scikit-learn.org/stable/modules/feature_extraction.html#tfidf-term-weighting
https://zh.wikipedia.org/wiki/Tf-idf

猜你喜欢

转载自blog.csdn.net/sty945/article/details/81813496
今日推荐