TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。
简介
原理
-
|D|:语料库中的文件总数
-
:包含词语的文件数目(即的文件数目)如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用作为分母。
目录
(2) IDF是逆向文件频率(Inverse Document Frequency)
1、TF-IDF算法介绍
TF-IDF(term frequency–inverse document frequency,词频-逆向文件频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。
TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。
TF-IDF的主要思想是:如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
(1)TF是词频(Term Frequency)
词频(TF)表示词条(关键字)在文本中出现的频率。
这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。
公式:
即:
其中 ni,j 是该词在文件 dj 中出现的次数,分母则是文件 dj 中所有词汇出现的次数总和;
(2) IDF是逆向文件频率(Inverse Document Frequency)
逆向文件频率 (IDF) :某一特定词语的IDF,可以由总文件数目除以包含该词语的文件的数目,再将得到的商取对数得到。
如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。
公式:
![]()
其中,|D| 是语料库中的文件总数。 |{j:ti∈dj}| 表示包含词语 ti 的文件数目(即 ni,j≠0 的文件数目)。如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用 1+|{j:ti∈dj}|
即:
(3)TF-IDF实际上是:TF * IDF
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
公式:
注: TF-IDF算法非常容易理解,并且很容易实现,但是其简单结构并没有考虑词语的语义信息,无法处理一词多义与一义多词的情况。
2、TF-IDF应用
(1)搜索引擎;(2)关键词提取;(3)文本相似性;(4)文本摘要
3、Python3实现TF-IDF算法
注意:该代码tf计算使用的是整个语料,这里只是举个简单的例子,大家在写的时候按文档计算词频即可!我这里就不做修改了
# -*- coding: utf-8 -*- from collections import defaultdict import math import operator """ 函数说明:创建数据样本 Returns: dataset - 实验样本切分的词条 classVec - 类别标签向量 """ def loadDataSet(): 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代表不好 return dataset, classVec """ 函数说明:特征选择TF-IDF算法 Parameters: list_words:词列表 Returns: dict_feature_select:特征选择词字典 """ def feature_select(list_words): #总词频统计 doc_frequency=defaultdict(int) for word_list in list_words: for i in word_list: doc_frequency[i]+=1 #计算每个词的TF值 word_tf={} #存储没个词的tf值 for i in doc_frequency: word_tf[i]=doc_frequency[i]/sum(doc_frequency.values()) #计算每个词的IDF值 doc_num=len(list_words) word_idf={} #存储每个词的idf值 word_doc=defaultdict(int) #存储包含该词的文档数 for i in doc_frequency: for j in list_words: if i in j: word_doc[i]+=1 for i in doc_frequency: word_idf[i]=math.log(doc_num/(word_doc[i]+1)) #计算每个词的TF*IDF的值 word_tf_idf={} 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 if __name__=='__main__': data_list,label_list=loadDataSet() #加载数据 features=feature_select(data_list) #所有词的TF-IDF值 print(features) print(len(features))
运行结果:
4、NLTK实现TF-IDF算法
from nltk.text import TextCollection from nltk.tokenize import word_tokenize #首先,构建语料库corpus sents=['this is sentence one','this is sentence two','this is sentence three'] sents=[word_tokenize(sent) for sent in sents] #对每个句子进行分词 print(sents) #输出分词后的结果 corpus=TextCollection(sents) #构建语料库 print(corpus) #输出语料库 #计算语料库中"one"的tf值 tf=corpus.tf('one',corpus) # 1/12 print(tf) #计算语料库中"one"的idf值 idf=corpus.idf('one') #log(3/1) print(idf) #计算语料库中"one"的tf-idf值 tf_idf=corpus.tf_idf('one',corpus) print(tf_idf)
运行结果:
5、Sklearn实现TF-IDF算法
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权值 tf_idf_transformer = TfidfTransformer() #将文本转为词频矩阵并计算tf-idf 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 = tf_idf_transformer.transform(vectorizer.transform(x_test)) x_test_weight = tf_idf.toarray() # 测试集TF-IDF权重矩阵 print('输出x_train文本向量:') print(x_train_weight) print('输出x_test文本向量:') print(x_test_weight)
运行结果:
6、Jieba实现TF-IDF算法
import jieba.analyse text='关键词是能够表达文档中心内容的词语,常用于计算机系统标引论文内容特征、 信息检索、系统汇集以供读者检阅。关键词提取是文本挖掘领域的一个分支,是文本检索、 文档比较、摘要生成、文档分类和聚类等文本挖掘研究的基础性工作' keywords=jieba.analyse.extract_tags(text, topK=5, withWeight=False, allowPOS=()) print(keywords)
运行结果:
注:
TF-IDF 采用文本逆频率 IDF 对 TF 值加权取权值大的作为关键词,但 IDF 的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以 TF-IDF 算法的精度并不是很高,尤其是当文本集已经分类的情况下。
在本质上 IDF 是一种试图抑制噪音的加权,并且单纯地认为文本频率小的单词就越重要,文本频率大的单词就越无用。这对于大部分文本信息,并不是完全正确的。IDF 的简单结构并不能使提取的关键词, 十分有效地反映单词的重要程度和特征词的分布情 况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被盖。
TF-IDF算法实现简单快速,但是仍有许多不足之处:
(1)没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。
(2)按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词。
(3)传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。
(4)对于文档中出现次数较少的重要人名、地名信息提取效果不佳。
详细改进方法参看论文:改进的 TF-IDF 关键词提取方法
交流学习资料共享欢迎入QQ群:955817470
背景
最近看吴军的《数学之美》了解了一些文本处理方法,其中TF-IDF给了我深刻的印象(因为之前也做过这方面的项目),正好这次做个记录。
信息熵
TF-IDF是在熵的基础上发展的概念,因此先介绍熵。
熵反映的是一个系统的混乱程度,一个系统越混乱,其熵就越大;越是整齐,熵就越小。熵增加原理指的是一个孤立系统内的自发过程,都是从朝越来越混乱的方向发展,意思是向熵增加的方向发展。
在熵的基础上发展出了信息熵的概念,用来衡量数据的信息量。下面介绍信息熵公式:
其中 代表随机事件X为 的概率。1,事件发生的概率越低,其发生时所能给出的信息量越大。
日常发生的事情没什么信息量,罕见的事情信息量就大了(如海南下雪了)
2,,因此负号是为了确保信息一定是正数或者是0
3,信息熵还可以作为一个系统复杂程度的度量,如果系统越复杂,出现不同情况的种类越多,那么他的信息熵是比较大的。如果一个系统越简单,出现情况种类很少,此时的信息熵较小。相对熵
用于衡量两个取值为正值的函数的相关性。公式如下:
1,两个函数完全相同,相对熵为0
2,相对熵越大,函数差异越大;反正差异越小。
3,对于概率分布或者概率密度函数,取值均大于0,相对熵可以衡量两个随机分布的差异性。
TF-IDF实际就是一种相对熵TF-IDF
TF-IDF算法在文本处理中有很重要的作用。下面作介绍:
1,TF(Term Frequency)
在搜索引擎中,如何对结果排序?一开始的做法是根据网页自身的质量以及网页中出现关键词的频率进行排序。但是这个办法有一个问题,篇幅长的网页会比篇幅短的网页占便宜,因为前者中含有更多的关键词。因此我们可以对数据进行归一化,也就是将关键词出现的次数除以网页的总字数,得到的就是TF。
如:输入、、…n个关键词进行查询,则一个网页的相关性可以用TF衡量,记为:
2,IDF(Inverse Document Frequency)
不同关键词应该有不同的权重,如一些无意义的停止词(的,是,和等)权重为0;而词预测主题的能力越强,其权重应该越大。
什么样的词预测能力强?一个词如果只在很少的网页中出现,那么就很容易通过这个词预测主题;那些在网页中经常出现的词,看到了也很难预测出网页的主题。
据此可以得到IDF的公式:
3,TF-IDF
TF-IDF是TF(频率)和IDF(预测主题能力)的加权求和:
代码
最后附上之前写的TF-IDF代码。
# -*- coding: utf-8 -*- from collections import defaultdict import math import operator import pandas as pd import jieba import re import csv #对文本进行分词 def list_build(csv_data_list): data_list=[] for one_list in csv_data_list: seg_list=jieba.cut(str(one_list)) z=[x for x in seg_list] zz=str(z) #去特殊符号 zz = re.sub(r'([\d]+)',' ',zz).lower() zz = re.sub("[0-9\s+\.\!\/_,$%^*()?;;:-【】+\"\']+|[+——!,;:。?、~@#¥%……&*()]+", " ", zz) #移除字符串开头的空格 zz = zz.strip() #根据空格将字符串分为列表中的元素 zz=zz.split(' ') #去除停用词 for i in range(len(zz)): for one in zz: if one in stop_words: zz.remove(one) #去除空元素 while '' in zz: zz.remove('') data_list.append(zz) return data_list """ 函数说明:特征选择TF-IDF算法 Parameters: list_words:词列表 Returns: dict_feature_select:特征选择词字典 """ def feature_select(list_words): #总词频统计,统计每个词语总共出现的次数 doc_frequency=defaultdict(int) for word_list in list_words: for i in word_list: doc_frequency[i]+=1 #计算每个词的TF值,每个词出现的次数除以所有词语出现的次数 word_tf={} #存储没个词的tf值 for i in doc_frequency: word_tf[i]=doc_frequency[i]/sum(doc_frequency.values()) #计算每个词的IDF值,微博数除以出现该词的微博数 doc_num=len(list_words) word_idf={} #存储每个词的idf值 word_doc=defaultdict(int) #存储包含该词的文档数 #读取每个词 for i in doc_frequency: #读取每条文档 for j in list_words: if i in j: word_doc[i]+=1 for i in doc_frequency: word_idf[i]=math.log(doc_num/(word_doc[i]+1)) #计算每个词的TF*IDF的值 word_tf_idf={} 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 if __name__=='__main__': f=open('DATA.txt',encoding="utf-8") data=pd.read_csv(f) csv_data_list = data['text'] stop_words=['二哈','摊手','分享','图片'......] data_list=list_build(csv_data_list) features=feature_select(data_list) #所有词的TF-IDF值 with open('结果.txt','w',encoding="utf-8",newline='') as f1: header=['text','num'] writer = csv.writer(f1, delimiter=',') writer.writerow(header) for i in range(len(features)): header=[features[i][0],str(features[i][1])] writer.writerow(header)
TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。
简介
TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜索引擎还会使用基于链接分析的评级方法,以确定文件在搜寻结果中出现的顺序。[1]原理
TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF逆向文件频率(Inverse Document Frequency)。TF表示词条在文档d中出现的频率。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处. 在一份给定的文件里,词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)对于在某一特定文件里的词语来说,它的重要性可表示为:以上式子中分子是该词在文件中的出现次数,而分母则是在文件中所有字词的出现次数之和。逆向文件频率(inverse document frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到:其中
|D|:语料库中的文件总数 :包含词语的文件数目(即的文件数目)如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用作为分母。举例
例1
有很多不同的数学公式可以用来计算TF-IDF。这边的例子以上述的数学公式来计算。词频 (TF) 是一词语出现的次数除以该文件的总词语数。假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (IDF) 的方法是测定有多少份文件出现过“母牛”一词,然后除以文件集里包含的文件总数。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 log(10,000,000 / 1,000)=4。最后的TF-IDF的分数为0.03 * 4=0.12。例2
在某个一共有一千词的网页中“原子能”、“的”和“应用”分别出现了 2 次、35 次 和 5 次,那么它们的词频就分别是 0.002、0.035 和 0.005。 我们将这三个数相加,其和 0.042 就是相应网页和查询“原子能的应用” 相关性的一个简单的度量。概括地讲,如果一个查询包含关键词 w1,w2,...,wN, 它们在一篇特定网页中的词频分别是: TF1, TF2, ..., TFN。 (TF: term frequency)。 那么,这个查询和该网页的相关性就是:TF1 + TF2 + ... + TFN。读者可能已经发现了又一个漏洞。在上面的例子中,词“的”占了总词频的 80% 以上,而它对确定网页的主题几乎没有用。我们称这种词叫“应删除词”(Stopwords),也就是说在度量相关性是不应考虑它们的频率。在汉语中,应删除词还有“是”、“和”、“中”、“地”、“得”等等几十个。忽略这些应删除词后,上述网页的相似度就变成了0.007,其中“原子能”贡献了 0.002,“应用”贡献了 0.005。细心的读者可能还会发现另一个小的漏洞。在汉语中,“应用”是个很通用的词,而“原子能”是个很专业的词,后者在相关性排名中比前者重要。因此我们需要给汉语中的每一个词给一个权重,这个权重的设定必须满足下面两个条件:1. 一个词预测主题能力越强,权重就越大,反之,权重就越小。我们在网页中看到“原子能”这个词,或多或少地能了解网页的主题。我们看到“应用”一次,对主题基本上还是一无所知。因此,“原子能“的权重就应该比应用大。2. 应删除词的权重应该是零。我们很容易发现,如果一个关键词只在很少的网页中出现,我们通过它就容易锁定搜索目标,它的权重也就应该大。反之如果一个词在大量网页中出现,我们看到它仍然不很清楚要找什么内容,因此它应该小。概括地讲,假定一个关键词 w 在 Dw 个网页中出现过,那么 Dw 越大,w的权重越小,反之亦然。在信息检索中,使用最多的权重是“逆文本频率指数” (Inverse document frequency 缩写为IDF),它的公式为log(D/Dw)其中D是全部网页数。比如,我们假定中文网页数是D=10亿,应删除词“的”在所有的网页中都出现,即Dw=10亿,那么它的IDF=log(10亿/10亿)= log (1) = 0。假如专用词“原子能”在两百万个网页中出现,即Dw=200万,则它的权重IDF=log(500) =2.7。又假定通用词“应用”,出现在五亿个网页中,它的权重IDF = log(2)则只有 0.3。也就是说,在网页中找到一个“原子能”的比配相当于找到九个“应用”的匹配。利用 IDF,上述相关性计算的公式就由词频的简单求和变成了加权求和,即 TF1*IDF1 + TF2*IDF2 +... + TFN*IDFN。在上面的例子中,该网页和“原子能的应用”的相关性为 0.0069,其中“原子能”贡献了 0.0054,而“应用”只贡献了0.0015。这个比例和我们的直觉比较一致了。[3]应用
权重计算方法经常会和余弦相似度(cosine similarity)一同使用于向量空间模型中,用以判断两份文件之间的相似性。理论假设
TFIDF算法是建立在这样一个假设之上的:对区别文档最有意义的词语应该是那些在文档中出现频率高,而在整个文档集合的其他文档中出现频率少的词语,所以如果特征空间坐标系取TF词频作为测度,就可以体现同类文本的特点。另外考虑到单词区别不同类别的能力,TFIDF法认为一个单词出现的文本频数越小,它区别不同类别文本的能力就越大。因此引入了逆文本频度IDF的概念,以TF和IDF的乘积作为特征空间坐标系的取值测度,并用它完成对权值TF的调整,调整权值的目的在于突出重要单词,抑制次要单词。但是在本质上IDF是一种试图抑制噪音的加权 ,并且单纯地认为文本频数小的单词就越重要,文本频数大的单词就越无用,显然这并不是完全正确的。IDF的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以TFIDF法的精度并不是很高。此外,在TFIDF算法中并没有体现出单词的位置信息,对于Web文档而言,权重的计算方法应该体现出HTML的结构特征。特征词在不同的标记符中对文章内容的反映程度不同,其权重的计算方法也应不同。因此应该对于处于网页不同位置的特征词分别赋予不同的系数,然后乘以特征词的词频,以提高文本表示的效果。模型概率
信息检索概述信息检索是当前应用十分广泛的一种技术,论文检索、搜索引擎都属于信息检索的范畴。通常,人们把信息检索问题抽象为:在文档集合D上,对于由关键词w[1] … w[k]组成的查询串q,返回一个按查询q和文档d匹配度 relevance (q, d)排序的相关文档列表D’。[4]对于这一基问题,先后出现了布尔模型、向量模型等各种经典的信息检索模型,它们从不同的角度提出了自己的一套解决方案。布尔模型以集合的布尔运算为基础,查询效率高,但模型过于简单,无法有效地对不同文档进行排序,查询效果不佳。向量模型把文档和查询串都视为词所构成的多维向量,而文档与查询的相关性即对应于向量间的夹角。不过,由于通常词的数量巨大,向量维度非常高,而大量的维度都是0,计算向量夹角的效果并不好。另外,庞大的计算量也使得向量模型几乎不具有在互联网搜索引擎这样海量数据集上实施的可行性。[4]tf-idf 模型当前,真正在搜索引擎等实际应用中广泛使用的是 tf-idf 模型。tf-idf 模型的主要思想是:如果词w在一篇文档d中出现的频率高,并且在其他文档中很少出现,则认为词w具有很好的区分能力,适合用来把文章d和其他文章区分开来。[4]信息检索的概率视角直观上看,tf 描述的是文档中词出现的频率;而 idf 是和词出现文档数相关的权重。我们比较容易定性地理解 tf-idf 的基本思想,但具体到 tf-idf 的一些细节却并不是那么容易说清楚为什么。[4]总结转载于:https://www.cnblogs.com/fclbky/p/4908209.html