自然语言处理之TF-IDF算法与TextRank算法的缠绵

        一、简介

        1.1 TD-IDF算法

        TD-IDF是一种统计方法,用于评估一个词在文档集或一个语料库中的重要程度。它的值越大,表示这个词在整个语料库中就越重要。TD-IDF算法由两部分组成:词频 (TF) 和逆文档频率 (IDF)。

        1.2 TextRank算法

        TextRank是由Google的PageRank算法启发而来的一种用于文本的无监督算法。它通过考虑文本中的词或句子的相互关系来评估其重要性。TextRank的主要思想是将文本看作是一个图结构,其中的节点是句子或词,边是它们之间的关系(如相似性)。然后,通过计算每个节点的“入度”(指向该节点的边的数量)和“出度”(从该节点出去的边的数量)来评估其重要性。

         二、TF-IDF算法和TextRank算法的应用场景

        TD-IDF:在信息检索、文档分类、关键词提取等场景中有着广泛的应用。例如,搜索引擎可以用TD-IDF算法来确定一个网页的主题。  

        TextRank:在文本摘要、关键词提取、文本聚类、文本分类等场景中有着广泛的应用。例如,可以用TextRank算法来自动生成文章的摘要。

         三、例子

        2.1 准备工作

        我是用的是pycharm社区版本,需要使用到如下python库,可以在解释器中下载,也可以在终端中使用pip命令下载。

import jieba
import jieba.posseg
import numpy as np
import pandas as pd
import math
import operator
import jieba.analyse
from pyecharts.charts import WordCloud
         2.2 TF-IDF算法
        2.2.1 获得停用词

        我们需要用到文档文本以及停用词表。我是用到的自己的文档文本和停用词表,由于我的文档文本以及停用词表数据较大,因此我就不便放出结果来看了。看你自己的实际需要来选择文档文本以及停用词表。还有一点需要说的是,不同操作系统下记事本的默认编码格式是不同的。例如,Win10系统下记事本英文默认为ansi(asc||)编码,中文默认为GBK编码,Win11系统的记事本默认为UTF-8编码,Linux系统的记事本默认也为UTF-8编码,所以encoding一定要搞清楚是什么编码,要不然会出现乱码(我的虽然是Win10系统但是文件是Win11系统发过来的文件,也可以用)。

# 获取停用词
def Stop_words():
    stopwords = []
    data = []
    f = open('D:\\wangye\\stopword.txt', encoding='utf8')
    for line in f.readlines():
        data.append(line)
    for i in data:
        output = str(i).replace('\n', '')
        stopwords.append(output)
    return stopwords
stopwords = Stop_words()
print('停用词表的大小为:', len(stopwords))

 

         2.2.2 对文档文本进行操作

        对文档文本进行过滤词性和停用词,将其变成一个只含有关键词的列表(再次提醒注意记事本的编码格式)。

# 加载文档集,对文档集过滤词性和停用词
def Filter_words(data_path, stopwords):
    documents = []
    for line in open(data_path, 'r', encoding='utf8'):
        segment = jieba.posseg.cut(line.strip())
        filter_words = []
        for word, flag in segment:
            if flag.startswith('n') is False:
                continue
            if word not in stopwords and len(word) > 1:
                filter_words.append(word)
        documents.append(filter_words)
    return documents
data_path = 'D:\\wangye\\corpus4keyword.txt'
documents = Filter_words(data_path, stopwords)
print('文档的数量为', len(documents))
         2.2.3 计算TF以及IDF
# TF-IDF 算法
def tf(filter_sent):
    # 统计TF值
    tf_dict = {}
    for word in filter_sent:
        if word not in tf_dict:
            tf_dict[word] = 1
        else:
            tf_dict[word] += 1
    for word in tf_dict:
        tf_dict[word] = tf_dict[word] / len(filter_sent)
    return tf_dict
def idf(documents):
    # 统计IDF值
    idf_dict = {}
    for doc in documents:
        for word in set(doc):
            if word not in idf_dict:
                idf_dict[word] = 1
            else:
                idf_dict[word] += 1
    return idf_dict
        2.2.4 计算总值并做可视化

        这里我是选取了前topK个词频最高的关键词以及某个编号的文档关键词做了个可视化(生成了一个html文件,运行了程序之后在你程序同级目录下会出现一个名为index1.html的文件,可以直接打开运行),因为我的文档较多,因此选取了一个,如果你文档较少可以适当修改。

def tf_idf(documents):
    temp_list = []
    # 计算TF-IDF值
    idf_dict = idf(documents)
    print('idf词典中词的个数为:', len(idf_dict))
    for filter_sent in documents:
        tf_idf_dict = {}
        tf_dict = tf(filter_sent)
        for word in tf_dict:
            tf_idf_dict[word] = tf_dict[word] * math.log(len(documents) / (idf_dict[word]))
        # 提取前10个关键词
        topk = 10
        sort_kwords=sorted(tf_idf_dict.items(), key=operator.itemgetter(1),reverse=True)
        kword_list=[kword for kword,value in sort_kwords[:topk]]
        print('TF-IDF模型结果:','/ '.join(kword_list))
        if filter_sent == documents[23]:
             temp_list = sort_kwords[:topk]
    return temp_list
mine_list = tf_idf(documents)
mywordcloud = WordCloud()
mywordcloud.add('',mine_list,shape='circle')
mywordcloud.render('index1.html')
        2.2.5 可视化结果 

        2.3 TextRank算法 

        2.3.1 分词

        TextRank算法使用jieba库中的analyst模块完成。我这是选取了一些名词的词频来作为分词限制,并选取词频最高的topK个关键词,并将他们的权重也记录下来。事实上你可以选择其他一些词性来设置allowPOS的值(具体请参考ICTCLAS汉语词性标注集)。

#TextRank算法
text ="2008年8月的一个清晨,A市女子某医院大院的水淹地里,一个熟睡的女婴被人发现。出生仅两天的她被父母遗弃,因为她患有先天性法式四联症,心脏动脉导管未闭,大动脉异常。随后女婴被福利院收养坚强的她安静地等待着希望的出现。2012年1月,萍萍来到北京进行治疗。2012年3月23日,在思源焦点公益基金的资助下,萍萍在医院进行了近10小时的高强度手术。虽然手术是成功的,但术后萍萍并没有完全摆脱危险,她的心脏只能借助体外循环才能跳动。目前,坚强的萍萍仍在重症病房接受监护。"
keywords= jieba.analyse.extract_tags(
    sentence=text,
    topK=10,
    allowPOS=('n','ns','nr','nt','nz'),
    withWeight=True)
print(keywords)
for keyword,weight in keywords:
    print(keyword,weight)
        2.3.2 可视化结果

          四、TF-IDF算法和TextRank算法的优劣 

        TD-IDF:

优点:

1、算法简单,易于理解和实现。

2、能够有效提取文档中的关键词,对文档进行有效的特征表述。

3、在信息检索、文本分类等任务中表现出良好的效果。

缺点:

1、无法处理一词多义的情况。

2、无法发现词语之间的关联关系。

3、对于低频词,其IDF会变小,可能导致一些重要的低频词被忽略。

4、主要依赖词频,对词序和上下文信息考虑不足。

        TextRank:

优点:

1、可以处理一词多义的情况。

2、能够发现词语之间的关联关系。

3、适用于文本摘要和关键词提取。

4、无监督方式,无需构造数据集训练。

5、继承了PageRank的思想,效果相对较好,相对于TF-IDF方法,可以更充分的利用文本元素之间的关系。

缺点:

1、计算复杂度较高,对硬件资源要求较高。

2、对于长文本的处理效果可能不理想。

3、结果受分词、文本清洗影响较大,即对于某些停用词的保留与否,直接影响最终结果。

4、虽然与TF-IDF比,不止利用了词频,但是仍然受高频词的影响,因此需要结合词性和词频进行筛选,以达到更好效果,但词性标注显然又是一个问题。

          五、结语

        综上所述,TD-IDF和TextRank各具优势,适用于不同的应用场景。在需要简单快捷且对准确率要求不是特别高的场景下,可以选择使用TD-IDF;而在需要更深入理解文本内容、处理一词多义或词语关联、进行文本摘要和关键词提取等情况下,使用TextRank可能会更有优势。同时,这两种方法都有其局限性,实际使用时可能需要结合其他的特征提取或机器学习方法以获得更好的效果。