【机器学习】TF-IDF以及TfidfVectorizer

news2024/12/24 3:22:45

TF-IDF定义

TF-IDF: 全称为"词频一逆文档频率"。
  TF:某一给定词语在该文档中出现的频率。 T F w = 词语 w 在该文档中个数 该文档内总词个数 TF_w = \frac{词语w在该文档中个数}{该文档内总词个数} TFw=该文档内总词个数词语w在该文档中个数
  IDF:整个训练集文档集合一共由 N N N篇文档组成,其中包含某个给定词语 w w w的文档数为 M M M. 则该给定词的 I D F IDF IDF值为: I D F = l o g e ( N M + 1 ) IDF=log_e(\frac{N}{M+1}) IDF=loge(M+1N),M+1是防止分母=0。
  一个词的 T F TF TF值反映了该词在某一篇文档中的重要性,而它的 I D F IDF IDF值则反映了它在整个文档集中的普遍重要程度。二者的乘积(TF-lDF ) 相当于取TF 和IDF的交集, 其值理论上可以较好地反映各个词的分类特征。某一特定文件内的较高词语频次,以及该词语在整个文件集合中的较低频次,可以产生较高的TF-IDF值,TF-IDF算法倾向于过滤常见词语,保留重要词语。经常结合余弦相似度用于向量空间中,判断两份文件的相似度。

python实现

直接使用TfidfVectorizer

这里采用的是[“Chinese Beijing Chinese”, “Chinese Chinese Shanghai”,“Chinese Macao”,“Tokyo Japan Chinese”]这个训练语料库,做一个简单的试验。
起初,我以为这样就能解决:

from sklearn.feature_extraction.text import TfidfVectorizer
tv = TfidfVectorizer()  # 实例化tf实例
train = ["Chinese Beijing Chinese", "Chinese Chinese Shanghai","Chinese Macao","Tokyo Japan Chinese"]  # 输入训练集矩阵,每行表示一个文本
tv_fit = tv.fit_transform(train)  # 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
print(f'词汇表{tv.get_feature_names_out()}')  # 查看一下构建的词汇表
print(f'不同词语对应下标:{tv.vocabulary_}')
print(f'矩阵{tv_fit.toarray()}')  # 查看输入文本列表的VSM矩阵

  这是借助TfidfVectorizer进行实现的,结果如下:[‘beijing’ ‘chinese’ ‘japan’ ‘macao’ ‘shanghai’ ‘tokyo’]代表了语料库内所有的词语;{‘chinese’: 1, ‘beijing’: 0, ‘shanghai’: 4, ‘macao’: 3, ‘tokyo’: 5, ‘japan’: 2}是不同词语对应下标,这个在下面的矩阵里面代表这个词语在第几列;
  矩阵的每一行代表一个文档内的每一个词语的TF-IDF值。举个例子,对于文档"Chinese Beijing Chinese"来讲它的结果就是第0行[0.69183461,0.722056 ,0. , 0. , 0. , 0. ],该文档中只有Chinese和Beijing 这两个词语,因此只有两个元素非零,其中chinese对应列是1,于是它在该文档中的TF-IDF值为0.722056,beijing1对应列是0.于是它在该文档中的TF-IDF值为0.69183461。
在这里插入图片描述

结果解释

  但是仔细一看,欸???为什么?这些数值是什么意思???
  就拿"Chinese Beijing Chinese"里的chinese来说,根据定义, T F = 2 3 , I D F = l o g e ( 4 5 ) , T F − I D F = − 0.1487 ? ? ? TF = \frac{2}{3},IDF = log_e(\frac{4}{5}),TF-IDF = -0.1487??? TF=32IDF=loge(54),TFIDF=0.1487???,不对劲啊!!
我就在网上找啊,发现TF_IDF公式还挺多,不止有定义里的;
一个例子来使用sklearn中的TfidfVectorizer
tf-idf原理 & TfidfVectorizer参数详解及实战
经过我实践证明TfidfVectorizer使用的计算TF-IDF公式如下:
T F = 给定词语在该文档中出现的频数 I D F = l n ( 1 + N 1 + M ) + 1 T F I D F = T F ∗ I D F 整个训练集文档集合一共由 N 篇文档组成,其中包含某个给定词语的文档数为 M . TF = 给定词语在该文档中出现的频数\\ IDF = ln(\frac{1+N}{1+M})+1\\ TFIDF = TF*IDF\\ 整个训练集文档集合一共由N篇文档组成,其中包含某个给定词语的文档数为M. TF=给定词语在该文档中出现的频数IDF=ln(1+M1+N)+1TFIDF=TFIDF整个训练集文档集合一共由N篇文档组成,其中包含某个给定词语的文档数为M.
然后TfidfVectorizer还对每个文档的向量进行规范化,即对于每个文档的词语TF-IDF向量 v v v还要除以2范数, v ∣ ∣ v ∣ ∣ 2 \frac{v}{||v||_2} ∣∣v2v

手敲代码

这是我根据这个公式写出的python代码:

# 求逆文档频率IDF
def Idf(nd,df):
    return np.log((1+nd)/(1+df)) + 1

train = ["Chinese Beijing Chinese", "Chinese Chinese Shanghai","Chinese Macao","Tokyo Japan Chinese"] 
wordInDoc = []  # 记录在每个文档语句中单词出现次数,元素为字典,每个字典记录该文档中单词出现次数
wordInCor = {}  # 语料库中单词出现的文档
'''
不会重复
'''
# 求出每个文档语句中单词出现次数
for doc in train:
    words = doc.split()  # 将句子按空格分割成单词
    word_counts = {}  # 使用字典存储词语出现次数
    for word in words:
        word = word.strip('.,!?"()[]{}')  # 去除标点符号
        word = word.lower()  # 转换为小写以忽略大小写差异
        # 更新字典中词语的出现次数
        word_counts[word] = word_counts.get(word,0)+1
    wordInDoc.append(word_counts)  # 添加该文档字典
    
# 语料库中单词出现的文档
for i  in wordInDoc:  # 遍历每个文档字典
    for j in i:  # 如果词汇j出现在文档i中则该词汇出现次数+1
        wordInCor[j] = wordInCor.get(j,0)+1
        
# 给出每个词汇在哪一列
ind = {}  # 每个词汇对应下标,对应后面,词汇result中的哪一列
for i,word in enumerate(list(np.sort(list(wordInCor.keys())))):
    ind[word] = i
    
# 结果是一个稀疏矩阵
result = np.zeros((len(train),len(wordInCor.keys())))
for i in  range(len(train)):  # 遍历每个文档
    for word in ind.keys():  # 遍历每个词汇
        if word in wordInDoc[i].keys():  # 如果该词汇在该文档中,则计算
            tf = wordInDoc[i][word]  # wordInDoc[i]第几个文档的字典,wordInDoc[i][word]该文档中词汇出现次数?
                                    # 这边其实是有点疑问的,网上tf公式大多是频率,但是TfidfVectorizer从结果来倒推,TfidfVectorizer用的是频数
            idf = Idf(len(train),wordInCor[word])  # len(train)为文档总数=4,wordInCor[word]为该词汇在文档中出现次数
            tfidf = tf*idf
            result[i,ind[word]] = tfidf
# 规范标准化,除以2范数
result = result/np.sqrt((result**2).sum(axis = 1)).reshape(-1,1)
print(result)

结果:可以看出结果是和调用TfidfVectorizer是一样的。当然,这里词语对应的列与上面不同。
在这里插入图片描述

总结

  TfidfVectorizer使用的计算TF-IDF的公式与定义有差别。但实际上表达的意思是相同的,都是在该文档中的重要性TF乘以在语料库中的重要性IDF的乘积。
  np.log()其实是以e为底的,所以如果要计算以其他数为底的对数,需要进行换底公式 L o g a b = l o g c b l o g c a Log_ {a}b=\frac {log_ {c}b} {log_ {c}a} Logab=logcalogcb

def Log(newd,number): #newd新底
	return np.log(number)/np.log(newd)
Log(10,10)

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

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

相关文章

FreeSWITCH 1.10.10 简单图形化界面9 - 鼎兴FXO网关SIP中继内网IPPBX落地

FreeSWITCH 1.10.10 简单图形化界面9 - 鼎兴FXO网关SIP中继内网IPPBX落地 0、 界面预览1、创建一个话务台2、创建PBX SIP中继并设置呼入权限3、设置呼出规则4、设置分机呼出权限5、设置FXO 网关相关信息6、设置FXO网关端口组呼入号码7、设置FXO网关的SIP中继8、设置FXO网关呼叫…

第二章 进程与线程 十、调度算法1(先来先服务、短作业优先、最高响应比优先)

目录 一、先来先服务算法 1、算法思想 2、算法规则 3、用于作业/进程调度 4、是否可抢占? 5、优缺点 优点: 缺点: 6、是否会导致饥饿 7、例子 二、短作业优先算法 1、算法思想 2、算法规则 3、用于作业/进程调度 4、是否可抢占? 5、优缺…

Linux多线程【线程控制】

✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌇前言🏙️正文1、线程知识补充1.2、线程私有资源1.3、线程共享资源1.4、原生线程库 2、线程…

FreeSWITCH 1.10.10 简单图形化界面8 - 讯时FXO网关SIP注册公网IPPBX落地

FreeSWITCH 1.10.10 简单图形化界面8 - 讯时FXO网关SIP注册公网IPPBX落地 0、 界面预览1、创建一个话务台2、创建PBX 分机中继并设置呼入权限3、设置呼出规则4、设置分机呼出权限5、设置FXO 网关相关信息6、设置FXO网关中继线路呼入号码7、设置FXO网关呼叫路由(呼入…

为啥我的第二个for循环不加框红的代码就运行失效呢?(文末赠书)

点击上方“Python爬虫与数据挖掘”,进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 苟全性命于乱世,不求闻达于诸侯。 大家好,我是皮皮。 一、前言 前几天在Python最强王者群【哎呦喂 是豆子~】问了一…

【机组】计算机系统组成课程笔记 第二章 计算机中的信息表示

2.1 无符号数和有符号数 2.1.1 无符号数 没有符号的数,其实就是非负数。在计算机中用字节码表示,目前最常用的是八位和十六位的。 2.1.2 有符号数 将正负符号数字化,0代表 ,1代表 - ,并把代表符号的数字放在有效数…

【Linux升级之路】6_进程间通信

🌟hello,各位读者大大们你们好呀🌟 🍭🍭系列专栏:【Linux升级之路】 ✒️✒️本篇内容:进程间通信介绍,管道,共享内存,消息队列,信号量 &#x1f…

八股文学习一(存储)

一. 存储 行式存储的原理与特点 对于 OLAP 场景,大多都是对一整行记录进行增删改查操作的,那么行式存储采用以行的行式在磁盘上存储数据就是一个不错的选择。 当查询基于需求字段查询和返回结果时,由于这些字段都埋藏在各行数据中&#xf…

直播设备之ENC1高级篇拆机刷uboot教程

直播设备之ENC1高级篇拆机刷uboot教程 第一步: 准备材料第二步:拆外壳取出裸板第三步:链接串口线第四步:进入电脑,开始刷uboot第五步:开始刷设备固件 老铁们好,好久没出文章了,这两天…

【面试题】智力题

文章目录 腾讯1000瓶毒药里面只有1瓶是有毒的,问需要多少只老鼠才能在24小时后试出那瓶有毒。有两根不规则的绳子,两根绳子从头烧到尾均需要一个小时,现在有一个45分钟的比赛,裁判员忘记带计时器,你能否通过烧绳子的方…

leetcode21合并两个有序链表

题目: 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4]示例 2: 输入:l1 [], l2 [] 输…

Android之MediaMetricsService实现本质(四十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

AE-如何让一副静止的画变成动态图

如何让一副静止的画变成动态图,如图所示,如何让图中静态的芦苇随风摆动? 制作过程如下: 1.安装AutoSway AutoSway 可以从lookae 下载。 AutoSway 安装方法: 1)复制 AutoSway.jsxbin和AutoSway_ffx文件夹到AE脚本目录: Win:...Adobe After Effects CC\Support Fil…

【SDXL_LORA模型训练详细教程(含云端教程)】

个人网站:https://tianfeng.space 一、前言 之前写过一篇SD1.5 LORA模型的炼制方法,有的人想要我详细点说说秋叶启动器的lora训练器,SDXL建议使用秋叶的训练器,SD1.5赛博丹炉,个人习惯仅供参考!这次基于s…

TCP详解之滑动窗口

TCP详解之滑动窗口 引入窗口概念的原因 我们都知道 TCP 是每发送一个数据,都要进行一次确认应答。当上一个数据包收到了应答了, 再发送下一个。 这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。 如果你…

红黑树的原理

文章目录 红黑树的原理红黑树的定义为什么会有红黑树红黑树构建 红黑树的原理 红黑树(Red-Black Tree)是一种自平衡的二叉搜索树,它在计算机科学中被广泛应用于实现有序集合和映射等数据结构。它通过引入颜色标记和一些特定的操作规则&#…

springboot+vue“智慧食堂”设计与实现springboot002

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…

JAVA医药进销存管理系统(附源码+调试)

JAVA医药进销存管理系统 功能描述 (1)登录模块:登录信息等存储在数据库中 (2)基本信息模块:分为药品信息模块、客户情况模块、供应商情况模块; (3)业务管理模块&#x…

QStandardItem通过setCheckable添加复选框后无法再次通过setCheckable取消复选框的问题

前言 如题所示&#xff0c;通过setCheckable添加复选框后&#xff0c;想要通过setCheckable(false)取消复选框&#xff0c;你会发现根本没有作用的。 问题复现 #include "widget.h" #include "ui_widget.h" #include <QList>Widget::Widget(QWidg…

QT基础教学(QMainWindow)

文章目录 前言一、QMainWindow介绍二、代码示例三、QMainWindow高级用法总结 前言 之前我们都是在QWidget中来进行学习的&#xff0c;那么今天我将为大家讲解一下QMainWindow。 一、QMainWindow介绍 QMainWindow是Qt框架提供的一个重要的窗口类&#xff0c;用于创建具有标准…