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

介绍

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

这就是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都已经奠定了坚实的基础,激励着研究者们不断探索更高效、更精准的文本处理策略。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

esp8266 rtos sdk开发环境搭建

1. 安装必要的工具 1.1 安装 Git Git 用于从远程仓库克隆代码,你可以从Git 官方网站下载 Windows 版本的安装程序。安装过程中可保持默认设置,安装完成后,在命令提示符(CMD)或 PowerShell 中输入git --version&#…

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: #

pytest下放pytest.ini文件就导致报错:ERROR: file or directory not found: # 如下: 项目文件目录如下: pytest.ini文件内容: [pytest] addopts -v -s --alluredir ./allure-results # 自动添加的命令行参数:# -…

Blender调整最佳渲染清晰度

1.渲染采样调高 512 2.根据需要 开启AO ,开启辉光 , 开启 屏幕空间反射 3.调高分辨率 4096x4096 100% 分辨率是清晰度的关键 , 分辨率不高 , 你其他参数调再高都没用 4.世界环境开启体积散射 , 可以增强氛围感 5.三点打光法 放在模型和相机45夹角上 白模 白模带线条 成品

Vllm进行Qwen2-vl部署(包含单卡多卡部署及爬虫请求)

1.简介 阿里云于今年9月宣布开源第二代视觉语言模型Qwen2-VL,包括 2B、7B、72B三个尺寸及其量化版本模型。Qwen2-VL具备完整图像、多语言的理解能力,性能强劲。 相比上代模型,Qwen2-VL 的基础性能全面提升,可以读懂不同分辨率和…

xr-frame 3D Marker识别,扬州古牌坊 3D识别技术稳定调研

目录 识别物体规范 3D Marker 识别目标文件 map 生成 生成任务状态解析 服务耗时: 对传入的视频有如下要求: 对传入的视频建议: 识别物体规范 为提高Marker质量,保证算法识别效果,可参考Marker规范文档 Marker规…

Windows环境下SuperMapGIS 11i 使用达梦数据库

1. 环境介绍: 1.1. 操作系统: windows server 2019 1.2. GIS 软件: 1.2.1. GIS 桌面 supermap-idesktopx-11.3.0-windows-x64-bin 下载链接:SuperMap技术资源中心|为您提供全面的在线技术服务 安装教程:绿色版&…

redis的下载和安装详解

一、下载redis安装包 进入redis官网查看当前稳定版本: https://redis.io/download/发现此时的稳定版本是6.2.4, 此时可以去这个网站下载6.2.4稳定版本的tar包。 暂时不考虑不在windows上使用redis,那样将无法发挥redis的性能 二、上传tar…

Prometheus + Grafana 监控

Prometheus Grafana 监控 官网介绍:Prometheus 是一个开源系统 监控和警报工具包最初由 SoundCloud 构建。自 2012 年成立以来,许多 公司和组织已经采用了 Prometheus,并且该项目具有非常 活跃的开发人员和用户社区。它现在是一个独立的开源…

使用Semantic Kernel:对DeepSeek添加自定义插件

SemanticKernel介绍 Semantic Kernel是一个SDK,它将OpenAI、Azure OpenAI等大型语言模型与C#、Python和Java等传统编程语言集成在一起。Semantic Kernel通过允许您定义插件来实现这一点。 为什么需要添加插件? 大语言模型虽然具有强大的自然语言理解和…

Grok3使用体验与模型版本对比分析

文章目录 Grok的功能DeepSearch思考功能绘画功能Grok 3的独特功能 Grok 3的版本和特点与其他AI模型的比较 最新新闻:Grok3被誉为“地球上最聪明的AI” 最近,xAI公司正式发布了Grok3,并宣称其在多项基准测试中展现了惊艳的表现。据官方消息&am…

QT——c++界面编程库

非界面编程 QT编译的时候,依赖于 .pro 配置文件: SOURCES: 所有需要参与编译的 .cpp 源文件 HEADERS:所有需要参与编译的.h 头文件 QT:所有需要参与编译的 QT函数库 .pro文件一旦修改,注意需要键盘按 ctrls 才能加载最新的配置文…

第十四届蓝桥杯大赛软件赛国赛C/C++大学C组

A 【跑步计划——日期问题】-CSDN博客 B 【残缺的数字】-CSDN博客 C 题目 代码 #include <bits/stdc.h> using namespace std;void change(int &x) {int sum 0, t x;while(t){sum t % 10;t / 10;}x - sum; } int main() {int n;cin >> n;int ans 0;…

pytorch基础-nn.linear

import torch import torch.nn as nn# 定义线性层 linear_layer nn.Linear(in_features10, out_features5, biasTrue)# 输入数据 input_data torch.randn(32, 10) # (batch_size32, in_features10)# 前向传播 output linear_layer(input_data) print(output.shape) # 输出…

Unity中Spine骨骼动画完全指南:从API详解到避坑实战

Unity中Spine骨骼动画完全指南&#xff1a;从API详解到避坑实战 一、为什么要选择Spine&#xff1f; Spine作为专业的2D骨骼动画工具&#xff0c;相比传统帧动画可节省90%资源量。在Unity中的典型应用场景包括&#xff1a; 角色换装系统&#xff08;通过插槽替换部件&#xf…

IP属地是通过卫星定位的吗?如何保护用户隐私

在数字时代&#xff0c;网络空间成为了人们日常生活不可或缺的一部分。随着社交媒体、在线服务等平台的兴起&#xff0c;用户IP属地信息的重要性日益凸显。然而&#xff0c;关于IP属地是如何确定的&#xff0c;尤其是是否通过卫星定位这一问题&#xff0c;却常常引发公众的疑问…

PyCharm中通过命令行执行`pip`命令下载到哪里了:虚拟环境目录下

PyCharm中通过命令行执行pip命令下载到哪里了:虚拟环境目录下 在PyCharm中通过命令行执行pip命令安装工具包,包的下载位置取决于多种因素 虚拟环境 如果项目使用了虚拟环境(通常是推荐的做法): Windows:虚拟环境通常位于项目目录下的.venv文件夹(默认情况)或你指定…

olmOCR:使用VLM解析PDF

在PDF解析中&#xff0c;目前主流的开源工具包括Minuer、GOT OCR等。主要都是通过飞桨等OCR套件组装的一套pipeline&#xff0c;或者直接通过VLM解析图像。 #一、 olmOCR是使用VLM进行的端到端的PDF文档解析 二、document-anchoring 与上述的不同在于&#xff0c;olmOCR使用…

Android ObjectBox数据库使用与集成指南

ObjectBox其核心特点ObjectBox与 SQLite 和 Realm 的对比Android集成ObjectBox创建ObjectBox实体对象创建ObjectBox操作管理类OBManager在Application初始化ObjectBox插入或更新数据查询数据统计数据分页数据查询删除数据总结今天分享一套Android另一个数据库ObjectBox。Object…

【深入理解JWT】从认证授权到网关安全

最近的项目学习中&#xff0c;在进行登陆模块的用户信息验证这一部分又用到了JWT的一些概念和相关知识&#xff0c;特在此写了这篇文章、方便各位笔者理解JWT相关概念 目录 先来理解JWT是什么&#xff1f; 区分有状态认证和无状态认证 有状态认证 VS 无状态认证 JWT令牌的…

使用write函数

使用open命令打开文件后&#xff0c;要往里面写入数据&#xff0c;使用write命令&#xff0c;把buf中count字节的数据写入fd中 关键是&#xff0c;写文件的时候要在这个文件的哪一个位置去写 假如写得时候&#xff0c;文件为空&#xff0c;指针指向最开始的位置&#xff0c;执…