上一篇博文中,我们使用结巴分词对文档进行分词处理,但分词所得结果并不是每个词语都是有意义的(即该词对文档的内容贡献少),那么如何来判断词语对文档的重要度呢,这里介绍一种方法:TF-IDF。

  一,TF-IDF介绍

  TF-IDF(Term Frequency–Inverse Document Frequency)是一种用于资讯检索与文本挖掘的常用加权技术。TF-IDF是一种统计方法,用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。

  TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF。

  (1)词频(Term Frequency,TF)指的是某一个给定的词语在该文件中出现的频率。即词w在文档d中出现的次数count(w, d)和文档d中总词数size(d)的比值。

tf(w,d) = count(w, d) / size(d)

  这个数字是对词数(term count)的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)

  (2)逆向文件频率(Inverse Document Frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。即文档总数n与词w所出现文件数docs(w, D)比值的对数。  

idf = log(n / docs(w, D))

  TF-IDF根据 tf 和 idf 为每一个文档d和由关键词w[1]...w[k]组成的查询串q计算一个权值,用于表示查询串q与文档d的匹配度:

tf-idf(q, d)
= sum { i = 1..k | tf-idf(w[i], d) }
= sum { i = 1..k | tf(w[i], d) * idf(w[i]) }

  某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

  关于TF-IDF的详细介绍和例子,有兴趣的同学可以看这一篇博客。  下面主要分享TF-IDF在Python的如何使用。

  二,Python中计算TF-IDF

  在Python中,scikit-learn包下有计算TF-IDF的api,其效果也很不错。首先得安装Scikit-clearn。不同系统安装请看:http://scikit-learn.org/stable/install.html。

  本机环境:linux(ubuntu) 64位,python2.7.6

  1. 安装scikit-learn包(先安装依赖包,再安装sklearn)

sudo apt-get install build-essential python-dev python-setuptools \
python-numpy python-scipy \
libatlas-dev libatlas3gf-base
sudo apt-get install python-sklearn

  或者通过pip进行安装,pip是一个给python用的挺不错的安装工具。

sudo apt-get install python-pip 
sudo pip install -U scikit-learn

  检验是否安装成功,在terminal里面输入

pip list

  会列出pip安装的所有东西,如果里面有sklearn这一项,则安装成功。

  2. 安装jieba分词包

  由于计算TF-IDF是对分词结果进行计算,所以这里需要使用jieba中文分词。有关结巴分词的使用,可以看上一篇博文:Python 结巴分词

sudo pip install jieba 

  3. 计算TF-IDF

  scikit-learn包进行TF-IDF分词权重计算主要用到了两个类:CountVectorizer和TfidfTransformer。其中

  CountVectorizer是通过fit_transform函数将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在第i个文本下的词频。即各个词语出现的次数,通过get_feature_names()可看到所有文本的关键字,通过toarray()可看到词频矩阵的结果。简例如下:

>>> from sklearn.feature_extraction.text import CountVectorizer
>>> vectorizer = CountVectorizer()
>>> corpus = [
... 'This is the first document.',
... 'This is the second second document.',
... 'And the third one.',
... 'Is this the first document?',
... ]
>>> X = vectorizer.fit_transform(corpus)
>>> X.toarray()
array([[0, 1, 1, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 2, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 0, 0, 1, 0, 1]]...)
>>> vectorizer.get_feature_names()
(['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this'])

  TfidfTransformer是统计vectorizer中每个词语的tf-idf权值,用法如下:

>>> from sklearn.feature_extraction.text import CountVectorizer
>>> 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()
array([[ 0.85..., 0. ..., 0.52...],
[ 1. ..., 0. ..., 0. ...],
[ 1. ..., 0. ..., 0. ...],
[ 1. ..., 0. ..., 0. ...],
[ 0.55..., 0.83..., 0. ...],
[ 0.63..., 0. ..., 0.77...]])

  关于函数的具体说明,请看官方说明文档:scikit-learn common-vectorizer-usage

  这里我处理的是对100份文档进行分词,然后进行TF-IDF的计算,其效果相当好。

import os
import jieba
import jieba.posseg as pseg
import sys
import string
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
reload(sys)
sys.setdefaultencoding('utf8')
#获取文件列表(该目录下放着100份文档)
def getFilelist(argv) :
path = argv[1]
filelist = []
files = os.listdir(path)
for f in files :
if(f[0] == '.') :
pass
else :
filelist.append(f)
return filelist,path
#对文档进行分词处理
def fenci(argv,path) :
#保存分词结果的目录
sFilePath = './segfile'
if not os.path.exists(sFilePath) :
os.mkdir(sFilePath)
#读取文档
filename = argv
f = open(path+filename,'r+')
file_list = f.read()
f.close() #对文档进行分词处理,采用默认模式
seg_list = jieba.cut(file_list,cut_all=True) #对空格,换行符进行处理
result = []
for seg in seg_list :
     seg = ''.join(seg.split())
if (seg != '' and seg != "\n" and seg != "\n\n") :
result.append(seg) #将分词后的结果用空格隔开,保存至本地。比如"我来到北京清华大学",分词结果写入为:"我 来到 北京 清华大学"
f = open(sFilePath+"/"+filename+"-seg.txt","w+")
f.write(' '.join(result))
f.close() #读取100份已分词好的文档,进行TF-IDF计算
def Tfidf(filelist) :
  path = './segfile/'
corpus = [] #存取100份文档的分词结果
for ff in filelist :
fname = path + ff
f = open(fname,'r+')
content = f.read()
f.close()
corpus.append(content) vectorizer = CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)) word = vectorizer.get_feature_names() #所有文本的关键字
weight = tfidf.toarray() #对应的tfidf矩阵 sFilePath = './tfidffile'
if not os.path.exists(sFilePath) :
os.mkdir(sFilePath) # 这里将每份文档词语的TF-IDF写入tfidffile文件夹中保存
for i in range(len(weight)) :
     print u"--------Writing all the tf-idf in the",i,u" file into ",sFilePath+'/'+string.zfill(i,5)+'.txt',"--------"
f = open(sFilePath+'/'+string.zfill(i,5)+'.txt','w+')
for j in range(len(word)) :
f.write(word[j]+" "+str(weight[i][j])+"\n")
f.close() if __name__ == "__main__" :
(allfile,path) = getFilelist(sys.argv)
  for ff in allfile :
print "Using jieba on "+ff
fenci(ff,path) Tfidf(allfile)

参考资料:

  1.维基百科:http://zh.wikipedia.org/wiki/TF-IDF

  2.TF-IDF模型的概率解释:http://www.cnblogs.com/weidagang2046/archive/2012/10/22/tf-idf-from-probabilistic-view.html#top

  3.liuxuejiang158的专栏:http://blog.csdn.net/liuxuejiang158blog/article/details/31360765

  4.Scikit-learn:http://scikit-learn.org/stable/modules/feature_extraction.html#common-vectorizer-usage

Python TF-IDF计算100份文档关键词权重的更多相关文章

  1. Atitit 计算word ppt文档的页数

    Atitit 计算word ppt文档的页数 http://localhost:8888/ http://git.oschina.net/attilax/ati_wordutil private vo ...

  2. DedeCms文档关键词替换,优先替换长尾关键词

    本文教大家:dedecms文档关键词维护之关键词出现多次,只给出现的第一个加链接的 举例:当文章中出现了一百次台历时,按官方的原理,他会给一百个台历都加上链接的.dedecms这如何是好? 解决方法( ...

  3. dedecms批量删除文档关键词可以吗

    这几天在重新整服务器,几个站点都是用dedecms搭建的,版本相对比较早,虽然都已经打了补丁,但客户还是在纠结,所以就下载了新的系统进行搭建(注意编码要和原来的一样),导入数据,一切安好,可发现后台有 ...

  4. 根据网站所做的SEO优化整理的一份文档

    今日给合作公司讲解本公司网站SEO优化整理的一份简单文档 架构 ########################################## 1.尽量避免Javascript和flash导航. ...

  5. python 使用win32com实现对word文档批量替换页眉页脚

    最近由于工作需要,需要将70个word文件的页眉页脚全部进行修改,在想到这个无聊/重复/没有任何技术含量的工作时,我的内心是相当奔溃的.就在我接近奔溃的时候我突然想到完全可以用python脚本来实现这 ...

  6. 用python批量生成简单的xml文档

    最近生成训练数据时,给一批无效的背景图片生成对应的xml文档,我用python写了一个简单的批量生成xml文档的demo,遇见了意外的小问题,记录一下. 报错问题为:ImportError: No m ...

  7. 使用sphinx自动提取python中的注释成为接口文档

    写好了代码,交付给他人使用的时候,查看代码固然可以了解各类和函数的功能细节,但接口文档能更方便的查找和说明功能.所以,一价与代码同步的接口文档是很有必要的.sphinx可以根据python中的注释,自 ...

  8. python开发_xml.dom_解析XML文档_完整版_博主推荐

    在阅读之前,你需要了解一些xml.dom的一些理论知识,在这里你可以对xml.dom有一定的了解,如果你阅读完之后. 下面是我做的demo 运行效果: 解析的XML文件位置:c:\\test\\hon ...

  9. Linux进阶文档丨阿里架构师十年Linux心得,全在这份文档里面

    Linux是什么 Linux就是个操作系统: 它和Windows XP.Windows 7.Windows 10什么的一样就是一个操作系统而已! Linux能干什么: 它能当服务器,服务器上安装者各种 ...

随机推荐

  1. K需要修改的内容

    1.需要保存默认案件,所有相关的页面的Title都要显示默认按键信息. 2.播放器需要调整,左侧的是播放信息,用户选择:案件/设备/然后就把该目录下的文件都展示出来.用户选择的时候马上进行播放.右侧有 ...

  2. qt 提高ui响应度

    如何使Qt 平台中的GUI保持响应流畅?一般来说耗时较长的操作,分为计算密集型操作和IO密集型操作,对于这两类操作如何提高响应速度. 而从操作的本质上来说,操作又可分为不可分解操作,如在第三方库中耗时 ...

  3. 使用Camera进行拍照

    Android应用提供了Camera来控制拍照,使用Camera进行拍照的步骤如下: 1.调用Camera的open()方法打开相机. 2.调用Camera的getParameters()方法获取拍照 ...

  4. 使用AlarmManager设置闹钟----之一

    import java.util.Calendar; import android.os.Bundle;import android.app.Activity;import android.app.A ...

  5. Difference between Linearizability and Serializability

    原文:http://stackoverflow.com/questions/8200015/what-is-the-difference-between-serializability-and-lin ...

  6. c# 调用 ShellExecute

    using System.Runtime.InteropServices; namespace ConsoleTest{    class Program    {        public enu ...

  7. Codeforces Round #257 (Div. 1) (Codeforces 449D)

    思路:定义f(x)为 Ai & x==x  的个数,g(x)为x表示为二进制时1的个数,最后答案为    .为什么会等于这个呢:运用容斥的思想,如果 我们假设 ai&x==x 有f(x ...

  8. 主机无法访问虚拟机上的elasticsearch服务器

    问题: es在linux上搭建好,通过curl -XGET ip:port可以获得服务器信息展示,但是主机在浏览器上无法访问. 原因: 主机通过telnet访问linux的80端口,发现是不通的.可以 ...

  9. addChildViewController

    http://www.cnblogs.com/zengyou/p/3386605.html //在parent view controller 中添加 child view controller Fi ...

  10. 【个人使用.Net类库】(2)Log日志记录类

    开发接口程序时,要保证程序稳定运行就要时刻监控接口程序发送和接收的数据,这就需要一个日志记录的类将需要的信息记录在日志文件中,便于自己维护接口程序.(Web系统也是如此,只是对应的日志实现比这个要复杂 ...