iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >TF-IDF算法解析与Python实现方法详解
  • 899
分享到

TF-IDF算法解析与Python实现方法详解

算法详解方法 2022-06-04 19:06:53 899人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

TF-IDF(term frequency?inverse document frequency)是一种用于信息检索(infORMation retrieval)与文本挖掘(text mining)的常用加

TF-IDF(term frequency?inverse document frequency)是一种用于信息检索(infORMation retrieval)与文本挖掘(text mining)的常用加权技术。比较容易理解的一个应用场景是当我们手头有一些文章时,我们希望计算机能够自动地进行关键词提取。而TF-IDF就是可以帮我们完成这项任务的一种统计方法。它能够用于评估一个词语对于一个文集或一个语料库中的其中一份文档的重要程度。

在一份给定的文件里,词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(分子一般小于分母 区别于IDF),以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)

  逆向文件频率 (inverse document frequency, IDF) 是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。

  某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF反文档频率(Inverse Document Frequency)。TF表示词条在文档d中出现的频率(另一说:TF词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数)。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。(另一说:IDF反文档频率(Inverse Document Frequency)是指果包含词条的文档越少,IDF越大,则说明词条具有很好的类别区分能力。)但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处.

为了演示在python中实现TF-IDF的方法,一些基于自然语言处理的预处理过程也会在本文中出现。如果你对NLTK和Scikit-Learn两个库还很陌生可以参考如下文章:

Python编程使用NLTK进行自然语言处理详解

Python自然语言处理之词干,词形与最大匹配算法代码详解

必要的预处理过程

首先,我们给出需要引用的各种包,以及用作处理对象的三段文本。


import nltk
import math
import string
from nltk.corpus import stopWords
from collections import Counter
from nltk.stem.porter import *
from sklearn.feature_extraction.text import TfidfVectorizer

text1 = "Python is a 2000 made-for-TV horror movie directed by Richard 
Clabaugh. The film features several cult favorite actors, including William 
Zabka of The Karate Kid fame, Wil Wheaton, Casper Van Dien, Jenny McCarthy, 
Keith Coogan, Robert Englund (best known for his role as Freddy Krueger in the 
A Nightmare on Elm Street series of films), Dana Barron, David Bowe, and Sean 
Whalen. The film concerns a genetically engineered snake, a python, that 
escapes and unleashes itself on a small town. It includes the classic final
girl scenario evident in films like Friday the 13th. It was filmed in Los Angeles, 
 California and Malibu, California. Python was followed by two sequels: Python 
 II (2002) and Boa vs. Python (2004), both also made-for-TV films."

text2 = "Python, from the Greek word (πύθων/πύθωνας), is a genus of 
nonvenomous pythons[2] found in Africa and Asia. Currently, 7 species are 
recognised.[2] A member of this genus, P. reticulatus, is among the longest 
snakes known."

text3 = "The Colt Python is a .357 Magnum caliber revolver formerly 
manufactured by Colt's Manufacturing Company of Hartford, Connecticut. 
It is sometimes referred to as a "Combat Magnum".[1] It was first introduced 
in 1955, the same year as Smith & Wesson's M29 .44 Magnum. The now discontinued 
Colt Python targeted the premium revolver market segment. Some firearm 
collectors and writers such as Jeff Cooper, Ian V. Hogg, Chuck Hawks, Leroy 
Thompson, Renee Smeets and Martin Dougherty have described the Python as the 
finest production revolver ever made."

TF-IDF的基本思想是:词语的重要性与它在文件中出现的次数成正比,但同时会随着它在语料库中出现的频率成反比下降。 但无论如何,统计每个单词在文档中出现的次数是必要的操作。所以说,TF-IDF也是一种基于 bag-of-word 的方法。

首先我们来做分词,其中比较值得注意的地方是我们设法剔除了其中的标点符号(显然,标点符号不应该成为最终的关键词)。


def get_tokens(text):
  lowers = text.lower()
  #remove the punctuation using the character deletion step of translate
  remove_punctuation_map = dict((ord(char), None) for char in string.punctuation)
  no_punctuation = lowers.translate(remove_punctuation_map)
  tokens = nltk.word_tokenize(no_punctuation)
  return tokens

下面的代码用于测试上述分词结果,Counter() 函数用于统计每个单词出现的次数。


tokens = get_tokens(text1)
count = Counter(tokens)
print (count.most_common(10))

执行上述代码后可以得到如下结果,我们输出了其中出现次数最多的10个词。


[('the', 6), ('python', 5), ('a', 5), ('and', 4), ('films', 3), ('in', 3), 
('madefortv', 2), ('on', 2), ('by', 2), ('was', 2)]

显然,像 the, a, and 这些词尽管出现的次数很多,但是它们与文档所表述的主题是无关的,所以我们还要去除“词袋”中的“停词”(stop words),代码如下:


def stem_tokens(tokens, stemmer):
  stemmed = []
  for item in tokens:
    stemmed.append(stemmer.stem(item))
  return stemmed

同样,我们来测试一下上述代码的执行效果。


tokens = get_tokens(text1)
filtered = [w for w in tokens if not w in stopwords.words('english')]
count = Counter(filtered)
print (count.most_common(10))

从下面的输出结果你会发现,之前那些缺乏实际意义的 the, a, and 等词已经被过滤掉了。


[('python', 5), ('films', 3), ('film', 2), ('california', 2), ('madefortv', 2), 
('genetically', 1), ('horror', 1), ('krueger', 1), ('filmed', 1), ('sean', 1)]

但这个结果还是不太理想,像 films, film, filmed 其实都可以看出是 film,而不应该把每个词型都分别进行统计。这时就需要要用到我们在前面文章中曾经介绍过的 Stemming 方法。代码如下:


tokens = get_tokens(text1)
filtered = [w for w in tokens if not w in stopwords.words('english')]
stemmer = PorterStemmer()
stemmed = stem_tokens(filtered, stemmer)

类似地,我们输出计数排在前10的词汇(以及它们出现的次数):


count = Counter(stemmed)
print(count)

上述代码执行结果如下:


Counter({'film': 6, 'python': 5, 'madefortv': 2, 'california': 2, 'includ': 2, '2004': 1,
 'role': 1, 'casper': 1, 'robert': 1, 'sequel': 1, 'two': 1, 'krueger': 1, 
'ii': 1, 'sean': 1, 'lo': 1, 'clabaugh': 1, 'finalgirl': 1, 'wheaton': 1, 
'concern': 1, 'whalen': 1, 'cult': 1, 'boa': 1, 'mccarthi': 1, 'englund': 1, 
'best': 1, 'direct': 1, 'known': 1, 'favorit': 1, 'movi': 1, 'keith': 1, 
'karat': 1, 'small': 1, 'classic': 1, 'coogan': 1, 'like': 1, 'elm': 1, 
'fame': 1, 'malibu': 1, 'sever': 1, 'richard': 1, 'scenario': 1, 'town': 1, 
'friday': 1, 'david': 1, 'unleash': 1, 'vs': 1, '2000': 1, 'angel': 1, 'nightmar': 1, 
'zabka': 1, '13th': 1, 'jenni': 1, 'seri': 1, 'horror': 1, 'william': 1, 
'street': 1, 'wil': 1, 'escap': 1, 'van': 1, 'snake': 1, 'evid': 1, 'freddi': 1, 
'bow': 1, 'dien': 1, 'follow': 1, 'engin': 1, 'also': 1})

至此,我们就完成了基本的预处理过程。

TF-IDF的算法原理

预处理过程中,我们已经把停词都过滤掉了。如果只考虑剩下的有实际意义的词,前我们已经讲过,显然词频(TF,Term Frequency)较高的词之于一篇文章来说可能是更为重要的词(也就是潜在的关键词)。但这样又会遇到了另一个问题,我们可能发现在上面例子中,madefortv、california、includ 都出现了2次(madefortv其实是原文中的made-for-TV,因为我们所选分词法的缘故,它被当做是一个词来看待),但这显然并不意味着“作为关键词,它们的重要性是等同的”。

因为”includ”是很常见的词(注意 includ 是 include 的词干)。相比之下,california 可能并不那么常见。如果这两个词在一篇文章的出现次数一样多,我们有理由认为,california 重要程度要大于 include ,也就是说,在关键词排序上面,california 应该排在 include 的前面。

于是,我们需要一个重要性权值调整参数,来衡量一个词是不是常见词。如果某个词比较少见,但是它在某篇文章中多次出现,那么它很可能就反映了这篇文章的特性,它就更有可能揭示这篇文字的话题所在。这个权重调整参数就是“逆文档频率”(IDF,Inverse Document Frequency),它的大小与一个词的常见程度成反比。

知道了 TF 和 IDF 以后,将这两个值相乘,就得到了一个词的TF-IDF值。某个词对文章的重要性越高,它的TF-IDF值就越大。如果用公式来表示,则对于某个特定文件中的词语 ti 而言,它的 TF 可以表示为:

查看图片

其中 ni,j是该词在文件 dj中出现的次数,而分母则是文件 dj 中所有词汇出现的次数总和。如果用更直白的表达是来描述就是,

查看图片

某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数即可:

查看图片

其中,|D| 是语料库中的文件总数。 |{j:ti∈dj}| 表示包含词语 ti 的文件数目(即 ni,j≠0 的文件数目)。如果该词语不在语料库中,就会导致分母为零,因此一般情况下使用 1+|{j:ti∈dj}|。同样,如果用更直白的语言表示就是

查看图片

最后,便可以来计算 TF-IDF(t)=TF(t)×IDF(t)。
下面的代码实现了计算TF-IDF值的功能。


def tf(word, count):
  return count[word] / sum(count.values())

def n_containing(word, count_list):
  return sum(1 for count in count_list if word in count)

def idf(word, count_list):
  return math.log(len(count_list) / (1 + n_containing(word, count_list)))

def tfidf(word, count, count_list):
  return tf(word, count) * idf(word, count_list)

再给出一段测试代码:


countlist = [count1, count2, count3]
for i, count in enumerate(countlist):
  print("Top words in document {}".format(i + 1))
  scores = {word: tfidf(word, count, countlist) for word in count}
  sorted_words = sorted(scores.items(), key=lambda x: x[1], reverse=True)
  for word, score in sorted_words[:3]:
    print("tWord: {}, TF-IDF: {}".format(word, round(score, 5)))

输出结果如下:


Top words in document 1
  Word: film, TF-IDF: 0.02829
  Word: madefortv, TF-IDF: 0.00943
  Word: california, TF-IDF: 0.00943
Top words in document 2
  Word: genu, TF-IDF: 0.03686
  Word: 7, TF-IDF: 0.01843
  Word: among, TF-IDF: 0.01843
Top words in document 3
  Word: revolv, TF-IDF: 0.02097
  Word: colt, TF-IDF: 0.02097
  Word: manufactur, TF-IDF: 0.01398

利用Scikit-Learn实现的TF-IDF

因为 TF-IDF 在文本数据挖掘时十分常用,所以在Python的机器学习包中也提供了内置的TF-IDF实现。主要使用的函数就是TfidfVectorizer(),来看一个简单的例子。


>>> corpus = ['This is the first document.',
   'This is the second second document.',
   'And the third one.',
   'Is this the first document?',]
>>> vectorizer = TfidfVectorizer(min_df=1)
>>> vectorizer.fit_transform(corpus)
<4x9 sparse matrix of type '<class 'numpy.float64'>'
  with 19 stored elements in Compressed Sparse Row format>
>>> vectorizer.get_feature_names()
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
>>> vectorizer.fit_transform(corpus).toarray()
array([[ 0.    , 0.43877674, 0.54197657, 0.43877674, 0.    ,
     0.    , 0.35872874, 0.    , 0.43877674],
    [ 0.    , 0.27230147, 0.    , 0.27230147, 0.    ,
     0.85322574, 0.22262429, 0.    , 0.27230147],
    [ 0.55280532, 0.    , 0.    , 0.    , 0.55280532,
     0.    , 0.28847675, 0.55280532, 0.    ],
    [ 0.    , 0.43877674, 0.54197657, 0.43877674, 0.    ,
     0.    , 0.35872874, 0.    , 0.43877674]])

最终的结果是一个 4×9 矩阵。每行表示一个文档,每列表示该文档中的每个词的评分。如果某个词没有出现在该文档中,则相应位置就为 0 。数字 9 表示语料库里词汇表中一共有 9 个(不同的)词。例如,你可以看到在文档1中,并没有出现 and,所以矩阵第一行第一列的值为 0 。单词 first 只在文档1中出现过,所以第一行中 first 这个词的权重较高。而 document 和 this 在 3 个文档中出现过,所以它们的权重较低。而 the 在 4 个文档中出现过,所以它的权重最低。

最后需要说明的是,由于函数 TfidfVectorizer() 有很多参数,我们这里仅仅采用了默认的形式,所以输出的结果可能与采用前面介绍的(最基本最原始的)算法所得出之结果有所差异(但数量的大小关系并不会改变)。有兴趣的读者可以参考这里来了解更多关于在Scikit-Learn中执行 TF-IDF 算法的细节。

总结

以上就是本文关于TF-IDF算法解析与Python实现方法详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

Python自然语言处理之词干,词形与最大匹配算法代码详解

Python编程实现蚁群算法详解

Python算法输出1-9数组形成的结果为100的所有运算式

如有不足之处,欢迎留言指出。

记者问一个大爷:大爷,您保持亮丽的秘诀是什么?
大爷说:白天敲代码,晚上撸系统,姿势不要动,眼动手动就可以。
记者:啊?大爷您是做什么工作的?
大爷:敲代码的呀。
记者:那大爷您是本身就很喜欢光头的吗?
大爷:掉光的~

查看图片

--结束END--

本文标题: TF-IDF算法解析与Python实现方法详解

本文链接: https://www.lsjlt.com/news/16047.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • TF-IDF理解及其Java实现的示例分析
    这篇文章将为大家详细讲解有关TF-IDF理解及其Java实现的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。TF-IDF前言前段时间,又具体看了自己以前整理的TF-IDF,这里把它发布在博客上,知...
    99+
    2023-05-30
    tf-idf算法 java
  • Python使用tf-idf算法计算文档关键字权重并生成词云的方法
    Python 使用tf-idf算法计算文档关键字权重,并生成词云 1. 根据tf-idf计算一个文档的关键词或者短语: 代码如下: 注意需要安装pip install sklean...
    99+
    2023-03-19
    Python tf-idf算法计算关键字权重并生成词云 Python生成词云 Python tf-idf算法关键字权重
  • 详解python实现邮件解析的方法
    目录前言一、安装二、代码实现1.邮件头2.邮件正文3.邮件附件总结前言 如何通过python实现邮件解析?邮件的格式十分复杂,主要是mime协议,本文主要是从实现出发,具体原理可以自...
    99+
    2024-04-02
  • Python实现KPM算法详解
    目录知识点说明:一、要获取KPM算法的next[]数组二、KMP函数知识点说明: 先说前缀,和后缀吧 比如有一个串:abab 则在下标为3处的(前缀和后缀都要比下标出的长度小1,此处...
    99+
    2024-04-02
  • Java贪心算法之Prime算法原理与实现方法详解
    本文实例讲述了Java贪心算法之Prime算法原理与实现方法。分享给大家供大家参考,具体如下:Prime算法:是一种穷举查找算法来从一个连通图中构造一棵最小生成树。利用始终找到与当前树中节点权重最小的边,找到节点,加到最小生成树的节点集合中...
    99+
    2023-05-31
    java 贪心算法 prime算法
  • Python数据结构与算法之算法分析详解
    目录0. 学习目标1. 算法的设计要求1.1 算法评价的标准1.2 算法选择的原则2. 算法效率分析2.1 大O表示法2.2 常见算法复杂度2.3 复杂度对比3. 算法的存储空间需求...
    99+
    2024-04-02
  • 详解Python AdaBoost算法的实现
    目录1. AdaBoost 算法简介2. AdaBoost算法 逻辑详解2.1 数据2.2 带权错误率2.3 损失函数 与 确定样本权重2.4 确定模型权重2.5 输出模型3.Ada...
    99+
    2024-04-02
  • Python实现解析参数的三种方法详解
    目录先决条件使用 argparse使用 JSON 文件使用 YAML 文件最后的想法今天我们分享的主要目的就是通过在 Python 中使用命令行和配置文件来提高代码的效率 Let&#...
    99+
    2024-04-02
  • 详解Java中KMP算法的图解与实现
    目录图解代码实现图解 kmp算法跟之前讲的bm算法思想有一定的相似性。之前提到过,bm算法中有个好后缀的概念,而在kmp中有个好前缀的概念,什么是好前缀,我们先来看下面这个例子。 ...
    99+
    2024-04-02
  • 超详细解析C++实现快速排序算法的方法
    目录一、前言1.分治算法2.分治算法解题方法二、快速排序1.问题分析2.算法设计3.算法分析三、AC代码一、前言 1.分治算法 快速排序,其实是一种分治算法,那么在了解快速排序之前,...
    99+
    2024-04-02
  • C#算法设计与分析详解
    目录1. 什么是科学方法??1.观察2.将问题规模和运行时间的关系量化2.数学模型近似近似运行时间成本模型总结3. 增长数量级的分类4. 倍率实验5.注意事项6. 处理对于输入的依赖...
    99+
    2024-04-02
  • Python实现线性搜索算法详解
    线性搜索是最简单的搜索算法,从数据集的开头开始,检查每一项数据,直到找到匹配项,一旦找到目标,搜索结束。 线性搜索算法的缺点 需要注意的是线性搜索算法尽管简单,但不适用数据大的情况,由于算法将每个数据一一比较,所以数据越多,耗时越...
    99+
    2024-01-23
    算法的概念
  • Python实现聚类K-means算法详解
    目录手动实现sklearn库中的KMeansK-means(K均值)算法是最简单的一种聚类算法,它期望最小化平方误差 注:为避免运行时间过长,通常设置一个最大运行轮数或最小调整幅度...
    99+
    2024-04-02
  • java数据结构与算法之桶排序实现方法详解
    本文实例讲述了java数据结构与算法之桶排序实现方法。分享给大家供大家参考,具体如下:基本思想:假定输入是由一个随机过程产生的[0, M)区间上均匀分布的实数。将区间[0, M)划分为n个大小相等的子区间(桶),将n个输入元素分配到这些桶中...
    99+
    2023-05-31
    java 数据结构 算法
  • python列表与列表算法详解
    目录1. 序列类型定义2. 列表的基础知识2.1 列表定义2.2 列表基本操作总结1. 序列类型定义 序列是具有先后关系的一组元素 序列是一维元素向量,元素类型可以不同 ...
    99+
    2024-04-02
  • Python实现印章代码的算法解析
    目录1.题目2.代码3.代码解析1.题目 2.代码 #共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。 n,m=map(int,input(...
    99+
    2024-04-02
  • php实现归并排序算法的方法详解
    目录php实现归并排序算法归并排序原理总结php实现归并排序算法 归并排序算法的复杂度是O(nlogn)。 代码如下,只需要clone下来执行composer install然后执行...
    99+
    2024-04-02
  • Vue计算属性与监视属性实现方法详解
    目录一、计算属性1、插值语法实现2、通过方法实现3、通过计算属性二、监视属性三、深度监视一、计算属性 在开发中,可以有这样的需求,在属性(date)中,有fistName和lastN...
    99+
    2024-04-02
  • 解析Ford-Fulkerson算法并通过Python实现
    Ford-Fulkerson算法是贪心算法,用于计算网络中的最大流量。其原理是找到剩余容量为正的增广路径,只要找到增广路径,就可以继续增加路径和计算流量。直到增广路径不再存在,这时就能得出最大流量。 Ford-Fulkerson算...
    99+
    2024-01-23
    贪心算法
  • Go语言实现JSON解析的方法详解
    目录1、json序列化2、Json反序列化为结构体对象3、Json反序列化为map类型4、Tag的使用在日常项目中,使用Json格式进行数据封装是比较常见的操作,看一下golang怎...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作