IF-IDF

TF-IDF与余弦相似性的应用(一):自动提取关键词

 

一篇很长的文章,我要用计算机提取它的关键词(Automatic Keyphrase extraction),完全不加以人工干预,请问怎样才能正确做到?

这个问题涉及到数据挖掘、文本处理、信息检索等很多计算机前沿领域,但是出乎意料的是,有一个非常简单的经典算法,可以给出令人相当满意的结果。它简单到都不需要高等数学,普通人只用10分钟就可以理解,这就是我今天想要介绍的TF-IDF算法。

让我们从一个实例开始讲起。假定现在有一篇长文《中国的蜜蜂养殖》,我们准备用计算机提取它的关键词。

一个容易想到的思路,就是找到出现次数最多的词。如果某个词很重要,它应该在这篇文章中多次出现。于是,我们进行"词频"(Term Frequency,缩写为TF)统计。

结果你肯定猜到了,出现次数最多的词是----"的"、"是"、"在"----这一类最常用的词。它们叫做"停用词"(stop words),表示对找到结果毫无帮助、必须过滤掉的词。

假设我们把它们都过滤掉了,只考虑剩下的有实际意义的词。这样又会遇到了另一个问题,我们可能发现"中国"、"蜜蜂"、"养殖"这三个词的出现次数一样多。这是不是意味着,作为关键词,它们的重要性是一样的?

显然不是这样。因为"中国"是很常见的词,相对而言,"蜜蜂"和"养殖"不那么常见。如果这三个词在一篇文章的出现次数一样多,有理由认为,"蜜蜂"和"养殖"的重要程度要大于"中国",也就是说,在关键词排序上面,"蜜蜂"和"养殖"应该排在"中国"的前面。

所以,我们需要一个重要性调整系数,衡量一个词是不是常见词。如果某个词比较少见,但是它在这篇文章中多次出现,那么它很可能就反映了这篇文章的特性,正是我们所需要的关键词。

用统计学语言表达,就是在词频的基础上,要对每个词分配一个"重要性"权重。最常见的词("的"、"是"、"在")给予最小的权重,较常见的词("中国")给予较小的权重,较少见的词("蜜蜂"、"养殖")给予较大的权重。这个权重叫做"逆文档频率"(Inverse Document Frequency,缩写为IDF),它的大小与一个词的常见程度成反比。

知道了"词频"(TF)和"逆文档频率"(IDF)以后,将这两个值相乘,就得到了一个词的TF-IDF值。某个词对文章的重要性越高,它的TF-IDF值就越大。所以,排在最前面的几个词,就是这篇文章的关键词

下面就是这个算法的细节。

第一步,计算词频。

考虑到文章有长短之分,为了便于不同文章的比较,进行"词频"标准化。

或者

第二步,计算逆文档频率。

这时,需要一个语料库(corpus),用来模拟语言的使用环境。

如果一个词越常见,那么分母就越大,逆文档频率就越小越接近0。分母之所以要加1,是为了避免分母为0(即所有文档都不包含该词)。log表示对得到的值取对数。

第三步,计算TF-IDF。

可以看到,TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比。所以,自动提取关键词的算法就很清楚了,就是计算出文档的每个词的TF-IDF值,然后按降序排列,取排在最前面的几个词。

还是以《中国的蜜蜂养殖》为例,假定该文长度为1000个词,"中国"、"蜜蜂"、"养殖"各出现20次,则这三个词的"词频"(TF)都为0.02。然后,搜索Google发现,包含"的"字的网页共有250亿张,假定这就是中文网页总数。包含"中国"的网页共有62.3亿张,包含"蜜蜂"的网页为0.484亿张,包含"养殖"的网页为0.973亿张。则它们的逆文档频率(IDF)和TF-IDF如下:

从上表可见,"蜜蜂"的TF-IDF值最高,"养殖"其次,"中国"最低。(如果还计算"的"字的TF-IDF,那将是一个极其接近0的值。)所以,如果只选择一个词,"蜜蜂"就是这篇文章的关键词。

除了自动提取关键词,TF-IDF算法还可以用于许多别的地方。比如,信息检索时,对于每个文档,都可以分别计算一组搜索词("中国"、"蜜蜂"、"养殖")的TF-IDF,将它们相加,就可以得到整个文档的TF-IDF。这个值最高的文档就是与搜索词最相关的文档。

TF-IDF算法的优点是简单快速,结果比较符合实际情况。缺点是,单纯以"词频"衡量一个词的重要性,不够全面,有时重要的词可能出现次数并不多。而且,这种算法无法体现词的位置信息,出现位置靠前的词与出现位置靠后的词,都被视为重要性相同,这是不正确的。(一种解决方法是,对全文的第一段和每一段的第一句话,给予较大的权重。)

下一次,我将用TF-IDF结合余弦相似性,衡量文档之间的相似程度。

==========================================================================================================================================================================================================================================================================

 

基于TF-IDF算法抽取文章关键词

0. 写在前面

本文目的,利用TF-IDF算法抽取一篇文章中的关键词,关于TF-IDF,这里放一篇阮一峰老师科普好文 。

TF-IDF与余弦相似性的应用(一):自动提取关键词 - 阮一峰的网络日志

TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。(百度百科)

TF(Term Frequency)词频,某个词在文章中出现的次数或频率,如果某篇文章中的某个词出现多次,那这个词可能是比较重要的词,当然,停用词不包括在这里。

IDF(inverse document frequency)逆文档频率,这是一个词语“权重”的度量,在词频的基础上,如果一个词在多篇文档中词频较低,也就表示这是一个比较少见的词,但在某一篇文章中却出现了很多次,则这个词IDF值越大,在这篇文章中的“权重”越大。所以当一个词越常见,IDF越低。

当计算出TFIDF的值后,两个一乘就得到TF-IDF,这个词的TF-IDF越高就表示,就表示在这篇文章中的重要性越大,越有可能就是文章的关键词。

而Python的scikit-learn包下有计算TF-IDF的API,我们就用这个来简单的实现抽取文章关键词。

这里用到的文本数据材料则是《冰与火之歌》的1-5季(冰歌粉哈哈哈)

1. 数据采集

文本数据来源《冰与火之歌》小说在线阅读网站的内容爬取,这个的网站很多,这里就不贴出是哪一个了

 

爬取的难度不大,爬取下来之后写入本地文件

 

2. 文档分词

爬取了所有文档之后,后续为了计算TF和IDF值,首先要提取文档中的所有词语,利用python的jieba库可以来进行中文分词。

下面遍历所有文件里所有文档来分词

import jieba  

wordslist = []
titlelist = []
# 遍历文件夹
for file in os.listdir('.'):
    if '.' not in file:
        # 遍历文档
        for f in os.listdir(file):
            # 标题
            # windows下编码问题添加:.decode('gbk', 'ignore').encode('utf-8'))
            titlelist.append(file+'--'+f.split('.')[0])
            # 读取文档
            with open(file + '//' + f, 'r') as f:
                content = f.read().strip().replace('\n', '').replace(' ', '').replace('\t', '').replace('\r', '')
            # 分词
            seg_list = jieba.cut(content, cut_all=True)
            result = ' '.join(seg_list)
            wordslist.append(result)

文档分词之后还需要去停用词来提高抽取准确性,这里先准备一个停用词字典。

stop_word = [unicode(line.rstrip()) for line in open('chinese_stopword.txt')]

...
seg_list = jieba.cut(content, cut_all=True)
seg_list_after = []
# 去停用词
for seg in seg_list:
    if seg.word not in stop_word:
        seg_list_after.append(seg)
result = ' '.join(seg_list_after)
wordslist.append(result)

同时,我们还可以新增自选的词典,提高程序纠错能力,例如

jieba.add_word(u'丹妮莉丝')

3. scikit-learn的TF-IDF实现

(装好anaconda之后,scikit-learn已经完成)

 

scikit-learn中TF-IDF权重计算方法主要用到CountVectorizer()类TfidfTransformer()类。

CountVectorizer类会将文本中的词语转换为词频矩阵。矩阵中word[ i ][ j ],它表示j词在i类文本下的词频。

fit_transform(raw_documents[, y])Learn the vocabulary dictionary and return term-document matrix.get_feature_names()Array mapping from feature integer indices to feature name

fit_transform(),学习词语词典并返回文档矩阵,矩阵中元素为词语出现的次数。

get_feature_names(),获取特征整数索引到特征名称映射的数组,即文档中所有关键字的数组。

vectorizer = CountVectorizer()
word_frequence = vectorizer.fit_transform(wordslist)
words = vectorizer.get_feature_names()

TfidfTransformer类用于统计每个词语的TF-IDF值。

transformer = TfidfTransformer()
tfidf = transformer.fit_transform(word_frequence)
weight = tfidf.toarray()

最后按权重大小顺序输出前n位的词语即可

def titlelist():
    for file in os.listdir('.'):
        if '.' not in file:
            for f in os.listdir(file):
                yield (file+'--'+f.split('.')[0]) # windows下编码问题添加:.decode('gbk', 'ignore').encode('utf-8'))

def wordslist():
    jieba.add_word(u'丹妮莉丝')   
    stop_word = [unicode(line.rstrip()) for line in open('chinese_stopword.txt')]
    print len(stop_word)
    for file in os.listdir('.'):
        if '.' not in file:
            for f in os.listdir(file):
                with open(file + '//' + f) as t:
                    content = t.read().strip().replace('\n', '').replace(' ', '').replace('\t', '').replace('\r', '')
                    seg_list = pseg.cut(content)
                    seg_list_after = []
                    # 去停用词
                    for seg in seg_list:
                        if seg.word not in stop_word:
                            seg_list_after.append(seg.word)
                    result = ' '.join(seg_list_after)
                    # wordslist.append(result)
                    yield result
    

if __name__ == "__main__":

    wordslist = list(wordslist())
    titlelist = list(titlelist())
    
    vectorizer = CountVectorizer()
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(vectorizer.fit_transform(wordslist))
    
    words = vectorizer.get_feature_names()  #所有文本的关键字
    weight = tfidf.toarray()
    
    print 'ssss'
    n = 5 # 前五位
    for (title, w) in zip(titlelist, weight):
        print u'{}:'.format(title)
        # 排序
        loc = np.argsort(-w)
        for i in range(n):
            print u'-{}: {} {}'.format(str(i + 1), words[loc[i]], w[loc[i]])
        print '\n'

运行结果

 

得到每篇文档的关键词。

===========================================================================================================================================================================================================================================================================

TF-IDF实现关键词提取

2018年11月12日 10:03:30 kawhi849 阅读数:48更多

个人分类: NLP

TF-IDF方法简介

TF-IDF,实际上是两个部分:TF和IDF的乘积。下面分别对两个次解释。

TF:词频。简单理解,就是词语在文章中出现的频率。计算方法也很简单:

即文档i中词语j的词频等于词语j在文档i中的出现次数nij除以文档i中所有词语的数量。

IDF:逆向词频,也叫反文档频率。首先了解一下文档频率DF:一个词在所有文档中出现的频率,如共有100篇文章,10篇文章中出现,则频率为0.1。那么,IDF就是这个DF的倒数,也就是10。之后,在分母上+1,防止分母为0,再取对数。逆向词频解决的问题是方式常用词霸占词频榜,导致提取出来的关键词都是没有意义的常用词...(例如介词)。

即词i的逆向词频等于文档总数除以包含词i的文档数+1,再取对数。

最终的tf-idf算法将词频和逆向词频相乘,解决了常用词的问题,便可提取出文章的关键词。

实现代码

 
  1. string = "Automatic keyword extraction is to extract topical and important words or phrases form document or document set. It is a basic and necessary work in text mining tasks such as text retrieval and text summarization. This paper discusses the connotation of keyword extraction and automatic keyword extraction. In the light of linguistics, cognitive science, complexity science, psychology and social science, this paper studies the theoretical basis of automatic keyword extraction. From macro, meso and micro perspectives, the development, techniques and methods of automatic keyword extraction are reviewed and analyzed. This paper summarizes the current key technologies and research progress of automatic keyword extraction methods, including statistical methods, topic based methods, and network based methods. The evaluation approach of automatic keyword extraction is analyzed, and the challenges and trends of automatic keyword extraction are also predicted."

  2.  
  3. from jieba.analyse import *

  4. # print(jieba.cut(str))

  5. # print()

  6.  
  7. for keyword, weight in extract_tags(string, withWeight=True):

  8. print('%s %s' % (keyword, weight))

  9.  
  10. # kw = tfidf(str)

  11. # print(kw)

基于复杂网络的关键词提取方法

        基于复杂网络的提取方法,主要是利用单词在文本中的共现解决问题。假设在一个句子中,词A和词B同时出现,那么在网络中就会新建一条权重为1的边(若已存在这条边,则权值+1即可),由此构建复杂网络,再利用网络的一些拓扑特征去衡量单词在网络中的重要性,以达到关键词提取的目的。如度等紧密中心性的度量方法,可以反映网络中的节点的重要程度,但也要进行进一步的处理,否则同样会导致词频计算中的问题:常用词的干扰过大。如在英文中的and/is/or等类似的词汇,并不能表示实际意义,但是出现的频率却很高(后续的代码结果中也有体现),这往往需要使用多种不同的网络拓扑特征进行关键字的提取。

以下是实现代码:

 
  1. # coding = utf-8

  2.  
  3. import re

  4. import jieba

  5. import networkx as nx

  6. import matplotlib.pyplot as plt

  7. from operator import itemgetter, attrgetter

  8.  
  9. string = "Automatic keyword extraction is to extract topical and important words or phrases form document or document set. It is a basic and necessary work in text mining tasks such as text retrieval and text summarization. This paper discusses the connotation of keyword extraction and automatic keyword extraction. In the light of linguistics, cognitive science, complexity science, psychology and social science, this paper studies the theoretical basis of automatic keyword extraction. From macro, meso and micro perspectives, the development, techniques and methods of automatic keyword extraction are reviewed and analyzed. This paper summarizes the current key technologies and research progress of automatic keyword extraction methods, including statistical methods, topic based methods, and network based methods. The evaluation approach of automatic keyword extraction is analyzed, and the challenges and trends of automatic keyword extraction are also predicted."

  10.  
  11. G = nx.Graph()

  12.  
  13. str = string.split('.')

  14. # print(str)

  15. for s in str:

  16. # s = ' '.join(jieba.cut(s))

  17.  
  18. ss = re.split(' ',s)

  19. for sss in ss:

  20. for yyy in ss:

  21. # print(sss)

  22. if yyy != sss:

  23. # G.add_node(sss)

  24. G.add_edge(sss,yyy)

  25.  
  26. nx.draw(G,pos = nx.spring_layout(G),with_labels= True,node_size = 50)

  27. plt.savefig('network.png')

  28. plt.show()

  29. print('------------度排序-------------')

  30. degree = list(G.degree())

  31. degree.sort(key = itemgetter(1),reverse = True)

  32. print(degree)

  33. print('----------紧密中心性-----------')

  34. closenessCentrality = nx.closeness_centrality(G)

  35. c = sorted(closenessCentrality.items(),key= lambda closenessCentrality:closenessCentrality[1],reverse=True) #紧密中心性

  36. print(c)

结果:

tf-idf方法:

 
  1. keyword 1.0395450002521738

  2. extraction 1.0395450002521738

  3. automatic 0.7796587501891303

  4. methods 0.6497156251576086

  5. text 0.38982937509456517

  6. paper 0.38982937509456517

  7. science 0.38982937509456517

  8. document 0.25988625006304344

  9. analyzed 0.25988625006304344

  10. based 0.25988625006304344

  11. Automatic 0.12994312503152172

  12. extract 0.12994312503152172

  13. topical 0.12994312503152172

  14. important 0.12994312503152172

  15. words 0.12994312503152172

  16. phrases 0.12994312503152172

  17. form 0.12994312503152172

  18. set 0.12994312503152172

  19. basic 0.12994312503152172

  20. necessary 0.12994312503152172

复杂网络方法:

 
  1. ------------度排序-------------

  2. [('and', 78), ('', 67), ('keyword', 65), ('extraction', 65), ('the', 54), ('of', 54), ('automatic', 54), ('is', 40), ('paper', 35), ('methods', 31), ('are', 26), ('This', 23), ('summarizes', 21), ('current', 21), ('key', 21), ('technologies', 21), ('research', 21), ('progress', 21), ('methods,', 21), ('including', 21), ('statistical', 21), ('topic', 21), ('based', 21), ('network', 21), ('In', 19), ('light', 19), ('linguistics,', 19), ('cognitive', 19), ('science,', 19), ('complexity', 19), ('psychology', 19), ('social', 19), ('this', 19), ('studies', 19), ('theoretical', 19), ('basis', 19), ('From', 17), ('macro,', 17), ('meso', 17), ('micro', 17), ('perspectives,', 17), ('development,', 17), ('techniques', 17), ('reviewed', 17), ('analyzed', 17), ('The', 16), ('evaluation', 16), ('approach', 16), ('analyzed,', 16), ('challenges', 16), ('trends', 16), ('also', 16), ('predicted', 16), ('It', 15), ('a', 15), ('basic', 15), ('necessary', 15), ('work', 15), ('in', 15), ('text', 15), ('mining', 15), ('tasks', 15), ('such', 15), ('as', 15), ('retrieval', 15), ('summarization', 15), ('Automatic', 14), ('to', 14), ('extract', 14), ('topical', 14), ('important', 14), ('words', 14), ('or', 14), ('phrases', 14), ('form', 14), ('document', 14), ('set', 14), ('discusses', 10), ('connotation', 10)]

  3. ----------紧密中心性-----------

  4. [('and', 1.0), ('', 0.8764044943820225), ('keyword', 0.8571428571428571), ('extraction', 0.8571428571428571), ('the', 0.7647058823529411), ('of', 0.7647058823529411), ('automatic', 0.7647058823529411), ('is', 0.6724137931034483), ('paper', 0.6446280991735537), ('methods', 0.624), ('are', 0.6), ('This', 0.5864661654135338), ('summarizes', 0.5777777777777777), ('current', 0.5777777777777777), ('key', 0.5777777777777777), ('technologies', 0.5777777777777777), ('research', 0.5777777777777777), ('progress', 0.5777777777777777), ('methods,', 0.5777777777777777), ('including', 0.5777777777777777), ('statistical', 0.5777777777777777), ('topic', 0.5777777777777777), ('based', 0.5777777777777777), ('network', 0.5777777777777777), ('In', 0.5693430656934306), ('light', 0.5693430656934306), ('linguistics,', 0.5693430656934306), ('cognitive', 0.5693430656934306), ('science,', 0.5693430656934306), ('complexity', 0.5693430656934306), ('psychology', 0.5693430656934306), ('social', 0.5693430656934306), ('this', 0.5693430656934306), ('studies', 0.5693430656934306), ('theoretical', 0.5693430656934306), ('basis', 0.5693430656934306), ('From', 0.5611510791366906), ('macro,', 0.5611510791366906), ('meso', 0.5611510791366906), ('micro', 0.5611510791366906), ('perspectives,', 0.5611510791366906), ('development,', 0.5611510791366906), ('techniques', 0.5611510791366906), ('reviewed', 0.5611510791366906), ('analyzed', 0.5611510791366906), ('The', 0.5571428571428572), ('evaluation', 0.5571428571428572), ('approach', 0.5571428571428572), ('analyzed,', 0.5571428571428572), ('challenges', 0.5571428571428572), ('trends', 0.5571428571428572), ('also', 0.5571428571428572), ('predicted', 0.5571428571428572), ('It', 0.5531914893617021), ('a', 0.5531914893617021), ('basic', 0.5531914893617021), ('necessary', 0.5531914893617021), ('work', 0.5531914893617021), ('in', 0.5531914893617021), ('text', 0.5531914893617021), ('mining', 0.5531914893617021), ('tasks', 0.5531914893617021), ('such', 0.5531914893617021), ('as', 0.5531914893617021), ('retrieval', 0.5531914893617021), ('summarization', 0.5531914893617021), ('Automatic', 0.5492957746478874), ('to', 0.5492957746478874), ('extract', 0.5492957746478874), ('topical', 0.5492957746478874), ('important', 0.5492957746478874), ('words', 0.5492957746478874), ('or', 0.5492957746478874), ('phrases', 0.5492957746478874), ('form', 0.5492957746478874), ('document', 0.5492957746478874), ('set', 0.5492957746478874), ('discusses', 0.5342465753424658), ('connotation', 0.5342465753424658)]

附上string原文:

Automatic keyword extraction is to extract topical and important words or phrases form document or document set. It is a basic and necessary work in text mining tasks such as text retrieval and text summarization. This paper discusses the connotation of keyword extraction and automatic keyword extraction. In the light of linguistics, cognitive science, complexity science, psychology and social science, this paper studies the theoretical basis of automatic keyword extraction. From macro, meso and micro perspectives, the development, techniques and methods of automatic keyword extraction are reviewed and analyzed. This paper summarizes the current key technologies and research progress of automatic keyword extraction methods, including statistical methods, topic based methods, and network based methods. The evaluation approach of automatic keyword extraction is analyzed, and the challenges and trends of automatic keyword extraction are also predicted.

 

参考文献:

http://www.jos.org.cn/html/2017/9/5301.htm

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值