TF-IDF(Term Frequency & Inverse Document Frequency),是一种用于信息检索(Information Retrieval,IR)与数据挖掘的常用加权技术。它的主要思想是:如果某个词或短语在一篇文章中出现的频率(term frequency)高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
tf i , j = n i , j ∑ k n k , j idf i = log ∣ D ∣ ∣ { j : t i ∈ d j } ∣ \begin{array}{ll} &\text{tf}_{i,j}=\frac{n_{i,j}}{\sum\limits_{k}n_{k,j}}\\ &\text{idf}_i=\log\frac{|D|}{|\{j:t_i\in d_j\}|} \end{array} tfi,j=k∑nk,jni,jidfi=log∣{j:ti∈dj}∣∣D∣
-
IF 定义式的:
- j:第 j 篇文章(文章编号);
- i:某个待考察的单词(第 i 个单词,单词在文章中的编号);
- k k k:第 j 篇文章的全部单词(文章中的全部单词);
-
idf 定义式:
- j:文章编号;
- i:待考察的单词编号;
- ∣ ⋅ ∣ |\cdot| ∣⋅∣:表示集合的大小;
1. 简单举例
- 一个文档有 100 个单词,baby 出现了 3 次;
- 则如果该文档编号为 j j j,该文档中的单词为 k k k( ∑ k n k , j = 100 \sum_k n_{k, j} = 100 ∑knk,j=100),对于单词 baby, t f b a b y , j = 3 100 = 0.03 tf_{baby, j}= \frac{3}{100}=0.03 tfbaby,j=1003=0.03
- 现有 10m 的文档,其中有 1000 篇文档中出现了单词 baby
- 10m 的文档,也即 ∣ D ∣ = 1 0 7 |D| = 10^7 ∣D∣=107,其中 1000 篇出现了单词 baby, ∣ { j : t i ∈ d j } ∣ = 1 0 3 |\{j:t_i\in d_j\}|=10^3 ∣{j:ti∈dj}∣=103
- 因此, i d f b a b y = log 1 0 7 1 0 3 = 4 idf_{baby}=\log \frac{10^7}{10^3}=4 idfbaby=log103107=4
- 该单词的 IF-IDF 值为 0.03*4 = 0.12
2. nltk 的计算
nltk.text 提供了 TextCollection 类以计算 tf-idf,
-
首先构建语料库:
from nltk.text import TextCollection sents = ['this is sentence one', 'this is sentence two', 'this is sentence three'] sents = [nltk.word_tokenize(sent) for sent in sents] corpus = TextCollection(sents)
-
计算 idf
此时已将全部的语料库fit进去,计算 idf 只需传递要计算的 word 即可:
>> corpus.idf('this') 0.0 # log(3/3) >> corpus.idf('three') 1.0986122886681098 # log(3/1)
-
计算某单词在某文档中的 tf:
>> corpus.tf('three', nltk.word_tokenize('one two three, go')) 0.2 # 1/5 >> corpus.tf_idf('three', nltk.word_tokenize('one two three, go')) 0.21972245773362198 # 0.2 * 1.0986122886681098