TextRank算法源自于PageRank算法。PageRank算法最初是做为互联网网页排序的方法,通过轻微地改动,能够被应用于文本摘要领域。html
本文分为两部分,第一部分介绍TextRank作文本自动摘要的原理,第二部分介绍用TextRank作中文新闻摘要的案例。git
1、基于TextRank的自动摘要原理github
一、PageRank算法算法
首先看PageRank的相关概念。PageRank对于每一个网页页面都给出一个正实数,表示网页的重要程度,PageRank值越高,表示网页越重要,在互联网搜索的排序中越可能被排在前面。假设整个互联网是一个有向图,节点是网页,每条边是转移几率。网页浏览者在每一个页面上依照链接出去的超连接,以等几率跳转到下一个网页,而且在网页上持续不断地进行这样的随机跳转,这个过程造成了一阶马尔科夫链,好比下图,每一个笑脸是一个网页,既有其余网页跳转到该网页,该网页也会跳转到其余网页。在不断地跳转以后,这个马尔科夫链会造成一个平稳分布,而PageRank就是这个平稳分布,每一个网页的PageRank值就是平稳几率。app
PageRank的核心公式是PageRank值的计算公式。这个公式来自于《统计学习方法》,和不少博客上的公式有点轻微的差异,那就是等号右边的平滑项不是(1-d),而是(1-d)/n。ide
加平滑项是由于有些网页没有跳出去的连接,那么转移到其余网页的几率将会是0,这样就没法保证存在马尔科夫链的平稳分布。因而,咱们假设网页以等几率(1/n)跳转到任何网页,再按照阻尼系数d,对这个等几率(1/n)与存在连接的网页的转移几率进行线性组合,那么马尔科夫链必定存在平稳分布,必定能够获得网页的PageRank值。学习
因此PageRank的定义意味着网页浏览者按照如下方式在网上随机游走:以几率d按照存在的超连接随机跳转,以等几率从超连接跳转到下一个页面;或以几率(1-d)进行彻底随机跳转,这时以等几率(1/n)跳转到任意网页。大数据
PageRank的计算是一个迭代过程,先假设一个初始的PageRank分布,经过迭代,不断计算全部网页的PageRank值,直到收敛为止,也就是:人工智能
二、TextRank算法spa
在文本自动摘要的案例中,TextRank和PageRank的类似之处在于:
用句子代替网页
任意两个句子的类似性等价于网页转换几率
类似性得分存储在一个方形矩阵中,相似于PageRank的矩阵M
不过公式有些小的差异,那就是用句子的类似度类比于网页转移几率,用归一化的句子类似度代替了PageRank中相等的转移几率,这意味着在TextRank中,全部节点的转移几率不会彻底相等。
而后迭代过程就和PageRank一致了。
三、TextRank作单领域多文本的自动摘要
用TextRank作单领域多文本的自动摘要的过程以下:
好的,那下面咱们就用TextRank算法,以及按照上面的流程,作一个新闻自动摘要的小案例。
2、基于TextRank的中文新闻摘要
参考了一篇用TextRank作英文新闻摘要的文章。
一、文章:《手把手|基于TextRank算法的文本摘要(附Python代码)》 https://mp.weixin.qq.com/s/fGaEYvo3WYKdzA3r8l6O3g 2、github地址 :https://github.com/prateekjoshi565/textrank_text_summarization
本文要处理的新闻一共3篇,都是关于证监会主席易会满同志新官上任的报道,新闻的大体内容是易会满同志怎么对中国资本市场的改革指点江山。
文档的原网页(看到百家号,不要鄙视我):
这个小实践的github:https://github.com/DengYangyong/textrank_summarization
好,那就开始。
一、整合文档,划分句子
首先把文档读入,放在列表中,能够看到,有些句子已经被划分出来了。
['信息量巨大!易会满首秀,直面科创板8大问题,对散户加速入场笑而不语……', '每日经济新闻', '02-2717:56', '每经编辑:郭鑫 王晓波', '图片来源:新华社记者 李鑫 摄', '易会满上任一个月,尚未在公开场合说过一句话。', '2月27日下午三点半开始,中国证监会主席易会满在北京国新办出席其首场新闻发布会,离发布会开始前两小时现场已经座无虚席,只等易主席来到现场。此外,副主席李超、副主席方星海,上海证券交易所理事长黄红元等也共同出席。',
...]
不过经过观察,咱们能够发现存在两个问题:
一是以[。?!;]做为句子的分隔符,那么列表中的每一个字符串元素中可能有多个句子;
二是每一个字符串元素可能以[:,]结尾,也就是说多是一个不完整的句子。
考虑到这只是一个小案例,因此就没花太多时间,仅仅处理一下第一个问题,把句子按照[。?!;]进行划分,若是字符串元素是不完整的句子,那也做为一句。
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])
前10个句子为: ['信息量巨大', '易会满首秀,直面科创板8大问题,对散户加速入场笑而不语……', '每日经济新闻', '02-2717:56',
'每经编辑:郭鑫 王晓波', '图片来源:新华社记者 李鑫 摄', '易会满上任一个月,尚未在公开场合说过一句话', '2月27日下午三点半开始,中国证监会主席易会满在北京国新办出席其首场新闻发布会,离发布会开始前两小时现场已经座无虚席,只等易主席来到现场', '此外,副主席李超、副主席方星海,上海证券交易所理事长黄红元等也共同出席', '这多是这个月国内关注的人最多的一场新闻发布会了']
二、文本预处理
文本预处理包括去除停用词和非汉字字符,并进行分词。处理的过程要保证处理以后的句子的数量和处理以前的同样,由于后面咱们计算了每一个句子的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数据预处理后句子的数量不变!")
一共有 347 个句子。 前10个句子分词后的结果为: [['信息量'],
['易会', '满首秀', '直面', '科创板', '散户', '加速', '入场', '笑', '不语'],
['每日', '经济', '新闻'],
[],
['每经', '编辑', '郭鑫', '王晓波'],
['图片', '来源', '李鑫', '摄'],
['易会', '上任', '一个月', '公开场合', '说', '一句', '话'],
['三点', '中国证监会', '主席', '易会', '北京', '国新办', '出席', '首场', '新闻', '发布会', '发布会', '前', '两', '小时', '现场', '座无虚席', '易', '主席', '来到', '现场'],
['副', '主席', '李超', '副', '主席', '星海', '上海证券交易所', '理事长', '黄红元', '出席'],
['国内', '关注', '一场', '新闻', '发布会']] 数据预处理后句子的数量不变!
三、加载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))+"个词语/字。")
一共有467140个词语/字。
四、获得词语的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)
五、计算句子之间的余弦类似度,构成类似度矩阵
"""第五步:计算句子之间的余弦类似度,构成类似度矩阵""" 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)
句子类似度矩阵的形状为: (347, 347)
六、迭代获得句子的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条摘要:
在新闻发布会上,易会满表示,我到证监会工做今天是31天,刚刚满月,是资本市场的新兵,从市场参与者到监管者,角色转换角色挑战很大,如履薄冰,不敢懈怠,惟恐辜负中央信任和市场期待,这也是我作好工做的动力,
近期增强调查研究,和部门协做维护市场平稳发展,维护科创板前期基础工做
第2条摘要:
易会满在新闻发布会上表示,防止发生系统性风险是底线和根本任务,当前受国内外多种因素影响,资本市场风险形式严峻复杂,证监会将坚持精准施策,作好股票质押私募基金、场外配资和地方各种场所的重点领域风险的防范化解
和处置工做,完善资本市场逆周期机制,健全及时反映风险波动系统,运用大数据、人工智能等手段对上市公司专业监管,平衡事前、事中、过后关系,监管端口前移,强化监管效能
第3条摘要:
证监会将坚持精准施策,作好股票质押私募基金、场外配资和地方各种场所的重点领域风险的防范化解和处置工做,完善资本市场逆周期机制,健全及时反映风险波动系统,运用大数据、人工智能等手段对上市公司专业监管,
平衡事前、事中、过后关系,监管端口前移,强化监管效能,切实作好打铁必须自身硬,作好中介机构和高管的强监管
第4条摘要:
这二者出发点和规则不一样,我来证监会后不断学习研究,这么专业的问题证监会有专业化的团队,资本市场是大的生态,什么叫市场,应该是依靠市场各参与者,调动市场参与者,市场规律办事, 培养健康生态比什么都重要,
这一考验和要求比专业更重要,生态建设好了,资本市场的健康发展才有保证
第5条摘要:
证监会副主席李超今天也给市场吃下定心丸:“对二级市场影响的问题,(科创板)设立时已经高度关注,在一系列的制度、规则层面做了相应安排
第6条摘要:
他表示,第一,设立科创板主要目的是加强资本市场对实体经济的包容性,更好地服务具备核心技术、行业领先、有良好发展前景和口碑的企业,经过改革进一步完善支持创新的资本造成机制
第7条摘要:
一是提升宏观思惟能力,贴近市场各参与方,坚持市场导向、法治导向、监管导向,增强对资本市场宏观战略问题的研究思考,增强顶层设计,加强战略定力,稳步推动重点关注问题的改革创新,在改革中、在发展中破解难题
第8条摘要:
集体学习的通稿中,中央给资本市场定的“法治化”要求有很多,好比“把好市场入口和市场出口两道关,增强全程监管”、“解决资本市场违法违规成本太低问题”
第9条摘要:
易会满表示,证监会将以xijinping新时代中国特点社会主义思想为指导,在国务院金融委的统一指挥协调下,主动增强与相关部委、地方党委政府和市场各方的沟通协做,努力造成工做协力,共同促进资本市场高质量发展
第10条摘要:
目前,资本市场已经回暖,这为改革提供了良好市场条件,咱们要齐心合力,坚持“严标准、稳起步”的原则,积极作好落实和应对工做,注重各市场之间的平衡,确保改革平稳启动实施
Nice!
这样就完成了一个文本自动摘要的小实践了。
这是抽取型的摘要方法,之后再探索其余的文本自动摘要方法。
参考资料:
一、李航:《统计学习方法》(第二版)第21章
二、https://mp.weixin.qq.com/s/fGaEYvo3WYKdzA3r8l6O3g