函數(shù)原型
tf.nn.dynamic_rnn(
? ? cell,
? ? inputs,
? ? sequence_length=None,
? ? initial_state=None,
? ? dtype=None,
? ? parallel_iterations=None,
? ? swap_memory=False,
? ? time_major=False,
? ? scope=None
參數(shù)講解:
cell: RNNCell的一個(gè)實(shí)例.
inputs: RNN輸入.
如果time_major == False(默認(rèn)), 則是一個(gè)shape為[batch_size, max_time, input_size]的Tensor,或者這些元素的嵌套元組。
如果time_major == True,則是一個(gè)shape為[max_time, batch_size, input_size]的Tensor,或這些元素的嵌套元組。
sequence_length: (可選)大小為[batch_size],數(shù)據(jù)的類(lèi)型是int32/int64向量。如果當(dāng)前時(shí)間步的index超過(guò)該序列的實(shí)際長(zhǎng)度時(shí),則該時(shí)間步不進(jìn)行計(jì)算,RNN的state復(fù)制上一個(gè)時(shí)間步的,同時(shí)該時(shí)間步的輸出全部為零。
initial_state: (可選)RNN的初始state(狀態(tài))。如果cell.state_size(一層的RNNCell)是一個(gè)整數(shù),那么它必須是一個(gè)具有適當(dāng)類(lèi)型和形狀的張量[batch_size,cell.state_size]。如果cell.state_size是一個(gè)元組(多層的RNNCell,如MultiRNNCell),那么它應(yīng)該是一個(gè)張量元組,每個(gè)元素的形狀為[batch_size,s] for s in cell.state_size。
time_major: inputs 和outputs 張量的形狀格式。如果為T(mén)rue,則這些張量都應(yīng)該是(都會(huì)是)[max_time, batch_size, depth]。如果為false,則這些張量都應(yīng)該是(都會(huì)是)[batch_size,max_time, depth]。time_major=true說(shuō)明輸入和輸出tensor的第一維是max_time。否則為batch_size。
使用time_major =True更有效,因?yàn)樗苊饬薘NN計(jì)算開(kāi)始和結(jié)束時(shí)的轉(zhuǎn)置.但是,大多數(shù)TensorFlow數(shù)據(jù)都是batch-major,因此默認(rèn)情況下,此函數(shù)接受輸入并以batch-major形式發(fā)出輸出.
返回值:
一對(duì)(outputs, state),其中:
outputs: RNN輸出Tensor.
如果time_major == False(默認(rèn)),這將是shape為[batch_size, max_time, cell.output_size]的Tensor.
如果time_major == True,這將是shape為[max_time, batch_size, cell.output_size]的Tensor.
state: 最終的狀態(tài).
一般情況下state的形狀為 [batch_size, cell.output_size ]
如果cell是LSTMCells,則state將是包含每個(gè)單元格的LSTMStateTuple的元組,state的形狀為[2,batch_size, cell.output_size ]
實(shí)列講解
import tensorflow as tf
import numpy as np
n_steps = 2
n_inputs = 3
n_neurons = 5? ? # 也就是hidden_size
X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
basic_cell = tf.contrib.rnn.BasicRNNCell(num_units=n_neurons)
seq_length = tf.placeholder(tf.int32, [None])
outputs, states = tf.nn.dynamic_rnn(basic_cell, X, dtype=tf.float32,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sequence_length=seq_length)
init = tf.global_variables_initializer()
X_batch = np.array([
? ? ? ? # step 0? ? step 1
? ? ? ? [[0, 1, 2], [9, 8, 7]], # instance 1
? ? ? ? [[3, 4, 5], [0, 0, 0]], # instance 2
? ? ? ? [[6, 7, 8], [6, 5, 4]], # instance 3
? ? ? ? [[9, 0, 1], [3, 2, 1]], # instance 4
? ? ])
seq_length_batch = np.array([2, 1, 2, 2])? ? #規(guī)定每個(gè)樣本的timestep的大小,如[3, 4, 5], [0, 0, 0]就只保留[3, 4, 5]的部分
with tf.Session() as sess:
? ? init.run()
? ? outputs_val, states_val = sess.run(
? ? ? ? [outputs, states], feed_dict={X: X_batch, seq_length: seq_length_batch})
? ? print("outputs_val.shape:", outputs_val.shape, "states_val.shape:", states_val.shape)
? ? print("outputs_val:", outputs_val, "states_val:", states_val)
輸出
outputs_val.shape: (4, 2, 5) states_val.shape: (4, 5)
outputs_val:? ? ? #對(duì)應(yīng)states_val中的部分用刪除線劃出,后面都是這種形式
[[[ 0.53073734, -0.61281306, -0.5437517 ,? 0.7320347,? -0.6109526 ]
? [
0.99996936 , 0.99990636 ,-0.9867181 ,? 0.99726075 ,-0.99999976]][[
0.9931584 ,? 0.5877845 , -0.9100412 ,? 0.988892 ,? -0.9982337]? [ 0.? ? ,? ? ? 0.? ? ?,? ? ?0.? ? ,? ? ? 0.? ? ? ,? ? 0.? ? ? ? ]]
[[ 0.99992317 , 0.96815354 ,-0.985101? ,? 0.9995968 , -0.9999936 ]
? [
0.99948144 , 0.9998127? -,0.57493806 , 0.91015154 -,0.99998355]][[ 0.99999255? ,0.9998929 ,? 0.26732785,? 0.36024097 ,-0.99991137]
? [
0.98875254?,0.9922327 ,? 0.6505734? ,0.4732064? ,-0.9957567]]]states_val:
[[ 0.99996936,? 0.99990636, -0.9867181 ,? 0.99726075 ,-0.99999976]
[ 0.9931584? ,0.5877845? ,-0.9100412,? ?0.988892 ,? -0.9982337 ]
[ 0.99948144? ,0.9998127 , -0.57493806,? 0.91015154, -0.99998355]
[ 0.98875254 , 0.9922327,? ?0.6505734 ,? 0.4732064 , -0.9957567 ]]
上面代碼搭建的RNN網(wǎng)絡(luò)如下圖所示

上圖中:橢圓表示tensor,矩形表示RNN cell。
outputs是最后一層的輸出,即 [batch_size,step,n_neurons] =?[4,2,5]?
states是每一層的最后一個(gè)step的輸出,即三個(gè)結(jié)構(gòu)為 [batch_size,n_neurons] =?[4,5] 的tensor
繼續(xù)觀察數(shù)據(jù),states中的最后一個(gè)array,正好是outputs的最后那個(gè)step的輸出
首先tf.nn.dynamic_rnn()的time_major是默認(rèn)的false,故輸入X應(yīng)該是一個(gè)[batch_size,step,input_size]=[4,2,3] 的tensor,注意我們這里調(diào)用的是BasicRNNCell,只有一層循環(huán)網(wǎng)絡(luò),outputs是最后一層每個(gè)step的輸出,它的結(jié)構(gòu)是[batch_size,step,n_neurons]=[4,2,5] ,states是每一層的最后那個(gè)step的輸出,由于本例中,我們的循環(huán)網(wǎng)絡(luò)只有一個(gè)隱藏層,所以它就代表這一層的最后那個(gè)step的輸出,因此它和step的大小是沒(méi)有關(guān)系的,我們的X有4個(gè)樣本組成,隱層神經(jīng)元個(gè)數(shù)為n_neurons是5,因此states的結(jié)構(gòu)就是[batch_size,n_neurons]=[4,5] ,最后我們觀察數(shù)據(jù),states的每條數(shù)據(jù)正好就是outputs的最后一個(gè)step的輸出。
下面我們繼續(xù)講解多個(gè)隱藏層的情況,這里是三個(gè)隱藏層,注意我們這里仍然是調(diào)用BasicRNNCell
import tensorflow as tf
import numpy as np
n_steps = 2
n_inputs = 3
n_neurons = 5
n_layers = 3
X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])
seq_length = tf.placeholder(tf.int32, [None])
layers = [tf.contrib.rnn.BasicRNNCell(num_units=n_neurons,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? activation=tf.nn.relu)
? ? ? ? ? for layer in range(n_layers)]
multi_layer_cell = tf.contrib.rnn.MultiRNNCell(layers)
outputs, states = tf.nn.dynamic_rnn(multi_layer_cell, X, dtype=tf.float32, sequence_length=seq_length)
init = tf.global_variables_initializer()
X_batch = np.array([
? ? ? ? # step 0? ? step 1
? ? ? ? [[0, 1, 2], [9, 8, 7]], # instance 1
? ? ? ? [[3, 4, 5], [0, 0, 0]], # instance 2 (padded with zero vectors)
? ? ? ? [[6, 7, 8], [6, 5, 4]], # instance 3
? ? ? ? [[9, 0, 1], [3, 2, 1]], # instance 4
? ? ])
seq_length_batch = np.array([2, 1, 2, 2])
with tf.Session() as sess:
? ? init.run()
? ? outputs_val, states_val = sess.run(
? ? ? ? [outputs, states], feed_dict={X: X_batch, seq_length: seq_length_batch})
? ? print("outputs_val.shape:", outputs, "states_val.shape:", states)
? ? print("outputs_val:", outputs_val, "states_val:", states_val)
輸出
outputs_val.shape:
Tensor("rnn/transpose_1:0", shape=(?, 2, 5), dtype=float32)
states_val.shape:
(<tf.Tensor 'rnn/while/Exit_3:0' shape=(?, 5) dtype=float32>,
<tf.Tensor 'rnn/while/Exit_4:0' shape=(?, 5) dtype=float32>,
<tf.Tensor 'rnn/while/Exit_5:0' shape=(?, 5) dtype=float32>)
outputs_val:
[[[0.? ?,? ? ? 0.? ? ?,? ? 0.? ?,? ? ? 0.? ?,? ? ? 0.? ? ? ? ]
? [
0.? ? ,? ? ?0.18740742, 0.? ? ,? ? ?0.2997518 , 0.? ? ? ?]][[
0.? ? ? ,? ?0.07222144 ,0.? ? ,? ? ?0.11551574 ,0.? ? ? ?]? [0.? ?,? ? ? 0.? ?,? ? ? 0.? ? ,? ? ?0.? ? ,? ? ?0.? ? ? ? ]]
[[0.? ? ,? ? ?0.13463384, 0.? ? ,? ? ?0.21534224, 0.? ? ? ? ]
? [
0.03702604, 0.18443246 ,0.? ? ,? ? ?0.34539366 ,0.? ? ? ?]][[0.? ,? ? ? 0.54511094 ,0.? ?,? ? ? 0.8718864 , 0.? ? ? ? ]
? [
0.5382122,? 0.? ?,? ? ? 0.04396425, 0.4040263 , 0.? ? ? ?]]]states_val:
(array([[0.? ? ? ? , 0.83723307, 0.? ? ? ? , 0.? ? ? ? , 2.8518028 ],
? ? ? [0.? ? ? ? , 0.1996038 , 0.? ? ? ? , 0.? ? ? ? , 1.5456247 ],
? ? ? [0.? ? ? ? , 1.1372368 , 0.? ? ? ? , 0.? ? ? ? , 0.832613? ],
? ? ? [0.? ? ? ? , 0.7904129 , 2.4675028 , 0.? ? ? ? , 0.36980057]],
? ? ? dtype=float32),
? array([[0.6524607 , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.25143963, 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.5010576 , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.3166597 , 0.4545995 , 0.? ? ? ? , 0.? ? ? ? ]],
? ? ? dtype=float32),
? array([[0.? ? ? ? , 0.18740742, 0.? ? ? ? , 0.2997518 , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.07222144, 0.? ? ? ? , 0.11551574, 0.? ? ? ? ],
? ? ? [0.03702604, 0.18443246, 0.? ? ? ? , 0.34539366, 0.? ? ? ? ],
? ? ? [0.5382122 , 0.? ? ? ? , 0.04396425, 0.4040263 , 0.? ? ? ? ]],
? ? ? dtype=float32))
多層的RNN網(wǎng)絡(luò)如下圖所示

我們說(shuō)過(guò),outputs是最后一層的輸出,即 [batch_size,step,n_neurons]=[4,2,5]?
states是每一層的最后一個(gè)step的輸出,即三個(gè)結(jié)構(gòu)為 [batch_size,n_neurons]=[4,5]的tensor繼續(xù)觀察數(shù)據(jù),states中的最后一個(gè)array,正好是outputs的最后那個(gè)step的輸出。
下面我們繼續(xù)講當(dāng)由BasicLSTMCell構(gòu)造單元工廠的時(shí)候,只講多層的情況,我們只需要將上面的 BasicRNNCell替換成BasicLSTMCell就行了,打印信息如下:
outputs_val.shape:
Tensor("rnn/transpose_1:0", shape=(?, 2, 5), dtype=float32)
states_val.shape:
(LSTMStateTuple(c=<tf.Tensor 'rnn/while/Exit_3:0' shape=(?, 5) dtype=float32>,
? ? ? ? ? ? ? ? h=<tf.Tensor 'rnn/while/Exit_4:0' shape=(?, 5) dtype=float32>),
LSTMStateTuple(c=<tf.Tensor 'rnn/while/Exit_5:0' shape=(?, 5) dtype=float32>,
? ? ? ? ? ? ? h=<tf.Tensor 'rnn/while/Exit_6:0' shape=(?, 5) dtype=float32>),
LSTMStateTuple(c=<tf.Tensor 'rnn/while/Exit_7:0' shape=(?, 5) dtype=float32>,
? ? ? ? ? ? ? h=<tf.Tensor 'rnn/while/Exit_8:0' shape=(?, 5) dtype=float32>))
outputs_val:
[[[1.2949290e-04 ,0.0000000e+0,0 2.7623639e-04, 0.0000000e+00, 0.0000000e+00]
? [
9.4675866e-05 ,0.0000000e+00 ,2.0214770e-04, 0.0000000e+00, 0.0000000e+00]][[
4.3100454e-06 ,4.2123037e-07 ,1.4312843e-06 ,0.0000000e+00, 0.0000000e+00]? [0.0000000e+00, 0.0000000e+00 ,0.0000000e+00 ,0.0000000e+00, 0.0000000e+00]]
[[0.0000000e+00 ,0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ,0.0000000e+00]
? [
0.0000000e+00, 0.0000000e+00 ,0.0000000e+00, 0.0000000e+00 ,0.0000000e+00]][[0.0000000e+00 ,0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ,0.0000000e+00]
? [
0.0000000e+00 ,0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ,0.0000000e+00]]]states_val:
(LSTMStateTuple(
c=array([[0.? ? ? ? , 0.? ? ? ? , 0.04676079, 0.04284539, 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.0115245 , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ]],
? ? ? dtype=float32),
h=array([[0.? ? ? ? , 0.? ? ? ? , 0.00035096, 0.04284406, 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.00142574, 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ],
? ? ? [0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? , 0.? ? ? ? ]],
? ? ? dtype=float32)),
LSTMStateTuple(
c=array([[0.0000000e+00, 1.0477135e-02, 4.9871090e-03, 8.2785974e-04,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 2.3306280e-04, 0.0000000e+00, 9.9445322e-05,
? ? ? ? 5.9535629e-05],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00]], dtype=float32),
h=array([[0.00000000e+00, 5.23016974e-03, 2.47756205e-03, 4.11730434e-04,
? ? ? ? 0.00000000e+00],
? ? ? [0.00000000e+00, 1.16522635e-04, 0.00000000e+00, 4.97301044e-05,
? ? ? ? 2.97713632e-05],
? ? ? [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
? ? ? ? 0.00000000e+00],
? ? ? [0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
? ? ? ? 0.00000000e+00]], dtype=float32)),
LSTMStateTuple(
c=array([[1.8937115e-04, 0.0000000e+00, 4.0442235e-04, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [8.6200516e-06, 8.4243663e-07, 2.8625946e-06, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00]], dtype=float32),
h=array([[9.4675866e-05, 0.0000000e+00, 2.0214770e-04, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [4.3100454e-06, 4.2123037e-07, 1.4312843e-06, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00],
? ? ? [0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
? ? ? ? 0.0000000e+00]], dtype=float32)))
LSTM的網(wǎng)絡(luò)結(jié)構(gòu)如下圖:

一個(gè)LSTM cell有兩個(gè)狀態(tài)Ct和ht ,而不是像一個(gè)RNN cell一樣只有ht?
關(guān)于LSTM的講解可以看博客:LSTM理論知識(shí)講解
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?LSTM模型與前向反向傳播算法 - 劉建平Pinard - 博客園
在tensorflow中,將一個(gè)LSTM cell的Ct 和ht 合在一起,稱(chēng)為L(zhǎng)STMStateTuple。
因此我們的states包含三個(gè)LSTMStateTuple,每一個(gè)LSTMStateTuple表示每一層的最后一個(gè)step的輸出,這個(gè)輸出有兩個(gè)信息,一個(gè)是ht 表示短期記憶信息,一個(gè)是Ct 表示長(zhǎng)期記憶信息。維度都是[batch_size,n_neurons] = [4,5],states的最后一個(gè)LSTMStateTuple中的ht 就是outputs的最后一個(gè)step的輸出。
先總結(jié)一下,num_units這個(gè)參數(shù)的大小就是LSTM輸出結(jié)果的維度。例如num_units=128, 那么LSTM網(wǎng)絡(luò)最后輸出就是一個(gè)128維的向量。
我們先換個(gè)角度舉個(gè)例子,最后再用公式來(lái)說(shuō)明。
假設(shè)在我們的訓(xùn)練數(shù)據(jù)中,每一個(gè)樣本 x 是 28*28 維的一個(gè)矩陣,那么將這個(gè)樣本的每一行當(dāng)成一個(gè)輸入,通過(guò)28個(gè)時(shí)間步驟展開(kāi)LSTM,在每一個(gè)LSTM單元,我們輸入一行維度為28的向量,如下圖所示。

那么,對(duì)每一個(gè)LSTM單元,參數(shù) num_units=128 的話,就是每一個(gè)單元的輸出為 128*1 的向量,在展開(kāi)的網(wǎng)絡(luò)維度來(lái)看,如下圖所示,對(duì)于每一個(gè)輸入28維的向量,LSTM單元都把它映射到128維的維度, 在下一個(gè)LSTM單元時(shí),LSTM會(huì)接收上一個(gè)128維的輸出,和新的28維的輸入,處理之后再映射成一個(gè)新的128維的向量輸出,就這么一直處理下去,知道網(wǎng)絡(luò)中最后一個(gè)LSTM單元,輸出一個(gè)128維的向量。

從LSTM的公式的角度看是什么原理呢?我們先看一下LSTM的結(jié)構(gòu)和公式:

參數(shù) num_units=128 的話,

所以最后LSTM單元輸出的h就是 128?1的向量。
參考鏈接:
https://blog.csdn.net/notHeadache/article/details/81164264
Tensorflow一些常用基本概念與函數(shù) - 吾知 - 博客園
https://blog.csdn.net/u010960155/article/details/81707498
https://blog.csdn.net/mch2869253130/article/details/89280203
LSTM案例