TF-IDF学习笔记
计算文本的权重向量,有个很有效的权重方案:TF-IDF权重策略。TF-IDF含义是词频逆文档频率,指的是,如果某个词或短语在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为此词或短语具有很好的分类区分能力,适合用来分类。简单的说,TF-IDF(词频-逆文档频率),它可以反映出语料库中某篇文档中某个词的重要性。目前所知应用是用来计算文档相似性(TF-IDF与余弦相似性的应用(二):找出相似文章)
TF-IDF权重公式参见这篇博文:TF-IDF与余弦相似性的应用(一):自动提取关键词。由于自己实现代码,在运算时效率很低,所以本文主要讲述sklearn里面的TF-IDF方法。里面主要用到了两个函数:CountVectorizer()和TfidfTransformer()。CountVectorizer是通过fit_transform函数将文本中的词语转换为词频矩阵,矩阵元素weight[i][j] 表示j词在第i个文本下的词频,即各个词语出现的次数;通过get_feature_names()可看到所有文本的关键字,通过toarray()可看到词频矩阵的结果。TfidfTransformer也有个fit_transform函数,它的作用是计算tf-idf值。这里附上一个我初学时用于理解的小例子(python2实现)。
# coding:utf-8
import jieba
import jieba.posseg as pseg
import os
import sys
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer if __name__ == "__main__":
corpus=["我 来到 北京 清华大学",#第一类文本切词后的结果,词之间以空格隔开
"他 来到 了 网易 杭研 大厦",#第二类文本的切词结果
"小明 硕士 毕业 与 中国 科学院",#第三类文本的切词结果
"我 爱 北京 天安门"]#第四类文本的切词结果
vectorizer=CountVectorizer()
#该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j],表示j词在i类文本下的词频
transformer=TfidfTransformer()
#该类会统计每个词语的tf-idf权值
tfidf=transformer.fit_transform(vectorizer.fit_transform(corpus))
#第一个fit_transform是计算tf-idf,第二个fit_transform是将文本转为词频矩阵
word=vectorizer.get_feature_names()
#获取词袋模型中的所有词语
weight=tfidf.toarray()
#将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重
for i in range(len(weight)):
#打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重
print u"-------这里输出第",i,u"类文本的词语tf-idf权重------"
for j in range(len(word)):
print word[j],weight[i][j]
若有多个文档统计TF-IDF权重时,则会出现一些计算结果不等值的问题。现取4个小样本txt数据做测试分析,每个txt中取单个句子,句子先做分词,再调用sklearn库做计算。测试案例代码实现如下图1,分词结果和计算结果展示如下图2:
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') def savefile(savepath, content):
fp = open(savepath, 'wb')
fp.write(content)
fp.close() def readfile(path):
fp = open(path, 'rb')
content = fp.read()
fp.close()
return content if __name__ == "__main__":
start_path = "segfile/"
end_path = "resultfile/"
corpus = []
tfidfdict = {}
for file_path in os.listdir(start_path):
fullname = start_path + file_path
content = readfile(fullname).strip()
#content = content.decode('gbk','ignore').encode('utf-8')
content = content.replace("\r\n", "")
content = content.decode('utf-8')
content_seg = jieba.cut(content.strip())
savefile(end_path + file_path, " ".join(content_seg))
for file_path in os.listdir(end_path):
fullname = end_path + file_path
content = readfile(fullname).strip()
content = content.decode('utf-8')
content = content.replace("\r\n", "").strip()
corpus.append(content)
#print corpus
for i in range(len(corpus)):
print str(corpus[i])
print "--------"
vectorizer = CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
word = vectorizer.get_feature_names()
weight = tfidf.toarray()
#print(weight)
for i in range(len(weight)):
print u"-------这里输出第", i, u"类文本的词语tf-idf权重------"
for j in range(len(word)):
print word[j], weight[i][j]
我 来到 北京 清华大学 。
他 来到 了 网易 杭研 大厦
小明 硕士 毕业 于 中国科学院
我 爱 北京 天安门
--------
-------这里输出第 0 类文本的词语tf-idf权重------
中国科学院 0.0
北京 0.52640543361
大厦 0.0
天安门 0.0
小明 0.0
来到 0.52640543361
杭研 0.0
毕业 0.0
清华大学 0.66767854461
硕士 0.0
网易 0.0
-------这里输出第 1 类文本的词语tf-idf权重------
中国科学院 0.0
北京 0.0
大厦 0.525472749264
天安门 0.0
小明 0.0
来到 0.414288751166
杭研 0.525472749264
毕业 0.0
清华大学 0.0
硕士 0.0
网易 0.525472749264
-------这里输出第 2 类文本的词语tf-idf权重------
中国科学院 0.5
北京 0.0
大厦 0.0
天安门 0.0
小明 0.5
来到 0.0
杭研 0.0
毕业 0.5
清华大学 0.0
硕士 0.5
网易 0.0
-------这里输出第 3 类文本的词语tf-idf权重------
中国科学院 0.0
北京 0.61913029649
大厦 0.0
天安门 0.78528827571
小明 0.0
来到 0.0
杭研 0.0
毕业 0.0
清华大学 0.0
硕士 0.0
网易 0.0
这时我们会发现问题,如果用传统的TF-IDF与余弦相似性的应用(一):自动提取关键词 中计算方法,笔算之后结果和程序结果完全不同,相差很大,在确定自己笔算无误后,debug调试研究计算的中间过程,我们发现计算过程中加入了tfidf平滑处理:
if self.use_idf:
n_samples, n_features = X.shape
df = _document_frequency(X) # perform idf smoothing if required 平滑处理
df += int(self.smooth_idf) #df+1 1处
n_samples += int(self.smooth_idf) #n_samples+1 2处
# log+1 instead of log makes sure terms with zero idf don't get
# suppressed entirely.
idf = np.log(float(n_samples) / df) + 1.0 #idf+1 3处
self._idf_diag = sp.spdiags(idf, diags=0, m=n_features,
n=n_features, format='csr')
假设t表示某个词,d表示一篇文档,则词频TF(t,d)是某个词t在文档d中出现的次数,而文档DF(t,D)是包含词t的文档数目,于是公式变成了这样:
IDF(t,D)=log(|D|+1)/(DF(t,D)+1) +1
这里|D|表示语料库的文档总数,为了不让分母为了0,在此进行了加1平滑操作。
TFIDF(t,d,D)=TF(t,d)*IDF(t,D)=TF(t,d)*(log(|D|+1)/(DF(t,D)+1) +1)
然后发现结果还是不对,除了做平滑处理以外,sklearn库还进行了归一化处理normalization,将值趋于0到1之间。什么是归一化,比如[1,2],归一化后成为[1/sqrt(5), 2/sqrt(5)]。(归一化问题未做研究,有时间再看看,跳过)
所以得出结论,调用sklearn库最后得出的TF-IDF结果是归一化后的idf值。不同的词在不同文档中有不同的idf,又有不同的tf词频,所以这个求得的值是在单篇文档中对于单个词做的分析,那么对于整个语料来说,如何利用求得的这个tf-idf值做热词分析呢?还是不知啊。
[ 0.52640543 0.52640543 0.66767854 0.41428875 0.52547275 0.52547275
0.52547275 0.5 0.5 0.5 0.5 0.6191303
0.78528828]
参考博文:用python开始机器学习(5:文本特征抽取与向量化)
TF-IDF学习笔记的更多相关文章
- 文本分类学习(三) 特征权重(TF/IDF)和特征提取
上一篇中,主要说的就是词袋模型.回顾一下,在进行文本分类之前,我们需要把待分类文本先用词袋模型进行文本表示.首先是将训练集中的所有单词经过去停用词之后组合成一个词袋,或者叫做字典,实际上一个维度很大的 ...
- Elasticsearch学习之相关度评分TF&IDF
relevance score算法,简单来说,就是计算出,一个索引中的文本,与搜索文本,他们之间的关联匹配程度 Elasticsearch使用的是 term frequency/inverse doc ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- Vue.js学习笔记(2)vue-router
vue中vue-router的使用:
- Tensorflow学习笔记2:About Session, Graph, Operation and Tensor
简介 上一篇笔记:Tensorflow学习笔记1:Get Started 我们谈到Tensorflow是基于图(Graph)的计算系统.而图的节点则是由操作(Operation)来构成的,而图的各个节 ...
- Android学习笔记(二)——探究一个活动
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 活动(Activity)是最容易吸引到用户的地方了,它是一种可以包含用户界面的组件,主要用于和用户进行交互.一 ...
- EasyARM i.mx28学习笔记——开箱试用总结
0 前言 本月初(2014年8月)购买了周立功的EasyARM开发板,主控为EasyARM i.mx287.出于下面几个理由购买了该开发板. [1]主要原因,有人约我一起学习一起使用该 ...
- CSS学习笔记——盒模型,块级元素和行内元素的区别和特性
今天本来打算根据自己的计划进行前端自动化的学习的,无奈早上接到一个任务需求需要新增一个页面.自从因为工作需要转前端之后,自己的主要注意力几 乎都放在JavaScript上面了,对CSS和HTML这方面 ...
- tf–idf算法解释及其python代码实现(下)
tf–idf算法python代码实现 这是我写的一个tf-idf的简单实现的代码,我们知道tfidf=tf*idf,所以可以分别计算tf和idf值在相乘,首先我们创建一个简单的语料库,作为例子,只有四 ...
- ESP32学习笔记(一) 环境搭建与下载
ESP32学习笔记(一) 环境搭建与下载 作者:Nevel 博客:nevel.cnblogs.com 转载请保留出处 前几天刚入手了ESP32模块,趁着放假有时间,我们先把ESP32的编译环境搭建好 ...
随机推荐
- 思维水题:UVa512-Spreadsheet Tracking
Spreadsheet Tracking Data in spreadsheets are stored in cells, which are organized in rows (r) and c ...
- Android Studio中不能显示svn的上传下载两个图标同时version control为灰,不可点击
最近在接触Android Studio,涉及到svn的配置,因为是先安装的svn,后安装的Android Studio,后边同事告诉我, Android Studio 的SVN安装与其他IDE有很大差 ...
- java模糊关键字查询
通过前台页面上传到后台的查询条件和关键字去数据库中进行查询,先在数据库中写好sql语句,数据库利用的是LIKE这个关键词进行查询的,然后就是dao层service层的调用,这条语句返回的是一个user ...
- BZOJ 4027: [HEOI2015]兔子与樱花
贪心 #include<cstdio> #include<algorithm> using namespace std; int cnt,n,m,F[2000005],c[20 ...
- TCP缓冲区大小及限制
这个问题在前面有的部分已经涉及,这里在重新总结下.主要参考UNIX网络编程. (1)数据报大小IPv4的数据报最大大小是65535字节,包括IPv4首部.因为首部中说明大小的字段为16位.IPv6的数 ...
- Django Form one
前戏: FromData:三种方式获取FromData 1. 创建一个FromData 的对象,然后再用append 的方法追个添加键值对 var formdata = new FormData(); ...
- UTV - URL Tag Validation
What`s UTV 1.URL Tag Validation 2.Special format of URL for preventing unauthorized usage and access ...
- ogre3d环境配置与简单程序示例
SDK安装以及编译 1.下载SDK,地址如下 http://www.ogre3d.org/download/sdk 2.安装SDK,直接解压到相应目录,如D:/ogreSDK 3.我用的是1.8版本, ...
- RF操作滚动条(竖拉)
方式一:window.scrollBy(0, document.body.scrollHeight) 方式二:window.scrollTo(0, document.body.scrollHeight ...
- day01_13.数组
数组基本语法 <?php $a = array(键1=>值1,键2=>值2); ?> <?php $arr = array(1=>'张三的裤子',2=>'李四 ...