[TOC]
TF-IDF算法
TF-IDF算法介绍
TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。
TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜索引擎还会使用基于链接分析的评级方法,以确定文件在搜寻结果中出现的顺序。
TF => 词频(Term Frequency)
词频表示关键字在文本中的出现频率(次数)。该数字通常会被归一化处理,即用词频除以文章的总词数,以防止偏向长的文件
公式:
$$ tf_ij = \frac{n_ij}{\sum_kn_kj}\\ \\ TF_w = \frac{在某一类中词条w出现的次数}{该类中所有的词条数目}\\ \\ 其中n_ij是该词在文件d_j中出现的次数,分母是文件d_j所有词汇出现的次数总和 $$
IDF => 逆向文件频率(Inverse Document Frequency)
逆向文件频率(IDF):某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到
如果包含该词t的文档越少,IDF越大,则说明词条具有很好的类别区分能力
公式:
$$ idf_i = log\frac{|D|}{|\{j:t_i\in d_j\}|} $$
其中,分子是语料库中的文件总数。分母是包含词语ti的文件数(即ni,j/=0的文件数目)。如果该词语不在语料库中,就会导致分母为0,因此一般情况下使用1+分母。
$$ IDF = log(\frac{语料库的文档总数}{包含词条w的文档数+1}),分母之所以要加1,是为了避免分母为0的情况 $$
TF-IDF实际上是:TF*IDF
某一特定的文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
$$ TF\_IDF = TF * IDF $$
TF-IDF算法并没有考虑到词语的语义信息,无法处理一词多意于一意多词的情况
python3实现
import operator
from collections import defaultdict
import math
dataset = [
['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting','stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate','my','steak', 'how', 'to','stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food','stupid']
]
classVec = [0, 1, 0, 1, 0, 1] # 类别的标签向量, 1好,0不好
def feature_select(list_words):
doc_frequency = defaultdict(int)
for word_list in list_words:
for i in word_list:
doc_frequency[i] += 1
word_tf = {
} # 存储每个词的tf
for i in doc_frequency:
word_tf[i] = doc_frequency[i]/sum(doc_frequency.values())
doc_num = len(list_words)
word_idf = {
} # 存储每个词的idf
word_doc = defaultdict(int) # 存储包含该词的文档数
word_tf_idf = {
}
for i in doc_frequency:
for j in list_words:
word_doc[i] += 1
for i in doc_frequency:
word_idf[i] - math.log(doc_num/(word_doc[i]+1))
for i in doc_frequency:
word_tf_idf[i] = word_tf[i]*word_idf[i]
dict_feature_select = sorted(word_tf_idf.items(), key=operator.itemgetter(1), reverse=True)
return dict_feature_select
data_list, label_list = loadDataSet()
features = feature_select(data_list)
NLTK实现
from nltk.text import TextCollection
from nltk.tokenize import word_tokenize
sents=['this is sentence one','this is sentence two','this is sentence three']
sents=[word_tokenize(sent) for sent in sents] #对每个句子进行分词
corpus=TextCollection(sents) #构建语料库
tf=corpus.tf('one',corpus) # 1/12
idf=corpus.idf('one') #log(3/1)
tf_idf=corpus.tf_idf('one',corpus)
Sklearn实现
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
x_train = ['TF-IDF 主要 思想 是','算法 一个 重要 特点 可以 脱离 语料库 背景',
'如果 一个 网页 被 很多 其他 网页 链接 说明 网页 重要']
x_test=['原始 文本 进行 标记','主要 思想']
#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频
vectorizer = CountVectorizer(max_features=10)
tf_idf_transformer = TfidfTransformer()
tf_idf = tf_idf_transformer.fit_transform(vectorizer.fit_transform(x_train))
#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
x_train_weight = tf_idf.toarray()
tf_idf = tf_idf_transformer.transform(vectorizer.transform(x_test))
x_test_weight = tf_idf.toarray() # 测试集TF-IDF权重矩阵
jiaba实现
text='关键词是能够表达文档中心内容的词语,常用于计算机系统标引论文内容特征、
信息检索、系统汇集以供读者检阅。关键词提取是文本挖掘领域的一个分支,是文本检索、
文档比较、摘要生成、文档py分类和聚类等文本挖掘研究的基础性工作'
keywords=jieba.analyse.extract_tags(text, topK=5, withWeight=False, allowPOS=())
注意:
- jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
- sentence 为待提取的文本
- topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
- withWeight 为是否一并返回关键词权重值,默认值为 False
- allowPOS 仅包括指定词性的词,默认值为空,即不筛选
TF-IDF算法缺点
TF-IDF 采用文本逆频率 IDF 对 TF 值加权取权值大的作为关键词,但 IDF 的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以 TF-IDF 算法的精度并不是很高,尤其是当文本集已经分类的情况下。
在本质上 IDF 是一种试图抑制噪音的加权,并且单纯地认为文本频率小的单词就越重要,文本频率大的单词就越无用。这对于大部分文本信息,并不是完全正确的。IDF 的简单结构并不能使提取的关键词, 十分有效地反映单词的重要程度和特征词的分布情 况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被盖。
TF-IDF算法实现简单快速,但是仍有许多不足之处:
(1)没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。
(2)按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词。
(3)传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。
(4)对于文档中出现次数较少的重要人名、地名信息提取效果不佳。
TF-IWF算法
- TF-IWF算法是TF-IDF算法的优化版,是一种加权算法
一方面,设某个词在文档中出现的总次数为 Nd,tNd,t,且文档的总词数为 NdNd,则词相对于文档的TF为:
$$ TF = \frac{N_d,t}{N_d} $$
另一方面,设某一文档集/语料库所有词的频数为 WcWc,其中词在文档集/语料库所有词中的频数为 Wc,tWc,t,则词相对于文档集/语料库的 IWFIWF 为:
$$ IWF = log(\frac{W_c}{W_c,t}) $$
从而,词相对于文档的 TF\raisebox0mm−IWFTF\raisebox0mm−IWF 为:
$$ TF-IWF = TF*IWF = \frac{N_d,t}{N_d}*log(\frac{W_c}{W_c,t}) $$
传统 TF\raisebox0mm−IDF所求的权值一般很小,甚至接近于 0,精确度也不高,计算结果恰能解决权值过小的问题。