本文將介紹如何利用sentence embedding來(lái)做文本摘要。
什么是文本摘要?
文本摘要是從一些文本資源中抽取重要信息并生成“主旨帝际、概要”的過(guò)程。
我們小時(shí)候的語(yǔ)文課上饶辙,老師要求概括段落大意蹲诀,指出主題思想。所以弃揽,人類很擅長(zhǎng)“文本摘要”這樣的工作脯爪,
首先通過(guò)理解文字內(nèi)容的含義,抽取重要信息矿微,并用自己的語(yǔ)言概括痕慢。在這樣一個(gè)信息爆炸的時(shí)代,人類已經(jīng)
沒有足夠的精力閱讀海量文本涌矢,自動(dòng)文本摘要算法應(yīng)運(yùn)而生:
文本摘要節(jié)省閱讀時(shí)間
文本摘要精簡(jiǎn)了文本信息掖举,讓文本檢索過(guò)程更簡(jiǎn)單,提升了檢索效率
文本摘要算法更加客觀娜庇,減少了人類的主觀“偏見”
QA系統(tǒng)中的文本摘要塔次,利于理解用戶個(gè)性化的需求
文本摘要的類型
文本摘要的類型有很多種方篮,根據(jù)輸入、意圖励负、輸出可以分為以下幾類:
[圖片上傳失敗...(image-c85cf9-1542199235016)]
根據(jù)輸入類型劃分
單文檔文本摘要
輸入是單個(gè)文檔藕溅,輸入的文本長(zhǎng)度不長(zhǎng),可以是一篇新聞继榆。早起的文本摘要系統(tǒng)都是處理單文檔的巾表。
多文檔文本摘要
輸入時(shí)多個(gè)文檔,可以是多篇新聞略吨。
根據(jù)意圖劃分
通用文本摘要
輸入文本可以是各種各樣的文本攒发,比如新聞、小說(shuō)等晋南。這一部分有大量的研究工作。
特定領(lǐng)域文本摘要
文本摘要模型要融入領(lǐng)域相關(guān)知識(shí)羔砾,來(lái)生成更準(zhǔn)確的摘要负间,比如生物醫(yī)學(xué)文檔的文本摘要生成。
基于用戶請(qǐng)求的文本摘要
根據(jù)用戶與會(huì)話機(jī)器人的對(duì)話內(nèi)容姜凄,生成會(huì)話內(nèi)容相關(guān)的文本摘要政溃。
基于輸出類型的文本摘要
抽取式
從文本中抽取句子,然后組合成為摘要态秧。這是目前廣泛使用的文本摘要算法董虱,這種文本摘要算法產(chǎn)生的句子一般沒有語(yǔ)病、邏輯問題(因?yàn)槭菑奈谋局谐槿〉穆铮?/p>
生成式
生成式的文本摘要首先從模型中申鱼,抽取phrase和sentence愤诱,然后生成摘要(很像人們概括段落大意的方式)。所以捐友,這種方法更有趣淫半、更貼近實(shí)際,當(dāng)然也更加難匣砖。
很多文本摘要算法的訓(xùn)練都需要有raw text和對(duì)應(yīng)的summary作為訓(xùn)練數(shù)據(jù)科吭。但是在大量的nlp任務(wù)中,很難獲得訓(xùn)練數(shù)據(jù)猴鲫,或者獲得訓(xùn)練數(shù)據(jù)的代價(jià)非常大对人。所以在實(shí)際的業(yè)務(wù)中,更傾向于unsupervised的方法拂共。這里簡(jiǎn)單介紹一下Kushal Chauhan在郵件文本summary方面的工作牺弄,介紹他是如何使用sentence embedding來(lái)做email summary的。
Kushal Chauhan為什么要用unsupervised text summarization方法呢匣缘?通用的文本摘要無(wú)法在郵件文本中發(fā)揮作用猖闪。一方面鲜棠,數(shù)據(jù)分布是不同的;另一方面培慌,Kushal面對(duì)的事多語(yǔ)言的文檔包含English, Danish, French等語(yǔ)言豁陆。他借鑒了《Unsupervised Text Summarization Using Sentence Embeddings》這篇論文中的方法,構(gòu)建了如下Pipeline:
步驟1:email數(shù)據(jù)清洗
首先吵护,我們來(lái)看一下email文本:
Hi Jane,
Thank you for keeping me updated on this issue. I'm happy to hear that the issue got resolved after all and you can now use the app in its full functionality again.
Also many thanks for your suggestions. We hope to improve this feature in the future.
In case you experience any further problems with the app, please don't hesitate to contact me again.
Best regards,
John Doe
Customer Support
1600 Amphitheatre Parkway
Mountain View, CA
United States
email開頭的 Hi name以及結(jié)尾的 best regards + name對(duì)文本摘要是沒有用處的盒音。郵件中的開頭和結(jié)尾“形態(tài)各異”,需要相應(yīng)的正則表達(dá)式去識(shí)別并刪除馅而。mailgun/talon在其github repo中實(shí)現(xiàn)了刪除郵件開頭祥诽、結(jié)尾的功能,支持多種語(yǔ)言(對(duì)于中文的支持,尚需檢驗(yàn))。這里我們給出代碼示例:
# clean() is a modified version of extract_signature() found in bruteforce.py in the GitHub repository linked above
cleaned_email, _ = clean(email)
lines = cleaned_email.split('\n')
lines = [line for line in lines if line != '']
cleaned_email = ' '.join(lines)
上面的email經(jīng)過(guò)處理繁堡,可以得到:
Thank you for keeping me updated on this issue. I'm happy to hear that the issue got resolved after all and you can now use the app in its full functionality again. Also many thanks for your suggestions. We hope to improve this feature in the future. In case you experience any further problems with the app, please don't hesitate to contact me again.
步驟2: 語(yǔ)言檢測(cè)
不同語(yǔ)言的sentence tokenization不同斑唬,不能都當(dāng)做英文進(jìn)行處理。所以,首先使用polyglot, langdetect 或 textblob來(lái)進(jìn)行語(yǔ)言檢測(cè)。langdetect的相關(guān)內(nèi)容,我在funNLP中介紹過(guò)阔挠,它支持55種不同的語(yǔ)言識(shí)別,如下所示:
from langdetect import detect
lang = detect(cleaned_email) # lang = 'en' for an English email
步驟3: 句子分割
識(shí)別出email使用的語(yǔ)言后脑蠕,使用對(duì)應(yīng)語(yǔ)言的tokenization方法购撼,對(duì)email進(jìn)行句子分割。對(duì)于英文email谴仙,可以使用nltk中的sent_tokenize進(jìn)行分割即可:
from nltk.tokenize import sent_tokenize
sentences = sent_tokenize(email, language = lang)
步驟4: skip-thought encoder
這一部分介紹如何對(duì)句子進(jìn)行編碼迂求。句子的編碼方式多種多樣,最簡(jiǎn)單的莫過(guò)于將句子中的每個(gè)詞對(duì)應(yīng)的詞向量加起來(lái)晃跺,再平均锁摔,類似于fasttext的做法。在此基礎(chǔ)上哼审,復(fù)雜一點(diǎn)的谐腰,不同的詞有不同的權(quán)重,比如 and, the 這類詞權(quán)重就應(yīng)該低一些涩盾。此時(shí)十气,可以使用tf-idf相關(guān)信息做權(quán)重。論文《A SIMPLE BUT TOUGH-TO-BEAT BASELINE FOR SEN- TENCE EMBEDDINGS》就是這么做的春霍。
上述方法砸西,沒有考慮句子中的詞的順序,這很可能會(huì)影響summarization的模型表現(xiàn),所以采用了skip-thought sentence encoder芹枷,并以wikipedia作為訓(xùn)練數(shù)據(jù)衅疙。skip-thought sentence encoder包含兩個(gè)部分:
- encoder network: GRU-RNN用于生成固定長(zhǎng)度的句子向量表示。
- decoder network: 用于產(chǎn)生的前后句和鸳慈,前后兩句采用分別的decoder:previous decoder和next decoder饱溢。
跟skip gram有點(diǎn)像,給定中間的元素走芋,預(yù)測(cè)前后的元素绩郎。skip-thought encoder最小化句子重構(gòu)的Loss,這樣encoder就能夠?qū)W會(huì)正確地編碼句子翁逞。對(duì)于具有類似意思的句子肋杖,其編碼后的向量依然相近⊥诤《Skip-Thought Vectors》論文中闡述了更多的細(xì)節(jié)状植。
[圖片上傳失敗...(image-932a53-1542199235016)]](https://upload-images.jianshu.io/upload_images/2528310-637b6b05249bcd13.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
作者使用了theano開源代碼來(lái)做訓(xùn)練,pytorch版本開源代碼怨喘。
將句子編碼的代碼就變得非常簡(jiǎn)單了:
# The 'skipthoughts' module can be found at the root of the GitHub repository linked above
import skipthoughts
# You would need to download pre-trained models first
model = skipthoughts.load_model()
encoder = skipthoughts.Encoder(model)
encoded = encoder.encode(sentences)
步驟5: 聚類
將email中的每一個(gè)句子編碼后浅萧,可以使用k-means進(jìn)行聚類。聚類的數(shù)目等于summary的句子數(shù)目哲思。
import numpy as np
from sklearn.cluster import KMeans
n_clusters = np.ceil(len(encoded)**0.5)
kmeans = KMeans(n_clusters=n_clusters)
kmeans = kmeans.fit(encoded)
步驟5: 形成摘要
對(duì)于幾個(gè)cluster,選取距離cluster中心最近的句子吩案。選出句子后棚赔,如何對(duì)這些句子排序呢?分析每個(gè)cluster中的全部句子在原文中的順序徘郭,如果該cluster中的多數(shù)句子排在第一靠益,那么該cluster中選取的那個(gè)句子也排在第一句,代碼如下:
from sklearn.metrics import pairwise_distances_argmin_min
avg = []
for j in range(n_clusters):
idx = np.where(kmeans.labels_ == j)[0]
avg.append(np.mean(idx))
closest, _ = pairwise_distances_argmin_min(kmeans.cluster_centers_, encoded)
ordering = sorted(range(n_clusters), key=lambda k: avg[k])
summary = ' '.join([email[closest[idx]] for idx in ordering])
上文中的郵件残揉,summary結(jié)果如下:
I'm happy to hear that the issue got resolved after all and you can now use the app in its full functionality again.
Also many thanks for your suggestions.
In case you experience any further problems with the app, please don't hesitate to contact me again.
skip-thought encoder的訓(xùn)練語(yǔ)料來(lái)自wikipedia胧后。email summarization的源代碼詳見github。
總結(jié)一下抱环,本文使用了wikipedia的數(shù)據(jù)壳快,訓(xùn)練了skip-thought encoder,用來(lái)做sentence embedding镇草,拿到embedding后眶痰,做clustering,然后挑選句子梯啤,并根據(jù)cluster中的所有句子的位置 進(jìn)行排序竖伯。