循环神经网络的原理
循环神经网络概念
对于dense网络和cnn网络,没有记忆功能,它们在处理每个输入数据的时候都是单独处理的,输入与输入之间时没有任何联系和状态的保存。
dens和cnn网络如何处理数据序列和时间序列
如果我们需要处理数据序列和时间序列,一般的做法时需要向网络输入整个数据的序列。
例如我们前面以节介绍的IMDB,将全吧的电影评论转换成一个大向量,如何一次性输入到网络中,一次性处理获得结果。这样称为前馈网络(feedforward network)
为什么需要循环网络
在处理文本信息的时候,一般我们正常的思维是一个词一个词的阅读,我们理解内容也是由词到句的理解,词与词前后的阅读会对我们的理解整句子有帮助,所以我们会记住前面的词语需要表达什么。 为了能够让机器也理解这个过程,我们的设计的网络也需要具备这样有序的信息处理方式,同时需要保存之前的处理信息的结果。循环神经网络(RNN,recurrent neural network)采用同样的原理。
循环神经网络的构成
首先我们这里先简单解释一下,程序员眼中的循环,就是遍历所需要处理的数据,就一个不断迭代的过程,直到完成所有的迭代数据。 这里的循环神经网络也是这样过程: - 遍历所有的输入序列元素 - 保存输出的状态
具体的结构如下图:
例如我们的在处理IMDB评论的是,在处理独立的两个不同的序列(也就是两条不同的评论)之间,RNN会被重置。这个很好理解,相当于处理两个不同的for循环,当然参数是要重置。但是在处理一条数据序列的时候,序列中的每个元素是遍历输入的,而且每个元素处理的结果会保存和被后面的输入元素利用起来。具体看下面的示例
Numpy实现一个简单的RNN
这里有两个概念需要理解: 内部环(loop) 这个可以理解为循环调用,从上面图中,更加直观的理解是有一个闭环。如下图所示:
状态(state) 就是序列中每个输入元素经过网络后的输出信息。
具体理解,我们可以看个例子,假设输入的数据是一个 (timesteps, input_features),timesteps表示每个时间的步的记录,input_features 表示,对于的时间步的输入数据。状态初始化为一个全零向量,这叫作网络的初始状态(initial state)。
# 简单的RNN网络伪代码
state_t = 0 # t 时刻的状态
for input_feature in input_features: # 遍历序列元素
output_feature = f(input_feature,state_t) #f:从输入和状态到输出的变换
state_t = outpu_feature #保存当前的输出状态,作为下一个状态的输入
# 利用两个矩阵(W 和 U)和一个偏置向量作为f变换的RNN伪代码
state_t = 0 # t 时刻的状态
for input_feature in input_features: # 遍历序列元素
output_feature = avctivation(dot(W,input_feature)+dot(U,state_t)+b) #f:从输入和状态到输出的变换
state_t = outpu_feature #保存当前的输出状态,作为下一个状态的输入
下面看一个实际的使用numpy实践RNN的代码例子
import numpy as np
# 输入序列的时间步数
timesteps = 100
# 输入特征空间的维度
input_features = 32
# 输出特征空间的维度
output_features = 64
#输入数据:随机噪声
inputs = np.random.random((timesteps,input_features))
#初始状态:全零向量
state_t = np.zeros((output_features))
# 创建随机的权重矩阵
U = np.random.random((output_features,output_features))
W = np.random.random((output_features,input_features))
b = np.random.random((output_features,))
successive_outputs = []
for input_t in inputs: # input_t 是形状为 (input_features,) 的向量
#由输入和当前状(前一个输出)计算得到当前输出
output_t = np.tanh(np.dot(W,input_t)+np.dot(U,state_t)+b)
#将这个输出保存到一个列表中
successive_outputs.append(output_t)
state_t = output_t
# 最终输出是一个形状为 (timesteps, output_features) 的二维张量
final_output_sequence = np.stack(successive_outputs, axis=0)
print(successive_outputs[2])
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
RNN 是一个 for 循环,它重复使用循环前一次迭代的计算结果,仅此而已. 具体展开如下图所示:
分享关于人工智能,机器学习,深度学习以及计算机视觉的好文章,同时自己对于这个领域学习心得笔记。想要一起深入学习人工智能的小伙伴一起结伴学习吧!扫码上车!