自然语言处理:TF-IDF(基于python)

一、定义

TF-IDF(term frequency–inverse document frequency,词频-逆文档频率)是一种用于信息检索(information retrieval)与文本挖掘(text mining)的常用加权技术。

TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

TF-IDF的主要思想是:如果某个单词在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

二、不足之处

  1. 没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。
  2. 按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词。
  3. 传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。
  4. 传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类别间的分布情况。

三、算法

参考:https://www.capitalone.com/tech/machine-learning/understanding-tf-idf/

  • TF定义 可以有多种方法:
    • Number of times the word appears in a document (raw count).
    • Term frequency adjusted for the length of the document (raw count of occurences divided by number of words in the document).
    • Logarithmically scaled frequency (e.g. log(1 + raw count)).
    • Boolean frequency (e.g. 1 if the term occurs, or 0 if the term does not occur, in the document).
  • IDF定义
    i d f ( t o k e n , d o c u m e n t ) = l o g ( c o u n t ( d o c u m e n t ) c o u n t ( t o k e n , d o c u m e n t ) ) idf(token,document)=log(\frac{count(document)}{count(token,document)}) idf(token,document)=log(count(token,document)count(document))
  • 在sklearn中,其计算方法如下(平滑因子,增加区分度):
    i d f ( t o k e n , d o c u m e n t ) = l o g ( 1 + c o u n t ( d o c u m e n t ) 1 + c o u n t ( t o k e n , d o c u m e n t ) ) + 1 idf(token,document)=log(\frac{1+count(document)}{1+count(token,document)})+1 idf(token,document)=log(1+count(token,document)1+count(document))+1

四、变种

  • 通过对数函数避免 TF 线性增长
    • 很多人注意到 TF 的值在原始的定义中没有任何上限。虽然我们一般认为一个文档包含查询关键词多次相对来说表达了某种相关度,但这样的关系很难说是线性的。拿我们刚才举过的关于 “Car Insurance” 的例子来说,文档 A 可能包含 “Car” 这个词 100 次,而文档 B 可能包含 200 次,是不是说文档 B 的相关度就是文档 A 的 2 倍呢?其实,很多人意识到,超过了某个阈值之后,这个 TF 也就没那么有区分度了。
    • 用 Log,也就是对数函数,对 TF 进行变换,就是一个不让 TF 线性增长的技巧。具体来说,人们常常用 1+Log(TF) 这个值来代替原来的 TF 取值。在这样新的计算下,假设 “Car” 出现一次,新的值是 1,出现 100 次,新的值是 5.6,而出现 200 次,新的值是 6.3。很明显,这样的计算保持了一个平衡,既有区分度,但也不至于完全线性增长。
  • 标准化解决长文档、短文档问题
    • 经典的计算并没有考虑 “长文档” 和“短文档”的区别。一个文档 A 有 3,000 个单词,一个文档 B 有 250 个单词,很明显,即便 “Car” 在这两个文档中都同样出现过 20 次,也不能说这两个文档都同等相关。对 TF 进行 “标准化”(Normalization),特别是根据文档的最大 TF 值进行的标准化,成了另外一个比较常用的技巧。
  • 对数函数处理 IDF
    • 第三个常用的技巧,也是利用了对数函数进行变换的,是对 IDF 进行处理。相对于直接使用 IDF 来作为 “惩罚因素”,我们可以使用 N+1 然后除以 DF 作为一个新的 DF 的倒数,并且再在这个基础上通过一个对数变化。这里的 N 是所有文档的总数。这样做的好处就是,第一,使用了文档总数来做标准化,很类似上面提到的标准化的思路;第二,利用对数来达到非线性增长的目的。
  • 查询词及文档向量标准化
    • 还有一个重要的 TF-IDF 变种,则是对查询关键字向量,以及文档向量进行标准化,使得这些向量能够不受向量里有效元素多少的影响,也就是不同的文档可能有不同的长度。在线性代数里,可以把向量都标准化为一个单位向量的长度。这个时候再进行点积运算,就相当于在原来的向量上进行余弦相似度的运算。所以,另外一个角度利用这个规则就是直接在多数时候进行余弦相似度运算,以代替点积运算。

五、代码实现

5.1 数据

import jieba

corpus = ['PHP是最好的语言,我用PHP','Java才是最好的语言,我用Java','人生苦短我用Python,Python']
words_list = [list(jieba.cut(doc)) for doc in corpus]
words_list

在这里插入图片描述

vocab = set([word for words in words_list for word in words]) #set函数—集合,去除重复的项;使用了双重for循环
vocab

在这里插入图片描述

5.2 python实现

5.2.1 方案1
import math
from collections import Counter

tf={}
total_words = sum([len(w) for w in words_list])
words = [w for words in words_list for w in words] # 二维转一维
count = Counter(words)
for w in vocab:
    tf = count.get(w)/total_words # 某个词的数量/总词数
    idf = (math.log(len(corpus)/(1+sum([w in word for word in words_list]))))
    print(f'{w}: tf={tf}, idf={idf}, tf-idf={tf*idf}')

在这里插入图片描述

5.2.2 方案2
import math

# 定义一个函数用于计算单词在文档中的出现次数
def count_words(word, document):
    return document.count(word)

# 定义一个函数用于计算单词在所有文档中的出现次数
def count_documents(word, documents):
    return sum(1 for document in documents if word in document)

# 定义一个函数用于计算单词的TF-IDF值
def calculate_tf_idf(word, document, documents):
    tf = count_words(word, document) / len(document)
    idf = math.log(len(documents) / (1 + count_documents(word, documents)))
    return tf * idf

# 定义一个函数用于计算文档的TF-IDF向量
def calculate_tf_idf_vector(document, documents):
    tf_idf_vector = {}
    for word in set(document):
        tf_idf_vector[word] = calculate_tf_idf(word, document, documents)
    return tf_idf_vector

# 示例用法
'''documents = [
    ["apple", "banana", "orange"],
    ["orange", "peach", "grape"],
    ["banana", "pear", "peach"],
]'''
documents = words_list

tf_idf_vectors = []
for document in documents:
    tf_idf_vector = calculate_tf_idf_vector(document, documents)
    tf_idf_vectors.append(tf_idf_vector)

print(documents)
for result in tf_idf_vectors:
    print(result)

在这里插入图片描述

5.3 pandas

import numpy as np
import pandas as pd
df = pd.DataFrame(corpus,columns=['doc'])

df['words'] = df.doc.apply(jieba.lcut)
df1 = df.explode('words')
df1

在这里插入图片描述

df2=df1.groupby('words')['doc'].agg(['count','nunique']).reset_index()
print()
df2['tf'] = df2['count']/len(df1)
df2['idf'] = np.log(len(df)/(1+df2['nunique']))
df2['tfidf'] = df2.tf*df2.idf
df2

在这里插入图片描述

df1.drop_duplicates().merge(df2,on=['words'])

在这里插入图片描述

六、应用场景

  • 信息检索:在搜索引擎中,TF-IDF被用于确定搜索查询与文档的相关性。通过计算查询词语和文档中词语的TF-IDF得分,搜索引擎可以排名并返回与查询最相关的文档。
  • 文档分类:TF-IDF可用于将文档自动分类到不同的类别,如垃圾邮件过滤、新闻分类等。它可以帮助系统确定文档中的关键词,从而更好地进行分类。
  • 关键词提取:TF-IDF可用于自动提取文档中的关键词或短语,这在文档摘要、标签生成和信息摘取方面非常有用。
  • 文本摘要:在文档摘要生成中,TF-IDF可用于确定哪些句子或段落在文档中最重要,从而生成文档的摘要。
  • 推荐系统:在推荐系统中,TF-IDF可以用于评估用户对不同项的兴趣程度。它可以帮助推荐系统推荐与用户兴趣相关的内容。
  • 自然语言处理任务:TF-IDF在文本分类、情感分析、命名实体识别和其他自然语言处理任务中用于特征选择和特征加权。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值