Logo

郎哥编程

TF-IDF模型与生成算法

2022-03-07 368

TF就是词频,即一个词在文档中出现的次数。若同一个词在两个文档中出现频率都很高时,一般会认为该词与两个文档有很强的相关性,可以提取该词作为两个文档的关键词,两个文档也具有较高的相似度。

使用词频作为文档关键字的提取或相似度分析方法,会存在一个高频词的问题。虽然在分词阶段过滤掉了语气助词、副词、介词、连词等一些无意义的词,但一些在文档中有意义的高频词不能过滤,如喜欢、朋友、很多、工作、时间等等,这些高频词在不同文档中词频会很高,但与文档内容的相关性并不强,不能作为文档的关键词,更不能作为判断两个文档相似度的依据。

相对高频词来说,在文档中出现的一些不常用的低频词若词频比较高,那么它很可能与文档内容的相关性很强,让这些词作为文档的关键词和判断文档相似度的依据,效果会比较理想。例如篮球、当归等低频词,若篮球在一篇文档中出现频率很高,这篇文档很大几率与篮球有关,可以把篮球作为该篇文档的一个关键词,若篮球在两篇文档中出现词频都很高,说明这两篇文档都与篮球相关,有较高的内容相似度。

在这种情况下,需要强调这个低频词的重要性。在词频的基础上,再对每个词分配一个权重系数,若某个词比较少见,但是它在这篇文章中多次出现,就增加该词的权重系数值,若某个词在多篇文档中出现的频率都比较高,就降低该词的权重系数值。这个权重系数就称为“逆文档频率”(Inverse Document Frequency,缩写为IDF),它的大小与一个词的常见程度成反比。

下面给出IDF的计算公式:

05.png

从公式中可以看出,若一个词在多个文档中的词频都很高,其分母值就越大,逆文档频率就越小,分母加1是为了避免分母为零(即所有文档都不包含该词)。

log是对比值进行对数转换,主要是缩小数据的绝对值,方便计算。

下面给出IF的计算公式:

06.png

TF-IDF计算公式:

07.png

 

从TF-IDF计算公式可以看出,TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语料库中的出现次数成反比。

在项目根目录下建立models目录,在models目录下建立tifmodel.py模块文件,代码如下:

"""
模块:IF_IDF模型
功能:
建立IF_IDF数据
"""
import math
 
class TifModel():
    def __init__(self, corpus,wordnum):
        self.corpus = corpus
        self.wordnum = wordnum
    # 输出IF-IDF模型数据
    def toTfIdfMode(self):
        tfmodes = []
        # 文档总数
        self.docnum = len(self.corpus)
        # 遍历文档
        for text in self.corpus:
            tfmode = []
            # 遍历单词
            for word in text:
                if word[1] != 0:
                    idf = self.getTF_IDF(word[0],word[1])
                    tfmode.append((word[0],idf))
                else:
                    tfmode.append((word[0],0))
            tfmodes.append(tfmode)
        return tfmodes
    #  计算TF-IDF
    def getTF_IDF(self,word,count):
        idf = (count/self.wordnum) * math.log10(self.docnum / (self.getWordInDoc(word)+1))
        return idf
    
    #  计算包含单词的文档数量
    def getWordInDoc(self,word):
        count = 0
        # 遍历文档
        for text in self.corpus:
            if(text[word][1] > 0 ):
                count += 1
        return count

该模块传入词袋数据,计算词袋内所有词的TF-IDF值,将词频项替换为TF-IDF值,并返回处理后的词袋数据。

支持TF-IDF模型数据的测试程序代码:

# 相似性分析测试程序
 
#导入db模块#
from db import readnews
#导入路径模块
from tool import participle as fc
# 导入csv模块
import csv
#导入路径模块
import tool.filepath as path
#导入字典模块
from corpora.dictionary import Dictionary
#导入分析模块
from similarities.similarity import Similarity
#导入IF_IDF模型模块
from models.tifmodel import TifModel
#导入时间模块
import datetime
 
 
# 计算时间间隔
def get_time_differ(t1,t2):
   duringtime = t2 - t1
   return duringtime.total_seconds()
 
# 程序入口
if __name__ == '__main__':
    starttime = datetime.datetime.now()
    # 读取前100条语料数据
    t1 = datetime.datetime.now()
    data = readnews.query_database_record_limit(0,6)
    t2 = datetime.datetime.now()
    runsecond = get_time_differ(t1,t2)
    print("从读取数据库100条新闻条目,耗时:%.3f秒" % (runsecond))
 
    if data == None:
       print("数据库读取发生错误")
    else:
        texts = []
        t1 = datetime.datetime.now()
         # 中文分词
        for  text in  data:
            words = fc.get_particlple(text[1])
            texts.append(words)
        t2 = datetime.datetime.now()
        runsecond = get_time_differ(t1,t2)
        print("中文分词,耗时:%.3f秒" % (runsecond))
 
         # 创建字典
        dictionary = Dictionary()
        t1 = datetime.datetime.now()
        # 添加文档到字典
        dictionary.add_documents(texts)
        t2 = datetime.datetime.now()
        runsecond = get_time_differ(t1,t2)
        print("建立字典,耗时:%.3f秒" % (runsecond))
        # 提取第1条语料数据进行相似性分析
        textwords = texts[3]
        t1 = datetime.datetime.now()
        simttext =  dictionary.update_doc2bow(textwords)
        # 从字典读取词袋数据
        croups = dictionary.new_doc2bow(texts)
        tfMode = TifModel(croups,dictionary.num_pos)
        tfmodedata = tfMode.toTfIdfMode()
        t2 = datetime.datetime.now()
        runsecond = get_time_differ(t1,t2)
        print("转换词袋数据,耗时:%.3f秒" % (runsecond))
        # 初始化相似性分析类
        # docsim = Similarity(croups)
        docsim = Similarity(tfmodedata)
        #  采用文档逐一分析方式
        t1 = datetime.datetime.now()
        sim = docsim.matrix_analysis(simttext)
        # sim = docsim.one_analysis(simttext)
        t2 = datetime.datetime.now()
        runsecond = get_time_differ(t1,t2)
        print("相似性分析,耗时:%.3f秒" % (runsecond))
        print(sim)
        endtime = datetime.datetime.now()
        runsecond = get_time_differ(starttime,endtime)
        print("总耗时:%.3f秒" % (runsecond))

程序运行结果如下图所示:

08.png

从输出结果可以看出,在相同测试数据的情况下,使用IF-IDF模型耗费时间为3.606秒,比不使用IF-IDF模型增加了0.6秒。


代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论