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的编译环境搭建好 ...
随机推荐
- leetcode-25-exercise_string&array
14. Longest Common Prefix Write a function to find the longest common prefix string amongst an array ...
- poj 3187 三角数问题
题意:给你两个数,一个n表示这个三角有多少层,一个sum表示总和 思路: 类似杨辉三角 1 1 1 1 2 1 第n行的第k个数 为 n!/k!(n-k)! 暴力枚举,因 ...
- Linux下open函数、read函数、write函数记录
open() #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int open( cons ...
- try_except__异常处理
try...except.raise 一.try...except 有时候我们写程序的时候,会出现一些错误或异常,导致程序终止.例如,做除法时,除数为0,会引起一个ZeroDivisionError ...
- NetBeans无法使用编码GBK安全地打开该文件
今天用NetBeans打开包含路径里面的UTF-8编码的文件时,提示:NetBeans无法使用编码GBK安全地打开该文件. 后来在网上搜索找到了解决方案,原文地址:http://qdjinxin.it ...
- Python学习——第一天
https://www.runoob.com/python/python-chinese-encoding.html 第一个python程序 [root@mini1 ~]# vi python01.p ...
- 第1章jquery选择器
一.jquery等价于$ jquery选择器继承了css选择器的风格. $("#ID")代替了document.getElementById()函数,即通过id获取元素. $(&q ...
- lambda遍历的精简
本文转自 http://it.deepinmind.com/java%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/2014/03/15/Java%E5%8 ...
- kb-07-RMQ线段树--07(动态规划)
RMQ是一类解决区间最值查询的算法的通称:.一共有四类:在代码中有说明: 下面是ST算法,就是动态规划做法: 来看一下ST算法是怎么实现的(以最大值为例): 首先是预处理,用一个DP解决.设a是要求区 ...
- (C++一本通)最少转弯问题 (经典搜索)
题目描述 给出一张地图,这张地图被分为n×m(n,m<=100)个方块,任何一个方块不是平地就是高山.平地可以通过,高山则不能.现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯才能 ...