Tensorflow- 循環神經網絡(LSTM)

tensorflow中文社區對官方文檔進行了完整翻譯。鑒于官方更新不少內容,而現有的翻譯基本上都已過時。故本人對更新后文檔進行翻譯工作,紕漏之處請大家指正。(如需了解其他方面知識,可參閱以下Tensorflow系列文章)。

Tensorflow系列文章



介紹


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

語言模型


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

語言模型是很多有趣難題的關鍵所在,比如語音識別,機器翻譯,圖像字幕等。它很有意思--可以參看 here

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

教程文件


本教程使用的文件在 models/tutorials/rnn/ptb 目錄下,請點擊 TensorFlow models repo 進行下載。

File Purpose
ptb_word_lm.py The code to train a language model on the PTB dataset.
reader.py The code to read the dataset.

下載及準備數據


點擊下載后,進行解壓,本教程所需要的數據在里面的 data/ 目錄下。

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

模型


LSTM

模型的核心由一個 LSTM 單元組成,其可以在某時刻處理一個詞語,以及計算語句中下個所有可能的詞語的概率 。網絡的存儲狀態由一個零矢量初始化并在讀取每一個詞語后更新。而且,由于計算上的原因,我們將以 batch_size 為最小批量來處理數據。在這個例子中,current_batch_of_words 并不是對應著“一個句子”。

在每個batch中的單詞應該對應時間 t ,Tensorflow會在每個batch中自動對梯度(gradient,此處不知翻譯是否準確)進行求和。

舉例說明:

 t=0  t=1    t=2  t=3     t=4
[The, brown, fox, is,     quick]
[The, red,   fox, jumped, high]

words_in_dataset[0] = [The, The]
words_in_dataset[1] = [fox, fox]
words_in_dataset[2] = [is, jumped]
words_in_dataset[3] = [quick, high]
num_batches = 4, batch_size = 2, time_steps = 5

基本的偽代碼如下:

words_in_dataset = tf.placeholder(tf.float32, [num_batches, batch_size, num_features])
lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size)
# Initial state of the LSTM memory.
hidden_state = tf.zeros([batch_size, lstm.state_size])
current_state = tf.zeros([batch_size, lstm.state_size])
state = hidden_state, current_state
probabilities = []
loss = 0.0
for current_batch_of_words in words_in_dataset:
    # The value of state is updated after processing each batch of words.
    output, state = lstm(current_batch_of_words, state)

    # The LSTM output can be used to make next word predictions
    logits = tf.matmul(output, softmax_w) + softmax_b
    probabilities.append(tf.nn.softmax(logits))
    loss += loss_function(probabilities, target_words)
截斷反向傳播

通過設計,遞歸神經網絡(RNN)的輸出依賴于任意遙遠的輸入(作者理解:比如很久之前的單詞對現在的輸出有影響)。不幸的是,這使得反向傳播計算很困難。為了使學習過程易于處理,創建一個 “unroll” 版本的網絡是很常見的做法,該版本包含了LSTM固定數目(num_steps)的輸入和輸出。然后將模型訓練成RNN的有限近似。這可以通過每次輸入長度num_steps的輸入來實現,并在每個輸入塊后執行反向傳播。

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

# Placeholder for the inputs in a given iteration.
words = tf.placeholder(tf.int32, [batch_size, num_steps])

lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size)
# Initial state of the LSTM memory.
initial_state = state = tf.zeros([batch_size, lstm.state_size])

for i in range(num_steps):
    # The value of state is updated after processing each batch of words.
    output, state = lstm(words[:, i], state)

    # The rest of the code.
    # ...

final_state = state

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

# A numpy array holding the state of LSTM after each batch of words.
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],
        # Initialize the LSTM state from the previous iteration.
        feed_dict={initial_state: numpy_state, words: current_batch_of_words})
    total_loss += current_loss
輸入

在輸入 LSTM 前,詞語 ID 被嵌入到了一個密集的表示中(查看 Vector Representations of Words)。這種方式允許模型高效地表示詞語,也便于寫代碼:

# embedding_matrix is a tensor of shape [vocabulary_size, embedding size]
word_embeddings = tf.nn.embedding_lookup(embedding_matrix, word_ids)

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

損失函數

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

實現起來并非很難,而且函數 sequence_loss_by_example 已經有了,可以直接使用。

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

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

多個 LSTM 層堆疊

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

類 MultiRNNCell 可以無縫的將其實現:

def lstm_cell():
  return tf.contrib.rnn.BasicLSTMCell(lstm_size)
stacked_lstm = tf.contrib.rnn.MultiRNNCell(
    [lstm_cell() for _ in range(number_of_layers)])

initial_state = state = stacked_lstm.zero_state(batch_size, tf.float32)
for i in range(num_steps):
    # The value of state is updated after processing each batch of words.
    output, state = stacked_lstm(words[:, i], state)

    # The rest of the code.
    # ...

final_state = state

運行代碼


在運行代碼之前,下載PTB數據集(見本教程開頭)。然后,將PTB數據集提取到你的 home directory

tar xvfz simple-examples.tgz -C $HOME

(注意:如果你是windows系統,你可能需要用 other tools.)

現在,從github上clone the TensorFlow models repo ,通過下面的命令行運行:

cd models/tutorials/rnn/ptbpython ptb_word_lm.py --data_path=$HOME/simple-examples/data/ --model=small

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

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

除此之外?


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

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

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

原文:Recurrent Neural Networks 翻譯:周乘

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容