自然语言处理:词频-逆文档频率

news2025/3/3 8:19:28

介绍

大家好,博主又来给大家分享知识了。本来博主计划完成稠密向量表示的内容分享后,就开启自然语言处理中文本表示的讲解。可在整理分享资料的时候,博主发现还有个知识点,必须得单独拎出来好好说道说道。

这就是TF-IDF,也就是词频-逆文档频率。它在自然语言处理里堪称“幕后功臣”,在文本表示、文本分类、信息检索等诸多关键任务中,发挥着超乎想象的作用。那么,我们直接进入正题。

TF-IDF

自然语言处理(NLP)领域,理解文本数据的含义并从中提取有价值的信息是核心任务。TF-IDF(Term Frequency-Inverse Document Frequency)作为一种重要的统计方法,在文本表示、文本分类、信息检索、关键词提取等众多任务中发挥着关键作用。

基础概念

词频

Term Frequency, TF。词频衡量的是一个词在一篇文档中出现的频率。直观地说,一个词在文档中出现的次数越多,它对该文档的重要性可能越高。例如,在文档“我喜欢苹果,苹果很美味”中,“苹果”这个词出现了两次,相对其他词出现的频率较高,可能在该文档中具有一定重要性。

其计算公式为:TF_{t,d} = \frac{n_{t,d}}{\sum_{k} n_{k,d}}

其中,TF_{t,d}表示词t在文档d中的词频,n_{t,d}是词t在文档d中出现的次数,\sum_{k} n_{k,d}是文档d中所有词的出现次数总和。

逆文档频率

Inverse Document Frequency, IDF。逆文档频率反映了一个词在整个文档集合中的普遍重要性。如果一个词在大量文档中都出现,那么它对于区分不同文档的作用就较小。相反,一个只在少数文档中出现的词,对于识别这些特定文档更为关键。

例如,“的”,“是”等常用词在几乎所有文档中都会频繁出现,它们的区分能力较弱。而专业术语如“量子纠缠”,只在特定领域的文档中出现,其区分能力较强。

其计算公式为:IDF_{t} = \log \frac{N}{n_{t}}

其中,IDF_{t}表示词t的逆文档频率,N是文档集合中的文档总数,n_{t}是包含词t的文档数量。

TF-IDF加权

TF-IDF加权综合了词频和逆文档频率,通过将两者相乘得到每个词在文档中的TF-IDF值。

公式为:TF-IDF_{t,d} = TF_{t,d} \times IDF_{t}

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:
                    # 则将该单词添加到字典中,并将其出现文档数初始化为 1
                    word_in_doc_count[word] = 1
                else:
                    # 否则,将该单词出现的文档数加 1
                    word_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:
                    # 则将该单词添加到字典中,并将其出现文档数初始化为1
                    word_in_doc_count[word] = 1
                else:
                    # 否则,将该单词出现的文档数加1
                    word_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都已经奠定了坚实的基础,激励着研究者们不断探索更高效、更精准的文本处理策略。

那么本次分享就到这里了。最后,博主还是那句话:请大家多去大胆的尝试和使用,成功总是在不断的失败中试验出来的,敢于尝试就已经成功了一半。如果大家对博主分享的内容感兴趣或有帮助,请点赞和关注。大家的点赞和关注是博主持续分享的动力🤭,博主也希望让更多的人学习到新的知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2308850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速在本地运行SpringBoot项目的流程介绍

目录 前言 一、环境配置 1.1Java环境 1.2Maven环境 1.3IntelliJ IDEA安装 1.4MySql安装 二、项目导入与启动的过程 2.1Maven镜像和本地仓库 2.1.2镜像配置 2.1.3配置本地仓库 2.2导入项目与启动 2.2.1加载Maven设置 2.2.2配置jdk与java版本 2.2.3创建数据库 2.2…

SpringBoot 端口配置

在Spring Boot中,配置应用程序的监听端口有多种方式。以下是常见的几种方法: 1. 通过 application.properties 或 application.yml 文件配置 application.properties server.port8081application.yml server:port: 8081如果没有显式配置 server.port…

Python 数据结构 4.单向链表

惟愿春日不迟,相逢终有时 —— 25.3.2 一、单向链表的基本概念 1.单向链表的概念 对于顺序存储的结构,最大的缺点就是:插入 和 删除 的时候需要移动大量的元素,所以基于前人的智慧,他们发明了链表。 链表是由一个个结…

LeeCode题库第四十题

40.组合总和II 项目场景: 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 示…

玩转大模型——deepseek本地部署与ollama 非C盘安装之ChatBox配置

文章目录 ollama安装ollama是什么DeepSeek是什么下载地址非C盘安装配置大模型目录大模型下载安装deepseek-r1:1.5b安装deepseek-r1:7b ChatBox安装参考资料 ollama安装 ollama是什么 Ollama 是一个专注于本地运行大型语言模型的工具。它允许用户在本地环境中部署和运行各种开…

DAV_postgresql_3-schema

schem介绍: 什么是schema? 用户对象的集合叫做模式 不同模式下的对象可以同名 可以把用户下对象根据业务分类,不同的对象放在不同的模式 一个用户可以创与拥有多个模式 一个模式只能属于一个用户 普通用户创建模式需要授权指定数据库下的创建权限…

Hive-04之存储格式、SerDe、企业级调优

一、主题 hive表的数据压缩和文件存储格式hive的自定义UDF函数hive的JDBC代码操作hive的SerDe介绍和使用hive的优化 二、要点 1. hive表的文件存储格式 Hive支持的存储数的格式主要有:TEXTFILE(行式存储) 、SEQUENCEFILE(行式存储)、ORC&…

信号和槽

connect(信号发送者,发送的信号,信号接收者,信号的处理); 信号函数和槽函数的参数必须是一样的,但信号的参数可以多余槽函数的参数(前面的参数类型必须一致) 是控件和控件间的信号传递,这两个…

从零开始用react + tailwindcss + express + mongodb实现一个聊天程序(八) 聊天框用户列表

简单画了个聊天框 就是咱们的HomePage.jsx 1.后端接口开发 在server/src/index.js 新增 messagesRoutes 先引入 import messageRoutes from ./routes/message.route.js // 消息接口 app.use(/api/messages, messageRoutes) 在routes文件夹下新建message.route.js 有3个路…

关于后端使用Boolean或boolean时前端收到的参数的区别

当后端使用的是Boolean时,调用的方法是setIsLoginUser,前端收到的参数的参数名是isLoginUser 而当后端使用的是boolean时,调用的方法是setLoginUser,前端收到的参数的参数名是loginUser 封装类和基本数据类型在使用时需要注意这…

智能称重搬物寻迹小车(论文+源码)

1 系统设计方案确定 本次设计的总系统有以下几个模块分别是避障模块,循迹模块,二维码扫描电路,称重电路,LCD显示电路和电机驱动模块,而且这几个模块都是由单片机stm32控制的,整个系统的框图如下图所示。其…

使用 ASP.NET Core 创建和下载 zip 文件

对于最近的一个功能,我必须从用 ASP.NET Core 编写的内部网站下载一批文件。在下载文件之前对其进行压缩,结果证明这是一种轻松实现多文件下载的好方法。.NET 提供了所有需要的功能,在本文中,我将向您展示如何实现它。 首先&#…

dify绑定飞书多维表格

dify 绑定飞书和绑定 notion 有差不多的过程,都需要套一层应用的壳子,而没有直接可以访问飞书文档的 API。本文记录如何在dify工具中使用新增多条记录工具。 创建飞书应用 在飞书开放平台创建一个应用,个人用户创建企业自建应用。 自定义应…

SQL server配置ODBC数据源(本地和服务器)

本地配置 1. 控制面板中找到系统ODBC数据源(打开控制面板直接搜) 2. 选择“系统DSN”,点击“添加” 3. 选择“SQL server” 4. 名称和描述自己填,服务器选择本机设备名称 5. 选择ID和密码验证,并填写本地SQL server登…

LogiSim教程

一、LogiSim是什么 Logisim是一种设计数字电路的工具。 二、安装LogiSim 下载地址 https://sourceforge.net/projects/circuit/ 此软件需要java运行环境。 三、使用LogiSim (一)界面 Logisim界面分为菜单栏、工具栏、资源管理器,属性表…

RAP: Efficient Text-Video Retrieval with Sparse-and-Correlated Adapter

​​标题:RAP:基于稀疏相关适配器的高效文本视频检索 原文链接:RAP: Efficient Text-Video Retrieval with Sparse-and-Correlated Adapter - ACL Anthology 发表:ACL-2024(NLP领域CCF A类) 摘要 文本-视频检索(TVR&#xff0…

I2C驱动(十一) -- gpio模拟的i2c总线驱动i2c-gpio.c分析

相关文章 I2C驱动(一) – I2C协议 I2C驱动(二) – SMBus协议 I2C驱动(三) – 驱动中的几个重要结构 I2C驱动(四) – I2C-Tools介绍 I2C驱动(五) – 通用驱动i2c-dev.c分析 I2C驱动(六) – I2C驱动程序模型 I2C驱动(七) – 编写I2C设备驱动之i2c_driver I2C驱动(八) – 编写I2C…

不要升级,Flutter Debug 在 iOS 18.4 beta 无法运行,提示 mprotect failed: Permission denied

近期如果有开发者的 iOS 真机升级到 18.4 beta,大概率会发现在 debug 运行时会有 Permission denied 的相关错误提示,其实从 log 可以很直观看出来,就是 Dart VM 在初始化时,对内核文件「解释运行(JIT)」时…

私有化部署大模型推理性能分析

从用户感知角度分析私有化部署的大模型推理性能,这里的用户感知包括响应速度、生成速度、系统可用性以及系统稳定性。大模型首先获取输入内容的字符串,将这部分内容转换为模型token,过模型推理,到最后输出第一个token的时间是ttft,从这以后&a…

EtherCAT总线绝对值伺服如何使用

EtherCAT总线掉线如何自动重启。 EtherCAT总线掉线如何自动重启_ethercat从站断线-CSDN博客文章浏览阅读1.2k次。本文介绍了在EtherCAT通信中,当从站出现掉线情况时,如何通过设置自动重启功能来解决这一问题。详细步骤包括在CODESYS环境中启用从站的自动重启选项。https://r…