TF-IDF、TextRank关键字抽取排序算法

本文介绍了两种无监督的关键字抽取算法:TF-IDF和TextRank。TF-IDF通过词频和逆文档频率计算关键词的重要性,而TextRank则基于图的排序算法,适用于关键词提取和文章摘要生成。文中还提供了python实现的示例代码,并提到了jieba库对这两种算法的支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键字抽取算法

TF-IDF

TF-IDF称为词频逆文本,结果严重依赖文本分词之后的效果。其公式又可以分成词频(Term Frequency,TF)的计算和逆文档概率(IDF)的计算。

TF的计算较为简单,统计每个词出现的频次。计算公式如式1所示:
T F = 某个词在文档中出现的次数 该文档的总词数 TF=\frac{某个词在文档中出现的次数}{该文档的总词数} TF=该文档的总词数某个词在文档中出现的次数
这里需要注意的是,该词的词频仅仅是计算在单一文档的词频,而不是所有文档出现的词频。也就是说每个词在不同的文档中出现的词频可能是不一样的。

IDF的计算稍显复杂,统计该词在所有文档出现的次数。也就是说如果该词仅在少数领域文档中出现,那么该词就在该领域更具有代表性,更可能是关键词。计算公式如式2所示:
I D F = l o g ( 语料库的文档总数 存在该词的文档数 + 1 ) IDF=log(\frac{语料库的文档总数}{存在该词的文档数+1}) IDF=log(存在该词的文档数+1语料库的文档总数)
TF-IDF的计算也就是两者的乘积,具体如下式3所示:
T F − I D F = T F ∗ I D F TF-IDF=TF*IDF TFIDF=TFIDF
jieba中竟然实现了TF-IDF关键字抽取,使用如下:

import sys
import jieba
import jieba.analyse
import argparse
def parser_args():
    parser = argparse.ArgumentParser(description='parse input information')
    parser.add_argument('--filename', default='./data/files.txt', type=str)
    parser.add_argument('--top_k', default=5, type=int)
    args = parser.parse_args()
    return args
args = parser_args()
content = open(args.filename, 'rb').read()
jieba.analyse.set_idf_path("./data/idf.txt.big.txt")
tags = jieba.analyse.extract_tags(content, topK=args.top_k)
print(",".join(tags))

另外自己实现了一份源码,

import jieba
import math
def read_file(filepath):
    with open(filepath, 'r', encoding='utf-8') as file:
        lines = file.readlines()
    return lines
def load_stop_word(filepath):
    with open(filepath, 'r', encoding='utf-8') as file:
        data = file.readlines()
    stop_words = set()
    for word in data:
        stop_words.add(word.strip())
    return list(stop_words)
def segment_line(line, stop_words):
    # start paddle segment
    jieba.enable_paddle()
    words_list = jieba.cut(line.strip(), use_paddle=True)
    results = []
    for word in words_list:
        if word not in stop_words:
            results.append(word)
    return results
def cal_term_frequency(lines_results):
    lines_tf = []
    for line_result in lines_results:
        temp_tf = {}
        for word in line_result:
            if word in temp_tf.keys():
                temp_tf[word] += 1
            else:
                temp_tf[word] = 1
        lines_tf.append(temp_tf)
    return lines_tf
def cal_idf(lines_tf):
    idf = {}
    for line_tf in lines_tf:
        for word in line_tf.keys():
            if word not in idf.keys():
                idf[word] = 1
            else:
                idf[word] += 1
    return idf
def cal_tf_idf(lines_tf, idf):
    lines_tf_idf = []
    for line_tf in lines_tf:
        temp_tf_idf = {}
        for word, tf in line_tf.items():
            temp_tf_idf[word] = tf * math.log(len(lines_tf) / (idf[word] + 1))
        lines_tf_idf.append(temp_tf_idf)
    return lines_tf_idf

TextRank

TextRank是一种基于图的排序算法,其思想来自于PageRank算法。TextRank算法有一篇较为经典的老论文( TextRank: Bringing Order into Texts),值得一读。

PageRank算法

PageRank最重要的也就是考虑了网络节点的出度(在有向图上),相对于其他的Rank算法。当然,PageRank也可以用于无向图,这就导致节点的出度等于入度,效果可能会稍微差点。其计算公式如下式4所示。
S ( V i ) = ( 1 − d ) + d ∗ ∑ j ∈ I n ( V i ) 1 ∣ O u t ( V j ) ∣ S ( V j ) S(V_i)=(1-d)+d*\sum_{j\in{In(V_i)}}\frac{1}{|Out(V_j)|}S(V_j) S(Vi)=(1d)+djIn(Vi)Out(Vj)1S(Vj)
其中各个参数含义如下:

S ( V i ) S(V_i) S(Vi):网页 V i V_i Vi的重要度(权重),初始值默认为1。

d d d:阻尼系数,一般为0.85,也就是看当前节点改变的自身的状态权重。

I n ( V i ) In(V_i) In(Vi):能跳转到网页 V i V_i Vi的页面,在图中对应入度对应的点。

O u t ( V j ) Out(V_j) Out(Vj):网页 V j V_j Vj能够跳转到的页面,在图中对应的出度的点。

TextRank关键字提取

提取关键词也可以采取和“网页中选哪个网页比较重要”类似的方法,只需要想办法把图构建出来。图的结点是“词”。把文章拆成句子,每个句子再拆成词,以词为结点。那么边如何定义呢?这里就可以利用n-gram的思路,简单来说,某个词,只与它附近的n个词有关,即与它附近的n个词对应的结点连一条无向边(两个有向边)。另外,还可以做一些操作,比如把某类词性的词删掉,一些自定义词删掉,只保留一部分单词,只有这些词之间能够连边。也就是TextRank的计算方法如下式5所示。
W S ( V i ) = ( 1 − d ) + d ∗ ∑ V j ∈ I n ( V i ) w j i ∑ V k ∈ O u t ( V j ) W S ( V j ) WS(V_i)=(1-d)+d*\sum_{V_j \in{In(V_i)}}\frac{w_{ji}}{\sum_{V_k\in{Out(V_j)}}}WS(V_j) WS(Vi)=(1d)+dVjIn(Vi)VkOut(Vj)wjiWS(Vj)

TextRank文章摘要提取

TextRank也可以用来提取文章摘要,以句子为节点,利用两个句子之间的相似度来计算边。两个句子的相似度如式5所示:
S i m i l a r i t y ( S i , S j ) = ∣ { w k ∣ w k ∈ S i & w k ∈ S j } ∣ l o g ( ∣ S i ∣ ) + l o g ( ∣ S j ∣ ) Similarity(S_i,S_j)=\frac{|\{w_k|w_k\in{S_i} \& w_k\in{S_j}\}|}{log(|S_i|)+log(|S_j|)} Similarity(Si,Sj)=log(Si)+log(Sj){wkwkSi&wkSj}
这个相似度也可以使用其他的计算方法,如word embedding来表示句子,来计算余弦相似度等。

python中已经实现TextRank实现的封装:

import codecs
from textrank4zh import TextRank4Keyword, TextRank4Sentence
text = codecs.open('./text/01.txt', 'r', 'utf-8').read()
tr4w = TextRank4Keyword(stop_words_file='./stopword.data')  # 导入停止词
# 使用词性过滤,文本小写,窗口为2
tr4w.train(text=text, speech_tag_filter=True, lower=True, window=2)  
print('关键词:')
# 20个关键词且每个的长度最小为1
print('/'.join(tr4w.get_keywords(20, word_min_len=1)) ) 
print('关键短语:')
# 20个关键词去构造短语,短语在原文本中出现次数最少为2
print('/'.join(tr4w.get_keyphrases(keywords_num=20, min_occur_num= 2)))  
tr4s = TextRank4Sentence(stop_words_file='./stopword.data')
# 使用词性过滤,文本小写,使用words_all_filters生成句子之间的相似性
tr4s.train(text=text, speech_tag_filter=True, lower=True, source = 'all_filters')
print('摘要:')
print('\n'.join(tr4s.get_key_sentences(num=3))) # 重要性最高的三个句子

甚至在jieba中提供TextRank的接口,可以实现关键字抽取。

import jieba.analyse
import argparse
def parser_args():
    parser = argparse.ArgumentParser(description='parse input information')
    parser.add_argument('--filename', default='./data/files.txt', type=str)
    parser.add_argument('--top_k', default=5, type=int)
    args = parser.parse_args()
    return args
args = parser_args()
content = open(args.filename, 'rb').read()
tags = jieba.analyse.textrank(content, topK=args.top_k, allowPOS=('n', 'nz', 'v', 'vd', 'vn', 'l', 'a', 'd'))
print(",".join(tags))

总结

这是常用的一些无监督的关键字抽取算法,主要可以用在推荐系统中,给用户按照关键字信息进行推荐,目前可能也有一些基于Transformer的关键字抽取,抽取的效果可能更佳准确,下周将对其进行扩展。

Reference

[1] TextRank系列之关键词提取算法_北木.的博客-CSDN博客_textrank英文关键词提取

[2] TextRank_coco_1998_2的博客-CSDN博客_textrank

[3] NLP中关键字提取方法总结和概述 - 知乎 (zhihu.com)

[4] Mihalcea R , Tarau P . TextRank: Bringing Order into Texts[J]. 2004.

[5] TextRank算法详细讲解与代码实现(完整) - 方格田 - 博客园 (cnblogs.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Trouble..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值