截至目前,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改成定長的訓練快。