App下載

【Python】RNN實(shí)現(xiàn)文本生成

猿友 2018-08-06 18:47:18 瀏覽數(shù) (7672)
反饋

本文轉(zhuǎn)載至知乎ID:Charles(白露未晞)知乎個(gè)人專欄

導(dǎo)語(yǔ)

本文將在此基礎(chǔ)上介紹LSTM網(wǎng)絡(luò)。最后舉一個(gè)類(lèi)似“Python學(xué)寫(xiě)作”的例子來(lái)實(shí)現(xiàn)文本生成,如生成詩(shī)歌、小說(shuō)等等。

讓我們愉快地開(kāi)始吧~~~


參考文獻(xiàn)

Understanding LSTM Networks:

http://colah.github.io/posts/2015-08-Understanding-LSTMs/


相關(guān)文件

百度網(wǎng)盤(pán)下載鏈接: https://pan.baidu.com/s/16hjmw1NtU9Oa4iwyj4qJuQ

密碼: gmpi


開(kāi)發(fā)工具

Python版本:3.6.4

相關(guān)模塊:

tensorflow-gpu模塊;

numpy模塊;

以及一些Python自帶的模塊。

其中TensorFlow-GPU版本為:

1.7.0


環(huán)境搭建

安裝Python并添加到環(huán)境變量,pip安裝需要的相關(guān)模塊即可。

另外,TensorFlow-GPU的環(huán)境搭建請(qǐng)自行參考相關(guān)的網(wǎng)絡(luò)教程,注意版本和驅(qū)動(dòng)嚴(yán)格對(duì)應(yīng)即可。


原理介紹

一. RNNs

人們的思維總是具有延續(xù)性的,比如當(dāng)你閱讀這篇文章時(shí),你對(duì)每個(gè)詞的理解都會(huì)依賴于你前面看到的一些詞,而不是把你前面看的內(nèi)容全部拋棄,再去理解每個(gè)詞。而傳統(tǒng)的神經(jīng)網(wǎng)絡(luò)(CNN)無(wú)法做到這一點(diǎn),因此有了循環(huán)神經(jīng)網(wǎng)絡(luò)(RNNs)。

在RNNs中,存在循環(huán)操作,使得它們能夠保留之前學(xué)習(xí)到的內(nèi)容:

在上圖網(wǎng)絡(luò)結(jié)構(gòu)中,對(duì)于矩形塊A的那部分,通過(guò)輸入Xt(t時(shí)刻的特征向量),它會(huì)輸出一個(gè)結(jié)果ht(t時(shí)刻的狀態(tài)或者輸出),網(wǎng)絡(luò)中的循環(huán)結(jié)構(gòu)使得當(dāng)前狀態(tài)作為下一時(shí)刻輸入的一部分。

將RNNs在時(shí)間步上進(jìn)行展開(kāi),就可以得到下圖:

也就是“Python實(shí)現(xiàn)簡(jiǎn)單的機(jī)器翻譯模型”一文中所使用的RNNs鏈狀的結(jié)構(gòu)。顯然,這樣的結(jié)構(gòu)是有利于處理序列相關(guān)問(wèn)題的。近年來(lái),其在語(yǔ)音識(shí)別、語(yǔ)言翻譯等等領(lǐng)域都取得了巨大的成功。

而RNNs的成功,主要?dú)w功于LSTMs這種特殊RNNs結(jié)構(gòu)的使用,而非普通的RNNs結(jié)構(gòu)。

二. LSTMs

全稱為L(zhǎng)ong Short Term Memory networks.

即長(zhǎng)短期記憶網(wǎng)絡(luò)。

普通RNNs的局限性在于當(dāng)我們所要預(yù)測(cè)的內(nèi)容和相關(guān)信息之間的間隔很大時(shí),普通RNNs很難去把它們關(guān)聯(lián)起來(lái):

盡管從理論上來(lái)講,只要參數(shù)合適,還是可以解決長(zhǎng)時(shí)期依賴關(guān)系無(wú)法很好聯(lián)系這一問(wèn)題的,但具體實(shí)現(xiàn)起來(lái)似乎并不容易,至少目前為止是不容易的。

幸運(yùn)的是,LSTMs能夠很好地解決這一問(wèn)題。它被設(shè)計(jì)的初衷就是為了能夠記住長(zhǎng)時(shí)期內(nèi)的信息。

循環(huán)神經(jīng)網(wǎng)絡(luò)是由相同結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò)模塊進(jìn)行復(fù)制而形成的。在標(biāo)準(zhǔn)的RNNs中,神經(jīng)網(wǎng)絡(luò)模塊的結(jié)構(gòu)非常簡(jiǎn)單,比如可以由單一的tanh層構(gòu)成:

LSTMs也有類(lèi)似的結(jié)構(gòu),不過(guò)神經(jīng)網(wǎng)絡(luò)模塊的結(jié)構(gòu)變得相對(duì)復(fù)雜了一些:

接下來(lái),我們來(lái)詳細(xì)介紹一下這個(gè)結(jié)構(gòu)。首先,我們來(lái)定義一下用到的符號(hào):

粉紅色的圈:

代表向量加之類(lèi)的逐點(diǎn)操作;

黃色矩形框:

代表神經(jīng)網(wǎng)絡(luò)層;

普通的線:

用于攜帶并傳遞向量;

合并的線:

代表對(duì)兩條線上所攜帶的向量進(jìn)行合并;

分開(kāi)的線:

代表將線上所攜帶的向量復(fù)制后傳給兩個(gè)地方。

2.1 LSTMs的核心思想

假設(shè)一個(gè)綠色的框就是一個(gè)cell。

向量通過(guò)結(jié)構(gòu)圖最上面的那條貫穿cell的水平線穿過(guò)整個(gè)cell,而cell僅對(duì)其做了少量的線性操作:

顯然,這樣的結(jié)構(gòu)能夠很輕松地讓信息從整個(gè)cell中穿過(guò)而不發(fā)生變化。

當(dāng)然,只有一條水平線是無(wú)法實(shí)現(xiàn)添加或者刪除信息的,也就是實(shí)現(xiàn)讓信息有選擇地通過(guò)cell,這需要通過(guò)一種叫做門(mén)(gates)的結(jié)構(gòu)來(lái)實(shí)現(xiàn)。

門(mén)結(jié)構(gòu)主要由一個(gè)sigmoid神經(jīng)網(wǎng)絡(luò)層和一個(gè)逐點(diǎn)相乘的操作來(lái)實(shí)現(xiàn):

sigmoid層輸出的向量每個(gè)元素都是介于0和1之間的實(shí)數(shù),表示此時(shí)通過(guò)的信息的權(quán)重,當(dāng)其為0時(shí)表示“此時(shí)不讓任何信息通過(guò)”,為1時(shí)表示“此時(shí)讓所有信息通過(guò)”。每個(gè)LSTM都有三個(gè)這樣的門(mén)結(jié)構(gòu),來(lái)實(shí)現(xiàn)保護(hù)和控制信息。

2.2 逐步理解LSTM

遺忘門(mén)(forget gate layer):

首先,LSTM需要決定哪些信息需要丟棄,哪些信息需要保留。這是通過(guò)一個(gè)叫做遺忘門(mén)的sigmoid層來(lái)實(shí)現(xiàn)的。它的輸入是ht-1xt,輸出是一個(gè)數(shù)值都在0到1之間的向量,表示Ct-1中各部分信息的權(quán)重,0表示不讓該部分信息通過(guò),1表示讓該部分信息全部通過(guò)。

具體而言,比如在語(yǔ)言模型中,我們要根據(jù)所有的上下文信息來(lái)預(yù)測(cè)下一個(gè)詞。在這種情況下,每個(gè)cell的狀態(tài)中都應(yīng)該包含了當(dāng)前主語(yǔ)的性別信息。這樣,接下來(lái)我們才能夠正確地使用代詞。但是,當(dāng)我們開(kāi)始描述一個(gè)新的主語(yǔ)時(shí),就應(yīng)該把之前的主語(yǔ)性別給丟棄了才對(duì)。

傳入門(mén)(input gate layer):

其次,LSTM將決定讓哪些新的信息加入到cell的狀態(tài)中來(lái)。該實(shí)現(xiàn)分兩個(gè)步驟進(jìn)行:

① 用一個(gè)tanh層生成一個(gè)備選向量,用于表示獲得的所有可添加信息;

② 用一個(gè)叫做傳入門(mén)的sigmoid層來(lái)決定步驟①中獲得的可添加信息各自的權(quán)重。

具體而言,比如在語(yǔ)言模型中,我們需要把新主語(yǔ)的性別信息添加到cell狀態(tài)中,來(lái)替換掉之前的主語(yǔ)性別信息。

有了遺忘門(mén)和傳入門(mén),我們就能夠更新cell的狀態(tài)了,即把Ct-1更新為Ct

還是以語(yǔ)言模型為例,假設(shè)我們的模型剛輸出了一個(gè)代詞,接下來(lái)可能要輸出一個(gè)動(dòng)詞,那么這個(gè)動(dòng)詞應(yīng)該采用單數(shù)形式還是復(fù)數(shù)形式呢?顯然,我們需要把代詞相關(guān)的信息和當(dāng)前的預(yù)測(cè)信息都加入到cell的狀態(tài)中來(lái),才能夠進(jìn)行正確的預(yù)測(cè)。

具體計(jì)算方式如下圖所示:

輸出門(mén)(Output):

最后,我們需要決定輸出值。輸出值的計(jì)算方式為:

① 使用sigmoid層來(lái)決定/計(jì)算出Ct中的哪部分信息會(huì)被輸出;

② 利用tanh層將Ct的取值壓縮到-1到1之間;

③ 將tanh層的輸出和sigmoid層的輸出相乘即為最終的輸出結(jié)果。

三. LSTMs的變種

① 將cell的狀態(tài)作為門(mén)結(jié)構(gòu)輸入的一部分。

② 將遺忘門(mén)與傳入門(mén)耦合,即不再分開(kāi)決定要遺忘和添加的信息。

③ GRU

GRU模型“簡(jiǎn)化”了LSTM模型的設(shè)計(jì),其中rt由LSTM中的遺忘門(mén)和傳入門(mén)合并而得,稱為重置門(mén);zt為更新門(mén),作用相當(dāng)于LSTM中的輸出門(mén)。

實(shí)際應(yīng)用

為了貫徹理論與實(shí)踐相結(jié)合的理念,本文將舉一個(gè)簡(jiǎn)單的小例子,該例子使用的模型與“Python學(xué)寫(xiě)作”類(lèi)似,本文不再作多余的介紹。

具體實(shí)現(xiàn)過(guò)程詳見(jiàn)相關(guān)文件中的源代碼。

使用演示

模型訓(xùn)練:

在cmd窗口運(yùn)行'train.py'文件即可:

如有需要,可自行修改相關(guān)參數(shù):

模型使用:

在cmd窗口運(yùn)行“generate.py”文件即可。

注意模型參數(shù)需和train.py文件中的模型參數(shù)一致:

結(jié)果展示

生成英文文本:

以莎士比亞的作品為訓(xùn)練素材獲得的結(jié)果:

生成中文文本:

以周杰倫的作品為訓(xùn)練素材獲得的結(jié)果:


更多

代碼截止2018-06-24測(cè)試無(wú)誤。

模型比較簡(jiǎn)單,有興趣的朋友可以在此基礎(chǔ)上進(jìn)行優(yōu)化,當(dāng)然RNN的作用可不僅僅是文本生成哦~

以后有機(jī)會(huì)再舉其他例子吧~~~

0 人點(diǎn)贊