自然语言处理:词频-逆文档频率
介绍
大家好,博主又来给大家分享知识了。本来博主计划完成稠密向量表示的内容分享后,就开启自然语言处理中文本表示的讲解。可在整理分享资料的时候,博主发现还有个知识点,必须得单独拎出来好好说道说道。
这就是TF-IDF,也就是词频-逆文档频率。它在自然语言处理里堪称“幕后功臣”,在文本表示、文本分类、信息检索等诸多关键任务中,发挥着超乎想象的作用。那么,我们直接进入正题。
TF-IDF
在自然语言处理(NLP)领域,理解文本数据的含义并从中提取有价值的信息是核心任务。TF-IDF(Term Frequency-Inverse Document Frequency)作为一种重要的统计方法,在文本表示、文本分类、信息检索、关键词提取等众多任务中发挥着关键作用。
基础概念
词频
Term Frequency, TF。词频衡量的是一个词在一篇文档中出现的频率。直观地说,一个词在文档中出现的次数越多,它对该文档的重要性可能越高。例如,在文档“我喜欢苹果,苹果很美味”中,“苹果”这个词出现了两次,相对其他词出现的频率较高,可能在该文档中具有一定重要性。
其计算公式为:
其中,表示词
在文档
中的词频,
是词
在文档
中出现的次数,
是文档
中所有词的出现次数总和。
逆文档频率
Inverse Document Frequency, IDF。逆文档频率反映了一个词在整个文档集合中的普遍重要性。如果一个词在大量文档中都出现,那么它对于区分不同文档的作用就较小。相反,一个只在少数文档中出现的词,对于识别这些特定文档更为关键。
例如,“的”,“是”等常用词在几乎所有文档中都会频繁出现,它们的区分能力较弱。而专业术语如“量子纠缠”,只在特定领域的文档中出现,其区分能力较强。
其计算公式为:
其中,表示词
的逆文档频率,
是文档集合中的文档总数,
是包含词
的文档数量。
TF-IDF加权
TF-IDF加权综合了词频和逆文档频率,通过将两者相乘得到每个词在文档中的TF-IDF值。
公式为:
TF-IDF值越高,说明该词对当前文档越重要,同时在整个文档集中相对不常见,具有较强的区分性。
代码实现
计算词频(TF)
完整代码
# 从collections模块导入Counter类,用于统计元素出现的次数
from collections import Counter# 定义一个名为NLPTextRepresentation的类,用于处理文本表示相关任务
class NLPTextRepresentation:# 类的初始化方法,此处不做任何初始化操作def __init__(self):# pass 语句占位,不进行实际操作pass# 定义一个方法,用于计算文档中每个单词的词频(TF)def compute_tf(self, document):# 将输入的文档按空格分割成单词列表words = document.split()# 使用Counter统计每个单词在文档中出现的次数word_count = Counter(words)# 计算文档中单词的总数total_words = len(words)# 初始化一个空字典,用于存储每个单词的词频tf_dict = {}# 遍历统计结果中的每个单词及其出现次数for word, count in word_count.items():# 计算该单词的词频并存储到字典中tf_dict[word] = count / total_words# 返回存储词频的字典return tf_dict# 当脚本作为主程序运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextRepresentation类的一个实例nlp_text_representation = NLPTextRepresentation()# 定义一个示例文档document = "我喜欢苹果 苹果很美味"# 调用compute_tf方法计算文档中单词的词频tf_result = nlp_text_representation.compute_tf(document)# 打印计算得到的词频结果print(tf_result)
运行结果
{'我喜欢苹果': 0.5, '苹果很美味': 0.5}进程已结束,退出代码为 0
在这段代码中,首先使用split()方法将输入的文档字符串分割成单词列表。然后,利用Counter类统计每个单词在文档中出现的次数。
接着,计算文档的总词数,通过遍历每个单词及其出现次数,将每个单词的出现次数除以总词数,得到该单词在文档中的词频,并存储在字典tf_dict中。
最后返回这个字典,其中键为单词,值为对应的词频。
计算逆文档频率(IDF)
完整代码
# 导入math模块,用于使用数学函数,这里主要是为了计算对数
import math# 定义一个名为NLPTextRepresentation的类,用于处理自然语言处理中的文本表示相关任务
class NLPTextRepresentation:# 类的初始化方法,目前不做任何初始化操作def __init__(self):# 占位语句,不执行任何实际逻辑pass# 定义一个方法,用于计算语料库中每个单词的逆文档频率(IDF)def compute_idf(self, corpus):# 计算语料库中文档的总数total_docs = len(corpus)# 初始化一个空字典,用于存储每个单词在多少个文档中出现过word_in_doc_count = {}# 遍历语料库中的每一个文档for doc in corpus:# 将当前文档按空格分割成单词,并使用 set 去重words = set(doc.split())# 遍历当前文档中出现的每个唯一单词for word in words:# 如果该单词还未在word_in_doc_count字典中if word not in word_in_doc_count:# 则将该单词添加到字典中,并将其出现文档数初始化为 1word_in_doc_count[word] = 1else:# 否则,将该单词出现的文档数加 1word_in_doc_count[word] += 1# 初始化一个空字典,用于存储每个单词的逆文档频率idf_dict = {}# 遍历word_in_doc_count字典中的每个单词及其出现文档数for word, count in word_in_doc_count.items():# 计算该单词的逆文档频率(使用自然对数),并存储到idf_dict中idf_dict[word] = math.log(total_docs / count)# 返回存储逆文档频率的字典return idf_dict# 当脚本作为主程序运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextRepresentation类的一个实例nlp_text_representation = NLPTextRepresentation()# 定义一个语料库,包含多个文档corpus = ["我喜欢苹果 苹果很美味", "我喜欢香蕉 香蕉很甜", "苹果和香蕉都是水果"]# 调用compute_idf方法计算语料库中每个单词的逆文档频率idf_result = nlp_text_representation.compute_idf(corpus)# 打印计算得到的逆文档频率结果print(idf_result)
运行结果
{'我喜欢苹果': 1.0986122886681098, '苹果很美味': 1.0986122886681098, '我喜欢香蕉': 1.0986122886681098, '香蕉很甜': 1.0986122886681098, '苹果和香蕉都是水果': 1.0986122886681098}进程已结束,退出代码为 0
在这段代码中,首先计算语料库中总的文档数量。然后,遍历语料库中的每一篇文档,将文档中的单词通过set()方法去重,以确保每个单词只被统计一次。
对于每个单词,如果它不在word_in_doc_count字典中,则将其初始值设为 1;如果已经存在,则将其对应的值加 1,这样word_in_doc_count字典记录了每个单词在多少篇文档中出现过。
接下来,通过遍历word_in_doc_count字典,根据逆文档频率的计算公式,计算每个单词的逆文档频率,并存储在idf_dict字典中返回。
计算词频-逆文档频率(TF-IDF)
完整代码
# 从collections模块导入Counter类,用于统计元素出现的次数
from collections import Counter
# 导入math模块,用于使用数学函数,这里主要是为了计算对数
import math# 定义一个名为NLPTextRepresentation的类,用于处理自然语言处理中的文本表示相关任务
class NLPTextRepresentation:# 类的初始化方法,目前不做任何初始化操作def __init__(self):# 占位语句,不执行任何实际逻辑pass# 定义一个方法,用于计算文档中每个单词的词频(TF)def compute_tf(self, document):# 将输入的文档按空格分割成单词列表words = document.split()# 使用Counter统计每个单词在文档中出现的次数word_count = Counter(words)# 计算文档中单词的总数total_words = len(words)# 初始化一个空字典,用于存储每个单词的词频tf_dict = {}# 遍历统计结果中的每个单词及其出现次数for word, count in word_count.items():# 计算该单词的词频并存储到字典中tf_dict[word] = count / total_words# 返回存储词频的字典return tf_dict# 定义一个方法,用于计算语料库中每个单词的逆文档频率(IDF)def compute_idf(self, corpus):# 计算语料库中文档的总数total_docs = len(corpus)# 初始化一个空字典,用于存储每个单词在多少个文档中出现过word_in_doc_count = {}# 遍历语料库中的每一个文档for doc in corpus:# 将当前文档按空格分割成单词,并使用set去重words = set(doc.split())# 遍历当前文档中出现的每个唯一单词for word in words:# 如果该单词还未在word_in_doc_count字典中if word not in word_in_doc_count:# 则将该单词添加到字典中,并将其出现文档数初始化为1word_in_doc_count[word] = 1else:# 否则,将该单词出现的文档数加1word_in_doc_count[word] += 1# 初始化一个空字典,用于存储每个单词的逆文档频率idf_dict = {}# 遍历word_in_doc_count字典中的每个单词及其出现文档数for word, count in word_in_doc_count.items():# 计算该单词的逆文档频率(使用自然对数),并存储到idf_dict中idf_dict[word] = math.log(total_docs / count)# 返回存储逆文档频率的字典return idf_dict# 定义一个方法,用于计算语料库中每个文档里单词的TF-IDF值def compute_tfidf(self, corpus):# 初始化一个空列表,用于存储每个文档的TF-IDF结果tfidf_corpus = []# 调用compute_idf方法计算语料库中所有单词的逆文档频率idf = self.compute_idf(corpus)# 遍历语料库中的每一个文档for doc in corpus:# 调用compute_tf方法计算当前文档中每个单词的词频tf = self.compute_tf(doc)# 初始化一个空字典,用于存储当前文档中每个单词的TF-IDF值tfidf_doc = {}# 遍历当前文档词频字典中的每个单词for word in tf:# 计算该单词的TF-IDF值并存储到字典中tfidf_doc[word] = tf[word] * idf[word]# 将当前文档的TF-IDF结果添加到tfidf_corpus列表中tfidf_corpus.append(tfidf_doc)# 返回存储所有文档TF-IDF结果的列表return tfidf_corpus# 当脚本作为主程序运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextRepresentation类的一个实例nlp_text_representation = NLPTextRepresentation()# 定义一个包含多个文档的语料库corpus = ["我喜欢苹果 苹果很美味", "我喜欢香蕉 香蕉很甜", "苹果和香蕉都是水果"]# 调用compute_tfidf方法计算语料库中每个文档里单词的TF-IDF值tfidf_result = nlp_text_representation.compute_tfidf(corpus)# 遍历计算得到的TF-IDF结果列表for i, doc in enumerate(tfidf_result):# 打印每个文档的TF-IDF计算结果print(f"文档{i + 1}的TF-IDF结果: {doc}")
运行结果
文档1的TF-IDF结果: {'我喜欢苹果': 0.5493061443340549, '苹果很美味': 0.5493061443340549}
文档2的TF-IDF结果: {'我喜欢香蕉': 0.5493061443340549, '香蕉很甜': 0.5493061443340549}
文档3的TF-IDF结果: {'苹果和香蕉都是水果': 1.0986122886681098}进程已结束,退出代码为 0
这段代码首先调用前面定义的compute_idf函数计算整个语料库的逆文档频率。然后,遍历语料库中的每一篇文档,对每篇文档调用compute_tf函数计算词频。
接着,对于每个词,将其在当前文档中的词频乘以其在整个语料库中的逆文档频率,得到该词在当前文档中的TF-IDF值,并存储在tfidf_doc字典中。
最后,将每篇文档的TF-IDF字典结果添加到tfidf_corpus列表中并返回。这段代码的目的是将前面计算得到的词频和逆文档频率进行综合计算,得到每篇文档中每个词的TF-IDF值,从而完成TF-IDF加权的计算过程。
TF-IDF的优点
- 简单有效:TF-IDF的计算原理直观易懂,实现相对简单,不需要复杂的模型训练过程,却能在很多实际应用中取得较好的效果,如文本分类、信息检索等。
- 突出关键信息:通过加权计算,能够突出那些在特定文档中频繁出现且在整个文档集中相对不常见的词,这些词往往与文档的主题紧密相关,有助于快速定位文档的核心内容。
- 可扩展性好:无论是小规模还是大规模的文档集合,TF-IDF都能适用,并且计算资源消耗相对可控。在处理大规模文本数据时,可以通过分布式计算等方式进一步优化计算效率。
TF-IDF的缺点
- 忽略语义信息:TF-IDF只考虑了词的出现频率和文档分布,完全没有涉及词与词之间的语义关系。例如,“汽车”和“轿车”在语义上相近,但TF-IDF无法体现这种关系,可能会导致在一些需要语义理解的任务中效果不佳。
- 依赖文档集合:逆文档频率的计算依赖于整个文档集合,当文档集合发生变化时,需要重新计算IDF值,这在实时性要求较高的应用场景中可能会带来不便。
- 无法处理多义词:对于具有多种含义的词,TF-IDF不能区分其在不同上下文中的语义差异,会将其视为同一个词进行计算,可能影响对文本的准确理解。
结论赋能
TF-IDF作为自然语言处理中的经典方法,在文本分析的众多领域有着广泛应用。通过对词频和逆文档频率的巧妙结合,能够有效地提取文本中的关键信息,为后续的文本处理任务提供有力支持。
然而,其固有的局限性也为研究人员提供了改进和创新的方向。在实际应用中,需要根据具体任务的需求和数据特点,合理选择是否使用TF-IDF,并结合其他技术(如词向量模型等)来弥补其不足,以更好地实现自然语言处理的目标。
结束
好了,以上就是本次分享的全部内容了。不知道大家是否对TF-IDF有了更深入的理解,以及对其在实际应用中的潜力有了新的认识呢?希望本次分享能为大家在自然语言处理的学习和实践中带来启发和帮助。
随着自然语言处理技术的不断发展,我们期待看到更多能够克服TF-IDF局限性的创新方法涌现。无论是在文本分类、信息检索,还是在文本摘要等领域,TF-IDF都已经奠定了坚实的基础,激励着研究者们不断探索更高效、更精准的文本处理策略。
那么本次分享就到这里了。最后,博主还是那句话:请大家多去大胆的尝试和使用,成功总是在不断的失败中试验出来的,敢于尝试就已经成功了一半。如果大家对博主分享的内容感兴趣或有帮助,请点赞和关注。大家的点赞和关注是博主持续分享的动力🤭,博主也希望让更多的人学习到新的知识。
相关文章:
自然语言处理:词频-逆文档频率
介绍 大家好,博主又来给大家分享知识了。本来博主计划完成稠密向量表示的内容分享后,就开启自然语言处理中文本表示的讲解。可在整理分享资料的时候,博主发现还有个知识点,必须得单独拎出来好好说道说道。 这就是TF-IDF…...

【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享
更多银河麒麟操作系统产品及技术讨论,欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer…...

基于大数据的民宿旅馆消费数据分析系统
【大数据】基于大数据的民宿旅馆消费数据分析系统(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统可以揭示民宿市场的消费模式和价格分布情况,帮助理解消费者偏好、价格走势及…...
Spring-AI搭建企业专属知识库 一
环境介绍:Spring3.3.2 JDK 21 POM文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&…...

极简本地体验deepseek大模型教程
一 题外随感:时代之问 就像狄更斯在双城记中所述,“这是最好的时代,这是最坏的时代”。每一代人都有其所处的时代,每一个时代都有其所谓好的一面和不那么好的一面。很多时候随口的一句大环境不好,就似乎给了自己一个最…...
RabbitMQ系列(五)基本概念之Queue
在 RabbitMQ 中,Queue(队列) 是存储消息的容器,也是消息传递的核心载体。以下是其核心特性与作用的全方位解析: 一、Queue 的定义与核心作用 消息存储容器 Queue 是 RabbitMQ 中实际存储消息的实体,生产者…...
【记录】成为创作者的第 730 天(两年)
收获 还是总在感叹走到今天收获的一切,都是自己曾经不敢想的。 无论是靠自己努力拿到的 Offer,还是在 CSDN 网站上结交的网友和前辈们,都是我莫大的荣幸和财富,感恩一切、感恩自己。 过去一年的收获真的数不胜数,抛…...

深度剖析数据分析职业成长阶梯
一、数据分析岗位剖析 目前,数据分析领域主要有以下几类岗位:业务数据分析师、商业数据分析师、数据运营、数据产品经理、数据工程师、数据科学家等,按照工作侧重点不同,本文将上述岗位分为偏业务和偏技术两大类,并对…...

【XSS】DVWA靶场XSS攻击
一、XSS攻击 1.1. XSS 攻击简介 XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的Web安全漏洞,它允许攻击者在受害者的浏览器中执行恶意脚本。攻击者通常通过在Web应用程序中注入恶意脚本代码(如JavaScript&…...

Fiddler在Windows下抓包Https
文章目录 1.Fiddler Classic 配置2.配置浏览器代理自动代理手动配置浏览器代理 3.抓取移动端 HTTPS 流量(可选)解决抓取 HTTPS 失败问题1.Fiddler证书过期了 默认情况下,Fiddler 无法直接解密 HTTPS 流量。需要开启 HTTPS 解密: 1…...
04 路由表的IP分组传输过程
目录 1、路由表的核心结构 2、IP分组传输过程和数据包转发过程 2.1、IP分组传输过程 2.2、数据包转发过程 2.3、IP分组传输过程和数据包转发的区别 3、数据包的变化 3.1、拓扑结构 3.2、传输过程详解(主机A → 主机B) 3.2.1、主机A发送数据 3.2…...
AI Agent 定义与核心要素详解
AI Agent(人工智能代理)是一种能够感知环境、自主决策并执行任务以达成目标的软件实体。它结合了感知、推理、学习和行动能力,能够在复杂环境中独立或协作工作。以下是其核心要素: 1. 感知 AI Agent 通过传感器或数据输入感知环…...

记忆化搜索与动态规划:原理、实现与比较
记忆化搜索和动态规划是解决优化问题的两种重要方法,尤其在处理具有重叠子问题和最优子结构性质的问题时非常有效。 目录 1. 记忆化搜索(Memoization) 定义: 实现步骤: 示例代码(斐波那契数列࿰…...

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南
随着人工智能技术的飞速发展,本地部署大型语言模型(LLM)已成为许多技术爱好者的热门选择。本地部署不仅能够保护隐私,还能提供更灵活的使用体验。本文将详细介绍如何在 Mac mini M2(24GB 内存)上部署 DeepS…...
计算机网络基础简答题资料(对口高考)
1、什么是计算机网络?计算机网络的功能有哪些? 答案:计算机网络,是指将分布在不同地理位置、具有独立功能的多台计算机及其外围设备,通过通信设备和通信线路连接起来,在网络操作系统、网络管理软件及网络通…...

mysql内置工具导入csv包,简单便捷高效
先创建一个你想要的数据库 create database uba; 分析导入文件的格式内容 提前在数据库里创建你需要的表格 不然就会收到”mysqlimport: Error: 1146“大礼包 (你的csv文件名和表格名字一摸一样,大小写也是) use uba; create table userBehavior (us…...
【汽车ECU电控数据管理篇】HEX文件格式解析篇章
一、HEX格式文件是啥 HEX 文件是 Intel 公司提出的一种按地址排列的数据信息格式,通常用于存储嵌入式系统的二进制代码。它以 ASCII 码的形式记录数据,每一行以冒号开头,包含数据长度、地址、记录类型、数据和校验码等信息。HEX 文件常用于程…...

SOLID Principle基础入门
(Robert C. Martin (Uncle Bob)) 什么是SOLID原则? SOLID原则是面向对象编程(OOP)中编写高质量代码的指导方针。实际上,即使不使用SOLID原则,仅通过类、继承、封装和多态性,也可以让程序正常运行。那么为…...

keil主题(vscode风格)
#修改global.prop文件,重新打开keil即可 # Keil uVision Global Properties File # This file is used to customize the appearance of the editor# Editor Font editor.font.nameConsolas editor.font.size10 editor.font.style0# Editor Colors editor.backgro…...
微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
一、微信小程序读取NFC文本(yyy优译小程序实现),网上有很多通过wx.getNFCAdapter方法来监听读取NFC卡信息,但怎么处理读取的message文本比较难找,现用下面方法来实现,同时还解决几个问题,1、在回调方法中this.setData不更新信息,因为this的指向问题,2、在退出页面时,…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...