当前位置: 首页 > article >正文

【自然语言处理】TextRank 算法提取关键词(Python实现)

文章目录

  • 前言
  • PageRank 实现
  • TextRank 简单版源码实现
  • jieba工具包实现TextRank


前言

  TextRank 算法是一种基于图的排序算法,主要用于文本处理中的关键词提取和文本摘要。它基于图中节点之间的关系来评估节点的重要性,类似于 Google 的 PageRank 算法。TextRank 算法的关键思想是,一个词语在文本中的重要性可以通过与其他词语的关系来评估,而这些关系可以表示为图中的边。
  图构建(Graph Construction): 将文本中的词语或短语表示为图的节点,词语之间的关系可以是共现关系、语义相似度等。通常,可以使用共现矩阵或者基于词向量的相似度来构建图。
边权重计算(Edge Weighting): 计算图中边的权重,反映节点之间的关系强度。例如,可以使用共现词频、词向量相似度等作为边的权重。
  节点权重计算(Node Weighting): 利用图中节点之间的关系以及边的权重来计算节点的权重。通常采用迭代方法,类似于 PageRank 算法,根据节点之间的相互影响来计算节点的权重。
  排名(Ranking): 根据节点的权重对节点进行排名,排名较高的节点被认为是重要的词语或短语。
  TextRank 算法的节点得分更新公式:

PageRank 实现

初始化时,每个网页的重要性为 1。

我们可以用一个矩阵来表示图中 a、b、e、f 之间的入站和出站链接。

一行中的每个节点表示来自其他节点的入站链接。例如,对于 e 行,节点 a 和 b 具有指向节点 e 的出站链接。本演示文稿将简化更新权重的计算。

根据 1/|out(vi)|​,从函数中,我们应该规范化每一列。

我们使用这个矩阵乘以所有节点的权重。这只是一次没有阻尼系数 d 的迭代。 我们可以使用 Python 进行多次迭代。
import numpy as np
g = [[0, 0, 0, 0],
     [0, 0, 0, 0],
     [1, 0.5, 0, 0],
     [0, 0.5, 0, 0]]
     
g = np.array(g)
pr = np.array([1, 1, 1, 1]) # initialization for a, b, e, f is 1
d = 0.85

for iter in range(10):
    pr = 0.15 + 0.85 * np.dot(g, pr)
    print(iter)
    print(pr)

0
[0.15 0.15 1.425 0.575]
1
[0.15 0.15 0.34125 0.21375]
2
[0.15 0.15 0.34125 0.21375]
3
[0.15 0.15 0.34125 0.21375]
4
[0.15 0.15 0.34125 0.21375]
5
[0.15 0.15 0.34125 0.21375]
6
[0.15 0.15 0.34125 0.21375]
7
[0.15 0.15 0.34125 0.21375]
8
[0.15 0.15 0.34125 0.21375]
9
[0.15 0.15 0.34125 0.21375]
10
[0.15 0.15 0.34125 0.21375]

所以 e 的权重(PageRank值)为 0.34125。

如果我们把有向边变成无向边,我们就可以相应地改变矩阵。

规范化。

我们应该相应地更改代码。

import numpy as np
g = [[0, 0, 0.5, 0],
     [0, 0, 0.5, 1],
     [1, 0.5, 0, 0],
     [0, 0.5, 0, 0]]
     
g = np.array(g)
pr = np.array([1, 1, 1, 1]) # initialization for a, b, e, f is 1
d = 0.85

for iter in range(10):
    pr = 0.15 + 0.85 * np.dot(g, pr)
    print(iter)
    print(pr)

0
[0.575 1.425 1.425 0.575]
1
[0.755625 1.244375 1.244375 0.755625]
2
[0.67885937 1.32114062 1.32114062 0.67885937]
3
[0.71148477 1.28851523 1.28851523 0.71148477]
4
[0.69761897 1.30238103 1.30238103 0.69761897]
5
[0.70351194 1.29648806 1.29648806 0.70351194]
6
[0.70100743 1.29899257 1.29899257 0.70100743]
7
[0.70207184 1.29792816 1.29792816 0.70207184]
8
[0.70161947 1.29838053 1.29838053 0.70161947]
9
[0.70181173 1.29818827 1.29818827 0.70181173]

所以 e 的权重(PageRank值)为 1.29818827。

TextRank 简单版源码实现

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu(余登武)
# @Date  : 2025/2/06
#@email:1344732766@qq.com

import numpy as np
import jieba
import jieba.posseg as pseg #posseg是Python中的一个分词工具,它可以将文本切割成词语,并且为每个词语标注词性

class TextRank(object):
    def __init__(self, sentence, window, alpha, iternum):
        self.sentence = sentence #文本
        self.window = window#窗口大小
        self.alpha = alpha#权重
        self.edge_dict = {}  # 记录节点的边连接字典
        self.iternum = iternum  # 迭代次数

    # 对句子进行分词
    def cutSentence(self):
        #jieba.load_userdict('user_dict.txt')
        #tag_filter = ['a', 'd', 'n', 'v'] #a形容词,d副词,n名称, v动词
        tag_filter = ['ns', 'n', 'vn', 'v']#地名、名词、动名词、动词
        seg_result = pseg.cut(self.sentence)
        self.word_list = [s.word for s in seg_result if s.flag in tag_filter and len(s.word)>1]
        #print(self.word_list)#['年度', '中国', '爱心', '城市', '公益活动', '新闻', '发布会'...]

    # 根据窗口,构建每个节点的相邻节点,返回边的集合
    def createNodes(self):
        tmp_list = []
        word_list_len = len(self.word_list)
        for index, word in enumerate(self.word_list):
            if word not in self.edge_dict.keys():
                tmp_list.append(word)
                #针对当前word取出左右边界词  word:{左边界词1,左边界词2...右边界词1,右边界词2}
                tmp_set = set()#当前word的
                left = index - self.window + 1  # 窗口左边界
                right = index + self.window  # 窗口右边界
                if left < 0: left = 0
                if right >= word_list_len: right = word_list_len
                for i in range(left, right):#左闭右开
                    if i == index:
                        continue
                    tmp_set.add(self.word_list[i])
                self.edge_dict[word] = tmp_set #{word:{左边界词1,左边界词2...右边界词1,右边界词2}}

    # 根据边的相连关系,构建矩阵
    def createMatrix(self):
        #self.word_list=['年度', '中国', '爱心', '城市', '公益活动', '新闻', '发布会'...]
        self.matrix = np.zeros([len(set(self.word_list)), len(set(self.word_list))])

        self.word_index = {}  # 记录词的index
        self.index_dict = {}  # 记录节点index对应的词
        for i, v in enumerate(set(self.word_list)):
            self.word_index[v] = i#{词:索引}
            self.index_dict[i] = v #{索引:词}
        for key in self.edge_dict.keys():#edge_dict {word:{左边界词1,左边界词2...右边界词1,右边界词2}|
            for w in self.edge_dict[key]:
                self.matrix[self.word_index[key]][self.word_index[w]] = 1
                self.matrix[self.word_index[w]][self.word_index[key]] = 1
        # 归一化
        for j in range(self.matrix.shape[1]):#列
            sum = 0
            for i in range(self.matrix.shape[0]):#行
                sum += self.matrix[i][j]#一列的和
            for i in range(self.matrix.shape[0]):
                self.matrix[i][j] /= sum

    # 根据textrank公式计算权重
    def calPR(self):
        self.PR = np.ones([len(set(self.word_list)), 1])#每个词语重要性初始化为1
        for i in range(self.iternum):
            self.PR = (1 - self.alpha) + self.alpha * np.dot(self.matrix, self.PR)#重要性迭代更新

    # 输出词和相应的权重
    def printResult(self):
        word_pr = {}
        for i in range(len(self.PR)):
            #self.index_dict[i] 得到位置索引i对应的词
            word_pr[self.index_dict[i]] = self.PR[i][0] #{词:重要性}
            res = sorted(word_pr.items(), key=lambda x: x[1], reverse=True)[:5]#前5个单词
        print(res)






if __name__ == '__main__':
    text = '6月19日,《2012年度“中国爱心城市”公益活动新闻发布会》在京举行。' + \
           '中华社会救助基金会理事长许嘉璐到会讲话。基金会高级顾问朱发忠,全国老龄' + \
           '办副主任朱勇,民政部社会救助司助理巡视员周萍,中华社会救助基金会副理事长耿志远,' + \
           '重庆市民政局巡视员谭明政。晋江市人大常委会主任陈健倩,以及10余个省、市、自治区民政局' + \
           '领导及四十多家媒体参加了发布会。中华社会救助基金会秘书长时正新介绍本年度“中国爱心城' + \
           '市”公益活动将以“爱心城市宣传、孤老关爱救助项目及第二届中国爱心城市大会”为主要内容,重庆市' + \
           '、呼和浩特市、长沙市、太原市、蚌埠市、南昌市、汕头市、沧州市、晋江市及遵化市将会积极参加' + \
           '这一公益活动。中国雅虎副总编张银生和凤凰网城市频道总监赵耀分别以各自媒体优势介绍了活动' + \
           '的宣传方案。会上,中华社会救助基金会与“第二届中国爱心城市大会”承办方晋江市签约,许嘉璐理' + \
           '事长接受晋江市参与“百万孤老关爱行动”向国家重点扶贫地区捐赠的价值400万元的款物。晋江市人大' + \
           '常委会主任陈健倩介绍了大会的筹备情况。'

    tr = TextRank(text, 3, 0.85, 600)
    tr.cutSentence()
    tr.createNodes()
    tr.createMatrix()
    tr.calPR()
    tr.printResult()

jieba工具包实现TextRank

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu(余登武)
# @Date  : 2025/2/06
#@email:1344732766@qq.com


import jieba
import jieba.posseg as psg
from jieba import analyse

def textrank_extract(text, pos=False, keyword_num=5):
    textrank = analyse.textrank
    keywords = textrank(text, allowPOS=('ns', 'n', 'vn', 'v'),topK=keyword_num,withWeight=
                        False,)
    # 输出抽取出的关键词
    for keyword in keywords:
        print(keyword + "/ ", end='')
    print()
if __name__ == '__main__':
    text = '6月19日,《2012年度“中国爱心城市”公益活动新闻发布会》在京举行。' + \
           '中华社会救助基金会理事长许嘉璐到会讲话。基金会高级顾问朱发忠,全国老龄' + \
           '办副主任朱勇,民政部社会救助司助理巡视员周萍,中华社会救助基金会副理事长耿志远,' + \
           '重庆市民政局巡视员谭明政。晋江市人大常委会主任陈健倩,以及10余个省、市、自治区民政局' + \
           '领导及四十多家媒体参加了发布会。中华社会救助基金会秘书长时正新介绍本年度“中国爱心城' + \
           '市”公益活动将以“爱心城市宣传、孤老关爱救助项目及第二届中国爱心城市大会”为主要内容,重庆市' + \
           '、呼和浩特市、长沙市、太原市、蚌埠市、南昌市、汕头市、沧州市、晋江市及遵化市将会积极参加' + \
           '这一公益活动。中国雅虎副总编张银生和凤凰网城市频道总监赵耀分别以各自媒体优势介绍了活动' + \
           '的宣传方案。会上,中华社会救助基金会与“第二届中国爱心城市大会”承办方晋江市签约,许嘉璐理' + \
           '事长接受晋江市参与“百万孤老关爱行动”向国家重点扶贫地区捐赠的价值400万元的款物。晋江市人大' + \
           '常委会主任陈健倩介绍了大会的筹备情况。'

    print('TextRank模型结果:')
    textrank_extract(text)

在这里插入图片描述


http://www.kler.cn/a/535650.html

相关文章:

  • 电脑可以自己换显卡吗?怎么操作
  • 通过多层混合MTL结构提升股票市场预测的准确性,R²最高为0.98
  • 通过Python编写的中国象棋小游戏
  • 【梦想终会实现】Linux驱动学习5
  • 解析PHP文件路径相关常量
  • 【重生之学习C语言----杨辉三角篇】
  • Java面试题简答(整理)
  • gitlab个别服务无法启动可能原因
  • 图解BWT(Burrows-Wheeler Transform) 算法
  • [Java基础]函数式编程
  • java面试题高级_Java高级面试题整理(附答案)
  • 【C语言】指针运算与数 组关系:详细分析与实例讲解
  • CSS实现自适应的正方形
  • C++ 使用CURL开源库实现Http/Https的get/post请求进行字串和文件传输
  • 【Linux】25.进程信号(1)
  • GGML、GGUF、GPTQ 都是啥?
  • MySQL 主从复制原理及其工作过程
  • unity学习28:灯光light相关 类型type,模式mode等
  • Java面试常见问题总结
  • 【苍穹外卖 Day1】前后端搭建 Swagger导入接口文档
  • JVM为什么要指针压缩?为什么能指针压缩?原理是什么?
  • 【1】高并发导出场景下,服务器性能瓶颈优化
  • 3D图形学与可视化大屏:什么是片段着色器,有什么作用。
  • 保姆级教程Docker部署KRaft模式的Kafka官方镜像
  • Sentinel 断路器在Spring Cloud使用
  • 【AI编程】从实践出发,分享“儿童时钟学习”小程序的改版历程