文本自動摘要:基於TextRank的中文新聞摘要

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作單領域多文本的自動摘要的過程以下:

  • 把全部文章整合成文本數據,並把文本分割成單個句子;
  • 用WordAVG的方法,將每一個句子中全部單詞的詞向量合併爲句子的向量表示;
  • 計算句子向量間的類似性並存放在矩陣中,做爲轉移機率矩陣M;
  • 而後將轉移機率矩陣轉換爲以句子爲節點、類似性得分爲邊的圖結構,用於句子TextRank計算;
  • 對句子按照TextRank值進行排序,排名最靠前的n個句子做爲摘要。

好的,那下面咱們就用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

相關文章
相關標籤/搜索