递归神经网络(CNN卷积神经网络)
介绍
人类不是每秒钟都从零开始构思。当你读这篇文章的时候,你会根据你对前面单词的理解来理解每一个单词。你不会抛弃一切,重新开始思考。你的想法很执着。
传统的神经网络不能做到这一点,这似乎是一个很大的缺点。例如,假设你想对一部电影中的每一个点进行分类。目前,还不清楚传统的神经网络如何利用其对电影中事件的推理,为后来的事件提供信息。
递归神经网络解决了这个问题。它们是带有环路的网络,允许信息持续存在。
上图,神经网络A,看一些输入xt,输出一个值ht。允许循环信息从网络的一级传递到下一级。递归神经网络可以被认为是同一网络的多个副本,每个副本都向后继者传递信息。考虑一下如果我们打开循环会发生什么:
这种链性质揭示了递归神经网络与序列和列表密切相关。它们是用于此类数据的神经网络的自然架构。他们当然可以使用它!在过去的几年里,RNN已经被成功地应用于各种问题:语音识别、语言建模、翻译、图像字幕...这样的例子不胜枚举。
什么是递归神经网络
香草神经网络(和卷积网络)的显著限制是它们的API过于有限:它们接受固定大小的向量作为输入(例如,图像),并生成固定大小的向量作为输出(例如,不同类别的概率)。不仅如此:这些模型使用固定数量的计算步骤(例如模型中的层数)来执行这种映射。
递归网络更令人兴奋的核心原因是,它们允许我们对向量序列进行操作:在最一般的情况下是输入、输出或序列。
一些例子可能会使这一点更加具体:
每个矩形是一个向量,箭头表示函数(比如矩阵乘法)。输入向量是红色的,输出向量是蓝色的,绿色向量是RNN状态(后面会详细描述)。从左至右:
没有RNN的香草模式,从固定大小的输入到固定大小的输出(如图像分类)。
输出(例如,图像字幕获取图像并输出一个单词的句子)。
序列输入(例如,给定的句子被分类为表达积极或消极情绪的情绪分析)
序列输入和序列输出(例如,机器翻译:一个RNN读取英语句子,然后输出法语句子)。
同步序列输入输出(比如我们要标记视频每一帧的视频分类)。
我们将在后面看到,RNN把输入向量和它们的状态向量结合起来,形成一个固定的(但已学习的)函数,从而产生一个新的状态向量。
RNN计算
那么这些东西是如何工作的呢?
它们接受一个输入向量X,给出一个输出向量y,然而,关键的一点是,这个输出向量的内容不仅受刚刚输入的输入的影响,还受过去输入的整个历史的影响。作为一个类,RNN的API由一个单步函数组成:
rnn = RNN()
y = rnn.step(x) # x是输入向量,y是rnn的输出向量
RN类有一些内部状态,每次调用这个步骤时都会更新。在最简单的情况下,该状态由单个隐藏向量h组成。以下是在普通RNN中阶跃函数的实现:
RNN等级:
# ...
定义步骤(自身,x):
#更新隐藏状态
self.h = np.tanh(np.dot(self。W_hh,self.h) + np.dot(self。W_xh,x))
#计算输出向量
y = np.dot(self。W_hy,self.h)
回车y
这个RNN的参数是三个矩阵。
W_hh:基于之前隐藏状态的矩阵。
W_xh:基于当前输入的矩阵。
W_hy:基于隐藏状态和输出的矩阵。
隐藏状态self.h用零向量初始化,np.tanh(双曲正切)函数实现了一个非线性,将活动范围压缩到范围[-1,1]。
那么它是如何工作的-
tanh中有两项:一项是基于之前的隐藏状态,另一项是基于当前的输入。在numpy中,np.dot是矩阵乘法。
隐藏状态更新的数学表示为
双曲正切在元素上的应用
我们使用随机数来初始化RNN矩阵。在训练过程中,做了大量的工作来寻找产生理想行为的矩阵。有些损失函数用来表示你倾向于看到的输出序列X和你希望看到的输出序列。
更深一步。
y1 = rnn1.step(x)
y = rnn2.step(y1)
换句话说,我们有两个独立的RNN:一个RNN接收输入向量,第二个RNN接收第一个RNN的输出作为其输入。除了这些rnn,他们不知道也不关心——这些只是进出向量,在反向传播过程中,一些梯度会流经每个模块。
我想简单提一下,在实践中,我们大多数人使用它的方式与上面提到的长期短期记忆(LSTM)网络略有不同。LSTM是一种特殊类型的循环网络,由于其更强大的更新方程和一些吸引人的反向传播动力学,在实际应用中效果稍好。我不会详细讨论它,但我所说的关于RNN的一切都保持不变,除了计算更新的数学形式(self.h =)...)会稍微复杂一点。从这里开始,我将交替使用“RNN/LSTM”这个术语,但是本文中的所有实验都使用LSTM。
一个例子 - 字符级语言模型
我们将训练RNN字符级语言模型。也就是说,我们会给RNN一大段文字,并要求它给出一系列先前字符序列中下一个字符的概率分布。这将允许我们一次生成一个新角色。
作为一个工作示例,假设我们只有四个可能字母“helo”的词汇表,并且想要在训练序列“hello”上训练一个RNN。这个训练序列实际上是四个独立训练样本的来源:
在“H”的情况下,“E”的概率应该是可能的,
“L”大概应该在“他”的范围内
“L”也应该是可能的,因为“hel”
“O”应该是可能的,因为“地狱”
具体来说,我们将使用1-k编码将每个字符编码到一个向量中(即,除了词汇表中字符索引处的单个字符之外,所有字符都是零),然后使用一个单步函数帮助将它们一次发送到RNN。然后,我们将观察一系列4维输出向量(每个字符一个维度),我们将其解释为RNN当前分配给序列中下一个字符的置信度。这是一张图表:
例如,我们看到,在第一个时间步骤中,当RNN看到字符“H”时,它将下一个字母“H”赋予1.0,将字母“E”赋予2.2,-3.0赋予“L”,将4.1赋予“O”。由于我们的训练数据(字符串“hello”)中下一个正确的字符是“e”,我们希望增加它的置信度(绿色),减少所有其他字母(红色)的置信度。同样,我们希望网络能够给予更多的信心,我们在四个时间步骤中的每一个步骤中都有所需的目标角色。
由于RNN完全由可微分运算组成,我们可以运行反向传播算法(这只是递归地应用微积分中的链规则)来找出我们应该调整其每个权重的方向,以增加正确分数的目标(绿色粗体数字)。
然后,我们可以进行参数更新,在这个梯度方向上轻轻地推动每个权重。如果我们在参数更新后向RNN提供相同的输入,我们会发现正确字符(例如第一个时间步中的“E”)的得分会略高(例如2.3而不是2.2),不正确字符的得分会略低。
然后我们重复这个过程很多次,直到网络收敛,它的预测最终与训练数据一致,因为正确的字符总是下一个被预测的。
更技术性的解释是,我们同时对每个输出向量使用标准的Softmax分类器(也称为交叉熵损失)。RN用小批量随机梯度下降进行训练,我喜欢用RMSProp或者Adam(每参数自适应学习率法)来稳定更新。
还要注意,第一次输入字符“L”时,目标是“L”,但第二次输入时,目标是“O”。因此,RNN不能只依靠输入,它必须利用其循环连接来跟踪上下文以实现这一任务。
在测试时,我们将为RNN提供一个角色,并分配下一个可能的角色。我们从这个分布中抽取一个样本,并将其反馈给下一个字母。重复这个过程,你就是在采样文本!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。系信息发布平台,仅提供信息存储空间服务。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。
本文来自网络,若有侵权,请联系删除,作者:张阳一,如若转载,请注明出处: