tensorflow LSTM

循環神經網絡

介紹

能夠在 this great article 查看循環神經網絡(RNN)以及 LSTM 的介紹。html

語言模型

此教程將展現如何在高難度的語言模型中訓練循環神經網絡。該問題的目標是得到一個能肯定語句機率的機率模型。爲了作到這一點,經過以前已經給出的詞語來預測後面的詞語。咱們將使用 PTB(Penn Tree Bank) 數據集,這是一種經常使用來衡量模型的基準,同時它比較小並且訓練起來相對快速。python

語言模型是不少有趣難題的關鍵所在,好比語音識別,機器翻譯,圖像字幕等。它頗有意思--能夠參看 heregit

本教程的目的是重現 Zaremba et al., 2014 的成果,他們在 PTB 數據集上獲得了很棒的結果。github

教程文件

本教程使用的下面文件的目錄是 models/rnn/ptb:數組

文件 做用
ptb_word_lm.py 在 PTB 數據集上訓練一個語言模型.
reader.py 讀取數據集.

下載及準備數據

本教程須要的數據在 data/ 路徑下,來源於 Tomas Mikolov 網站上的 PTB 數據集http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz網絡

該數據集已經預先處理過而且包含了所有的 10000 個不一樣的詞語,其中包括語句結束標記符,以及標記稀有詞語的特殊符號 (<unk>) 。咱們在 reader.py 中轉換全部的詞語,讓他們各自有惟一的整型標識符,便於神經網絡處理。session

模型

LSTM

模型的核心由一個 LSTM 單元組成,其能夠在某時刻處理一個詞語,以及計算語句可能的延續性的機率。網絡的存儲狀態由一個零矢量初始化並在讀取每個詞語後更新。並且,因爲計算上的緣由,咱們將以 batch_size 爲最小批量來處理數據。函數

基礎的僞代碼就像下面這樣:post

lstm = rnn_cell.BasicLSTMCell(lstm_size)
# 初始化 LSTM 存儲狀態. state = tf.zeros([batch_size, lstm.state_size]) loss = 0.0 for current_batch_of_words in words_in_dataset: # 每次處理一批詞語後更新狀態值. output, state = lstm(current_batch_of_words, state) # LSTM 輸出可用於產生下一個詞語的預測 logits = tf.matmul(output, softmax_w) + softmax_b probabilities = tf.nn.softmax(logits) loss += loss_function(probabilities, target_words) 

截斷反向傳播

爲使學習過程易於處理,一般的作法是將反向傳播的梯度在(按時間)展開的步驟上照一個固定長度(num_steps)截斷。 經過在一次迭代中的每一個時刻上提供長度爲 num_steps 的輸入和每次迭代完成以後反向傳導,這會很容易實現。學習

一個簡化版的用於計算圖建立的截斷反向傳播代碼:

# 一次給定的迭代中的輸入佔位符. words = tf.placeholder(tf.int32, [batch_size, num_steps]) lstm = rnn_cell.BasicLSTMCell(lstm_size) # 初始化 LSTM 存儲狀態. initial_state = state = tf.zeros([batch_size, lstm.state_size]) for i in range(len(num_steps)): # 每處理一批詞語後更新狀態值. output, state = lstm(words[:, i], state) # 其他的代碼. # ... final_state = state 

下面展示如何實現迭代整個數據集:

# 一個 numpy 數組,保存每一批詞語以後的 LSTM 狀態. numpy_state = initial_state.eval() total_loss = 0.0 for current_batch_of_words in words_in_dataset: numpy_state, current_loss = session.run([final_state, loss], # 經過上一次迭代結果初始化 LSTM 狀態. feed_dict={initial_state: numpy_state, words: current_batch_of_words}) total_loss += current_loss 

輸入

在輸入 LSTM 前,詞語 ID 被嵌入到了一個密集的表示中(查看 矢量表示教程)。這種方式容許模型高效地表示詞語,也便於寫代碼:

# embedding_matrix 張量的形狀是: [vocabulary_size, embedding_size] word_embeddings = tf.nn.embedding_lookup(embedding_matrix, word_ids) 

嵌入的矩陣會被隨機地初始化,模型會學會經過數據分辨不一樣詞語的意思。

損失函數

咱們想使目標詞語的平均負對數機率最小

實現起來並不是很難,並且函數 sequence_loss_by_example 已經有了,能夠直接使用。

論文中的典型衡量標準是每一個詞語的平均困惑度(perplexity),計算式爲

同時咱們會觀察訓練過程當中的困惑度值(perplexity)。

多個 LSTM 層堆疊

要想給模型更強的表達能力,能夠添加多層 LSTM 來處理數據。第一層的輸出做爲第二層的輸入,以此類推。

MultiRNNCell 能夠無縫的將其實現:

lstm = rnn_cell.BasicLSTMCell(lstm_size)
stacked_lstm = rnn_cell.MultiRNNCell([lstm] * number_of_layers)

initial_state = state = stacked_lstm.zero_state(batch_size, tf.float32)
for i in range(len(num_steps)): # 每次處理一批詞語後更新狀態值. output, state = stacked_lstm(words[:, i], state) # 其他的代碼. # ... final_state = state 

編譯並運行代碼

首先須要構建庫,在 CPU 上編譯:

bazel build -c opt tensorflow/models/rnn/ptb:ptb_word_lm

若是你有一個強大的 GPU,能夠運行:

bazel build -c opt --config=cuda tensorflow/models/rnn/ptb:ptb_word_lm

運行模型:

bazel-bin/tensorflow/models/rnn/ptb/ptb_word_lm \
  --data_path=/tmp/simple-examples/data/ --alsologtostderr --model small

教程代碼中有 3 個支持的模型配置參數:"small", "medium" 和 "large"。它們指的是 LSTM 的大小,以及用於訓練的超參數集。

模型越大,獲得的結果應該更好。在測試集中 small 模型應該能夠達到低於 120 的困惑度(perplexity),large 模型則是低於 80,但它可能花費數小時來訓練。

除此以外?

還有幾個優化模型的技巧沒有提到,包括:

  • 隨時間下降學習率,
  • LSTM 層間 dropout.

繼續學習和更改代碼以進一步改善模型吧。

原文:Recurrent Neural Networks 翻譯:Warln

相關文章
相關標籤/搜索