sklearn中tfidf的计算与手工计算不同详解

news2024/11/27 0:15:45

sklearn中tfidf的计算与手工计算不同详解
引言:本周数据仓库与数据挖掘课程布置了word2vec的课程作业,要求是手动计算corpus中各个词的tfidf,并用sklearn验证自己计算的结果。但是博主手动计算的结果无论如何也与sklearn中的结果无法对应,在查阅大量资料无果的情况下,只好自己去阅读源码了,最后成功解决了这一问题。

题目背景:
作业:

1. corpus=["我 来到 北京 清华大学""他 来到 了 网易 杭研 大厦",
"小明 硕士 毕业 于 中国 科学院",
"我 爱 北京 天安门"]
手工计算完成BOW向量化和tfidf向量化,并 用python及sklearn实现,看下手工计算和程序输出结果一样吗 。
TF-IDF手工计算
(tf-idf计算这里网络上的其他文章基本都有,这里只给出基本的定义)

简介:TF-IDF(Term Frequency-InversDocument Frequency)是一种常用于信息处理和数据挖掘的加权技术。该技术采用一种统计方法,根据字词的在文本中出现的次数和在整个语料中出现的文档频率来计算一个字词在整个语料中的重要程度。它的优点是能过滤掉一些常见的却无关紧要本的词语,同时保留影响整个文本的重要字词。

计算步骤:

1.计算TF

简介:TF,是Term Frequency的缩写,就是某个关键字出现的频率,即词库中的某个词在当前文章中出现的频率。

计算公式:

词频TF = 某个词在文章中出现的次数 / 本篇文章中词的总数

考虑到文章有长短之分,为了便于不同文章的比较,进行"词频"标准化。

其中如果一个词在文中出现的频率越多,说明这个词TF就越大。

2.计算IDF

英文全称:Inverse Document Frequency,即“逆文档频率”。计算IDF需要一个语料库,用来模拟语言的使用环境。文档频率DF就是一个词在整个文库词典中出现的频率,如一个文件集中有100篇文章,共有10篇文章包含“机器学习”这个词,那么它的文档频率就是10/100=0.1,逆文档频率IDF就是这个值的倒数,即10。

计算公式:

IDF(N) = log(文档总数 / 出现N这一词汇的文档数目)

其中如果一个词越常见,那么分母就越大,逆文档频率就越小越接近0。

log表示对得到的值取对数。

3.计算TF-IDF=TF*IDF

Sklearn中的TFIDF
(下面引用一段sklearn源码中的注释,可以帮助不了解的读者直接使用)

Examples
--------
>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> from sklearn.feature_extraction.text import CountVectorizer
>>> from sklearn.pipeline import Pipeline
>>> import numpy as np
>>> corpus = ['this is the first document',
... 'this document is the second document',
... 'and this is the third one',
... 'is this the first document']
>>> vocabulary = ['this', 'document', 'first', 'is', 'second', 'the',
... 'and', 'one']
>>> pipe = Pipeline([('count', CountVectorizer(vocabulary=vocabulary)),
... ('tfid', TfidfTransformer())]).fit(corpus)
>>> pipe['count'].transform(corpus).toarray()
array([[1, 1, 1, 1, 0, 1, 0, 0],
[1, 2, 0, 1, 1, 1, 0, 0],
[1, 0, 0, 1, 0, 1, 1, 1],
[1, 1, 1, 1, 0, 1, 0, 0]])
>>> pipe['tfid'].idf_
array([1. , 1.22314355, 1.51082562, 1. , 1.91629073,
1. , 1.91629073, 1.91629073])
>>> pipe.transform(corpus).shape
(4, 8)

现在进入正题,在本次作业中,以上面的corpus和程序范例为背景运行程序会得出以下的结果

from sklearn.feature_extraction.textimport TfidfTransformer
from sklearn.feature_extraction.textimport CountVectorizer
if __name__ =="__main__":
corpus = ["我 来到 北京 清华大学", # 第一类文本切词后的结果,词之间以空格隔开
"他 来到 了 网易 杭研 大厦", # 第二类文本的切词结果
"小明 硕士 毕业 于 中国 科学院", # 第三类文本的切词结果
"我 爱 北京 天安门"]# 第四类文本的切词结果
vectorizer = CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
print(tfidf)

在这里插入图片描述

程序运行结果

我相信绝大多数的朋友得到的也是上图的结果,这与手工计算的结果大相径庭。不止结果不一样,甚至词汇数目都对不上,这实在令人难以接受。那么究竟是怎么一回事呢?

先说结论:
1.更改CountVectorizer的初始化参数token_pattern=r"(?u)\b\w+\b"

2.更改TfidfTransformer的初始化参数norm=None,smooth_idf=False.

3.更改手工idf计算方式:由lg(以10为底)改为ln(以e为底)

经过以上步骤的处理,手工计算的tfidf和程序计算的tfidf就是相同的了,那么为什么会出现这样的问题呢?

还是从源码说起吧

1.更改CountVectorizer的初始化参数
源码中的注释部分这样解释token_pattern

token_pattern : str, default=r"(?u)\\b\\w\\w+\\b"
Regular expression denoting what constitutes a "token", only used
if ``analyzer == 'word'``. The default regexp select tokens of 2
or more alphanumeric characters (punctuation is completely ignored
and always treated as a token separator).
If there is a capturing group in token_pattern then the
captured group content, not the entire match, becomes the token.
At most one capturing group is permitted.

个人理解:CountVectorizer类在初始化时会默认词汇辨认形式为r"(?u)\b\w\w+\b",这是一个双字符以上的字符串,这样就导致了在原题目中"我",“他”,“了”,“于"的丢失,这就是导致我们词汇数目不匹配的元凶!因为他们是单字符,所以我们把这个类的接受形式改为单字符即可(r”(?u)\b\w+\b")。

2. 更改TfidfTransformer的初始化参数
源码中的norm解释部分,以及smooth_idf解释部分

norm : {'l1', 'l2'}, default='l2'
Each output row will have unit norm, either:
* 'l2': Sum of squares of vector elements is 1. The cosine
similarity between two vectors is their dot product when l2 norm has
been applied.
* 'l1': Sum of absolute values of vector elements is 1.
See :func:`preprocessing.normalize`
smooth_idf : bool, default=True
Smooth idf weights by adding one to document frequencies, as if an
extra document was seen containing every term in the collection
exactly once. Prevents zero divisions.

norm很好理解,sklearn自动为我们做了l2正则化,所以我们的结果和他的不同。因此只要不使用正则化即可(norm=None)

那下面的smooth_idf又是什么情况呢?(这里网上的各种资料简直是迷惑行为大赏,抄来抄去,说的全都含混不清)

首先我们要牢记,最基础的idf定义就是文章上面写的定义!!!

那其他的idf定义是正确的吗?比如idf = log(N + 1/ N(x) + 1),以及该式子的各种变形?

如果你使用了smooth_idf,那么上式正确。

那么什么是smooth_idf呢,举个栗子:

corpus_no_smooth=["我 来到 北京 清华大学""他 来到 了 网易 杭研 大厦",
"小明 硕士 毕业 于 中国 科学院",
"我 爱 北京 天安门"]
corpus_with_smooth=["我 来到 北京 清华大学",
"他 来到 了 网易 杭研 大厦",
"小明 硕士 毕业 于 中国 科学院",
"我 爱 北京 天安门",
"我 来到 北京 清华大学 他 了 网易 杭研 大厦 小明 硕士 毕业 于 中国 科学院 爱 天安门 " ]
其实就是将出现过的所有词汇放入一个新生成的文章之中,确保idf初始定义中的分母不为0。

3.用ln来计算自己的idf
其实这是一个很搞的问题,sklearn中使用的是numpy库中的log函数,这个函数就是ln函数,在源码中所有的计算都是用的numpy.log(),这同样导致了我们的结果与程序完全不同。

虽然这个问题事后看来并不是一个非常困难的问题,但是因为这个问题需要更改好几个参数甚至要更改自己,也因为某些垃圾博主只会抄袭,根本不深入研究,导致我根本找不到一个解决这个问题的博客,最后只能自己动手解决。尽管浪费了很多时间,但还是比较值得的,也希望对其他被这个问题困扰的同学有帮助吧 。

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

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

相关文章

ChatGLM 6B 部署及微调 【干货】

代码地址、模型地址、安装环境:Ubuntu20.04,RTX3060 12G 一、部署 1.1 下载代码 cd /opt git clone https://github.com/THUDM/ChatGLM2-6B1.2 下载模型 将模型下载后放到项目文件夹内 git lfs install # 确认安装了lfs,或者直接到项目地…

基于ssm的网上订餐系统

一、系统架构 前端:jsp | js | css | jquery 后端:spring | springmvc | mybatis 环境:jdk1.7 | mysql | maven | tomcat 二、代码与数据库 三、功能介绍 01. web端-首页 02. web端-我的餐车 03. web端-我的订单 04. web端-用户中心 05. web…

西门子PLC与组态王无线通讯中如何设置从站

本方案主要详述了在多台西门子300PLC与组态王之间Modbus无线通讯中如何设置从站。方案中所用到的无线通讯终端是DTD434MC——欧美系PLC专用无线通讯终端。 一、方案概述 无线Modbus网络组成如下: 二、测试背景 ● PC端组态软件版本:组态王6.55 ● 默…

tomcat-pass-getshell 弱口令 漏洞复现

tomcat-pass-getshell 弱口令 漏洞复现 名称: tomcat-pass-getshell 弱口令 描述: Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。 通过弱口令登…

2024 IEEE Fellow名单公布,上百位华人学者入选!

就在近日,美国电子电气工程师学会(Institute of Electrical and Electronic Engineers,IEEE)公布了新一届Fellow名单。 IEEE Fellow为学会最高等级会员,是IEEE授予成员的最高荣誉,旨在表彰那些在电气、电子…

内网隧道学习

默认密码:hongrisec2019 一.环境搭建 网卡学习 一个网卡一个分段,想象成一个管道 192.168.52一段 192.168.150一段 仅主机模式保证不予外界连通,保证恶意操作不会跑到真实机之上 52段是内部通信,150段属于服务器(…

23款奔驰E300L升级23P驾驶辅助 智驾出行 缓解开车疲劳

辅助驾驶越来越多的被大家所青睐!为了提升驾驶安全性和舒适便捷性奔驰改装原厂半自动驾驶23P辅助系统 23P智能辅助驾驶系统还是很有必要的,因为在跑高速的时候可以使用23P智能驾驶的自动保持车速,保持车距,车道自动居中行驶以及自…

小型内衣洗衣机什么牌子好?口碑最好的小型洗衣机

很多人会觉得内衣洗衣机是智商税,洗个内衣只需要两分钟的事情,需要花个几百块钱去入手一个洗衣机吗?然而清洗贴身衣物的并不是一件简单的事情,如果只是简单的搓洗,内裤上看不见的细菌也无法消除,而且对来生…

英特尔工作站:助力专业用户实现高效创作

原创 | 文 BFT机器人 英特尔工作站是由全球知名的英特尔公司设计和开发的一款计算平台。英特尔在工作站处理器领域将其产品分为性能型和移动型两类,它的诞生旨在满足专业用户在科学、工程、设计等领域对高性能计算的需求。英特尔工作站配备了最新的英特尔处理器、大…

关于卸载亚信安全防火墙软件

电脑根据需求上安装亚信安全防火墙,不需要时,要卸载需要密码 关于卸载亚信安全防火墙客户端-适用于win10和win11的方法(系统64位). 亲测有效: 1.电脑上winR,运行输入msconfig 2.勾选引导中的安全引导,然后重新启动,进入安全模式. 3.winR输入regedit,打开注册表编辑器进入/Mis…

苹果用户如何恢复手机数据?盘点3个实用方法!

随着手机功能的不断增强和应用程序的不断丰富,人们越来越依赖手机,离不开手机。然而,有时因为误操作、系统故障或者数据丢失等原因,我们需要找回手机上丢失的数据。那么,苹果用户如何恢复手机数据呢?本文将…

java开发必备的Vue知识点和技能

vue介绍 什么是Vue?vue就是一款用于构建用户界面的渐进式的JavaScript框架。(官方:https://cn.vuejs.org/) 框架:就是一套完整的项目解决方案,用于快速构建项目。 优点:大大提升前端项目的开…

Java基础之集合类

Java基础之集合类 一、集合的框架1.1、集合概述1.2、集合与数组区别1.3、数组的缺点:1.4、常用集合分类1.5、Collection常用方法 二、List集合2.1、ArrayList2.2、LinkedList2.3、Vector2.4、区别 三、Set集合3.1、HashSet集合3.2、LinkedHashSet集合3.3、TreeSet集…

终于等到你!常用的组织架构图模板,高清图片一键导出

组织架构图是一种用来展示一个组织内部人员和职责关系的图表。通过组织架构图,我们可以清晰地了解一个组织的层级架构和各个部门之间的关系。在本文中,我们将向大家推荐8个常用的组织架构图模板,帮助你快速制作出专业的组织架构图。 1. 市场营…

数据结构——动态规划

动态规划:有很多重叠子问题,每一个状态一定是由上一个状态推导出来的 贪心:没有状态推导,而是从局部直接选最优的 动规五步曲: 确定dp数组(dp table)以及下标的含义 确定递推公式(容…

招投标信息可以用CRM系统来查看吗?

对于B2B企业来说获客难、获客成本高是共识。做大客户的企业通过招投标获取商机是一个重要获客途径,然而传统方式管理招投标信息问题很多,例如资料丢失、手工录入出错、信息分散、信息查找费时费力。为了解决这些难题小编推荐CRM系统,CRM系统需…

非参数估计与参数估计的区别,以及详细列举了常用的非参数估计方法和参数估计方法,一网打尽非参数估计与参数估计!!!

文章目录 前言一、非参数估计与参数估计的区别二、常用的非参数估计方法三、常用的参数估计方法总结 前言 非参数估计和参数估计是统计学中的两种不同的估计方法。 一、非参数估计与参数估计的区别 参数估计是指,对于已知分布形式的数据,根据样本数据…

WinEdt打开.tex文件显示error reading错误

原因: 是因为.tex文件中包含了utf-8字符,而在打开的时候并没有指明utf-8打开方式 解决方法 在WinEdt中,【File】-【Open】(或使用快捷键CtrlO),在弹出的打开对话框中,右下角【文件名】右侧有…

全面探讨HTTP协议从0.9到3.0版本的发展和特点

前言: 最近的几场面试都问到了http的相关知识点,博主在此结合书籍和网上资料做下总结。本篇文章讲收录到秋招专题,该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮…

EI期刊论文复现:考虑电动汽车可调度潜力的充电站两阶段市场投标策略程序代码!

本程序代码参考EI期刊论文《考虑电动汽车可调度潜力的充电站两阶段市场投标策略》,程序中基于历史数据评估可调度潜力,由联合报价模型确定节点边际电价,作为报价的参考,包含个体竞价模式,纳什博弈竞价,算例…