今日資料:
https://www.tensorflow.org/tutorials/recurrent
中文版:
http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/recurrent.html
代碼:
https://github.com/tensorflow/models/blob/master/tutorials/rnn/ptb/ptb_word_lm.py
今天的內(nèi)容是基于 LSTM 建立一個(gè)語言模型
人每次思考時(shí)不會(huì)從頭開始,而是保留之前思考的一些結(jié)果寸宵,為現(xiàn)在的決策提供支持登渣。RNN 的最大特點(diǎn)是可以利用之前的信息巨朦,即模擬一定的記憶嚎莉,具體可以看我之前寫過的這篇文章:
詳解循環(huán)神經(jīng)網(wǎng)絡(luò)(Recurrent Neural Network)
http://www.reibang.com/p/39a99c88a565
RNN 雖然可以處理整個(gè)時(shí)間序列信息跌榔,但是它記憶最深的還是最后輸入的一些信號(hào)折剃,而之前的信號(hào)的強(qiáng)度就會(huì)越來越低镶奉,起到的作用會(huì)比較小测蹲。
而 LSTM 可以改善長(zhǎng)距離依賴的問題莹捡,不需要特別復(fù)雜的調(diào)試超參數(shù)就可以記住長(zhǎng)期的信息。關(guān)于 LSTM 可以看這一篇文章:
詳解 LSTM
http://www.reibang.com/p/dcec3f07d3b5
今天要實(shí)現(xiàn)一個(gè)語言模型扣甲,它是 NLP 中比較重要的一部分篮赢,給上文的語境后,可以預(yù)測(cè)下一個(gè)單詞出現(xiàn)的概率文捶。
首先下載 ptb 數(shù)據(jù)集荷逞,有一萬個(gè)不同的單詞,有句尾的標(biāo)記粹排,并且將罕見的詞匯統(tǒng)一處理成特殊字符种远;
$ wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
$ tar xvf simple-examples.tgz
PTBInput,
定義語言模型處理輸入數(shù)據(jù)的一些參數(shù)顽耳,包括 LSTM 的展開步數(shù) num_steps
坠敷,用 reader.ptb_producer
讀取數(shù)據(jù)和標(biāo)簽:
PTBModel,
def __init__(self, is_training, config, input_)
包括三個(gè)參數(shù)射富,訓(xùn)練標(biāo)記膝迎,配置參數(shù)以及輸入數(shù)據(jù)的實(shí)例;
把這幾個(gè)變量讀取到本地,hidden_size
是隱藏層的節(jié)點(diǎn)數(shù)胰耗,vocab_size
是詞匯表的大邢薮巍;
def lstm_cell()
,設(shè)定基本的 LSTM 單元卖漫,用的是 tf.contrib.rnn.BasicLSTMCell
费尽;
如果 if is_training and config.keep_prob < 1
這個(gè)條件的話,在 LSTM 單元后面可以加一個(gè) dropout 層羊始;
再用 tf.contrib.rnn.MultiRNNCell
把多層的 LSTM 堆加到一起旱幼;
用 cell.zero_state
將 LSTM 的初始狀態(tài)設(shè)置為0;
接下來是 embedding 矩陣突委,行數(shù)是詞匯表的大小柏卤,列數(shù)是每個(gè)單詞的向量表達(dá)的維度,在訓(xùn)練過程中匀油,它可以被優(yōu)化和更新缘缚;
接下來我們要定義輸出,限制一下反向傳播時(shí)可以展開的步數(shù)钧唐,將 inputs 和 state 傳到 LSTM忙灼,然后把輸出結(jié)果添加到 outputs 的列表里;
然后將輸出的內(nèi)容串到一起钝侠,接下來 softmax 層该园,接著要定義損失函數(shù) loss,它的定義形式是這樣的:
然后我們要加和整個(gè) batch 的誤差帅韧,再平均到每個(gè)樣本的誤差里初,并且保留最終的狀態(tài),如果不是訓(xùn)練狀態(tài)就直接返回忽舟;
接下來是定義學(xué)習(xí)速率双妨,根據(jù)前面的 cost 計(jì)算一下梯度,并將梯度的最大范數(shù)設(shè)置好叮阅,相當(dāng)于正則化的作用刁品,可以防止梯度爆炸;
這個(gè)學(xué)習(xí)速率還可以更新浩姥,將其傳入給 _new_lr
挑随,再執(zhí)行 _lr_update
完成修改:
接下來可以定義幾種不同大小的模型的參數(shù),其中有學(xué)習(xí)速率勒叠,還有梯度的最大范數(shù)兜挨,還是 LSTM 的層數(shù),反向傳播的步數(shù)眯分,隱含層節(jié)點(diǎn)數(shù)拌汇,dropout 保留節(jié)點(diǎn)的比例,學(xué)習(xí)速率的衰減速度:
run_epoch
弊决,是定義訓(xùn)練一個(gè) epoch 數(shù)據(jù)的函數(shù)噪舀,首先初始化 costs 還有 iters,state;
將 LSTM 的所有 state 加入到 feed_dict
中与倡,然后會(huì)生成結(jié)果的字典表 fetches先改,其中會(huì)有 cost 和 final_state
;
每完成 10% 的 epoch 就顯示一次結(jié)果蒸走,包括 epoch 的進(jìn)度,perplexity(是cost 的自然常數(shù)指數(shù)貌嫡,這個(gè)指標(biāo)越低比驻,表示預(yù)測(cè)越好),還有訓(xùn)練速度(單詞數(shù)每秒):
在 main() 中:
用 reader.ptb_raw_data
讀取解壓后的數(shù)據(jù)岛抄;
得到 train_data, valid_data, test_data
數(shù)據(jù)集别惦;
用 PTBInput 和 PTBModel 分別定義用來訓(xùn)練的模型 m,驗(yàn)證的模型 mvalid夫椭,測(cè)試的模型 mtest掸掸;
m.assign_lr
對(duì) m 應(yīng)用累計(jì)的 learning rate;
每個(gè)循環(huán)內(nèi)執(zhí)行一個(gè) epoch 的訓(xùn)練和驗(yàn)證蹭秋,輸出 Learning rate,Train Perplexity仁讨, Valid Perplexity羽莺。
推薦閱讀 歷史技術(shù)博文鏈接匯總
http://www.reibang.com/p/28f02bb59fe5
也許可以找到你想要的