天天看點

簡單實用的 TensorFlow 實作 RNN 入門教程

最近在看rnn模型,為簡單起見,本篇就以簡單的二進制序列作為訓練資料,而不實作具體的論文仿真,主要目的是了解rnn的原理和如何在tensorflow中構造一個簡單基礎的模型架構。其中代碼參考了這篇部落格。

首先我們看一下實驗資料的構造:

輸入資料x:在時間t,xt的值有50%的機率為1,50%的機率為0;  輸出資料y:在實踐t,yt的值有50%的機率為1,50%的機率為0,除此之外,如果`xt-3 == 1`,yt為1的機率增加50%, 如果`xt-8 == 1`,則yt為1的機率減少25%, 如果上述兩個條件同時滿足,則yt為1的機率為75%。

可知,y與x有兩個依賴關系,一個是t-3,一個是t-8。我們實驗的目的就是檢驗rnn能否捕捉到y與x之間的這兩個依賴關系。實驗使用交叉熵作為評價标準,則有下面三條理想的實驗結果:

如果rnn沒有學習到任何一條依賴,那麼yt為1的機率就是0.625(0.5+0.5*0.5-0.5*0.25),是以所獲得的交叉熵應該是0.66(-(0.625 * np.log(0.625) + 0.375 * np.log(0.375)))。

如果rnn學習到第一條依賴關系,即xt-3為1時yt一定為1。那麼,是以最終的交叉熵應該是0.52(-0.5 * (0.875 * np.log(0.875) + 0.125 * np.log(0.125)) -0.5 * (0.625 * np.log(0.625) + 0.375 * np.log(0.375)))。

如果rnn學習到了兩條依賴, 那麼有0.25的機率全對,0.5的機率正确率是75%,還有0.25的機率正确率是0.5。是以其交叉熵為0.45(-0.50 * (0.75 * np.log(0.75) + 0.25 * np.log(0.25)) - 0.25 * (2 * 0.50 * np.log (0.50)) - 0.25 * (0))。

這部分主要是生成實驗資料,并将其按照rnn模型的輸入格式進行切分和batch化。代碼入下: 

1,生成實驗資料:

接下來将生成的資料按照模型參數設定進行切分,這裡需要用得到的參數主要包括:batch_size和num_steps,分别是批量資料大小和rnn每層rnn_cell循環的次數,也就是下圖中sn中n的大小。代碼入下:

根據上面的代碼我們可以看出來,這裡的資料劃分并沒有将資料完全的按照原先的資料順序,而是每隔一段取num_steps個資料,這樣組成的batch進行訓練==這裡是為了省事還是另有原因還有待後面學習中考證。

rnn的具體原理我們就不再進行贅述,主要是隐層狀态和輸入連接配接後計算新的隐層狀态和輸出。這裡用的是單層的rnn。公式和原理圖如下所示:

簡單實用的 TensorFlow 實作 RNN 入門教程

至于使用tensorflow建構rnn模型,主要就是定義rnn_cell類型,然後将其複用即可。代碼如下所示:

定義好我們的模型之後,接下來就是将資料傳入,然後進行訓練,代碼入下:

實驗結果如下所示: 

簡單實用的 TensorFlow 實作 RNN 入門教程

從上圖可以看出交叉熵最終穩定在0。52,按照我們上面的分析可以知道:rnn模型成功的學習到了第一條依賴關系,因為我們的循環步長選擇的是5,是以他隻能學習到t-3的第一條依賴關系,而無法學習到t-8的第二條依賴。 

接下來可以嘗試num_steps==10,區捕捉第二條依賴關系。最終的結果圖如下所示: 

簡單實用的 TensorFlow 實作 RNN 入門教程

從上圖可以看出,我們的rnn模型成功的學習到了兩條依賴關系。最終的交叉熵未定在0.46附近。

1,首先上面的代碼中,為了盡可能詳細的解釋tensorflow中rnn模型的構造方法,将rnn_cell的定義寫的很詳細,其實這些工作tf已經封裝好了,我們隻需要一行指令就可以實作,是以第一個要改進的地方就是将rnn_cell的定義和循環使用部分的代碼簡化:

2,使用動态rnn模型,上面的模型中,我們将輸入表示成清單的形式,即rnn_inputs是一個長度為num_steps的清單,其中每個元素是[batch_size, features]的tensor(即每個rnn_cell要處理的資料),這樣做事比較麻煩的,我們還可以使用tf提供的dynamic_rnn函數,這樣做不僅會使程式設計更加簡單,還可以提高計算效率。使用dynamic_rnn 時,我們直接将輸入表示成[batch_size, num_steps, features]的三維tensor即可。最終的動态rnn模型代碼如下所示:

至此,我們就實作了一個很簡單的rnn模型的構造,在這個過程中,我們需要注意的主要有以下三點:

如何将資料轉化成rnn所能接受的輸入格式,需要注意batch_size和num_steps之間的關系。

定義rnn_cell,這裡使用的是下面這條指令:cell = tf.contrib.rnn.basicrnncell(state_size)

定義rnn模型,可以使用下面這兩條指令分别靜态和動态建構:

====================================分割線================================

本文作者:ai研習社

繼續閱讀