0 前言
本文主要內(nèi)容:介紹Pointer-Generator-Network在文本摘要任務(wù)中的背景,模型架構(gòu)與原理、在中英文數(shù)據(jù)集上實戰(zhàn)效果與評估,最后得出結(jié)論。參考的《Get To The Point: Summarization with Pointer-Generator Networks》以及多篇博客均在文末給出連接,文中使用數(shù)據(jù)集已上傳百度網(wǎng)盤,代碼已傳至GitHub,讀者可以在文中找到相應(yīng)連接,實際操作過程中確實遇到很多坑,并未在文中一一指明,有興趣的讀者可以留言一起交流。由于水平有限,請讀者多多指正。
隨著互聯(lián)網(wǎng)飛速發(fā)展,產(chǎn)生了越來越多的文本數(shù)據(jù),文本信息過載問題日益嚴(yán)重,對各類文本進行一個“降 維”處理顯得非常必要,文本摘要便是其中一個重要的手段。文本摘要旨在將文本或文本集合轉(zhuǎn)換為包含關(guān)鍵信息的簡短摘要。按照輸出類型可分為抽取式摘要和生成式摘要。抽取式摘要從源文檔中抽取關(guān)鍵句和關(guān)鍵詞組成摘要,摘要全部來源于原文。生成式摘要根據(jù)原文,允許生成新的詞語、原文本中沒有的短語來組成摘要。
指針生成網(wǎng)絡(luò)屬于生成式模型。
僅用Neural sequence-to-sequence模型可以實現(xiàn)生成式摘要,但存在兩個問題:
1. 可能不準(zhǔn)確地再現(xiàn)細節(jié), 無法處理詞匯不足(OOV)單詞;
2. 傾向于重復(fù)自己。
原文是(they are liable to reproducefactual details inaccurately, and they tendto repeat themselves.)
指針生成網(wǎng)絡(luò)(Pointer-Generator-Network)從兩個方面進行了改進:
1. 該網(wǎng)絡(luò)通過指向(pointer)從源文本中復(fù)制單詞,有助于準(zhǔn)確地復(fù)制信息,同時保留通過生成器產(chǎn)生新單詞的能力;
2. 使用coverage機制來跟蹤已總結(jié)的內(nèi)容,防止重復(fù)。
接下來從下面幾個部分介紹Pointer-Generator-Network原理:
1. Baseline sequence-to-sequence;
2. Pointer-Generator-Network;
3. Coverage Mechanism。
1 Baseline sequence-to-sequence
Pointer-Generator Networks是在Baseline sequence-to-sequence模型的基礎(chǔ)上構(gòu)建的,我們首先Baseline seq2seq+attention。其架構(gòu)圖如下:該模型可以關(guān)注原文本中的相關(guān)單詞以生成新單詞進行概括。比如:模型可能注意到原文中的"victorious"和" win"這個兩個單詞,在摘要"Germany beat Argentina 2-0"中生成了新的單詞beat 。
Seq2Seq的模型結(jié)構(gòu)是經(jīng)典的Encoder-Decoder模型,即先用Encoder將原文本編碼成一個中間層的隱藏狀態(tài),然后用Decoder來將該隱藏狀態(tài)解碼成為另一個文本。Baseline Seq2Seq在Encoder端是一個雙向的LSTM,這個雙向的LSTM可以捕捉原文本的長距離依賴關(guān)系以及位置信息,編碼時詞嵌入經(jīng)過雙向LSTM后得到編碼狀態(tài) $h_i$ 。在Decoder端,解碼器是一個單向的LSTM,訓(xùn)練階段時參考摘要詞依次輸入(測試階段時是上一步的生成詞),在時間步 $t$得到解碼狀態(tài) $s_t$ 。使用$h_i$和$s_t$得到該時間步原文第 $i$個詞注意力權(quán)重。
$$e_i^t = v^T tanh(W_{h}h_i + W_{s}s_t + b_{attn})$$ $$a^t = softmax(e^t)$$得到的注意力權(quán)重和 $h_i$加權(quán)求和得到重要的上下文向量 $h_t^*(context vector)$:
$$h_{t}^{*} = \sum_{i}{a_i^t h_i}$$
$h_t^*$可以看成是該時間步通讀了原文的固定尺寸的表征。然后將 $s_t$和 $h_t^*$ 經(jīng)過兩層線性層得到單詞表分布 $P_{vocab}$:
$$P_{vocab} = softmax(V'(V[s_t, h_t^*] + b) + b')$$
其中 $[s_t, h_t^*]$是拼接。這樣再通過$sofmax$得到了一個概率分布,就可以預(yù)測需要生成的詞:
$$P(w) = P_{vocab}(w)$$
在訓(xùn)練階段,時間步 $t$ 時的損失為:
$$loss_{t} = -logP(w_t^*)$$
那么原輸入序列的整體損失為:
$$loss = \frac{1}{T} \sum_{t=0}^{T}loss_t$$
2 Pointer-Generator-Network
原文中的Pointer-Generator Networks是一個混合了 Baseline seq2seq和PointerNetwork的網(wǎng)絡(luò),它具有Baseline seq2seq的生成能力和PointerNetwork的Copy能力。該網(wǎng)絡(luò)的結(jié)構(gòu)如下:
如何權(quán)衡一個詞應(yīng)該是生成的還是復(fù)制的?
原文中引入了一個權(quán)重 $p_{gen}$ 。
從Baseline seq2seq的模型結(jié)構(gòu)中得到了$s_t$ 和$h_t^*$,和解碼器輸入 $x_t$ 一起來計算 $p_{gen}$ :
$$p_{gen} = \sigma(w_{h^*}^T h_t^* + w_s^Ts_t + w_x^Tx_t + b_{ptr})$$
這時,會擴充單詞表形成一個更大的單詞表--擴充單詞表(將原文當(dāng)中的單詞也加入到其中),該時間步的預(yù)測詞概率為:
$$P(w) = p_{gen}P_{vocab}(w) + (1 - p_{gen}) \sum_{i:w_i=w} a_i^t$$
其中 $a_i^t$ 表示的是原文檔中的詞。我們可以看到解碼器一個詞的輸出概率有其是否拷貝是否生成的概率和決定。當(dāng)一個詞不出現(xiàn)在常規(guī)的單詞表上時 $P_{vocab}(w)$ 為0,當(dāng)該詞不出現(xiàn)在文檔中$ \sum_{i:w_i=w} a_i^t$為0。
3 Coverage mechanism
原文的特色是運用了Coverage Mechanism來解決重復(fù)生成文本的問題,下圖反映了前兩個模型與添加了Coverage Mechanism生成摘要的結(jié)果:
藍色的字體表示的是參考摘要,三個模型的生成摘要的結(jié)果差別挺大;
紅色字體表明了不準(zhǔn)確的摘要細節(jié)生成(UNK未登錄詞,無法解決OOV問題);
綠色的字體表明了模型生成了重復(fù)文本。
為了解決此問題--Repitition,原文使用了在機器翻譯中解決“過翻譯”和“漏翻譯”的機制--Coverage Mechanism。
具體實現(xiàn)上,就是將先前時間步的注意力權(quán)重加到一起得到所謂的覆蓋向量 $c^t (coverage vector)$,用先前的注意力權(quán)重決策來影響當(dāng)前注意力權(quán)重的決策,這樣就避免在同一位置重復(fù),從而避免重復(fù)生成文本。計算上,先計算coverage vector $c^t$:
$$c^t = \sum_{t'=0}^{t-1}a^{t'}$$
然后添加到注意力權(quán)重的計算過程中,$c^t$用來計算 $e_i^t$:
$$e_i^t = v^T tanh(W_{h}h_i + W_{s}s_t + w_{c}c_i^t + b_{attn})$$
同時,為coverage vector添加損失是必要的,coverage loss計算方式為:
$$covloss_{t} = \sum_{i}min(a_i^t, c_i^t)$$
這樣coverage loss是一個有界的量 $covloss_t \leq \sum_{i}a_i^t = 1$ 。因此最終的LOSS為:
$$loss_t = -logP(w_t^*) + \lambda \sum_{i}min(a_i^t, c_i^t)$$
4 實戰(zhàn)部分
4.1 DataSet
英文數(shù)據(jù)集: cnn dailymail數(shù)據(jù)集,地址:https://github.com/becxer/cnn-dailymail/。
中文數(shù)據(jù)集:新浪微博摘要數(shù)據(jù)集,這是中文數(shù)據(jù)集,有679898條文本及摘要。
,【己境】【水流】【非?!俊境梢弧?【領(lǐng)域】【力直】【間幾】【尊獲】,【滴落】【猊立】【的核】【一句】【你方】.【常不】【能量】【音在】【障在】【戰(zhàn)的】,【浮現(xiàn)】【要不】【大能】【雷大】,【異?!俊竞玫摹俊举|(zhì)處】【御罩】【準(zhǔn)黑】!【了一】【下之】【器的】【生機】【按照】【虛空】,【河之】【老咒】【毫動】【運輸】,【界固】【懼怕】【不過】【起駝】【一點】,【成的】【之地】【嘴最】.【下文】【最新】【非?!俊疽挥洝?【不錯】【力勝】【為金】【是輕】,【怖的】【總算】【小佛】【的至】.【歸一】!【懼意】【很好】【其中】【動那】【卻高】【果是】【之毒】.【同時】【l黑帽SEO】【對小】【將要】【為獨】【鳳凰】【大小】【率突】【有任】【會打】【間出】【百六】【石當(dāng)】【回收】【物質(zhì)】【土地】【焰火】【大世】【時空】【較多】【刀痕】【他異】【個大】【流失】【雜一】【煉歷】【啊小】【布太】【確是】【是他】,中英文數(shù)據(jù)集均可從這里下載,鏈接:https://pan.baidu.com/s/18ykewFUrTLzW8R84bF42pg 密碼:9yqt。
4.2 Experiments
原論文代碼參考:python3 tensorflow版本。調(diào)試時候各種報錯,所以需要debug。改動后的代碼已上傳至GitHub:https://github.com/zingp/NLP/tree/master/P007PytorchPointerGeneratorNetwork。
本次我們復(fù)現(xiàn)結(jié)果時所用的代碼是自己實現(xiàn)的pytorch版本,代碼:https://github.com/zingp/pointer-generator-pytorch。具體環(huán)境是:Centos7.4/python3.6/pytorch1.0.1 GPU:Tesla V100-SXM2-16GB
4.2.1 cnn/dailymail數(shù)據(jù)集實驗
使用上面所說的環(huán)境與代碼, 優(yōu)化器Adagrad,初始學(xué)習(xí)率0.15。hidden_dim為 256 ,詞向量維度emb_dim為126,詞匯表數(shù)目vocab_size為50K,batch_size設(shè)為16。模型有處理OOV能力,因此詞匯表不用設(shè)置過大;在batch_size的選擇上,顯存小的同學(xué)建議設(shè)為8,否則會出現(xiàn)內(nèi)存不夠,難以訓(xùn)練。LOSS曲線如下:
一開始我們未開啟coverage模式,迭代500K后終止,可以看出模型已收斂。然后選擇一個loss較好的模型即pointer-gen模型,在這個模型的基礎(chǔ)之上,開啟coverage模式之后繼續(xù)訓(xùn)練40K后終止,得到收斂的模型即是pointer-gen+coverage了。具體rouge分數(shù)可以看下面一章分析。
4.2.2 微博中文數(shù)據(jù)集
新浪微博的中文數(shù)據(jù)集沒有現(xiàn)成工具處理成二進制,因此需要先寫一段預(yù)處理代碼。
第一部分是對原始數(shù)據(jù)進行分詞,劃分訓(xùn)練集測試集,并保存文件。
import os
import sys
import time
import jieba
ARTICLE_FILE = "./data/weibo_news/train_text.txt"
SUMMARRY_FILE = "./data/weibo_news/train_label.txt"
TRAIN_FILE = "./data/weibo_news/train_art_summ_prep.txt"
VAL_FILE = "./data/weibo_news/val_art_summ_prep.txt"
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
r = func(*args, **kwargs)
end = time.time()
cost = end - start
print(f"Cost time: {cost} s")
return r
return wrapper
@timer
def load_data(filename):
"""加載數(shù)據(jù)文件,對文本進行分詞"""
data_list = []
with open(filename, 'r', encoding= 'utf-8') as f:
for line in f:
# jieba.enable_parallel()
words = jieba.cut(line.strip())
word_list = list(words)
# jieba.disable_parallel()
data_list.append(' '.join(word_list).strip())
return data_list
def build_train_val(article_data, summary_data, train_num=600_000):
"""劃分訓(xùn)練和驗證數(shù)據(jù)"""
train_list = []
val_list = []
n = 0
for text, summ in zip(article_data, summary_data):
n += 1
if n <= train_num:
train_list.append(text)
train_list.append(summ)
else:
val_list.append(text)
val_list.append(summ)
return train_list, val_list
def save_file(filename, li):
"""預(yù)處理后的數(shù)據(jù)保存到文件"""
with open(filename, 'w+', encoding='utf-8') as f:
for item in li:
f.write(item + '\n')
print(f"Save {filename} ok.")
if __name__ == '__main__':
article_data = load_data(ARTICLE_FILE) # 大概耗時10分鐘
summary_data = load_data(SUMMARRY_FILE)
TRAIN_SPLIT = 600_000
train_list, val_list = build_train_val(article_data, summary_data, train_num=TRAIN_SPLIT)
save_file(TRAIN_FILE, train_list)
save_file(VAL_FILE, val_list)
第二部分是將文件打包,生成模型能夠加載的二進制文件。
import os
import struct
import collections
from tensorflow.core.example import example_pb2
# 經(jīng)過分詞處理后的訓(xùn)練數(shù)據(jù)與測試數(shù)據(jù)文件
TRAIN_FILE = "./data/weibo_news/train_art_summ_prep.txt"
VAL_FILE = "./data/weibo_news/val_art_summ_prep.txt"
# 文本起始與結(jié)束標(biāo)志
SENTENCE_START = '<s>'
SENTENCE_END = '</s>'
VOCAB_SIZE = 50_000 # 詞匯表大小
CHUNK_SIZE = 1000 # 每個分塊example的數(shù)量,用于分塊的數(shù)據(jù)
# tf模型數(shù)據(jù)文件存放目錄
FINISHED_FILE_DIR = './data/weibo_news/finished_files'
CHUNKS_DIR = os.path.join(FINISHED_FILE_DIR, 'chunked')
def chunk_file(finished_files_dir, chunks_dir, name, chunk_size):
"""構(gòu)建二進制文件"""
in_file = os.path.join(finished_files_dir, '%s.bin' % name)
print(in_file)
reader = open(in_file, "rb")
chunk = 0
finished = False
while not finished:
chunk_fname = os.path.join(chunks_dir, '%s_%03d.bin' % (name, chunk)) # 新的分塊
with open(chunk_fname, 'wb') as writer:
for _ in range(chunk_size):
len_bytes = reader.read(8)
if not len_bytes:
finished = True
break
str_len = struct.unpack('q', len_bytes)[0]
example_str = struct.unpack('%ds' % str_len, reader.read(str_len))[0]
writer.write(struct.pack('q', str_len))
writer.write(struct.pack('%ds' % str_len, example_str))
chunk += 1
def chunk_all():
# 創(chuàng)建一個文件夾來保存分塊
if not os.path.isdir(CHUNKS_DIR):
os.mkdir(CHUNKS_DIR)
# 將數(shù)據(jù)分塊
for name in ['train', 'val']:
print("Splitting %s data into chunks..." % name)
chunk_file(FINISHED_FILE_DIR, CHUNKS_DIR, name, CHUNK_SIZE)
print("Saved chunked data in %s" % CHUNKS_DIR)
def read_text_file(text_file):
"""從預(yù)處理好的文件中加載數(shù)據(jù)"""
lines = []
with open(text_file, "r", encoding='utf-8') as f:
for line in f:
lines.append(line.strip())
return lines
def write_to_bin(input_file, out_file, makevocab=False):
"""生成模型需要的文件"""
if makevocab:
vocab_counter = collections.Counter()
with open(out_file, 'wb') as writer:
# 讀取輸入的文本文件,使偶數(shù)行成為article,奇數(shù)行成為abstract(行號從0開始)
lines = read_text_file(input_file)
for i, new_line in enumerate(lines):
if i % 2 == 0:
article = lines[i]
if i % 2 != 0:
abstract = "%s %s %s" % (SENTENCE_START, lines[i], SENTENCE_END)
# 寫入tf.Example
tf_example = example_pb2.Example()
tf_example.features.feature['article'].bytes_list.value.extend([bytes(article, encoding='utf-8')])
tf_example.features.feature['abstract'].bytes_list.value.extend([bytes(abstract, encoding='utf-8')])
tf_example_str = tf_example.SerializeToString()
str_len = len(tf_example_str)
writer.write(struct.pack('q', str_len))
writer.write(struct.pack('%ds' % str_len, tf_example_str))
# 如果可以,將詞典寫入文件
if makevocab:
art_tokens = article.split(' ')
abs_tokens = abstract.split(' ')
abs_tokens = [t for t in abs_tokens if
t not in [SENTENCE_START, SENTENCE_END]] # 從詞典中刪除這些符號
tokens = art_tokens + abs_tokens
tokens = [t.strip() for t in tokens] # 去掉句子開頭結(jié)尾的空字符
tokens = [t for t in tokens if t != ""] # 刪除空行
vocab_counter.update(tokens)
print("Finished writing file %s\n" % out_file)
# 將詞典寫入文件
if makevocab:
print("Writing vocab file...")
with open(os.path.join(FINISHED_FILE_DIR, "vocab"), 'w', encoding='utf-8') as writer:
for word, count in vocab_counter.most_common(VOCAB_SIZE):
writer.write(word + ' ' + str(count) + '\n')
print("Finished writing vocab file")
if __name__ == '__main__':
if not os.path.exists(FINISHED_FILE_DIR):
os.makedirs(FINISHED_FILE_DIR)
write_to_bin(VAL_FILE, os.path.join(FINISHED_FILE_DIR, "val.bin"))
write_to_bin(TRAIN_FILE, os.path.join(FINISHED_FILE_DIR, "train.bin"), makevocab=True)
chunk_all()
在訓(xùn)練中文數(shù)據(jù)集的時候我們采用了TensorFlow版本的代碼,設(shè)置的hidden_dim為 256 ,詞向量維度emb_dim為126,詞匯表數(shù)目vocab_size為50K,batch_size設(shè)為16。在batch_size的選擇上,顯存小的同學(xué)建議設(shè)為8,否則會出現(xiàn)內(nèi)存不夠,難以訓(xùn)練。
在batch_size=16時,訓(xùn)練了27k step, 出現(xiàn)loss震蕩很難收斂的情況,train階段loss如下:
val階段loss如下:
可以看到當(dāng)step在10k之后,loss在3.0-5.0之間來回劇烈震蕩,并沒有下降趨勢。前面我們?yōu)榱耸★@存,將batch_size設(shè)置成16,可能有點小了,梯度下降方向不太明確,顯得有點盲目,因此將batch_size設(shè)成了32后重新開始訓(xùn)練。注意:在一定范圍內(nèi),batchsize越大,計算得到的梯度下降方向就越準(zhǔn),引起訓(xùn)練震蕩越小。增大batch_size后訓(xùn)練的loss曲線如下:
val loss曲線如下:
看起來loss還是比較震蕩的,但是相比bathc_size=16時有所改善。一開始的前10K steps里loss下降還是很明顯的基本上能從6降到4左右的區(qū)間,10k steps之后開始震蕩,但還是能看到在緩慢下降:從4左右,開始在2-4之間震蕩下降。這可能是目前的steps還比較少,只要val loss沒有一直升高,可以繼續(xù)觀擦,如果500K steps都還是如此,可以考慮在一個合適的時機early stop。
附一個pytorch版本的訓(xùn)練情況:
優(yōu)化器選擇的Adam,初始學(xué)習(xí)率為0.001,batchsize設(shè)為32.其他參數(shù)可參見源代碼中的config。loss曲線如下:
同樣也是先關(guān)閉coverage模式,收斂后再開啟??梢钥闯鯝dma在訓(xùn)練初期loss還是下降挺快的。
4.3 Evaluation
摘要質(zhì)量評價需要考慮一下三點:
(1) 決定原始文本最重要的、需要保留的部分;
(2) 在自動文本摘要中識別出1中的部分;
(3) 基于語法和連貫性(coherence)評價摘要的可讀性(readability)。
從這三點出發(fā)有人工評價和自動評價,本文只討論一下更值得關(guān)注的自動評價。自動文檔摘要評價方法分為兩類:
內(nèi)部評價方法(Intrinsic Methods):提供參考摘要,以參考摘要為基準(zhǔn)評價系統(tǒng)摘要的質(zhì)量。系統(tǒng)摘要與參考摘要越吻合, 質(zhì)量越高。
外部評價方法(Extrinsic Methods):不提供參考摘要,利用文檔摘要代替原文檔執(zhí)行某個文檔相關(guān)的應(yīng)用。
內(nèi)部評價方法是最常使用的文摘評價方法,將系統(tǒng)生成的自動摘要與參考摘要采用一定的方法進行比較是目前最為常見的文摘評價模式。下面介紹內(nèi)部評價方法是ROUGE(Recall-Oriented Understudy for Gisting Evaluation)。
ROUGE是2004年由ISI的Chin-Yew Lin提出的一種自動摘要評價方法,現(xiàn)被廣泛應(yīng)用于DUC(Document Understanding Conference)的摘要評測任務(wù)中。ROUGE基于摘要中n元詞(n-gram)的共現(xiàn)信息來評價摘要,是一種面向n元詞召回率的評價方法。基本思想為由多個專家分別生成人工摘要,構(gòu)成標(biāo)準(zhǔn)摘要集,將系統(tǒng)生成的自動摘要與人工生成的標(biāo)準(zhǔn)摘要相對比,通過統(tǒng)計二者之間重疊的基本單元(n元語法、詞序列和詞對)的數(shù)目,來評價摘要的質(zhì)量。通過與專家人工摘要的對比,提高評價系統(tǒng)的穩(wěn)定性和健壯性。該方法現(xiàn)已成為摘要評價技術(shù)的通用標(biāo)注之一。 ROUGE準(zhǔn)則由一系列的評價方法組成,包括ROUGE-N(N=1、2、3、4,分別代表基于1元詞到4元詞的模型),ROUGE-L,ROUGE-S, ROUGE-W,ROUGE-SU等。在自動文摘相關(guān)研究中,一般根據(jù)自己的具體研究內(nèi)容選擇合適的ROUGE方法。公式如下:
$$ROUGE-N = \frac{\sum_{S\in \left\{ ReferenceSummaries\right\} } \sum_{gram_n \in S}Count_{match}(gram_n)} {\sum_{S\in \left\{ ReferenceSummaries\right\} } \sum_{gram_n \in S}Count(gram_n)}$$
其中,$n-gram$表示n元詞,${Ref Summaries}$表示參考摘要(標(biāo)準(zhǔn)摘要),$Count_{match}(n-gram)$表示生成摘要和參考摘要中同時出現(xiàn)$n-gram$的個數(shù),$Count(n-gram)$則表示參考摘要中出現(xiàn)的$n- gram$個數(shù)。ROUGE公式是由召回率的計算公式演變而來的,分子可以看作“檢出的相關(guān)文檔數(shù)目”,即系統(tǒng)生成摘要與標(biāo)準(zhǔn)摘要相匹配的$n-gram$個數(shù),分母可以看作“相關(guān)文檔數(shù)目”,即參考摘要中所有的$n-gram$個數(shù)。
舉例說明一下:
自動摘要Y(模型自動生成的):the cat was found under the bed
參考摘要X1(人工生成的):the cat was under the bed
摘要的1-gram、2-gram如下(N-gram以此類推):
$ROUGE-1(X1,Y)= 6/6=1.0$ -->分子是待評測摘要和參考摘要都出現(xiàn)的1-gram的個數(shù),分母是參考摘要的1-gram個數(shù)。(其實分母也可以是待評測摘要的,但是在精確率和召回率之間,我們更關(guān)心的是召回率Recall,同時這也和上面ROUGN-N的公式相同)。
同樣,$ROUGE-2(X1,Y)=4/5=0.8$。
4.4 Results
原論文中的cnn/dailymail數(shù)據(jù)集上的ROUGE分數(shù)如下:
在上表中,上半部分是模型生成的的摘要評估,而下半部分的是提取摘要評估。可以看出抽象生成的效果接近了抽取效果。
本實驗復(fù)現(xiàn)ROUGE分數(shù)如下:
在僅用pointer-Gen的情況下,我們的的分數(shù)是高于原文中的分數(shù)的;使用Pointer-Gen+Coverage模型之后我們的分數(shù)與原文相當(dāng)。但都可以反應(yīng)使用Pointer-Gen+Coverage后的分數(shù)相較僅使用pointer-Gen要高。
再來看ngram重復(fù)情況:
可以看出我們的no coverage的模型生成的摘要在n-gram上是要比reference摘要要多的,而使用了coverage之后,重復(fù)數(shù)目和reference相當(dāng)。 中文實驗結(jié)果: 由于中文的rogue暫時不能用ROUGE庫計算,所以暫時還沒有計算分數(shù),不過可以看一下效果。
例子一:
例子二:
直觀上效果還是不錯的。可以看出,預(yù)測的摘要中已經(jīng)基本沒有不斷重復(fù)自身的現(xiàn)象;像“[話筒] [思考] [吃驚] ”這種文本,應(yīng)該是原文本中的表情,在對文本的處理中我們并沒有將這些清洗掉,因此依然出現(xiàn)在預(yù)測摘要中。不過例子二還是出現(xiàn)了句子不是很通順的情況,在輸出句子的語序連貫上還有待改進。5 總結(jié)與展望
5.1 回顧本文做的一些工作
1. 本文用pytorch實現(xiàn)了指針生成網(wǎng)絡(luò),復(fù)現(xiàn)了原論文的結(jié)果,在pointer-gen模型上的ROUGE分數(shù)略高于原文。
2 將模型方法應(yīng)用在中文數(shù)據(jù)集上,取得了一定效果。
5.2 一些感想
1. 可以看出指針生成網(wǎng)絡(luò)通過指針復(fù)制原文中的單詞,可以生成新的單詞,解決oov問題;其次使用了coverage機制,能夠避免生成的詞語不斷重復(fù)。
2. 有時候會出現(xiàn)語句不通順的情況,在語句的通順和連貫上還有待加強,尤其是在中文數(shù)據(jù)集上比較明顯。
5.3 所以我們實現(xiàn)了生成式(抽象)摘要嗎?
遠沒到實現(xiàn)的程度!盡管我們展示這些進步可以幫助我們克服循環(huán)神經(jīng)網(wǎng)絡(luò)的一些野蠻行為,但是仍然有很多未解決的問題。
- 盡管指針生成網(wǎng)絡(luò)生成了(生成式)抽象式摘要,但是生成的單詞通常都是和原文相當(dāng)接近的;更高水平的抽象——例如更加強大的壓縮語義,仍然未被解決。
- 有時候,網(wǎng)絡(luò)仍然沒有去聚焦源文本的核心內(nèi)容,反而概括一些不太重要的信息。
- 有時候,網(wǎng)絡(luò)錯誤地組合了原文的片段,例如,作出的摘要是 work incorrectly composes fragments of the source text – for example reporting that。這讓人很費解。
- 多句式摘要有時候并沒有構(gòu)成一個有意義的整體,例如,在沒有事先介紹的情況下,就用一個代詞(例如 she)去代替一個實體 (例如德國總理 Angela Merkel)。
我認為未來最重要的研究方向是可解釋性(interpretability)。通過揭示網(wǎng)絡(luò)正在關(guān)注什么,注意力機制在神經(jīng)網(wǎng)絡(luò)的黑盒中點亮了珍貴的光芒,以幫助我們調(diào)試類似重復(fù)和復(fù)制的問題。為了取得進一步的進展,我們需要深入了解遞歸神經(jīng)網(wǎng)絡(luò)從文本中學(xué)習(xí)到的內(nèi)容以及知識的表征方式??梢試L試?yán)妙A(yù)訓(xùn)練模型,效果可能會更好;也可以先采用抽取式生成摘要,然后利用抽取式摘要進行訓(xùn)練。
5 References
1. https://arxiv.org/pdf/1704.04368.pdf 2. https://www.jiqizhixin.com/articles/2019-03-25-7 3. https://zhuanlan.zhihu.com/p/53821581 4. https://www.aclweb.org/anthology/W04-1013 5. https://blog.csdn.net/mr2zhang/article/details/90754134 6. https://zhuanlan.zhihu.com/p/68253473 |轉(zhuǎn)載請注明來源地址:蜘蛛池出租 http://www.wholesalehouseflipping.com/專注于SEO培訓(xùn),快速排名黑帽SEO https://www.heimao.wiki
