TFIDF 算法及其应用

2018/04/14 NLP 信息检索

TFIDF(词频-逆文档频率,term frequency–inverse document frequency),是一种用于信息检索与文本挖掘的常用加权技术。tf-idf是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文档的重要程度。字词的重要性随着它在文档中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。tf-idf的各种版本常被搜索引擎应用,作为文档与用户查询之间相关程度的度量或评级。

1、词频 TF

对于词项 t,根据其在文档 d 中的权重来计算它的得分。最简单的方式是将权重设置为 t 在文档中的出现次数。这种权重计算的结果为词频(term frequency),记为 $\text{tf}_{t,d}$,其中的两个下标分别对应词项和文档。

通常,我们要对词数(term count)进行归一化,以防止它偏向长的文件(同一个词项,在长文件里可能有更高的词数)。归一化的词数可表示为:

以上式子中,$n_{t,d}$ 是该词在文件 d 中的出现次数,而分母则是在文件 d 中所有字词的出现次数之和。

2、逆文档频率 IDF

词频 TF 会面临这样一个严重问题,即在进行相关度计算时,所有的词项都被认为是同等重要的。实际上,某些词项对于相关度计算来说几乎没有或很少区分能力。例如,在一个有关汽车工业的文档集中,几乎所有的文档都会包含 auto,此时,auto 就没有区分能力。

逆文档频率(inverse document frequency,IDF)是一个词语普遍重要性的度量,可用于解决上述问题。一个罕见词的 IDF 往往很高,而高频词的 IDF 就可能较低。IDF 可表示为:

其中,N 为文档的数目,$\text{df}_t$ 出现词项 t 的文档数目。

3、TFIDF 权重计算

对于每篇文档中的每个词项,可以将其 TF 和 IDF 组合在一起形成最终的权重。TFIDF权重机制对文档 d 中的词频 t 赋予的权重如下:

换句话说,$\text{tf-idf}_{t,d}$ 按照如下的方式对文档 d 中的词项 t 赋予权重:

  • 当 t 只在少数几篇文档中多次出现时,权重取值最大(此时能够对这些文档提供最强的区分能力)
  • 当 t 在一篇文档中出现次数很少,或者在很多文档中出现,权重取值较小(此时对最后的相关度计算作用不大)
  • 如果 t 在所有文档中都出现,那么权重取值最小

这样,就可以把文档看成是一个向量,其中的每个分量都对应词典中的一个词项。当某词项在文档中没有出现时,其对应的分量值为 0。这种文档的向量化,可用于检索的评分和排序。另外,也可将文档的向量作为机器学习模型的输入特征,对文档进行分类。

TF 和 IDF 有多种变种形式。如,TF 有采用原始词频频率的对数版本:$1+\log n_{t,d}$。

TF 的常见版本:

tf

IDF 的常见版本:

idf

不同的 TF 和 IDF 版本组合,形成不同的TFIDF 权重计算版本。

4、使用 scikit-learn 计算 TFIDF

scikit-learn 提供了从文本内容中提取数字特征的最常见方法:

  • 令牌化(tokenizing) 字符串(对字符串切分,例如通过使用空格和标点符号作为令牌分隔符),对每个可能的词令牌赋予一个整数id。
  • 统计(counting) 每个词令牌在文档中的出现次数。
  • 标准化(normalizing),若词令牌在大多数的样本/文档中出现,则削弱其权重。

CountVectorizer 实现了 tokenization (词语切分)和 occurrence counting (频数统计)。我们可以通过参数 ngram_range 设置词语切分时使用的 n-grams 模型。如,可提取 1-grams 和 2-grams 的单词的 CountVectorizer 类:

bigram_vectorizer = CountVectorizer(ngram_range=(1, 2),
                                    token_pattern=r'\b\w+\b', min_df=1)

而类 TfidfTransformer 可基于 CountVectorizer 类的统计结果,计算 TFIDF:

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

而类 TfidfVectorizerCountVectorizerTfidfTransformer 的功能组合在一个单例模型中:

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer


remove = ('headers', 'footers', 'quotes')
data_train = fetch_20newsgroups(subset='train', shuffle=True, 
                                random_state=42, remove=remove)
data_test = fetch_20newsgroups(subset='test',shuffle=True, 
                               random_state=42, remove=remove)

vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5,
                             stop_words='english')

X_train = vectorizer.fit_transform(data_train.data)
X_test = vectorizer.transform(data_test.data)

5、参考文献

  1. 信息检索导论[M]. 人民邮电出版社, 2010.
  2. 维基百科:tf–idf
  3. sklearn 文本特征提取

版权声明:如需转载,请注明出处

Search

    Table of Contents