如何生成文本: 通過(guò) Transformers 用不同的解碼方法生成文本

簡(jiǎn)介
近年來(lái),隨著以 OpenAI?GPT2 模型?為代表的基于數(shù)百萬(wàn)網(wǎng)頁(yè)數(shù)據(jù)訓(xùn)練的大型 Transformer 語(yǔ)言模型的興起,開(kāi)放域語(yǔ)言生成領(lǐng)域吸引了越來(lái)越多的關(guān)注。開(kāi)放域中的條件語(yǔ)言生成效果令人深刻,典型的例子有:?GPT2 在獨(dú)角獸話題上的精彩續(xù)寫(xiě),XLNet?以及?使用 CTRL 模型生成受控文本?等。促成這些進(jìn)展的除了 transformer 架構(gòu)的改進(jìn)和大規(guī)模無(wú)監(jiān)督訓(xùn)練數(shù)據(jù)外,更好的解碼方法?也發(fā)揮了不可或缺的作用。
本文簡(jiǎn)述了不同的解碼策略,同時(shí)向讀者展示了如何使用流行的?transformers
?庫(kù)輕松實(shí)現(xiàn)這些解碼策略!
下文中的所有功能均可用于?自回歸?語(yǔ)言生成任務(wù) (點(diǎn)擊?此處?回顧)。簡(jiǎn)單復(fù)習(xí)一下,?自回歸?語(yǔ)言生成是基于如下假設(shè): 一個(gè)文本序列的概率分布可以分解為每個(gè)詞基于其上文的條件概率的乘積。

上式中,W0?是初始?上下文?單詞序列。文本序列的長(zhǎng)度?通常時(shí)變的,并且對(duì)應(yīng)于時(shí)間步 t =?T。?P(wt|w1:t-1,?W0)的詞表中已包含 終止符 (End Of Sequence,EOS)。?transformers
?目前已支持的自回歸語(yǔ)言生成任務(wù)包括?GPT2
?、?XLNet
?、?OpenAi-GPT
?、?CTRL
?、?TransfoXL
?、?XLM
?、?Bart
?、?T5
?模型,并支持 PyTorch 和 TensorFlow (>= 2.0) 兩種框架!
我們會(huì)介紹目前最常用的解碼方法,主要有?貪心搜索 (Greedy search)、波束搜索 (Beam search)、Top-K 采樣 (Top-K sampling)?以及?Top-p 采樣 (Top-p sampling)?。
在此之前,我們先快速安裝一下?transformers
?并把模型加載進(jìn)來(lái)。本文我們用 GPT2 模型在 TensorFlow 2.1 中進(jìn)行演示,但 API 和使用 PyTorch 框架是一一對(duì)應(yīng)的。
貪心搜索
貪心搜索在每個(gè)時(shí)間步?都簡(jiǎn)單地選擇概率最高的詞作為當(dāng)前輸出詞:

從單詞 “The”?開(kāi)始,算法在第一步貪心地選擇條件概率最高的詞 “nice”?作為輸出,依此往后。最終生成的單詞序列為(“The”, “nice”,“woman”)?,其聯(lián)合概率為?。
下面,我們輸入文本序列?給 GPT2 模型,讓模型生成下文。我們以此為例看看如何在?transformers
?中使用貪心搜索:
print("Output:\n" + 100 *'-')
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with my dog. I'm not sure if I'll ever be able to walk with my dog.I'm not sure if I'll
print(tokenizer.decode(greedy_output[0], skip_special_tokens=True))
好,我們已經(jīng)用 GPT2 生成了第一個(gè)短文本[gf]1f60a[/gf]。根據(jù)上文生成的單詞是合理的,但模型很快開(kāi)始輸出重復(fù)的文本!這在語(yǔ)言生成中是一個(gè)非常普遍的問(wèn)題,在貪心搜索和波束搜索中似乎更是如此 - 詳見(jiàn)?Vijayakumar 等人,2016?和?Shao 等人,2017?的論文。
貪心搜索的主要缺點(diǎn)是它錯(cuò)過(guò)了隱藏在低概率詞后面的高概率詞,如上圖所示:
條件概率為 0.9?的單詞 “has”?隱藏在單詞 “dog”?后面,而?“dog”?因?yàn)樵?t=1
?時(shí)條件概率值只排第二所以未被選擇,因此貪心搜索會(huì)錯(cuò)過(guò)序列?“The”,“dog”,“has”。
幸好我們可以用波束搜索來(lái)緩解這個(gè)問(wèn)題!
波束搜索
波束搜索通過(guò)在每個(gè)時(shí)間步保留最可能的?num_beams
?個(gè)詞,并從中最終選擇出概率最高的序列來(lái)降低丟失潛在的高概率序列的風(fēng)險(xiǎn)。以?num_beams=2
?為例:

在時(shí)間步 1,除了最有可能的假設(shè)?(“The”, “nice”),波束搜索還跟蹤第二可能的假設(shè)(“The”, “dog”)。在時(shí)間步 2,波束搜索發(fā)現(xiàn)序列?(“The”, “dog”,“has”)?概率為 0.36,比?(“The”, “nice”,“woman”)?的 0.2?更高。太棒了,在我們的例子中它已經(jīng)找到了最有可能的序列!
波束搜索一般都會(huì)找到比貪心搜索概率更高的輸出序列,但仍不保證找到全局最優(yōu)解。
讓我們看看如何在?transformers
?中使用波束搜索。我們?cè)O(shè)置?num_beams > 1
?和?early_stopping=True
?以便在所有波束達(dá)到 EOS 時(shí)直接結(jié)束生成。
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.I'm not sure if I'll ever be able to walk with him again. I'm not sure if I'll
雖然結(jié)果比貪心搜索更流暢,但輸出中仍然包含重復(fù)。一個(gè)簡(jiǎn)單的補(bǔ)救措施是引入?n-grams?(即連續(xù) n 個(gè)詞的詞序列) 懲罰,該方法是由?Paulus 等人 (2017)?和?Klein 等人 (2017)?引入的。最常見(jiàn)的?n-grams?懲罰是確保每個(gè)?n-gram?都只出現(xiàn)一次,方法是如果看到當(dāng)前候選詞與其上文所組成的?n-gram?已經(jīng)出現(xiàn)過(guò)了,就將該候選詞的概率設(shè)置為 0。
我們可以通過(guò)設(shè)置?no_repeat_ngram_size=2
?來(lái)試試,這樣任意?2-gram?不會(huì)出現(xiàn)兩次:
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.I've been thinking about this for a while now, and I think it's time for me to take a break
不錯(cuò),看起來(lái)好多了!我們看到生成的文本已經(jīng)沒(méi)有重復(fù)了。但是,?n-gram?懲罰使用時(shí)必須謹(jǐn)慎,如一篇關(guān)于?紐約?這個(gè)城市的文章就不應(yīng)使用?2-gram?懲罰,否則,城市名稱在整個(gè)文本中將只出現(xiàn)一次!
波束搜索的另一個(gè)重要特性是我們能夠比較概率最高的幾個(gè)波束,并選擇最符合我們要求的波束作為最終生成文本。
在?transformers
?中,我們只需將參數(shù)?num_return_sequences
?設(shè)置為需返回的概率最高的波束的數(shù)量,記得確保?num_return_sequences <= num_beams
!
Output:----------------------------------------------------------------------------------------------------0: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.I've been thinking about this for a while now, and I think it's time for me to take a break1: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.I've been thinking about this for a while now, and I think it's time for me to get back to2: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.I've been thinking about this for a while now, and I think it's time for me to take a break3: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.I've been thinking about this for a while now, and I think it's time for me to get back to4: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.I've been thinking about this for a while now, and I think it's time for me to take a step
如我們所見(jiàn),五個(gè)波束彼此之間僅有少量差別 —— 這在僅使用 5 個(gè)波束時(shí)不足為奇。
開(kāi)放域文本生成的研究人員最近提出了幾個(gè)理由來(lái)說(shuō)明對(duì)該領(lǐng)域而言波束搜索可能不是最佳方案:
在機(jī)器翻譯或摘要等任務(wù)中,因?yàn)樗枭傻拈L(zhǎng)度或多或少都是可預(yù)測(cè)的,所以波束搜索效果比較好 - 參見(jiàn)?Murray 等人 (2018)?和?Yang 等人 (2018)?的工作。但開(kāi)放域文本生成情況有所不同,其輸出文本長(zhǎng)度可能會(huì)有很大差異,如對(duì)話和故事生成的輸出文本長(zhǎng)度就有很大不同。
我們已經(jīng)看到波束搜索已被證明存在重復(fù)生成的問(wèn)題。在故事生成這樣的場(chǎng)景中,很難用?n-gram?或其他懲罰來(lái)控制,因?yàn)樵凇安恢貜?fù)”和最大可重復(fù)?n-grams之間找到一個(gè)好的折衷需要大量的微調(diào)。
正如?Ari Holtzman 等人 (2019)?所論證的那樣,高質(zhì)量的人類語(yǔ)言并不遵循最大概率法則。換句話說(shuō),作為人類,我們希望生成的文本能讓我們感到驚喜,而可預(yù)測(cè)的文本使人感覺(jué)無(wú)聊。論文作者畫(huà)了一個(gè)概率圖,很好地展示了這一點(diǎn),從圖中可以看出人類文本帶來(lái)的驚喜度比波束搜索好不少。

因此,讓我們開(kāi)始玩點(diǎn)刺激的,引入一些隨機(jī)性。
采樣
在其最基本的形式中,采樣意味著根據(jù)當(dāng)前條件概率分布隨機(jī)選擇輸出詞?:

繼續(xù)使用上文中的例子,下圖可視化了使用采樣生成文本的過(guò)程。

很明顯,使用采樣方法時(shí)文本生成本身不再是?確定性的。單詞 “car”?從條件概率分布?P(w|“The”)?中采樣而得,而 “drives”?則采樣自?P(w|“The”,“car”)?。
在?transformers
?中,我們?cè)O(shè)置?do_sample=True
?并通過(guò)設(shè)置?top_k=0
?停用?Top-K?采樣 (稍后詳細(xì)介紹)。在下文中,為便于復(fù)現(xiàn),我們會(huì)固定?random_seed=0
,但你可以在自己的模型中隨意更改?random_seed
。
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog. He just gave me a whole new hand sense."But it seems that the dogs have learned a lot from teasing at the local batte harness once they take on the outside."I take
有意思!生成的文本看起來(lái)不錯(cuò) - 但仔細(xì)觀察會(huì)發(fā)現(xiàn)它不是很連貫。?3-grams?new hand sense?和?local batte harness?非常奇怪,看起來(lái)不像是人寫(xiě)的。這就是對(duì)單詞序列進(jìn)行采樣時(shí)的大問(wèn)題: 模型通常會(huì)產(chǎn)生不連貫的亂碼,?參見(jiàn)?Ari Holtzman 等人 (2019)?的論文。
緩解這一問(wèn)題的一個(gè)技巧是通過(guò)降低所謂的?softmax?的“溫度”使分布?更陡峭。而降低“溫度”,本質(zhì)上是增加高概率單詞的似然并降低低概率單詞的似然。
將溫度應(yīng)用到于我們的例子中后,結(jié)果如下圖所示。

t = 1 時(shí)刻單詞的條件分布變得更加陡峭,幾乎沒(méi)有機(jī)會(huì)選擇單詞 “car”?了。
讓我們看看如何通過(guò)設(shè)置?temperature=0.7
?來(lái)冷卻生成過(guò)程:
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog, but I don't like to be at home too much. I also find it a bit weird when I'm out shopping. I am always away from my house a lot, but I do have a few friends
好,奇怪的 n-gram 變少了,現(xiàn)在輸出更連貫了!雖然溫度可以使分布的隨機(jī)性降低,但極限條件下,當(dāng)“溫度”設(shè)置為?時(shí),溫度縮放采樣就退化成貪心解碼了,因此會(huì)遇到與貪心解碼相同的問(wèn)題。
Top-K 采樣
Fan 等人 (2018)?的論文介紹了一種簡(jiǎn)單但非常強(qiáng)大的采樣方案,稱為?Top-K?采樣。在?Top-K?采樣中,概率最大的?K?個(gè)詞會(huì)被選出,然后這?K?個(gè)詞的概率會(huì)被重新歸一化,最后就在這重新被歸一化概率后的?K?個(gè)詞中采樣。 GPT2 采用了這種采樣方案,這也是它在故事生成這樣的任務(wù)上取得成功的原因之一。
我們將上文例子中的候選單詞數(shù)從 3 個(gè)單詞擴(kuò)展到 10 個(gè)單詞,以更好地說(shuō)明?Top-K?采樣。

設(shè)?,即我們將在兩個(gè)采樣步的采樣池大小限制為 6 個(gè)單詞。我們定義 6 個(gè)最有可能的詞的集合為?。在第一步中,?僅占總概率的大約三分之二,但在第二步,它幾乎占了全部的概率。同時(shí),我們可以看到在第二步該方法成功地消除了那些奇怪的候選詞?。
我們以設(shè)置?top_k=50
?為例看下如何在?transformers
?庫(kù)中使用?Top-K:
Output:----------------------------------------------------------------------------------------------------I enjoy walking with my cute dog. It's so good to have an environment where your dog is available to share with you and we'll be taking care of you.We hope you'll find this story interesting!I am from
相當(dāng)不錯(cuò)!該文本可以說(shuō)是迄今為止生成的最 "像人" 的文本?,F(xiàn)在還有一個(gè)問(wèn)題,?Top-K?采樣不會(huì)動(dòng)態(tài)調(diào)整從需要概率分布?P(w|w1:t-1)?中選出的單詞數(shù)。這可能會(huì)有問(wèn)題,因?yàn)槟承┓植伎赡苁欠浅<怃J (上圖中右側(cè)的分布),而另一些可能更平坦 (上圖中左側(cè)的分布),所以對(duì)不同的分布使用同一個(gè)絕對(duì)數(shù)?K?可能并不普適。
在 t = 1?時(shí),?Top-K?將(“people”, “big”,“cat”)排出了采樣池,而這些詞似乎是合理的候選詞。另一方面,在 t = 2?時(shí),該方法卻又把不太合適的 (“down”, “a”)?納入了采樣池。因此,將采樣池限制為固定大小?K?可能會(huì)在分布比較尖銳的時(shí)候產(chǎn)生胡言亂語(yǔ),而在分布比較平坦的時(shí)候限制模型的創(chuàng)造力。這一發(fā)現(xiàn)促使?Ari Holtzman 等人 (2019)?發(fā)明了?Top-p?- 或?核- 采樣。
Top-p (核) 采樣
在?Top-p?中,采樣不只是在最有可能的?K?個(gè)單詞中進(jìn)行,而是在累積概率超過(guò)概率?p?的最小單詞集中進(jìn)行。然后在這組詞中重新分配概率質(zhì)量。這樣,詞集的大小 (又名?集合中的詞數(shù)) 可以根據(jù)下一個(gè)詞的概率分布動(dòng)態(tài)增加和減少。好吧,說(shuō)的很啰嗦,一圖勝千言。

假設(shè) p= 0.92?,?Top-p?采樣對(duì)單詞概率進(jìn)行降序排列并累加,然后選擇概率和首次超過(guò) p = 92?的單詞集作為采樣池,定義為 Vtop-p?。在 t = 1時(shí)?Vtop-p?有 9 個(gè)詞,而在 t = 2?時(shí)它只需要選擇前 3 個(gè)詞就超過(guò)了 92%。其實(shí)很簡(jiǎn)單吧!可以看出,在單詞比較不可預(yù)測(cè)時(shí),它保留了更多的候選詞,?如?P(w|“The”),而當(dāng)單詞似乎更容易預(yù)測(cè)時(shí),只保留了幾個(gè)候選詞,?如?P(w|“The”,“car”)。
好的,是時(shí)候看看它在?transformers
?里怎么用了!我們可以通過(guò)設(shè)置?0 < top_p < 1
?來(lái)激活?Top-p?采樣:
Output:
----------------------------------------------------------------------------------------------------
I enjoy walking with my cute dog. He will never be the same. I watch him play.
Guys, my dog needs a name. Especially if he is found with wings.
What was that? I had a lot o
太好了,這看起來(lái)跟人類寫(xiě)的差不多了,雖然還不算完全是。
雖然從理論上講,?Top-p?似乎比?Top-K?更優(yōu)雅,但這兩種方法在實(shí)踐中都很有效。?Top-p?也可以與?Top-K?結(jié)合使用,這樣可以避免排名非常低的詞,同時(shí)允許進(jìn)行一些動(dòng)態(tài)選擇。
最后,如果想要獲得多個(gè)獨(dú)立采樣的輸出,我們可以?再次?設(shè)置參數(shù)?num_return_sequences > 1
:
Output:
----------------------------------------------------------------------------------------------------
0: I enjoy walking with my cute dog. It's so good to have the chance to walk with a dog. But I have this problem with the dog and how he's always looking at us and always trying to make me see that I can do something
1: I enjoy walking with my cute dog, she loves taking trips to different places on the planet, even in the desert! The world isn't big enough for us to travel by the bus with our beloved pup, but that's where I find my love
2: I enjoy walking with my cute dog and playing with our kids," said David J. Smith, director of the Humane Society of the US.
"So as a result, I've got more work in my time," he said.
很酷,現(xiàn)在你擁有了所有可以在?transformers
?里用模型來(lái)幫你寫(xiě)故事的工具了!
總結(jié)
在開(kāi)放域語(yǔ)言生成場(chǎng)景中,作為最新的解碼方法,?top-p?和?top-K?采樣于傳統(tǒng)的?貪心?和?波束?搜索相比,似乎能產(chǎn)生更流暢的文本。但,最近有更多的證據(jù)表明?貪心?和?波束?搜索的明顯缺陷 - 主要是生成重復(fù)的單詞序列 - 是由模型 (特別是模型的訓(xùn)練方式) 引起的,而不是解碼方法,?參見(jiàn)?Welleck 等人 (2019)?的論文。此外,如?Welleck 等人 (2020)?的論文所述,看起來(lái)?top-K?和?top-p?采樣也會(huì)產(chǎn)生重復(fù)的單詞序列。
在?Welleck 等人 (2019)?的論文中,作者表明,根據(jù)人類評(píng)估,在調(diào)整訓(xùn)練目標(biāo)后,波束搜索相比?Top-p?采樣能產(chǎn)生更流暢的文本。
開(kāi)放域語(yǔ)言生成是一個(gè)快速發(fā)展的研究領(lǐng)域,而且通常情況下這里沒(méi)有放之四海而皆準(zhǔn)的方法,因此必須了解哪種方法最適合自己的特定場(chǎng)景。
好的方面是,?你?可以在?transfomers
?中嘗試所有不同的解碼方法 [gf]1f917[/gf]。
以上是對(duì)如何在?transformers
?中使用不同的解碼方法以及開(kāi)放域語(yǔ)言生成的最新趨勢(shì)的簡(jiǎn)要介紹。
非常歡迎大家在?Github 代碼庫(kù)?上提供反饋和問(wèn)題。
如果想要體驗(yàn)下用模型生成故事的樂(lè)趣,可以訪問(wèn)我們的 web 應(yīng)用?Writing with Transformers。
感謝為本文做出貢獻(xiàn)的所有人: Alexander Rush、Julien Chaumand、Thomas Wolf、Victor Sanh、Sam Shleifer、Clément Delangue、Yacine Jernite、Oliver [gf]c5[/gf]strand 和 John de Wasseige。
附錄
generate
?方法還有幾個(gè)正文未提及的參數(shù),這里我們簡(jiǎn)要解釋一下它們!
min_length
?用于強(qiáng)制模型在達(dá)到?min_length
?之前不生成 EOS。這在摘要場(chǎng)景中使用得比較多,但如果用戶想要更長(zhǎng)的文本輸出,也會(huì)很有用。repetition_penalty
?可用于對(duì)生成重復(fù)的單詞這一行為進(jìn)行懲罰。它首先由?Keskar 等人 (2019)?引入,在?Welleck 等人 (2019)?的工作中,它是訓(xùn)練目標(biāo)的一部分。它可以非常有效地防止重復(fù),但似乎對(duì)模型和用戶場(chǎng)景非常敏感,其中一個(gè)例子見(jiàn) Github 上的?討論。attention_mask
?可用于屏蔽填充符。pad_token_id
、bos_token_id
、eos_token_id
: 如果模型默認(rèn)沒(méi)有這些 token,用戶可以手動(dòng)選擇其他 token id 來(lái)表示它們。
更多信息,請(qǐng)查閱?generate
?函數(shù) 手冊(cè)。
英文原文:?https://hf.co/blog/how-to-generate
原文作者: Patrick von Platen
譯者: Matrix Yao (姚偉峰),英特爾深度學(xué)習(xí)工程師,工作方向?yàn)?transformer-family 模型在各模態(tài)數(shù)據(jù)上的應(yīng)用及大規(guī)模模型的訓(xùn)練推理。
審校/排版: zhongdongy (阿東)