循环神经网络
主要用途:处理和预测序列数据
刻画一个序列当前的输出与之前信息的关系,记忆之前的信息,并利用之前的信息影响后面结点的输出。其为同一神经网络结构被无限复制(循环体)
参数:
假设输入向量的维度为x,隐藏状态的维度为n
循环体的全连接层神经网络的输入大小为n+x(将上一时刻的状态与当前时刻的输入拼接为一个大向量作为循环体的输入)
那么循环体中的参数个数:(n+x)*n+n
不同时刻用于输出的全连接神经网络中的参数一致
简单的神经网络前向传播过程:
import numpy as np
X = [1, 2]
state = [0.0, 0.0]
w_cell_state = np.asarray([[0.1, 0.2], [0.3, 0.4]])
w_cell_input = np.asarray([0.5, 0.6])
b_cell = np.asarray([0.1, -0.1])
w_output = np.asarray([[1.0], [2.0]])
b_output = 0.1
for i in range(len(X)):
before_activation = np.dot(state, w_cell_state) + X[i] * w_cell_input + b_cell
state = np.tanh(before_activation)
final_output = np.dot(state, w_output) + b_output
print("output:", final_output)
注意:循环神经网络中若序列过长,会导致优化时出现梯度消失和梯度爆炸问题,同时展开后的前馈神经网络会占用过大的内存,所以实际中一般会规定一个最大长度,当序列长度超过规定长度后会对序列进行截断。
LSTM长短时记忆网络
拥有三个“门”结构的特殊网络结构:输入门、遗忘门、输出门,以此有选择性的让信息影响循环神经网络每个时刻的状态。
门:sigmoid+按位做乘法,即sigmoid获得0~1之间的数值,然后与信息按位相乘,从而使得信息有选择的进入或遗忘。
1、输入门:sigmoid(当前时刻输入+上一时刻输出) ∗ * ∗(tanh [当前时刻输入+上一时刻输出])——决定哪些新输入信息被加入
2、遗忘门:sigmoid(当前时刻输入+上一时刻输出) ∗ * ∗(上一时刻状态c)——决定上一时刻哪些内容被忘记
3、新状态 = 1中决定加入的信息 + 2中决定删除后剩下的之前状态信息
4、输出门:sigmoid(当前时刻输入+上一时刻输出) ∗ * ∗(新状态)——获取该时刻的输出
在TensorFlow中LSTM结构可以被很简单实现:
import tensorflow as tf
lstm = tf.nn.rnn_cell.BasicLSTMCell(lstm_hidder_size)
# lstm中的状态初始化为0,state中包含c状态和h状态
state = lstm.zero_state(batch_size, tf.float32)
loss = 0.0
# num_steps为数据序列长度,每一步处理时间序列的一个时刻
for i in range(num_steps):
if i>0:
tf.get_variable_scope().reuse_variables()
# lstm可以直接根据输入和状态h、c来获取输出和新状态
lstm_output, state = lstm(current_input, state)
# 当前时刻的输出需要再传入一个全连接层才能得到最后的输出
final_output = fully_connected(lstm_output)
loss += calc_loss(final_output, expected_ouput)