RNN-LSTM
- 1.RNN
- 2.LSTM
- 3. tensorflow 中的RNN-LSTM
- 3.1 tf.nn.rnn_cell.BasicRNNCell()
- 3.2 tf.nn.rnn_cell.BasicLSTMCell()
- 3.3 tf.nn.dynamic_rnn()--多步执行循环神经网络
1.RNN
RNN-Recurrent Neural Network-循环神经网络
RNN用来处理序列数据。多层感知机MLP层间节点全联接,层内节点并无链接。 RNN层内节点的之间存在连接关系,用来反映上一层隐层状态作为下一层的输入,将直接输给中间隐藏层。
RNN网络模块图如下所示:
其中: xtx_txt 网络t时刻输入, hth_tht 网络t时刻的输出。 如果将RNN按时间序列展开,可以得到以下链式结构:
用简单的权重矩阵建模rnn, 输入-状态-输出之间存在以下的关系:[oto_tot即上文的hth_tht]
st=f(U⋅xt+W⋅st−1)s_{t} = f(U\cdot x_t + W\cdot s_{t-1})st=f(U⋅xt+W⋅st−1)
ot=g(V⋅st)o_t = g(V\cdot s_t)ot=g(V⋅st)
st−1s_{t-1}st−1能够建模历史信息对当前输出的影响。原始RNN随着时间的推移,历史状态对当前输出的影响减弱。但是很多任务需要长时依赖关系。LSTM营运而生。
2.LSTM
LSTM-Long Short-Term Memory 可以学习长时依赖信息,LSTM网络模块图如下所示:
状态传递机制决定了上一时刻状态信息的保留量,以及新输入信息的增量。LSTM包含三个关键的门用于实现这一传递机制。
**遗忘门:**上一时刻输出和这一个时刻输入决定上一时刻的状态保留百分比ftf_tft。【sigmoid输出0-1 之间的一个数】
输入门:C~t\tilde{C}_tC~t为新信息候选向量, iti_tit 决定了多少新信息候选向量能够通过。随后更新状态信息:
输出门: 当前状态CtC_tCt 和 ht−1h_{t-1}ht−1 以及xtx_txt 共同决定当前时刻输出信息hth_tht
参考资料:https://colah.github.io/posts/2015-08-Understanding-LSTMs/
3. tensorflow 中的RNN-LSTM
RNNCell是TensorFlow中实现RNN的基本单元,每个RNNCell都有一个call方法,使用方式是:(output, next_state) = call(input, state)。RNNCell是一个抽象类,实际使用时候,用它的两个子类BasicRNNCell [RNN的基础类] 和BasicLSTMCell [LSTM的基础类]。
3.1 tf.nn.rnn_cell.BasicRNNCell()
RNNCell,具有两个比较重要类属性:state_size–决定隐层的大小,output_size决定输出大小
例如将(batch_size, input_size)数据输入RNN,得到的隐层状态就是(batch_size, state_size),输出是(batch_size, output_size)。
import tensorflow as tf
import numpy as np
cell = tf.nn.rnn_cell.BasicRNNCell(num_units=128) # state_size = 128
print(cell.state_size) # 128inputs = tf.placeholder(np.float32, shape=(32, 100)) # batch_size=32
h0 = cell.zero_state(32, np.float32) # 全零状态(batch_size, state_size)
output, h1 = cell.call(inputs, h0)
print(h1.shape) # (32, 128)
、
3.2 tf.nn.rnn_cell.BasicLSTMCell()
tf.nn.rnn_cell.BasicLSTMCell(num_units, # int类型,隐层输出大小forget_bias=1.0, # float类型, 遗忘门偏置state_is_tuple=True, # 回的状态是h_t和c_t的2元tuple LSTM可以看做有两个隐状态h和cactivation=None, # 内部状态的激活函数。默认为tanhreuse=None,name=None,dtype=None)
3.3 tf.nn.dynamic_rnn()–多步执行循环神经网络
基础的RNNCell使用它的call函数进行运算时,只是在序列时间上前进了一步。例如使用(x1,h0)得到h1,(x2, h1)得到h2等。如果序列长度为10,需调用10次call函数,比较麻烦。
TensorFlow提供了一个tf.nn.dynamic_rnn函数,该函数可实现n次调用call函数。即通过{h0,x1, x2, …., xn}得{h1,h2…,hn}。
输入数据格式为(batch_size, time_steps, input_size),其中time_steps表示序列长度,input_size表示单个序列元素的特征长度。
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
)
对于一个定义的的cell ,多次执行该cell 的demo 为:
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)。
动态调整sequence_length tf.nn.dynamic_rnn 详解
参考资料:
tensorflow学习之BasicLSTMCell详解
TensorFlow中RNN实现的正确打开方式