当前位置:   article > 正文

TextRank系列之文本自动摘要提取_textrank得到每个节点的pr值后如何对新的句子进行抽取摘要

textrank得到每个节点的pr值后如何对新的句子进行抽取摘要

前期回顾

TextRank系列之关键词提取算法


原文链接:文本自动摘要:基于TextRank的中文新闻摘要

用TextRank做单领域多文本的自动摘要的过程如下:
  • 把所有文章整合成文本数据,并把文本分割成单个句子;
  • 用WordAVG的方法,将每个句子中所有单词的词向量合并为句子的向量表示;
  • 计算句子向量间的相似性并存放在矩阵中,作为转移概率矩阵M;
  • 然后将转移概率矩阵转换为以句子为节点、相似性得分为边的图结构,用于句子TextRank计算;
  • 对句子按照TextRank值进行排序,排名最靠前的n个句子作为摘要。

好的,那下面我们就用TextRank算法,以及按照上面的流程,做一个新闻自动摘要的小案例。


基于TextRank的中文新闻摘要

参考了一篇用TextRank做英文新闻摘要的文章。

1、文章:《手把手|基于TextRank算法的文本摘要(附Python代码)》

2、github地址

文档的原网页:

实践的github

好,那就开始。

1. 整合文档,划分句子

首先把文档读入,放在列表中,可以看到,有些句子已经被划分出来了。

['信息量巨大!易会满首秀,直面科创板8大问题,对散户加速入场笑而不语……',

 '每日经济新闻',

 '02-2717:56',

 '每经编辑:郭鑫 王晓波',

 '图片来源:新华社记者 李鑫 摄',

 '易会满上任一个月,还没有在公开场合说过一句话。',

 '2月27日下午三点半开始,XX出席其首场新闻发布会,离发布会开始前两小时现场已经座无虚席,只等XX来到现场。此外,XX、XX等也共同出席。',
 ...]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

不过通过观察,我们可以发现存在两个问题:

一是以[。?!;]作为句子的分隔符,那么列表中的每个字符串元素中可能有多个句子;

二是每个字符串元素可能以[:,]结尾,也就是说可能是一个不完整的句子。

考虑到这只是一个小案例,所以就没花太多时间,仅仅处理一下第一个问题,把句子按照[。?!;]进行划分,如果字符串元素是不完整的句子,那也作为一句。

import numpy as np
import pandas as pd
import re,os,jieba
from itertools import chain
 
"""第一步:把文档划分成句子"""
 
# 文档所在的文件夹
c_root = os.getcwd()+os.sep+"cnews"+os.sep  
 
sentences_list = []
for file in os.listdir(c_root): 
    fp = open(c_root+file,'r',encoding="utf8")
    for line in fp.readlines():
        if line.strip():
            # 把元素按照[。!;?]进行分隔,得到句子。
            line_split = re.split(r'[。!;?]',line.strip())
            # [。!;?]这些符号也会划分出来,把它们去掉。
            line_split = [line.strip() for line in line_split if line.strip() not in ['。','!','?',';'] and len(line.strip())>1]
            sentences_list.append(line_split)
sentences_list = list(chain.from_iterable(sentences_list))
print("前10个句子为:\n")
print(sentences_list[:10])

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

前10个句子为:

['信息量巨大',

 '易会满首秀,直面科创板8大问题,对散户加速入场笑而不语……',

 '每日经济新闻',

 '02-2717:56', 
 '每经编辑:郭鑫 王晓波',

 '图片来源:新华社记者 李鑫 摄',

 '易会满上任一个月,还没有在公开场合说过一句话',

 '2月27日下午三点半开始,中XX出席其首场新闻发布会,离发布会开始前两小时现场已经座无虚席,只等XX来到现场',

 '此外,XX、XX等也共同出席',

 '这可能是这个月国内关注的人最多的一场新闻发布会了']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
2. 文本预处理

文本预处理包括去除停用词和非汉字字符,并进行分词。处理的过程要保证处理之后的句子的数量和处理之前的一样,因为后面我们计算了每个句子的textrank值之后,需要根据textrank值的大小,取出相应的句子作为摘要。

比如 ‘02-2717:56’ 这个句子整个被过滤了,那就令这个句子为[],下面也会给它一个句子的向量表示,只是元素都为0。

"""第二步:文本预处理,去除停用词和非汉字字符,并进行分词"""
 
#创建停用词列表
stopwords = [line.strip() for line in open('./stopwords.txt',encoding='UTF-8').readlines()]
 
# 对句子进行分词
def seg_depart(sentence):
    # 去掉非汉字字符
    sentence = re.sub(r'[^\u4e00-\u9fa5]+','',sentence)
    sentence_depart = jieba.cut(sentence.strip())
    word_list = []
    for word in sentence_depart:
        if word not in stopwords:
            word_list.append(word)   
    # 如果句子整个被过滤掉了,如:'02-2717:56'被过滤,那就返回[],保持句子的数量不变
    return word_list
 
sentence_word_list = []
for sentence in sentences_list:   
    line_seg = seg_depart(sentence)
    sentence_word_list.append(line_seg)
print("一共有",len(sentences_list),'个句子。\n')
print("前10个句子分词后的结果为:\n",sentence_word_list[:10])
 
# 保证处理后句子的数量不变,我们后面才好根据textrank值取出未处理之前的句子作为摘要。
if len(sentences_list) == len(sentence_word_list):
    print("\n数据预处理后句子的数量不变!")

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

一共有 347 个句子。

前10个句子分词后的结果为:

 [['信息量'], 
  ['易会', '满首秀', '直面', '科创板', '散户', '加速', '入场', '笑', '不语'], 
  ['每日', '经济', '新闻'], 
  [], 
  ['每经', '编辑', '郭鑫', '王晓波'], 
  ['图片', '来源', '李鑫', '摄'], 
  ['易会', '上任', '一个月', '公开场合', '说', '一句', '话'],...]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

数据预处理后句子的数量不变!

3. 加载word2vec词向量

从这里下载了金融新闻word2vec词向量:https://github.com/Embedding/Chinese-Word-Vectors

词向量是300维的,字和词语都有。我们把词向量加载进来,做成一个字典,共有467140个词语或字。

"""第三步:准备词向量"""
 
word_embeddings = {}
f = open('./sgns.financial.char', encoding='utf-8')
for line in f:
    # 把第一行的内容去掉
    if '467389 300\n' not in line:
        values = line.split()
        # 第一个元素是词语
        word = values[0]
        embedding = np.asarray(values[1:], dtype='float32')
        word_embeddings[word] = embedding
f.close()
print("一共有"+str(len(word_embeddings))+"个词语/字。")

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

一共有467140个词语/字。

4. 得到词语的embedding,用WordAVG作为句子的向量表示

WordAVG也就是先得到句子中的所有词语的词向量,然后求词向量的平均,作为该句子的向量表示。WordAVG可以用来计算句子的相似度。

"""第四步:得到词语的embedding,用WordAVG作为句子的向量表示"""
 
sentence_vectors = []
for i in sentence_word_list:
    if len(i)!=0:
        # 如果句子中的词语不在字典中,那就把embedding设为300维元素为0的向量。
        # 得到句子中全部词的词向量后,求平均值,得到句子的向量表示
        v = sum([word_embeddings.get(w, np.zeros((300,))) for w in i])/(len(i))
    else:
        # 如果句子为[],那么就向量表示为300维元素为0个向量。
        v = np.zeros((300,))
    sentence_vectors.append(v)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
5. 计算句子之间的余弦相似度,构成相似度矩阵
"""第五步:计算句子之间的余弦相似度,构成相似度矩阵"""
sim_mat = np.zeros([len(sentences_list), len(sentences_list)])
 
from sklearn.metrics.pairwise import cosine_similarity
 
for i in range(len(sentences_list)):
  for j in range(len(sentences_list)):
    if i != j:
      sim_mat[i][j] = cosine_similarity(sentence_vectors[i].reshape(1,300), sentence_vectors[j].reshape(1,300))[0,0]
print("句子相似度矩阵的形状为:",sim_mat.shape)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

句子相似度矩阵的形状为: (347, 347)

6. 迭代得到句子的textrank值,排序并取出摘要

以句子为节点、相似性得分为转移概率,构建图结构,然后迭代得到句子的TextRank分数。

对句子按照TextRank值进行降序排序,取出排名最靠前的10个句子作为摘要。

"""第六步:迭代得到句子的textrank值,排序并取出摘要"""
import networkx as nx
 
# 利用句子相似度矩阵构建图结构,句子为节点,句子相似度为转移概率
nx_graph = nx.from_numpy_array(sim_mat)
 
# 得到所有句子的textrank值
scores = nx.pagerank(nx_graph)
 
# 根据textrank值对未处理的句子进行排序
ranked_sentences = sorted(((scores[i],s) for i,s in enumerate(sentences_list)), reverse=True)
 
# 取出得分最高的前10个句子作为摘要
sn = 10
for i in range(sn):
    print("第"+str(i+1)+"条摘要:\n\n",ranked_sentences[i][1],'\n')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
1条摘要:...2条摘要:...3条摘要:...4条摘要:...5条摘要:...6条摘要:...7条摘要:...8条摘要:...9条摘要:...10条摘要:...

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

声明:因文本中包含敏感信息,故省略

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/281675
推荐阅读
相关标签
  

闽ICP备14008679号