如何建立多层的LSTM(以及双向lstm构建) 基于最新的tensorflow(相对来说,区别于一些老版本)

首先MultiRNNCell函数第一个参数是RNN实例形成的列表,第二个参数就是让状态成为一个元组。 

#tf.nn.rnn_cell.MultiRNNCell([list RNNcell], state_is_tuple=True).这个函数里面主要这两个参数,
# 第一个参数就是输入的RNN实例形成的列表,第二个参数就是让状态是一个元祖,官方推荐就是用True。

方法一:

stacked_rnn = []
for iiLyr in range(layer_num):
    stacked_rnn.append(tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, state_is_tuple=True))
mlstm_cell = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_rnn, state_is_tuple=True)

方法二:

def lstm_cell():
    cell = rnn.LSTMCell(hidden_size)#, reuse=tf.get_variable_scope().reuse)###考虑中 明天问一下  问过了 没用####

    return rnn.DropoutWrapper(cell, output_keep_prob=keep_prob)
mlstm_cell = tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(layer_num)], state_is_tuple=True)

其实方法2和方法1效果一样 只不过加了一个dropout层而已 (一般dropout层只设置output_keep_prob即可)

下面再来说一下关于双向LSTM的建立:

在上篇博客里我们说明了static和dynamic建立lstm的区别,在此我们在此再次看一下建立双向lstm的过程中static和dynamic的区别:

1.首先关于tf.contrib.rnn.static_bidirectional_rnn建立双向lstm,代码如下:(总之大体意思就是,这个已经是级联好了的,所以说output【-1】就代表我们的最终输出,他的size是【time,batch_size,hidden_size*2】*2是因为把双向的lstm进行级联)

def BiRNN(x, weights, biases):
    x = tf.transpose(x, [1, 0, 2])
    x = tf.reshape(x, [-1, n_input])
    x = tf.split(x, n_steps)
    lstm_fw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)
    lstm_bw_cell = tf.contrib.rnn.BasicLSTMCell(n_hidden, forget_bias=1.0)
    outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(
    lstm_fw_cell,
    lstm_bw_cell,
    x,
    dtype=tf.float32)
    #outputs = tf.concat(outputs,2)
    return tf.matmul(outputs[-1], weights) + biases
#这个地方是因为static已经对正向和反向的输出进行级联了,所以这里不需要concat  而dynamic需要进行拼接
Aliases:

tf.contrib.rnn.static_bidirectional_rnn
	tf.nn.static_bidirectional_rnn
创建双向循环神经网络。

与单向循环神经网络类似,只不过双向循环神经网络同时接受前向和反向的RNN神经元,最终对前向和反向的输出进行深度级联,输出的格式如: [time][batch][cell_fw.output_size + cell_bw.output_size].前向和反向神经元的input_size必须匹配。默认情况下,前向和反向的初始状态为0,并且不反回任何中间状态。如果给定序列的长度,网络完全展开,如果没有给定长度,则不展开。

#########################################################
格式:

tf.nn.static_bidirectional_rnn(
    cell_fw,

    cell_bw,

    inputs,

    initial_state_fw=None,

    initial_state_bw=None,

    dtype=None,

    sequence_length=None,

    scope=None
)

################################################
参数说明:

cell_fw:前向神经元,如BasicRNNCell.
	cell_bw:反向神经元
	input:网络输入,一个长度为T的list,list中的每个Tensor元素shape为[batch_size,input_size]
	initial_state_fw:可选参数。前向RNN的初始RNN,必须是合适类型的Tensor以及shape为[batch_size,cell_fw.state_size]。
	Initial_state_bw:可选参数。同initial_state_fw。
	dtype:初始状态的数据类型。
	sequence_length:一个int32/int64的向量,长度为[batch_size],包含每个序列的实际长度。
	scope:默认为”bidirectional_rnn
#################################################
返回:

一个(outputs,output_state_fw,output_state_bw)的元组,其中,outputs是一个长度为T的list,list中的每个元素对应每个时间步的输出,它们是深度级联的前向和反向输出。output_state_fw是前向RNN的最终状态,output_state_bw是反向RNN的最终状态。

2.然后我们看一下动态函数tf.nn.bidirectional_dynamic_rnn建立(在此说明,本身两个lstm是反向的,通过reverse逆向保证了可以用相同的数字去索引 比如正向的第一个和逆向的最后一个都可以通过0去索引到,这里要注意的是,因为这里得到的返回值是【outputs_fw,outputs_bw】的格式,所以我们需要通过tf.concat(outputs,2)在最后一维进行连接才能保证最后输出是outputs【-1】):

def bidirectional_dynamic_rnn(
cell_fw, # 前向RNN
cell_bw, # 后向RNN
inputs, # 输入
sequence_length=None,# 输入序列的实际长度(可选,默认为输入序列的最大长度)
initial_state_fw=None,  # 前向的初始化状态(可选)
initial_state_bw=None,  # 后向的初始化状态(可选)
dtype=None, # 初始化和输出的数据类型(可选)
parallel_iterations=None,
swap_memory=False, 
time_major=False,
# 决定了输入输出tensor的格式:如果为true, 向量的形状必须为 `[max_time, batch_size, depth]`. 
# 如果为false, tensor的形状必须为`[batch_size, max_time, depth]`. 
scope=None
)
返回值:
元组:(outputs, output_states)
1.outputs为(output_fw, output_bw),是一个包含前向cell输出tensor和后向cell输出tensor组成的元组。假设 time_major=false,tensor的shape为[batch_size, max_time, depth]。实验中使用tf.concat(outputs, 2)将其拼接。
2.output_states为(output_state_fw, output_state_bw),包含了前向和后向最后的隐藏状态的组成的元组。 
output_state_fw和output_state_bw的类型为LSTMStateTuple。 
LSTMStateTuple由(c,h)组成,分别代表memory cell和hidden state。
#################################

而cell_fw和cell_bw的定义是完全一样的。如果这两个cell选LSTM cell整个结构就是双向LSTM了。

# lstm模型 正方向传播的RNN
lstm_fw_cell = tf.nn.rnn_cell.BasicLSTMCell(embedding_size, forget_bias=1.0)
# 反方向传播的RNN
lstm_bw_cell = tf.nn.rnn_cell.BasicLSTMCell(embedding_size, forget_bias=1.0)
12345

##################################
其实在bidirectional_dynamic_rnn函数的内部,会把反向传播的cell使用array_ops.reverse_sequence的函数将输入的序列逆序排列,使其可以达到反向传播的效果。 
在实现的时候,我们是需要传入两个cell作为参数就可以了:

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值