截至目前,TensorFlow的RNN APIs還處於Draft階段。不過據官方解釋,RNN的相關API已經出現在Tutorials裡了,大幅度的改動應該是不大可能,現在入手TF的RNN APIs風險應該是不大的。
目前TF的RNN APIs主要集中在tensorflow.models.rnn中的rnn和rnn_cell兩個模組。其中,後者定義了一些常用的RNN cells,包括RNN和優化的LSTM、GRU等等;前者則提供了一些helper方法。
建立一個基礎的RNN很簡單:
1 |
from tensorflow.models.rnn import rnn_cell |
2 |
cell = rnn_cell.BasicRNNCell(inputs, state) |
建立一個LSTM或者GRU的cell?
1 |
cell = rnn_cell.BasicLSTMCell(num_units) |
2 |
cell = rnn_cell.LSTMCell(num_units, input_size) |
3 |
cell = rnn_cell.GRUCell(num_units) |
呼叫呢?
1 |
output, state = cell( input , state) |
這樣自己按timestep呼叫需要設定variable_scope的reuse屬性為True,懶人怎麼做,TF也給想好了:
1 |
state = cell.zero_state(batch_size, dtype = tf.float32) |
2 |
outputs, states = rnn.rnn(cell, inputs, initial_state = state) |
再懶一點:
1 |
outputs, states = rnn.rnn(cell, inputs, dtype = tf.float32) |
怕overfit,加個Dropout如何?
1 |
cell = rnn_cell.DropoutWrapper(cell, input_keep_prob = 0.5 , output_keep_prob = 0.5 ) |
做個三層的帶Dropout的網路?
1 |
cell = rnn_cell.DropoutWrapper(cell, output_keep_prob = 0.5 ) |
2 |
cell = rnn_cell.MultiRNNCell([cell] * 3 ) |
3 |
inputs = tf.nn.dropout(inputs, 0.5 ) |
一個坑——用rnn.rnn要按照timestep來轉換一下輸入資料,比如像這樣:
1 |
inputs = [tf.reshape(t, (input_dim[ 0 ], 1 )) for t in tf.split( 1 , input_dim[ 1 ], inputs)] |
rnn.rnn()的輸出也是對應每一個timestep的,如果只關心最後一步的輸出,取outputs[-1]即可。
注意一下子返回值的dimension和對應關係,損失函式和其它情況沒有大的區別。
目前飽受詬病的是TF本身還不支援Theano中scan()那樣可以輕鬆實現的不定長輸入的RNN,不過有人反饋說Theano中不定長訓練起來還不如提前給inputs加個padding改成定長的訓練快。