1. 程式人生 > >Tensorflow中的RNN以及LSTM

Tensorflow中的RNN以及LSTM

先了解RNN:

每個RNNCell都有一個call方法,使用方式是:(output, next_state) = call(input, state)。每呼叫一次RNNCell的call方法,就相當於在時間上“推進了一步”,這就是RNNCell的基本功能。

import tensorflow as tf

import numpy as np

cell = tf.nn.rnn_cell.BasicRNNCell(num_units=128) # state_size = 128

print(cell.state_size) # 128

inputs = tf.placeholder(np.float32, shape=(32, 128)) # 32 是 batch_size

h0 = cell.zero_state(32, np.float32) # 通過zero_state得到一個全0的初始狀態,形狀為(batch_size, state_size)

output, h1 = cell.call(inputs, h0) #呼叫call函式,我所理解的輸出維度應該為[batch_size,  state_size],當然後面還會有輸出層。

print(h1.shape) # (32, 128)

在程式碼實現上,RNNCell只是一個抽象類,我們用的時候都是用的它的兩個子類BasicRNNCell和BasicLSTMCell。顧名思義,前者是RNN的基礎類,後者是LSTM的基礎類。

除了call方法外,對於RNNCell,還有兩個類屬性比較重要:state_size、output_size。前者是隱層的大小,後者是輸出的大小。比如我們通常是將一個batch送入模型計算,設輸入資料的形狀為(batch_size, input_size),那麼計算時得到的隱層狀態就是(batch_size, state_size),輸出就是(batch_size, output_size)。

對於BasicLSTMCell,情況有些許不同,因為LSTM可以看做有兩個隱狀態h和c,(此處可參見LSTM的結構)對應的隱層就是一個Tuple,每個都是(batch_size, state_size)的形狀。

import tensorflow as tf

import numpy as np

lstm_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units=128)

inputs = tf.placeholder(np.float32, shape=(32, 100)) # 32 是 batch_size

h0 = lstm_cell.zero_state(32, np.float32) # 通過zero_state得到一個全0的初始狀態

output, h1 = lstm_cell.call(inputs, h0)

print(h1.h)  # shape=(32, 128),  PS:這裡維度為什麼和c一樣?

print(h1.c)  # shape=(32, 128)

執行多步:使用tf.nn.dynamic_rnn函式。呼叫方式:

#inputs: shape = (batch_size, time_steps, input_size)

#cell: RNNCell

# initial_state: shape = (batch_size, cell.state_size)。初始狀態。一般可以取零矩陣

outputs, state = tf.nn.dynamic_rnn(cell, inputs, initial_state=initial_state)

得到的outputs就是time_steps步裡所有的輸出。它的形狀為(batch_size, time_steps, cell.output_size)。state是最後一步的隱狀態,它的形狀為(batch_size, cell.state_size)。cell.state_size也即隱藏層的大小。(這裡關於隱藏層狀態的個數和時間步沒有關係?不太明白

堆疊RNNCell:MultiRNNCell

將x輸入第一層RNN的後得到隱層狀態h,這個隱層狀態就相當於第二層RNN的輸入,第二層RNN的隱層狀態又相當於第三層RNN的輸入,以此類推。在TensorFlow中,可以使用tf.nn.rnn_cell.MultiRNNCell函式對RNNCell進行堆疊,相應的示例程式如下:
import tensorflow as tf
import numpy as np
num_layers = 2
rnn_cell = tf.nn.rnn_cell.BasicRNNCell(num_units=128)
# 得到的cell實際也是RNNCell的子類
mutil_rnn_cell = tf.nn.rnn_cell.MultiRNNCell([rnn_cell]*num_layers)
# 它的state_size是(128, 128)
print(mutil_rnn_cell.state_size) # (128, 128)並不是128x128的意思,而是表示共有2個隱層狀態,每個隱層狀態的大小為128
input = tf.placeholder(dtype=np.float32, shape=[32, 128])
h0 = mutil_rnn_cell.zero_state(batch_size=32, dtype=np.float32)
output, h1 = mutil_rnn_cell.call(input, h0)
print(output.shape) #(32, 128)
print(h1)  # tuple中含有2個32x128的向量