丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗(yàn),強(qiáng)烈建議使用更快更安全的瀏覽器
此為臨時(shí)鏈接,僅用于文章預(yù)覽,將在時(shí)失效
人工智能開發(fā)者 正文
發(fā)私信給AI研習(xí)社
發(fā)送

0

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

本文作者: AI研習(xí)社 編輯:賈智龍 2017-05-26 16:01
導(dǎo)語:從0開始實(shí)現(xiàn)LSTM。

前言

最近看完了 LSTM 的一些外文資料,主要參考了 Colah 的 blog以及 Andrej Karpathy blog的一些關(guān)于 RNN 和 LSTM 的材料,準(zhǔn)備動(dòng)手去實(shí)現(xiàn)一個(gè) LSTM 模型。代碼的基礎(chǔ)框架來自于 Udacity 上深度學(xué)習(xí)納米學(xué)位的課程(付費(fèi)課程)的一個(gè) demo,我剛開始看代碼的時(shí)候真的是一頭霧水,很多東西沒有理解,后來反復(fù)查閱資料,并我重新對代碼進(jìn)行了學(xué)習(xí)和修改,對步驟進(jìn)行了進(jìn)一步的剖析,下面將一步步用 TensorFlow 來構(gòu)建 LSTM 模型進(jìn)行文本學(xué)習(xí)并試圖去生成新的文本。本篇文章比較適合新手去操作,LSTM 層采用的是 BasicLSTMCell。

關(guān)于 RNN 與 LSTM 模型本文不做介紹,詳情去查閱資料過著去看上面的 blog 鏈接,講的很清楚啦。這篇文章主要是偏向?qū)崙?zhàn),來自己動(dòng)手構(gòu)建 LSTM 模型。

數(shù)據(jù)集來自于外文版《安娜卡列妮娜》書籍的文本文檔(本文后面會(huì)提供整個(gè) project 的 git 鏈接)。

工具介紹

  • 語言:Python 3

  • 包:TensorFlow 及其它數(shù)據(jù)處理包(見代碼中)

  • 編輯器:jupyter notebook

  • 線上 GPU:floyd

正文部分

正文部分主要包括以下四個(gè)部分:

- 數(shù)據(jù)預(yù)處理:加載數(shù)據(jù)、轉(zhuǎn)換數(shù)據(jù)、分割數(shù)據(jù) mini-batch

- 模型構(gòu)建:輸入層,LSTM 層,輸出層,訓(xùn)練誤差,loss,optimizer

- 模型訓(xùn)練:設(shè)置模型參數(shù)對模型進(jìn)行訓(xùn)練

- 生成新文本:訓(xùn)練新的文本

主題:整個(gè)文本將基于《安娜卡列妮娜》這本書的英文文本作為 LSTM 模型的訓(xùn)練數(shù)據(jù),輸入為單個(gè)字符,通過學(xué)習(xí)整個(gè)英文文檔的字符(包括字母和標(biāo)點(diǎn)符號等)來進(jìn)行文本生成。在開始建模之前,我們首先要明確我們的輸入和輸出。即輸入是字符,輸出是預(yù)測出的新字符。

一. 數(shù)據(jù)預(yù)處理

在開始模型之前,我們首先要導(dǎo)入需要的包:


import timeimport numpy as npimport tensorflow as tf


這一部分主要包括了數(shù)據(jù)的轉(zhuǎn)換與 mini-batch 的分割步驟。

首先我們來進(jìn)行數(shù)據(jù)的加載與編碼轉(zhuǎn)換。由于我們是基于字符(字母和標(biāo)點(diǎn)符號等單個(gè)字符串,以下統(tǒng)稱為字符)進(jìn)行模型構(gòu)建,也就是說我們的輸入和輸出都是字符。舉個(gè)栗子,假如我們有一個(gè)單詞 “hello”,我們想要基于這個(gè)單詞構(gòu)建 LSTM,那么希望的到的結(jié)果是,輸入 “h”,預(yù)測下一個(gè)字母為 “e”;輸入 “e” 時(shí),預(yù)測下一個(gè)字母為 “l(fā)”,等等。

因此我們的輸入便是一個(gè)個(gè)字母,下面我們將文章進(jìn)行轉(zhuǎn)換。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

上面的代碼主要完成了下面三個(gè)任務(wù):

- 得到了文章中所有的字符集合 vocab

- 得到一個(gè)字符 - 數(shù)字的映射 vocab_to_int

- 得到一個(gè)數(shù)字 - 字符的映射 int_to_vocab

- 對原文進(jìn)行轉(zhuǎn)碼后的列表 encoded

完成了前面的數(shù)據(jù)預(yù)處理操作,接下來就是要?jiǎng)澐治覀兊臄?shù)據(jù)集,在這里我們使用 mini-batch 來進(jìn)行模型訓(xùn)練,那么我們要如何劃分?jǐn)?shù)據(jù)集呢?在進(jìn)行 mini-batch 劃分之前,我們先來了解幾個(gè)概念。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

假如我們目前手里有一個(gè)序列 1-12,我們接下來以這個(gè)序列為例來說明劃分 mini-batch 中的幾個(gè)概念。首先我們回顧一下,在 DNN 和 CNN 中,我們都會(huì)將數(shù)據(jù)分 batch 輸入給神經(jīng)網(wǎng)絡(luò),加入我們有 100 個(gè)樣本,如果設(shè)置我們的 batch_size=10,那么意味著每次我們都會(huì)向神經(jīng)網(wǎng)絡(luò)輸入 10 個(gè)樣本進(jìn)行訓(xùn)練調(diào)整參數(shù)。同樣的,在 LSTM 中,batch_size 意味著每次向網(wǎng)絡(luò)輸入多少個(gè)樣本,在上圖中,當(dāng)我們設(shè)置 batch_size=2 時(shí),我們會(huì)將整個(gè)序列劃分為 6 個(gè) batch,每個(gè) batch 中有兩個(gè)數(shù)字。

然而由于 RNN 中存在著 “記憶”,也就是循環(huán)。事實(shí)上一個(gè)循環(huán)神經(jīng)網(wǎng)絡(luò)能夠被看做是多個(gè)相同神經(jīng)網(wǎng)絡(luò)的疊加,在這個(gè)系統(tǒng)中,每一個(gè)網(wǎng)絡(luò)都會(huì)傳遞信息給下一個(gè)。上面的圖中,我們可以看到整個(gè) RNN 網(wǎng)絡(luò)由三個(gè)相同的神經(jīng)網(wǎng)絡(luò)單元疊加起來的序列。那么在這里就有了第二個(gè)概念 sequence_length(也叫 steps),中文叫序列長度。上圖中序列長度是 3,可以看到將三個(gè)字符作為了一個(gè)序列。

有了上面兩個(gè)概念,我們來規(guī)范一下后面的定義。我們定義一個(gè) batch 中的序列個(gè)數(shù)為 N(即 batch_size),定義單個(gè)序列長度為 M(也就是我們的 num_steps)。那么實(shí)際上我們每個(gè) batch 是一個(gè)N×M的數(shù)組,相當(dāng)于我們的每個(gè) batch 中有N×M個(gè)字符。在上圖中,當(dāng)我們設(shè)置 N=2, M=3 時(shí),我們可以得到每個(gè) batch 的大小為 2 x 3 = 6 個(gè)字符,整個(gè)序列可以被分割成 12 / 6 = 2 個(gè) batch。

基于上面的分析,我們下面來進(jìn)行 mini-batch 的分割:

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

上面的代碼定義了一個(gè) generator,調(diào)用函數(shù)會(huì)返回一個(gè) generator 對象,我們可以獲取一個(gè) batch。

經(jīng)過上面的步驟,我們已經(jīng)完成了對數(shù)據(jù)集的預(yù)處理。下一步我們開始構(gòu)建模型。

二. 模型構(gòu)建

模型構(gòu)建部分主要包括了輸入層,LSTM 層,輸出層,loss,optimizer 等部分的構(gòu)建,我們將一塊一塊來進(jìn)行實(shí)現(xiàn)。

1. 輸入層

在數(shù)據(jù)預(yù)處理階段,我們定義了 mini-batch 的分割函數(shù),輸入層的 size 取決于我們設(shè)置 batch 的 size(n_seqs × n_steps),下面我們首先構(gòu)建輸入層。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

同樣的,輸出層的(因?yàn)檩斎胍粋€(gè)字符,同樣會(huì)輸出一個(gè)字符)。除了輸入輸出外,我們還定義了 keep_prob 參數(shù)用來在后面控制 dropout 的保留結(jié)點(diǎn)數(shù)。關(guān)于 dropout 正則化請參考鏈接。

2.LSTM 層

LSTM 層是整個(gè)神經(jīng)網(wǎng)絡(luò)的關(guān)鍵部分。TensorFlow 中,tf.contrib.rnn 模塊中有 BasicLSTMCell 和 LSTMCell 兩個(gè)包,它們的區(qū)別在于:

BasicLSTMCell does not allow cell clipping, a projection layer, and does not use peep-hole connections: it is the basic baseline.(來自 TensorFlow 官網(wǎng))

在這里我們僅使用基本模塊 BasicLSTMCell。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

上面的代碼中,我并沒有使用 tf.contrib.rnn 模塊,是因?yàn)槲以谑褂眠h(yuǎn)程 floyd 的 GPU 運(yùn)行代碼時(shí)候告訴我找不到這個(gè)模塊,可以用 tf.nn.run_cell.BasicLSTMCell 替代。構(gòu)建好 LSTM cell 后,為了防止過擬合,在它的隱層添加了 dropout 正則。

后面的 MultiRNNCell實(shí)現(xiàn)了對基本 LSTM cell 的順序堆疊,它接收的是 cell 對象組成的 list。最后 initial_state 定義了初始 cell state。

3. 輸出層

到目前為止,我們的輸入和 LSTM 層都已經(jīng)構(gòu)建完畢。接下來就要構(gòu)造我們的輸出層,輸出層采用 softmax,它與 LSTM 進(jìn)行全連接。對于每一個(gè)字符來說,它經(jīng)過 LSTM 后的輸出大小是1×L(L 為 LSTM cell 隱層的結(jié)點(diǎn)數(shù)量),我們上面也分析過輸入一個(gè) N x M 的 batch,我們從 LSTM 層得到的輸出為N×M×L,要將這個(gè)輸出與 softmax 全連接層建立連接,就需要對 LSTM 的輸出進(jìn)行重塑,變成( N * M ) × L 的一個(gè) 2D 的 tensor。softmax 層的結(jié)點(diǎn)數(shù)應(yīng)該是 vocab 的大?。ㄎ覀円?jì)算概率分布)。因此整個(gè) LSTM 層到 softmax 層的大小為L×vocab_size。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

將數(shù)據(jù)重塑后,我們對 LSTM 層和 softmax 層進(jìn)行連接。并計(jì)算 logits 和 softmax 后的概率分布。

4. 訓(xùn)練誤差計(jì)算

至此我們已經(jīng)完成了整個(gè)網(wǎng)絡(luò)的構(gòu)建,接下來要定義 train loss 和 optimizer。我們知道從 sotfmax 層輸出的是概率分布,因此我們要對 targets 進(jìn)行 one-hot 編碼。我們采用 softmax_cross_entropy_with_logits交叉熵來計(jì)算 loss。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

5.Optimizer

我們知道 RNN 會(huì)遇到梯度爆炸(gradients exploding)梯度彌散(gradients disappearing) 的問題。LSTM 解決了梯度彌散的問題,但是 gradients 仍然可能會(huì)爆炸,因此我們采用 gradient clippling 的方式來防止梯度爆炸。即通過設(shè)置一個(gè)閾值,當(dāng) gradients 超過這個(gè)閾值時(shí),就將它重置為閾值大小,這就保證了梯度不會(huì)變得很大。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

tf.clip_by_global_norm會(huì)返回 clip 以后的 gradients 以及 global_norm。整個(gè)學(xué)習(xí)過程采用 AdamOptimizer

6. 模型組合

經(jīng)過上面五個(gè)步驟,我們完成了所有的模塊設(shè)置。下面我們來將這些部分組合起來,構(gòu)建一個(gè)類。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

我們使用 tf.nn.dynamic_run 來運(yùn)行 RNN 序列。

三. 模型訓(xùn)練

在模型訓(xùn)練之前,我們首先初始化一些參數(shù),我們的參數(shù)主要有:

  • batch_size: 單個(gè) batch 中序列的個(gè)數(shù)

  • num_steps: 單個(gè)序列中字符數(shù)目

  • lstm_size: 隱層結(jié)點(diǎn)個(gè)數(shù)

  • num_layers: LSTM 層個(gè)數(shù)

  • learning_rate: 學(xué)習(xí)率

  • keep_prob: 訓(xùn)練時(shí) dropout 層中保留結(jié)點(diǎn)比例

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

這是我自己設(shè)置的一些參數(shù),具體一些調(diào)參經(jīng)驗(yàn)可以參考 Andrej Karpathy 的 git 上的建議

參數(shù)設(shè)置完畢后,離運(yùn)行整個(gè) LSTM 就差一步啦,下面我們來運(yùn)行整個(gè)模型。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

我這里設(shè)置的迭代次數(shù)為 20 次,并且在代碼運(yùn)行中我們設(shè)置了結(jié)點(diǎn)的保存,設(shè)置了每運(yùn)行 200 次進(jìn)行一次變量保存,這樣的好處是有利于我們后面去直觀地觀察在整個(gè)訓(xùn)練過程中文本生成的結(jié)果是如何一步步 “進(jìn)化” 的。

四. 文本生成

經(jīng)過漫長的模型訓(xùn)練,我們得到了一系列訓(xùn)練過程中保存下來的參數(shù),可以利用這些參數(shù)來進(jìn)行文本生成啦。當(dāng)我們輸入一個(gè)字符時(shí),它會(huì)預(yù)測下一個(gè),我們再將這個(gè)新的字符輸入模型,就可以一直不斷地生成字符,從而形成文本。

為了減少噪音,每次的預(yù)測值我會(huì)選擇最可能的前 5 個(gè)進(jìn)行隨機(jī)選擇,比如輸入 h,預(yù)測結(jié)果概率最大的前五個(gè)為[o,i,e,u,b],我們將隨機(jī)從這五個(gè)中挑選一個(gè)作為新的字符,讓過程加入隨機(jī)因素會(huì)減少一些噪音的生成。

代碼封裝了兩個(gè)函數(shù)來做文本生成,具體請參看文章尾部的 git 鏈接中的源碼。

訓(xùn)練步數(shù):200

當(dāng)訓(xùn)練步數(shù)為 200 的時(shí)候,LSTM 生成的文本大概長下面這個(gè)樣子:

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

看起來像是字符的隨機(jī)組合,但是可以看到有一些單詞例如 hat,her 等已經(jīng)出現(xiàn),并且生成了成對的引號。

訓(xùn)練步數(shù):1000

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

當(dāng)訓(xùn)練步數(shù)到達(dá) 1000 的時(shí)候,已經(jīng)開始有簡單的句子出現(xiàn),并且單詞看起來似乎不是那么亂了。

訓(xùn)練步數(shù):2000

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

當(dāng)訓(xùn)練步數(shù)達(dá)到 2000 的時(shí)候,單詞和句子看起來已經(jīng)有所規(guī)范。

訓(xùn)練步數(shù):3960

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

當(dāng)訓(xùn)練結(jié)束時(shí)(本文僅訓(xùn)練了 3960 步),生成的文本已經(jīng)有小部分可以讀的比較通順了,而且很少有單詞拼寫的錯(cuò)誤。

五. 總結(jié)

整個(gè)文章通過構(gòu)建 LSTM 模型完成了對《安娜卡列寧娜》文本的學(xué)習(xí)并且基于學(xué)習(xí)成果生成了新的文本。

通過觀察上面的生成文本,我們可以看出隨著訓(xùn)練步數(shù)的增加,模型的訓(xùn)練誤差在持續(xù)減少。本文僅設(shè)置了 20 次迭代,嘗試更大次數(shù)的迭代可能會(huì)取得更好的效果。

個(gè)人覺得 LSTM 對于文本的學(xué)習(xí)能力還是很強(qiáng),后面可能將針對中文文本構(gòu)造一些學(xué)習(xí)模型,應(yīng)該會(huì)更有意思!

我對 RNN 也是在不斷地探索與學(xué)習(xí)中,文中不免會(huì)有一些錯(cuò)誤和謬誤,懇請各位指正,非常感謝!

----------------------------------------------------------------------------------------------------------

整個(gè)項(xiàng)目地址已經(jīng)上傳到個(gè)人的 GitHub上。

如果覺得有用,請叫上全村兒的小伙伴兒幫我 star 一下,不勝感激!

雷鋒網(wǎng)按:本文原作者天雨粟,原載于知乎專欄。

雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。

《安娜卡列尼娜》文本生成——利用 TensorFlow 構(gòu)建 LSTM 模型

分享:
相關(guān)文章

編輯

聚焦數(shù)據(jù)科學(xué),連接 AI 開發(fā)者。更多精彩內(nèi)容,請?jiān)L問:yanxishe.com
當(dāng)月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個(gè)人簡介
為了您的賬戶安全,請驗(yàn)證郵箱
您的郵箱還未驗(yàn)證,完成可獲20積分喲!
請驗(yàn)證您的郵箱
立即驗(yàn)證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說