TF-IDF 算法介绍

什么是TF-IDF算法?

TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术,常用于挖掘文章中的关键词,而且算法简单高效,常被工业用于最开始的文本数据清洗。

TF-IDF有两层意思:
  • TF:"词频"(Term Frequency)

  • IDF"逆文档频率"(Inverse Document Frequency)

TF-IDF应用

  • 搜索引擎
  • 关键词提取
  • 文本相似性
  • 文本摘要

TF-IDF算法步骤

第一步,计算词频:

img

第二步,计算逆文档频率:

这时,需要一个语料库(corpus),用来模拟语言的使用环境。

img

如果一个词越常见,那么分母就越大,逆文档频率就越小越接近0。分母之所以要加1,是为了避免分母为0(即所有文档都不包含该词)。log表示对得到的值取对数。

第三步,计算TF-IDF:

img

可以看到,TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比。

所以,自动提取关键词的算法就很清楚了,就是计算出文档的每个词的TF-IDF值,取最大的几个。

TF-IDF算法的不足

TF-IDF 采用文本逆频率 IDF 对 TF 值加权取权值大的作为关键词,但 IDF 的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以 TF-IDF 算法的精度并不是很高,尤其是当文本集已经分类的情况下。

在本质上 IDF 是一种试图抑制噪音的加权,并且单纯地认为文本频率小的单词就越重要,文本频率大的单词就越无用。这对于大部分文本信息,并不是完全正确的。

IDF 的简单结构并不能使提取的关键词,十分有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能。尤其是在同类语料库中,这一方法有很大弊端,往往一些同类文本的关键词被盖。

  • 没有考虑特征词的位置因素对文本的区分度,词条出现在文档的不同位置时,对区分度的贡献大小是不一样的。
  • 按照传统TF-IDF,往往一些生僻词的IDF(反文档频率)会比较高、因此这些生僻词常会被误认为是文档关键词
  • 传统TF-IDF中的IDF部分只考虑了特征词与它出现的文本数之间的关系,而忽略了特征项在一个类别中不同的类目间的分布情况。
  • 对于文档中出现次数较少的重要人名、地名信息提取效果不佳。

Python实现

import math
 
corpus = [
    "what is the weather like today",
    "what is for dinner tonight",
    "this is a question worth pondering",
    "it is a beautiful day today"
]
words = []
# 对corpus分词
for i in corpus:
    words.append(i.split())
 
 
# 如果有自定义的停用词典,我们可以用下列方法来分词并去掉停用词
# f = ["is", "the"]
# for i in corpus:
#     all_words = i.split()
#     new_words = []
#     for j in all_words:
#         if j not in f:
#             new_words.append(j)
#     words.append(new_words)
# print(words)
 
# 进行词频统计
def Counter(word_list):
    wordcount = []
    for i in word_list:
        count = {}
        for j in i:
            if not count.get(j):
                count.update({j: 1})
            elif count.get(j):
                count[j] += 1
        wordcount.append(count)
    return wordcount
 
 
wordcount = Counter(words)
 
 
# 计算TF(word代表被计算的单词,word_list是被计算单词所在文档分词后的字典)
def tf(word, word_list):
    return word_list.get(word) / sum(word_list.values())
 
 
# 统计含有该单词的句子数
def count_sentence(word, wordcount):
    return sum(1 for i in wordcount if i.get(word))
 
 
# 计算IDF
def idf(word, wordcount):
    return math.log(len(wordcount) / (count_sentence(word, wordcount) + 1))
 
 
# 计算TF-IDF
def tfidf(word, word_list, wordcount):
    return tf(word, word_list) * idf(word, wordcount)
 
 
p = 1
for i in wordcount:
    print("part:{}".format(p))
    p = p+1
    for j, k in i.items():
        print("word: {} ---- TF-IDF:{}".format(j, tfidf(j, i, wordcount)))
原文地址:https://www.cnblogs.com/aduner/p/13843244.html