TensorFlow 深度学习框架(13) -- 循环神经网络 RNN 简介

在我们处理的大多数网络结构中,虽然两层神经网络之间都有连接,但是,同一层的网络节点之间是独立的。但是往往一个神经网络的输出不仅仅与他的输入有关,还与之前的输入有关。循环神经网络通过上一时刻的状态来代替上一层的输入,并与新的输入一起组成一个输入序列,从而作为新的输入传入网络。也就是说,循环神经网络擅长解决与时间序列相关的问题。一个经典的循环神经网络示意图如下:

设想一下,在自然语言处理领域,我们可以将文本的上下文信息作为时间序列处理,表示输出不仅仅与输入有关,更与上下文顺序有关。循环神经网络前向传播的具体示例如下:

解释:t0 输入为1, 和初始状态[0.0,0.0] 组合作为输入经过 tanh 函数输出层的输出为 [0.537,0.462]。然后在 t1 时刻,输入为2,此时 t-1 即 t0 时刻的状态为 [0.537,0.462]加上输入2 组成 [0.537,0.462,2.0] 作为新的输入,生成的状态 [0.860,0.884] 又作为下一时刻的状态。。。如此循环。

 

长短时记忆网络 LSTM

这句话很重要,个人理解:循环神经网络 lstm 结构的标准输入包括 batch 的话是一个二维的数组 ,不包括batch 在内就是一维数组,跟全连接神经网络输入结构一样,每个时刻的输出也是 [batch_size, lstm_hidden_size] 的二维数据。把每个时刻的输出组合起来成为 lstm 的输出,将 lstm 某一时刻当做一层隐藏层看待即可,即看成某种具有时序状态的隐藏层。(在利用 RNN 生成语言模型时就会发现利用了句子词序列的词向量顺序体现上下文时间序列)

长短时记忆网络 LSTM 是循环神经网络 RNN 中一个重要的结构,它的设计主要是为了解决 在复杂的场景中,有用信息的间隔有大有小,长短不一对循环神经网络造成限制的问题。基本结构是 输入门,遗忘门 和输出门,遗忘门的作用是让循环神经网络“忘记”之前没有用的信息。在 TensorFlow 中使用 LSTM 结构的循环神经网络前向传播过程如下:

# 定义一个 LSTM 结构,在 TensorFlow中只要一个简单的命令就可以实现
''' lstm_hidden_size 就是 lstm 结构隐藏层的规模大小
    我个人理解为代表时间序列状态的长度 '''
lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_hidden_size)

# 将 LSTM 中的状态初始化为全 0 数组
# 在优化神经网络时,每次也是使用一个 batch 的训练样本
state = lstm.zero_state(batch_size,tf.float32)

# 计算每一个时刻的前向传播并计算该时刻的损失函数
loss = 0.0
# 理论上循环神经网络可以处理任意长度的序列,但是为了避免梯度消散的问题
# 在训练的时候会规定一个最大的序列长度,用 num_steps 表示
for i in range(num_steps):
    # 在第一个时刻声明 lstm 结构中使用的变量,后面复用这些变量
    if i >0:tf.get_variable_scope().reuse_variables()
    # 每一步处理时间序列中的一个时刻。将当前输入 current_input 和前一时刻状态 state 
    # 传入定义的 lstm 结构可以得到当前 lstm 结构的输出 lstm_output 和更新后的状态 state
    lstm_output,state = lstm(current_input,state)
    
    # 将当前时刻 lstm 结构的输出传入一个全连接层得到最后的输出
    final_output = fully_connected(lstm_output)
    
    # 计算损失函数
    loss += calc_loss(final_output,expected_output)

RNN 变种 -- 双向循环神经网络

在经典的循环神经网络中,状态的传输是从前往后单向的。但是在有些问题中,当前时刻的输出不仅仅和之前的状态有关系,也和之后的状态有关。这时就需要用到双向循环神经网络(bidirectional RNN)

RNN 变种 -- 深层循环神经网络

深层循环网络(deepRNN)是循环神经网络的另一个变种,为了增强模型的表达能力,可以将每一个时刻上的循环体重复多次。

# 定义一个基本的 lstm 结构作为循环体的基础结构。
# lstm_hidden_size 就是 lstm 隐藏层的规模,我理解为状态的长度
lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_hidden_size)

# 通过 MultiRNNCell 类实现深层循环神经网络中每一个时刻的前向传播过程,其中num_of_layers 表示层数
stacked_lstm = tf.nn.rnn_cell.MultiRNNCell([lstm] * num_of_layers)

# 状态初始化
state = stacked_lstm.zero_state(batch_size,tf.float32)

# 计算每一时刻的前向传播结果
for i in range(len(num_steps)):
    if i>0:tf.get_variable_scope().reuse_variables()
    stacked_lstm_output,state = stacked_lstm(current_input,state)
    final_output = fully_connected(stacked_lstm_output)
    loss += calc_loss(final_output,expected_output)

循环神经网络的 dropout

循环神经网络只在不同层循环体之间使用 dropout ,而不在同一层循环体结构之间使用。也就是说从 t-1 时刻传递到时刻 t 时,循环神经网络不会进行状态的 dropout;而在同一时刻 t 中,不同层循环体之间会使用 dropout

lstm = rnn_cell.BasicLSTMCell(lstm_hidden_size)

# 使用 DropoutWrapper 类来实现 dropout 功能。该类提供两个参数来控制 dropout 概率
# 一个参数为 input_keep_prob 控制输入的 dropout 概率
# 另一个参数为 output_keep_prob 控制输出的 dropout 概率
dropout_lstm = tf.nn.rnn_cell.DropoutWrapper(lstm,output_keep_prob = 0.5)

# 在使用了 dropout 的基础上定义
stacked_lstm = rnn_cell.MultiRNNCell([dropout_lstm] * num_of_layers)

# 接下来跟上述一样了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值