0
雷鋒網(wǎng) AI 科技評論按:人們已經(jīng)給神經(jīng)網(wǎng)絡(luò)找到了越來越多人的事情做,比如畫畫和寫詩,微軟的小冰都已經(jīng)出版了一本詩集了。而其實訓(xùn)練一個能寫詩的神經(jīng)網(wǎng)絡(luò)并不難,Automattic 公司的數(shù)據(jù)科學(xué)家 Carly Stambaugh 就寫了一篇文章介紹如何簡單快捷地建立一個會寫詩的人工智能。雷鋒網(wǎng) AI 科技評論全文翻譯如下。
「代碼即詩篇」,這是 WordPress 社區(qū)的哲學(xué)。
作為一個 coder 同時也是一個詩人,我一直都十分喜愛這句話。然而,如果將這句話翻轉(zhuǎn)過來,我不禁要問:「我能否通過代碼寫詩呢?我能否創(chuàng)造一個能夠?qū)懗鲈瓌?chuàng)性詩詞的機器?」于是,我做了一系列實驗去探究這個問題的答案。
首先,我們都知道如果想讓機器學(xué)會寫詩,那么它必須先學(xué)會讀詩。在整個 2017 年中,使用 WordPress 系統(tǒng)發(fā)布的、標(biāo)注為詩歌的帖子有超過 50 萬篇(https://wordpress.com/tag/poetry)。我聯(lián)系了一些通過 WordPress 分享作品的高產(chǎn)詩人,詢問他們是否愿意與我合作完成一個有趣的實驗:能否讓我的機器閱讀他們的作品,讓我的機器能夠?qū)W到詩歌的形式和結(jié)構(gòu),最終讓機器能夠自己完成詩歌創(chuàng)作?
O at the Edges – Robert Okaji(https://robertokaji.com )
Wolff Poetry – Linda J. Wolff(http://wolffpoetry.com )
Poetry, Short Prose and Walking – Frank Hubeny(https://frankhubeny.blog )
Perspectives on Life, the Universe and Everything – Aurangzeb Bozdar(https://abozdar.wordpress.com )
我使用了一種名為 LSTM (Long Short Term Memory network, 即長短時期記憶網(wǎng)絡(luò)) 的神經(jīng)網(wǎng)絡(luò)來構(gòu)建我的詩歌機器人。
神經(jīng)網(wǎng)絡(luò)通過層次結(jié)構(gòu)將一個問題分解為多個小問題。舉例而言,假如你想訓(xùn)練一個用于識別正方形的神經(jīng)網(wǎng)絡(luò),其中一層可能會負(fù)責(zé)識別直角,另一層可能負(fù)責(zé)識別平行線。為了將圖片認(rèn)定為正方形,所有這些特征都會被機器呈現(xiàn)出來。神經(jīng)網(wǎng)絡(luò)會通過將數(shù)以百萬計的正方形圖片作為輸入訓(xùn)練模型,從而學(xué)習(xí)到這些必要的特征的參數(shù)。這個機器還會學(xué)到圖片的哪些特征對于識別正方形是重要的,哪些是不重要的。
現(xiàn)在,假設(shè)你想要使用神經(jīng)網(wǎng)路去預(yù)測這兩個字母的下一個字母:
Th_
對于一個人來說,這個任務(wù)是十分簡單的。很有可能,你猜下一個字母應(yīng)該是 e。但是,我敢打賭,如果你是一個說英語的人,你不會猜下一個字母是 q。這是因為你已經(jīng)通過學(xué)習(xí)知道:在英語中,q 不會跟在 th 的后面。一個單詞中,前面的字母對于預(yù)測后面會出現(xiàn)什么字母是及其相關(guān)的。一個 LSTM 可以「記住」它之前的狀態(tài)并將其告訴它當(dāng)前的決策過程。關(guān)于 LSTM 如何工作的更深入的解釋,可以參考谷歌大腦的 Chris Olah 所寫的這篇精彩的文章。
與許多基于 LSTM 的文本生成案例一樣,我的詩歌機器人通過一次生成一個字符來生成文本。因此,要想把單詞組合成任何有意義的樣式,詩歌機器人首先必須學(xué)會如何造詞。為了實現(xiàn)這一點,它需要數(shù)百萬個有效的單詞的例句。值得慶幸的是,WordPress.com 上有海量的詩歌。
首先,我從 Elasticsearch 索引中抓取了上面列出的所有網(wǎng)站中的詩歌。我使用一種非常簡單的規(guī)則(根據(jù)每遇到一次「\n」的字符和上一個「\n」之間的詞數(shù))把除了詩歌的文本之外的所有東西清洗掉了。如果一塊文本包含許多單詞但是包含很少的「\n」字符,它可能是一個或多個段落的集合。然而,一塊跨越多行的文本更有可能是一首詩。這是一個簡單的方法,當(dāng)然,我可以想到很多優(yōu)秀的詩歌都無法滿足這個規(guī)則!但是,就本實驗的目的而言,我對于 LSTM 是否能學(xué)習(xí)到諸如換行、詩的章節(jié)等詩歌的結(jié)構(gòu),以及其他的例如押韻、類韻、輔韻、頭韻修辭手法十分感興趣。因此,將訓(xùn)練數(shù)據(jù)限制為相當(dāng)結(jié)構(gòu)化的詩歌是合理的。
一旦一塊文本被認(rèn)定為一首詩,我就將它輸出到一個文本文件,并且在他前面加上「++++\n」的前綴以表示一首新詩的開始。這樣做可以產(chǎn)生大約 500KB 的訓(xùn)練數(shù)據(jù)。通常,我試著使用至少 1MB 的文本去訓(xùn)練一個 LSTM 網(wǎng)絡(luò),因此,我需要尋找更多的詩歌!為了補充更多有特色的詩人的作品,我使用了去年發(fā)表的被標(biāo)記為詩歌的公開的帖子中產(chǎn)生的隨機樣本。這就好像你在 WordPress.com 閱讀器里用詩歌標(biāo)簽瀏覽之后(https://en.wordpress.com/tag/poetry/)得到的結(jié)果。我將隨機抓取的詩歌的規(guī)模限制在每個詩人一個帖子。
當(dāng)我有了超過 1MB 的詩歌之后,我開始構(gòu)建一個 LSTM 網(wǎng)絡(luò)。我使用 Python 深度學(xué)習(xí)庫 keras 以滿足我所有對神經(jīng)網(wǎng)絡(luò)的需求。keras(https://github.com/keras-team/keras)在 Github 上的 repo 代碼倉庫有許多示例文件,可以幫助學(xué)習(xí)一系列不同的神經(jīng)網(wǎng)絡(luò),其中就包括使用 LSTM 生成文本(https://github.com/keras-team/keras/blob/master/examples/lstm_text_generation.py )。我根據(jù)這個示例編寫了我的模型的代碼,并且開始進(jìn)行不同模型配置之下的實驗。這個模型的目標(biāo)是要產(chǎn)生原創(chuàng)的詩歌。在這種情況下,過擬合,換而言之,太過于詳細(xì)地學(xué)習(xí)訓(xùn)練數(shù)據(jù)以致于模型不能很好地泛化,會導(dǎo)致生成的文本與輸入地文本太相似。(這就好像剽竊,沒有詩人會喜歡這樣做!)一個防止過擬合的方法是在網(wǎng)絡(luò)中使用 dropout 。這就迫使在每一個批次的訓(xùn)練中,隨機地使一個子集的節(jié)點權(quán)重降為 0。這有點像迫使網(wǎng)絡(luò)「忘記」一些它剛剛學(xué)到的知識。(我還添加了額外的后期處理去檢查,防止詩人的作品被詩歌機器人復(fù)制)
我使用 FloydHub(https://www.floydhub.com/ )的 GPU 來完成我的神經(jīng)網(wǎng)絡(luò)繁重的訓(xùn)練工作。這使我能夠以將近比我的筆記本快十倍的速度訓(xùn)練我的神經(jīng)網(wǎng)絡(luò)。我的第一個神經(jīng)網(wǎng)絡(luò)有一個 LSTM 層,后面跟隨著一個 dropout 層。這個網(wǎng)絡(luò)產(chǎn)生了一個看上去十分像詩歌的文本。它有換行和詩的章節(jié),并且?guī)缀跛械淖址M合都是真實的單詞。偶爾整行都是較為通順的。實際上,它第一次迭代產(chǎn)生了這樣的佳句:
我增加了一些 LSTM 層,嘗試著改變每一層中 dropout 的程度,知道最終定下了一個如下面代碼所示的最終模型。我最終選擇使用三層 LSTM,因為此時訓(xùn)練時間開始變得很長,而訓(xùn)練的結(jié)果相當(dāng)好。(下面是程序代碼)
1. model = Sequential()
2. model.add(LSTM(300, input_shape=(maxlen, len(chars)), return_sequences=True, dropout=.20, recurrent_dropout=.20))
3. model.add(LSTM(300, return_sequences=True, dropout=.20, recurrent_dropout=.20))
4. model.add(LSTM(300, dropout=.20, recurrent_dropout=.20))
5. model.add(Dropout(.20))
6. model.add(Dense(len(chars)))
7. model.add(Activation('softmax'))
8. model.compile(loss='categorical_crossentropy', optimizer='adam')
這里有一個圖,比較了隨著LSTM層數(shù)增加而變化的模型的損失函數(shù)曲線。
隨著模型中LSTM層數(shù)增加,驗證損失迅速下降
哦!這是怎么回事呢?(https://stats.stackexchange.com/questions/303857/explanation-of-spikes-in-training-loss-vs-iterations-with-adam-optimizer )事實上,當(dāng)我們使用 adam 優(yōu)化器訓(xùn)練模型時,這是很常見的。注意,隨著我向網(wǎng)絡(luò)中增加 LSTM 層,模型的驗證損失整體上以很快的速率持續(xù)下降。這說明在較少的迭代次數(shù)內(nèi)可以得到可行的實驗結(jié)果,但是額外的 LSTM 層會增加每次迭代的訓(xùn)練時間。訓(xùn)練單層 LSTM 時,每次迭代大概需要 600 秒,一晚上可以完成實驗。然而,訓(xùn)練三層 LSTM 時,每次迭代需要 7000 秒,總共需要好幾天的時間完成訓(xùn)練。所以,更快的驗證損失的下降實際上并不意味著更快地得出結(jié)果。完全從我的主觀視角來說,盡管需要花費更多時間去訓(xùn)練,使用三層 LSTM 層的網(wǎng)絡(luò)生成的詩是更好的。
為了產(chǎn)生完全原創(chuàng)的文本,我還需要改變文本的生成方式。在 keras 庫中的示例中,腳本從訓(xùn)練數(shù)據(jù)中選擇一個隨機的字符序列作為輸入,即訓(xùn)練神經(jīng)網(wǎng)絡(luò)的種子。我想要構(gòu)建一個能寫出原創(chuàng)詩歌的詩歌機器人,而不是轉(zhuǎn)寫其他詩人的詩句!因此,我在生成文本的步驟中,嘗試了不同的種子。由于我已經(jīng)在訓(xùn)練集合中為每首詩加上了「++++\n」的開頭,我想這就已經(jīng)注意創(chuàng)造完全原創(chuàng)的詩歌了。但是結(jié)果是一組沒有意義的「\n」、「.」、「_」和「&」的組合。盡管反復(fù)的試驗和糾錯,我發(fā)現(xiàn)種子序列需要與訓(xùn)練序列擁有相同數(shù)目的字符。在事后看來,這是顯而易見的。最終,我使用了一個有 300 個字符的序列,我通過重復(fù)「++++\n」來生成剛好 300 個字符的用于文本生成的種子。這個詩歌機器人每輪可以生成幾首詩并偶爾用「++++\n」將這幾首詩分割開來。
在腳本生成了新一輪詩歌后,我做了最后的剽竊檢查。為了達(dá)到這一點,我首先在訓(xùn)練集中建立了一個所有 4-gram(包含 4 個單詞的短語)的集合,并且對我的詩歌機器人寫的詩做了同樣的操作。之后,我計算出了這兩個集合的交集。為了達(dá)到本實驗的目的,我手動檢查了 4-gram,確保出現(xiàn)在兩個 4-gram 集合中的短語是無意義的。多數(shù)時候,這個交集里的短語都是這樣:
i don't want
i can not be
i want to be
the sound of the
為了得到更好的測試結(jié)果,我在 5-gram 和 6-gram 上重復(fù)了這個步驟。如果我要將這個過程自動化,我可能會采用一種基于頻率的方法,并且排除掉那些被認(rèn)為是剽竊的、多個作者詩作間的共同的 n-gram。
在每一輪迭代之后輸出模型的權(quán)重意味著我們可以在訓(xùn)練時在一些節(jié)點上裝載模型的快照。當(dāng)我們觀察最終模型的前期迭代時,很顯然,詩歌機器人會立刻領(lǐng)悟換行技巧。我預(yù)料到了這一點,因為根據(jù)設(shè)計,訓(xùn)練設(shè)計最顯著的特征是每行字符數(shù)很少。下面是一個經(jīng)過一輪迭代的訓(xùn)練生成的詩:
詩歌機器人已經(jīng)學(xué)習(xí)到了一些真實的詞匯,并且模仿在行與行之間留出空白的常見做法。乍看之下,如果你不仔細(xì)探究,這看上去就像一首詩。在單層 LSTM 模型的損失函數(shù)收斂之后,除了換行,模型還學(xué)會了詩的分節(jié),甚至顯示出了一些常見的重復(fù)的詩歌修辭手法。
LSTM 的強大之處在單行詩句中非常明顯了。除了本文題目的那一行,另一個我最喜歡的詩行是:
在有史以來最有趣的格言機器人 Inspirobot 的輔助下,Demet從她最愛的詩行中學(xué)習(xí),創(chuàng)造了這樣的佳句:
盡管單一的 LSTM 模型在一首詩中并沒有完全掌握主題,但它在整個作品的創(chuàng)作過程中似乎都有一個共同的主線。下面是一個從所有單層 LSTM 模型生成的詩詞中產(chǎn)生的詞云:
多么令人沉醉??!這個詩歌機器人著迷于驕陽和星辰
如果太陽是訓(xùn)練數(shù)據(jù)中最常見的主題,那也就不足為奇了,然而事實并非如此!下面是一個訓(xùn)練數(shù)據(jù)中產(chǎn)生的詞云:
Emily Dickinson曾經(jīng)描寫過關(guān)于自然和死亡的詩歌。我的詩歌機器人則描寫關(guān)于天體的詩歌。各有千秋!
在增加了第二層 LSTM 網(wǎng)絡(luò)之后,我開始看到了其他的類似于頭韻和押韻的詩歌修辭手法:
它也開始寫出一些十分有詩意的短語。這些短語有些類似于之前的模型偶爾產(chǎn)生的絕佳的詩句,但是他們有些時候跨越了不止一行。例如:
天??!這就很深刻了!
到了這里,我們已經(jīng)看到了換行、節(jié)律、押韻(包括在中間和結(jié)尾)、重復(fù)和頭韻。這還不錯!但是,除了偶得的佳句,這時詩歌機器人寫出的詩大多數(shù)都是不通順的單詞的集合。在大多數(shù)情況下,它沒有意義的短語甚至都不符合語法結(jié)構(gòu)規(guī)范。
然而,隨著第三層 LSTM 的加入,這個情況產(chǎn)生了改觀。即使仍然沒有意義,模型產(chǎn)生的詩句更加可能合乎語法規(guī)范。例如:
這個句子似乎說不通,但是它恰當(dāng)?shù)匕才帕苏Z言的各個組成部分。它也包含頭韻的修辭手法,名詞性從句也有詩意的感覺。三層 LSTM 的網(wǎng)絡(luò)模型也產(chǎn)生了三行我認(rèn)為非常有功力,飽含詩意的詩句:
但是,下面這首完整的詩卻可以被稱作這個三層LSTM模型取得的最高成就!
這首詩并不是節(jié)選自一大段文字的文本。這些詩行被牢牢地分隔在兩個「++++\n」之間!
看啊,人性是多么有趣!我們是如此獨一無二,我們身上有無限的可能!
特別鳴謝與我合作完成這個有趣的實驗的詩人們!請大家一定要去訪問他們的網(wǎng)站欣賞他們的佳作哦!
O at the Edges – Robert Okaji
Wolff Poetry – Linda J. Wolff
Poetry, Short Prose and Walking – Frank Hubeny
Perspectives on Life, the Universe and Everything – Aurangzeb Bozdar
via Data for Breakfast,雷鋒網(wǎng) AI 科技評論編譯
相關(guān)文章:
"LSTM之父"Jürgen Schmidhuber:我一直在努力實現(xiàn)三十年前的目標(biāo) “AI奴役人類”很愚蠢
《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。