热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

详解TFIDF

文章目录1. TF-IDF概念2. sklearn中的TF-IDF2.1 sklearn中TF-IDF的公式及计算过程2.2 使用LightGBM进行文本分类2.3 小结3. jieba使用tf-id

文章目录

  • 1. TF-IDF概念
  • 2. sklearn中的TF-IDF
    • 2.1 sklearn中TF-IDF的公式及计算过程
    • 2.2 使用LightGBM进行文本分类
    • 2.3 小结
  • 3. jieba使用tf-idf提取关键词
    • 3.1 一行代码提取关键词
    • 3.2 具体实现
    • 3.3 小结
  • 4 总结


1. TF-IDF概念

TF-IDF是NLP中常用的方法,也比较经典,基本思想是:如果一个词在文档中出现了很多次,但是这个词在其它文档中出现的次数很少,则这个词对这篇文档很重要。在一定程度上这个词可以表达这篇文档的关键信息,所以在网页搜索、关键词提取中常用到TF-IDF。

TF-IDF就是tf−idf(t,d)=tf(t,d)×idf(t)tf-idf(t,d)=tf(t,d) \times idf(t)tfidf(t,d)=tf(t,d)×idf(t),公式中t代表词term,d代表文档document。其实就是TF与IDF相乘。

TF是词频term frequency ,idf是逆文档频率inverse document-frequency。频率与频数不同,这里的词频是指词的频数,也就是一个词在文档中出现的个数,比如“的”在一个文档中出现了128次数,则tf(t,d)=128tf(t,d)=128tf(t,d)=128,这个比较好理解。

逆文档频率:为什么要有IDF呢?如果只用TF会有什么问题呢?比如“的”在一个文档中出现128次,是整个文档中出现次数最多的词。但是这个词并没有什么意义。所以要求有意义的词在这篇文档中出现的次数多,但是在其它的文档中出现的少。我们理解的频率的概念是频数除以总数。“逆”就是倒过来的意思,为了防止分母为0,在分母上了个1,再做log处理。所以:
idf(t)=logn1+df(t)idf(t)=log\frac{n}{1+df(t)}idf(t)=log1+df(t)n
公式中nnn代表文档的总数,df(t)df(t)df(t)代表包含单词t的文档的个数。对于这个公式sklearn做了优化。

2. sklearn中的TF-IDF

2.1 sklearn中TF-IDF的公式及计算过程

在sklearn中 TfidfTransformerTfidfVectorizer 设置参数 smooth_idf=False时,IDF的计算公式,如下:idf(t)=logndf(t)+1idf(t)=log\frac{n}{df(t)}+1idf(t)=logdf(t)n+1
把分子中的1拿到了外边。如果smooth_idf=True时分子和分母同时加了1,做平滑处理。如下:
idf(t)=log1+n1+df(t)+1idf(t) = log\frac{1+n}{1+df(t)}+1idf(t)=log1+df(t)1+n+1
然后再l2l_2l2正则化:
vnorm=vv12+v22+...+vn2v_{norm}=\frac{v}{\sqrt{v_1^2+v_2^2+...+v_n^2}}vnorm=v12+v22+...+vn2

v
这个向量其实是每个词的权重(weight),一开始是用于信息检索(information retrieval),后来发现这个词向量在文本分类与文本聚类中也很有效果。或许会问,为什么要做正则化?有没有发现正则化后,两个向量的点乘就是这两个向量的余弦相似度了。

举个例子:

>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> transformer = TfidfTransformer(smooth_idf=False)
>>> transformer
# 未做smooth处理
TfidfTransformer(smooth_idf=False)
# 有6个文档,每个文档有三个特征词,一行是一个文档。
>>> counts = [[3, 0, 1],
...[2, 0, 0],
...[3, 0, 0],
...[4, 0, 0],
...[3, 2, 0],
...[3, 0, 2]]
...
# 使用sklearn的
>>> tfidf = transformer.fit_transform(counts)
>>> tfidf
<6x3 sparse matrix of type &#39;<... &#39;numpy.float64&#39;>&#39;with 9 stored elements in Compressed Sparse ... format>>>> tfidf.toarray()
array([[0.81940995, 0. , 0.57320793],[1. , 0. , 0. ],[1. , 0. , 0. ],[1. , 0. , 0. ],[0.47330339, 0.88089948, 0. ],# 做smooth处理的
>>> transformer &#61; TfidfTransformer()
>>> transformer.fit_transform(counts).toarray()
array([[0.85151335, 0. , 0.52433293],[1. , 0. , 0. ],[1. , 0. , 0. ],[1. , 0. , 0. ],[0.55422893, 0.83236428, 0. ],[0.63035731, 0. , 0.77630514]])

TfidfVectorizer&#xff1a;

>>> from sklearn.feature_extraction.text import TfidfVectorizer
>>> vectorizer &#61; TfidfVectorizer()
# 直接把语料转换为if-idf的向量
>>> vectorizer.fit_transform(corpus)
<4x9 sparse matrix of type &#39;<... &#39;numpy.float64&#39;>&#39;with 19 stored elements in Compressed Sparse ... format>

这个例子中6篇文档3个特征的tf-idf的计算过程&#xff1a;

一共有6个文档&#xff0c;n&#61;6&#xff0c;特征词有三个&#xff0c;对于term1在所有的文档中都出现过&#xff0c;所以&#xff0c;df(t)term1&#61;6df(t)_{term1}&#61;6df(t)term1&#61;6&#xff0c;

对于doc1的第一个term的tf &#61; 3&#xff0c;所以tf−idfterm1&#61;tf∗idf(t)term1&#61;3×(log66&#43;1)&#61;3tf-idf_{term1}&#61; tf * idf(t)_{term1} &#61; 3 \times (log\frac{6}{6}&#43;1)&#61;3tfidfterm1&#61;tfidf(t)term1&#61;3×(log66&#43;1)&#61;3

对于doc2的第二个term的tf &#61; 0&#xff0c;所以tf−idfterm1&#61;tf∗idf(t)term1&#61;0×(log61&#43;1)&#61;0tf-idf_{term1}&#61; tf * idf(t)_{term1} &#61; 0 \times (log\frac{6}{1}&#43;1)&#61;0tfidfterm1&#61;tfidf(t)term1&#61;0×(log16&#43;1)&#61;0

对于doc1的第三个term的tf &#61; 1&#xff0c;所以tf−idfterm1&#61;tf∗idf(t)term1&#61;1×(log62&#43;1)&#61;2.0986tf-idf_{term1}&#61; tf * idf(t)_{term1} &#61; 1 \times (log\frac{6}{2}&#43;1)&#61;2.0986tfidfterm1&#61;tfidf(t)term1&#61;1×(log26&#43;1)&#61;2.0986

原始的tf-idf向量&#xff1a;[3, 0, 2.0986]
正则化&#xff1a;
[3,0,2.0986]32&#43;02&#43;2.09862&#61;[0.819,0,0.573]\frac{[3,0,2.0986]}{\sqrt{3^2&#43;0^2&#43;2.0986^2}}&#61;[0.819,0,0.573]32&#43;02&#43;2.09862

[3,0,2.0986]&#61;[0.819,0,0.573]
在sklearn中TfidfVecotrizerCountVectorizerTfidfTransformer的结合&#xff0c;可以直接把文本的语料转化为以词为特征的向量。其实这个向量就是一个文本转化为向量后的结果&#xff0c;如果不限定的话&#xff0c;是所有文本组成的词典的长度&#xff0c;但是可以根据max_dfmin_df来选择&#xff0c;超过max_df或低于min_df的词是不被选入词典的。max_df的默认值是1.0&#xff0c;也就是最高文档频率是没有限制的&#xff0c;min_df的默认值是1&#xff0c;也就是说单词要在所有的文档中有出现。特征是所有的转化为后向量可以用于文本分类或文本聚类。

2.2 使用LightGBM进行文本分类

使用的是sklearn中自带的文本样本20newsgroups数据集&#xff0c;一共有11314篇文档&#xff0c;20个类别。对样本向量化&#xff0c;再使用LightGBM对样本进行分类。对比了sklearn中两种tf-idf向量化的方式&#xff0c;向量化的结果是一样的。但是向量化后&#xff0c;数据比较稀疏&#xff0c;训练有点慢。不过仅仅使用这么稀疏的数据&#xff0c;而且使用的lgb的baseline模型&#xff0c;效果还是不错的了&#xff0c;最好的类别f1 score能到94%。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.3 小结


  • 文本需要切词&#xff0c;构建所有文本的词典&#xff1b;
  • 把词典的词作为样本的特征&#xff0c;特征值是每个词在文档中出现的次数&#xff1b;
  • 根据次数及tf-idf公式计算每个词的tf-idf值&#xff0c;然后l2正则化&#xff1b;经过tf-idf处理后的向量也可以作为文本的向量&#xff1b;
  • 样本的tf-id向量中权重比较大的词就可以作为样本的关键词&#xff1b;
  • 可以通过限制max_dfmin_df来限制样本的tf-idf向量的维度&#xff1b;
  • 所有样本的tf-idf matrix是一个稀疏矩阵&#xff0c;对于传统的机器学习算法不友好&#xff0c;训练时间比较长&#xff1b;所以后来word embedding就是把稀疏矩阵降维的&#xff1b;
  • 这种文本向量化的模型其实基于词袋模型(Bag of Word model)的。

3. jieba使用tf-idf提取关键词

3.1 一行代码提取关键词

from jieba import analyse
sentence &#61; "人工智能&#xff08;Artificial Intelligence&#xff09;&#xff0c;英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是计算机科学的一个分支&#xff0c;它企图了解智能的实质&#xff0c;并生产出一种新的能以人类智能相似的方式做出反应的智能机器&#xff0c;该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来&#xff0c;理论和技术日益成熟&#xff0c;应用领域也不断扩大&#xff0c;可以设想&#xff0c;未来人工智能带来的科技产品&#xff0c;将会是人类智慧的“容器”。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能&#xff0c;但能像人那样思考、也可能超过人的智能。人工智能是一门极富挑战性的科学&#xff0c;从事这项工作的人必须懂得计算机知识&#xff0c;心理学和哲学。人工智能是包括十分广泛的科学&#xff0c;它由不同的领域组成&#xff0c;如机器学习&#xff0c;计算机视觉等等&#xff0c;总的说来&#xff0c;人工智能研究的一个主要目标是使机器能够胜任一些通常需要人类智能才能完成的复杂工作。但不同的时代、不同的人对这种“复杂工作”的理解是不同的。2017年12月&#xff0c;人工智能入选“2017年度中国媒体十大流行语“。"
keywords &#61; analyse.extract_tags(sentence, topK&#61;10, withWeight&#61;False, allowPOS&#61;(), withFlag&#61;False)
print(keywords)
# [&#39;人工智能&#39;, &#39;智能&#39;, &#39;2017&#39;, &#39;机器&#39;, &#39;不同&#39;, &#39;人类&#39;, &#39;科学&#39;, &#39;模拟&#39;, &#39;一门&#39;, &#39;技术&#39;]

输入是一段字符串&#xff0c;输出关键词的list。
其中的参数&#xff1a;

  • sentence&#xff1a;需要提取关键词的字符串
  • topK&#xff1a;返回权重前top K个单词
  • withWeight&#xff1a;返回结果是否需要带tf-idf值
  • allowPOS&#xff1a;关键词的词性
  • withFlag&#xff1a;返回结果是否要带词性

使用起来确实简单&#xff0c;直接输入一段话就可以提取其中的关键词了。但是有一个问题是&#xff0c;idf的计算是需要看出现这个词的文档的个数&#xff0c;及总的文档数量的&#xff0c;jieba难道不需要么&#xff1f;

3.2 具体实现

jieba中有一个自带的idf.txt&#xff0c;第一列单词&#xff0c;第二列是idf。这个idf是通过离线训练好的。
在这里插入图片描述
jieba的tf-idf计算比较简单&#xff0c;源码如下&#xff1a;
在这里插入图片描述
有三步&#xff1a;

  • 第一步&#xff1a;对sentence分词&#xff0c;分词使用的HMM算法&#xff0c;当然&#xff0c;也是内置的转移矩阵、发射矩阵及初始概率。分词这个有时间可以写一下。
  • 第二步&#xff1a;统计sentence中每个单词的个数。具体实现是用一个dict放的&#xff0c;当然也根据参数allowPOS、stop_words&#xff0c;单词的长度(大于2)进行了过滤。
  • 第三步&#xff1a;计算tf-idf。idf是通过内置的idf.txt得到的&#xff0c;类初始化的时候会加载idf.txt文件为一个diict&#xff0c;即self.idf_freq。如果单词不在self.freq中时&#xff0c;返回的是平均的idf值self.median_idf。然后用第二步的tf值与得到idf相乘。至于为什么要除以一个total&#xff0c;我觉得是为了把tf-idf值变的小一些&#xff0c;比较容易比较大小&#xff0c;毕竟所有的tf-idf都除以一个正数对大小的比较没有影响。

3.3 小结


  • jieba的tf-idf值的计算&#xff0c;不需要输入多篇文档&#xff0c;只需要输入需要提取关键词的文档即可
  • 关键词可以有词性的限制
  • jieba是通过内置的idf来计算单词的tf-idf值的
  • 缺点&#xff1a;对于专业性比较强的文档&#xff0c;可能会有问题。毕竟jieba使用的训练样本是不清楚的。

4 总结
  • tf-idf的计算公式及优化
  • tf-idf的一个应用是基于词袋模型为文本提取特征向量&#xff0c;然后用于文本分类或聚类。优点是比较好理解 &#xff0c;缺点是matrix太稀疏&#xff0c;向量与向量之间的相似性不太靠谱。试想一下两个文档&#xff0c;里面所用的词不同&#xff0c;但是意思差不多&#xff0c;直观上两个向量应该是相似的。但是其实两个向量相乘的结果为零向量。词不相同&#xff0c;向量正交。
  • tf-idf的另一个应用是提取关键词&#xff0c;jieba的实现中是利用已经训练好的idf来作的&#xff0c;对于比较专业的领域可能会有偏差。如果有小伙伴儿知道jieba是用什么语料训练的&#xff0c;欢迎留言。

参考&#xff1a;

  • https://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction
  • https://lightgbm.readthedocs.io/en/latest/index.html
  • https://github.com/fxsjy/jieba

声明&#xff1a;原创文章&#xff0c;转载请注明出处。


推荐阅读
  • Python 工具推荐 | PyHubWeekly 第二十一期:提升命令行体验的五大工具
    本期 PyHubWeekly 为大家精选了 GitHub 上五个优秀的 Python 工具,涵盖金融数据可视化、终端美化、国际化支持、图像增强和远程 Shell 环境配置。欢迎关注并参与项目。 ... [详细]
  • 探讨ChatGPT在法律和版权方面的潜在风险及影响,分析其作为内容创造工具的合法性和合规性。 ... [详细]
  • 本文旨在探讨如何利用决策树算法实现对男女性别的分类。通过引入信息熵和信息增益的概念,结合具体的数据集,详细介绍了决策树的构建过程,并展示了其在实际应用中的效果。 ... [详细]
  • 2017年人工智能领域的十大里程碑事件回顾
    随着2018年的临近,我们一同回顾过去一年中人工智能领域的重要进展。这一年,无论是政策层面的支持,还是技术上的突破,都显示了人工智能发展的迅猛势头。以下是精选的2017年人工智能领域最具影响力的事件。 ... [详细]
  • 智慧城市建设现状及未来趋势
    随着新基建政策的推进及‘十四五’规划的实施,我国正步入以5G、人工智能等先进技术引领的智慧经济新时代。规划强调加速数字化转型,促进数字政府建设,新基建政策亦倡导城市基础设施的全面数字化。本文探讨了智慧城市的发展背景、全球及国内进展、市场规模、架构设计,以及百度、阿里、腾讯、华为等领军企业在该领域的布局策略。 ... [详细]
  • 本文介绍如何使用MFC和ADO技术调用SQL Server中的存储过程,以查询指定小区在特定时间段内的通话统计数据。通过用户界面选择小区ID、开始时间和结束时间,系统将计算并展示小时级的通话量、拥塞率及半速率通话比例。 ... [详细]
  • 本文探讨了如何在 F# Interactive (FSI) 中通过 AddPrinter 和 AddPrintTransformer 方法自定义类型(尤其是集合类型)的输出格式,提供了详细的指南和示例代码。 ... [详细]
  • 本文将探讨2015年RCTF竞赛中的一道PWN题目——shaxian,重点分析其利用Fastbin和堆溢出的技巧。通过详细解析代码流程和漏洞利用过程,帮助读者理解此类题目的破解方法。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 一个登陆界面
    预览截图html部分123456789101112用户登入1314邮箱名称邮箱为空15密码密码为空16登 ... [详细]
  • java文本编辑器,java文本编辑器设计思路
    java文本编辑器,java文本编辑器设计思路 ... [详细]
  • Logback使用小结
    1一定要使用slf4j的jar包,不要使用apachecommons的jar。否则滚动生成文件不生效,不滚动的时候却生效~~importorg.slf ... [详细]
  • iOS绘制就是采集点,贝塞尔曲线得到形状,绘图上下文去渲染出来AsanaDrawsana图形库,设计的挺好他可以画多种图形, ... [详细]
  • 开发笔记:精通 CSS 第 10 章 变换过渡与动画 学习笔记
    开发笔记:精通 CSS 第 10 章 变换过渡与动画 学习笔记 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
author-avatar
手机用户2602922857
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有