TensorFlow中对LSTM的一些理解

tensorflow中的tf.nn.rnn_cell.LSTMCell中num_units的参数理解

在这里插入图片描述
喂数据的方式
绿色的框是一个细胞的不同时刻的展开,展开成time_step个时刻,
喂数据方式,每次进入batch_size个数据,每个数据的形状都是input_size

所以每个time_step的输出都是batch_size*output_size的形状

unites的深入理解
具体维度计算,可参考链接 1. https://blog.csdn.net/notHeadache/article/details/81164264

batchsize, time_step, input_size参数的理解
在这里,可以把batch_size,time_step, input_size三个参数想象成往碎纸机里放A4的白纸
其中input_size可以看成A4纸的宽度,
batch_size是喂数据时喂多少输入,可以看成是A4纸的长度
time_step是多少个时刻,每隔一个时刻喂一次数据,所以time_step可以看成A4纸的厚度,每一个时刻放入一张A4纸搅碎

深入理解可参考链接 https://zhuanlan.zhihu.com/p/36455374

tf.nn.dynamic_rnn的输入参数与返回值的理解

tf.nn.dynamic_rnn的输入参数

在这里插入图片描述
cell:RNNCell实例
inputs:是一个tensor,
如果time_major== False(默认),则张量的形状必须是:[batch_size,max_time,embed_size];
如果time_major== True(默认),则张量的形状必须是:[max_time,batch_size,embed_size]
sequence_length: (可选)
大小为[batch_size],数据的类型是int32/int64向量。
如果当前时间步的index超过该序列的实际长度时,则该时间步不进行计算,RNN的state复制上一个时间步的,同时该时间步的输出全部为零。
如果batch_size的max_time不同,则输入每个batch_size的max_time
initial_state: (可选)
RNN的初始state(状态)。
如果cell.state_size(一层的RNNCell)是一个整数,那么它必须是一个具有适当类型和形状的张量[batch_size,cell.state_size]。
如果cell.state_size是一个元组(多层的RNNCell,如MultiRNNCell),那么它应该是一个张量元组,每个元素的形状为[batch_size,s] for s in cell.state_size].

time_major: inputs 和outputs 张量的形状格式。
如果为True,则这些张量都应该是(都会是)[max_time,batch_size,depth.]。
如果为false,则这些张量都应该是(都会是)[batch_size,max_time,depth]。

tf.nn.dynamic_rnn的返回值outputs与state的含义

返回的是outputs与state

outputs.

** outputs是一个tensor。**
如果time_major==True,outputs形状为 [max_time, batch_size, cell.output_size ](要求rnn输入与rnn输出形状保持一致)

如果time_major==False(默认),outputs形状为 [ batch_size, max_time, cell.output_size ]

代表outputs输出为为batch_size* time_step* cell.output_size的矩阵;
所以outputs里面保存了所有时刻的ht的信息,(数据每次输入是batch_size个,当max_time= 1 时,输出的是batch_size*output_size,当max_time有取值时,输出把time_step放入中间的维度,说明保存了所有时刻的信息)

:这里的max_time与上文的time_step是一个意思

state

state是一个tensor。
state是最终的状态,也就是序列中最后一个cell输出的状态。(state保存了最后一个时刻的Ct和ht的信息)

一般情况下state的形状为 [batch_size, cell.output_size ],
但当输入的cell为BasicLSTMCell时,state的形状为[2,batch_size, cell.output_size ],
其中2也对应着LSTM中的cell state和hidden state。
(state可以看成是一个元组,当最前面取0时,它代表的是最后一个时刻的cell satae的形状,即最后一个时刻Ct的形状为batch_sizeoutput_size, 当它取1时,代表的是最后一个时刻的hidden state的形状,即,最后一个时刻ht的形状为batch_sizeoutput_size)

state[ 1, batch_size, : ] == outputs[ batch_size, -1, : ]

这代表的是矩阵的对应元素相等,
其中batch_size代表一个可以从0到batch_size取值的变量,
取:是因为可以从里面把它取出一个矩阵来,其中state的形状为1 * 1 * : outputs的形状为1 * 1 * :,形状相同,所以最后一个可以取成冒号,取出矩阵

tf.nn.dynamic_rnn的实例

import tensorflow as tf
import numpy as np
 
def dynamic_rnn(rnn_type='lstm'):

    X = np.random.randn(3, 6, 4)
    #3代表batch size,6代表输入序列的最大步长(max time), 4代表输入数据x的维度(input_size)
	
	X[1, 4:] = 0
	#选1是指选到了第二个维度,4是指从4后面起都让它等于0,所以第二维的最大长度是4,不是和其它几维一样的6
	
	X_lengths = [6, 4, 6]
	#所以3个batch的最大长度(max time)分别为[4, 6, 4]

	Cell = tf.contrib.rnn.BasicLSTMCell(num_units=rnn_hidden_size, state_is_tuple=True)
	
    rnn_hidden_size = 5  #神经元个数
    if rnn_type == 'lstm':
        cell = tf.contrib.rnn.BasicLSTMCell(num_units=rnn_hidden_size, state_is_tuple=True)
    else:
        cell = tf.contrib.rnn.GRUCell(num_units=rnn_hidden_size)
 
    outputs, last_states = tf.nn.dynamic_rnn(
        cell=cell,
        dtype=tf.float64,
        sequence_length=X_lengths,
        inputs=X)
 
    with tf.Session() as session:
        session.run(tf.global_variables_initializer())
        o1, s1 = session.run([outputs, last_states])
        print(np.shape(o1))
        print(o1)
        print(np.shape(s1))
        print(s1)
 
 
if __name__ == '__main__':
    dynamic_rnn(rnn_type='lstm')

实验结果
在这里插入图片描述
输入的形状为 [ 3, 6, 4 ]
经过tf.nn.dynamic_rnn后outputs的形状为 [ 3, 6, 5 ]

3是batch_size,6是max_time, 4是input_size

经过细胞之后,维度变成了[batch_size, max_time, output_size],
output_size也是unites的个数,所以输出形状变成了[3, 6, 5]
输出output_size的形状,输出了所有时刻的ht的信息

state形状为 [ 2, 3, 5 ],
其中state第一部分为c,代表cell state;第二部分为h,代表hidden state。

当state的一个维度为0时,代表最后一个时刻的cell state 的形状为[batch_size, output_size]
当state的一个维度为1时,代表最后一个时刻的hidden state的形状为[batchsize, output_size]

所以
把output最后一个时刻的ht都输出来,即第7行,12行, 21行拼起来是最后一个时刻的batchsize的ht的输出,与state的第二个部分的输出(ht的最后一个时刻)的输出相同。

另外需要注意的是输入一共有三个序列,
但第二个序列的长度只有4,可以看到outputs中对应的两行值都为0,所以hidden state对应的是最后一个不为0的部分。tf.nn.dynamic_rnn通过设置sequence_length来实现这一逻辑。

参考链接 https://blog.csdn.net/u010960155/article/details/81707498


版权声明:本文为weixin_44268208原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。