This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
<audio id="audio" title="28 深度学习框架下的神经网络 | 枯木逢春:深度信念网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/0b/76/0b4d868c39540e55e1b9c9535d64cc76.mp3"></audio>
2006年深度学习的祖师爷乔弗里·辛顿提出了深度信念网络模型它吹响了连接主义学派复兴的号角也打开了通向人工智能新世界的大门。
**深度信念网络是一种概率生成模型,能够建立输入数据和输出类别的联合概率分布**。网络中包含多个隐藏层,隐藏层中的隐藏变量通常是二进制数,用来对输入信号进行特征提取。输入信号从深度信念网络的最底层输入,并自下而上有向地传递给隐藏层。而在网络最上面的两层中,神经元之间的连接是没有方向并且对称的,这两个层次共同构成了联想记忆。
从功能上看,深度信念网络的每一个隐藏层都代表着对输入数据的一种中间表示,而隐藏层中的每个神经元都代表着输入数据不同层次上的特征,不同层神经元之间的连接则代表着不同层次特征之间的联系,所有特征和特征之间的所有关系共同形成了对输入数据的抽象描述。
**从结构上看,复杂的深度信念网络可以看成由若干简单的学习单元构成的整体,而构成它的基本单元就是受限玻尔兹曼机**restricted boltzmann machine。受限玻尔兹曼机早在1986年便已诞生可直到20年后才因辛顿的成果而得到重视。
**受限玻尔兹曼机的模型非常简单,就是一个两层的神经网络,包括一个可见层和一个隐藏层**。可见层用来接收数据,隐藏层则用来处理数据。可见层和隐藏层以全连接的方式相连,也就是任意两个不同层次中的神经元都会两两相连。但同一层中的神经元则不会互相连接,因而每个层内也就没有信息流动,这正是其名称中“受限”的来源。
回忆一下神经网络中介绍过的神经元的工作机制:每个隐藏神经元的输入都是数据向量中所有元素的线性组合,这个线性组合和偏置信号相加后,共同作为神经元传递函数的输入,而传递函数的输出就是隐藏神经元的输出。但受限玻尔兹曼机所做的远非得到个输出这么简单的事情,它还要以无监督的方式对数据进行重构。即使没有更深层的网络结构,数据也会在输入层和隐藏层中进行多次前向和反向的传递。
在隐藏神经元得到输出后,受限玻尔兹曼机需要将输出结果反馈给可见层。具体的做法是保持所有连接的权重系数不变,但是将方向反转,这样一来,每个隐藏单元的输出就会按照已经确定的系数反馈给可见层,可见层的每个神经元接收到的反馈信息是不同隐藏单元输出的线性组合。反馈信息和一组新的偏置分量求和就得到了对原始输入的估计,估计值和原始输入的差值则表示了重构误差。通过让重构误差在可见层和隐藏层之间循环往复地传播,就可以求出使重构误差最小化的一组权重系数。
以上的学习算法就是由辛顿提出的**对比散度contrastive divergence方法**它既能让隐藏层准确地提取可见层的特征也能根据隐藏层的特征较好地还原出可见层。当隐藏层和可见层的神经元都使用S型函数作为传递函数时神经元的输出就可以视为单个节点的激活概率。在这种情况下对比散度方法具体的训练过程包括以下几个步骤
1. 输入训练样本列向量$\mathbf{v}$,计算隐层节点的概率,在此基础上从这一概率分布中抽取一个隐层节点激活向量的样本列向量$\mathbf{h}$
1. 计算$\mathbf{v}$和$\mathbf{h}$的外积$\mathbf{v} \mathbf{h} ^ T$,结果记为“正梯度”;
1. 利用$\mathbf{h}$重构可见层节点的激活向量样本$\mathbf{v&#39;}$,输入$\mathbf{v&#39;}$再次获得一个隐层节点的激活向量样本$\mathbf{h&#39;}$
1. 计算$\mathbf{v&#39;}$和$\mathbf{h&#39;}$的外积$\mathbf{v&#39;} \mathbf{h&#39;} ^ T$,结果记为“负梯度”;
1. 使用正梯度和负梯度的差值,以学习率$\epsilon$更新权重系数,即$\mathbf{W} = \mathbf{W} + \epsilon (\mathbf{v} \mathbf{h} ^ T - \mathbf{v&#39;} \mathbf{h&#39;} ^ T)$
1. 以学习率$\epsilon$更新可见层的偏置系数$\mathbf{a}$和隐藏层的偏置系数$\mathbf{b}$,即$\mathbf{a} = \mathbf{a} + \epsilon (\mathbf{v} - \mathbf{v&#39;}), \mathbf{b} = \mathbf{b} + \epsilon (\mathbf{h} - \mathbf{h&#39;})$}。
**对比散度的训练过程本质上是求出一个最符合训练数据集统计特性的概率分布,也就是使训练数据集出现的概率最大的分布参数**。在数据的前向传输中,受限玻尔兹曼机的目标是在给定权重系数$w$的条件下利用输入$x$预测输出$a$,也就是求解条件概率$p(a | x; w)$;而在使用输出$a$重构输入$x$的反向传输中,受限玻尔兹曼机的目标变成了求解条件概率$p(x | a; w)$。将两个条件概率结合,就可以得到输入输出的联合概率分布$p(x, a)$。
**将几个受限玻尔兹曼机堆叠在一起,就可以得到深度信念网络**deep belief network。除了最顶层和最底层外深度信念网络的每个隐藏层都扮演着双重角色它既作为之前神经元的隐藏层也作为之后神经元的可见层。在之前自编码器的介绍中我曾提到栈式自编码器的训练遵循的是无监督预训练结合有监督微调的策略深度信念网络采用的同样是这套训练方式两者的区别只是基本单元的不同。
**深度信念网络的无监督预训练也是逐层实现的**。对于构成深度信念网络的第一个受限玻尔兹曼机来说,它的可见层就是深度网络的输入层。利用输入样本$x = h ^ {(0)}$训练这个玻尔兹曼机,得到的结果就是条件概率$p(h ^ {(1)} | h ^ {(0)})$,其中$h ^ {(1)}$是第一个玻尔兹曼机的隐藏层,也就是深度信念网络的第一个隐藏层的输出。第一个玻尔兹曼机的隐藏层又是第二个玻尔兹曼机的可见层,因此$h ^ {(1)}$就可以作为输入样本来训练得到深度网络第二个隐藏层的输出$h ^ {(2)}$。不断重复以上步骤,就可以完成对所有玻尔兹曼机,或者说所有隐藏层的逐层预训练。
**栈式自编码器使用softmax分类器实现有监督微调深度信念网络采用的方法则是在最顶层的受限玻尔兹曼机上又添加了额外的反向传播层**。反向传播层以受限玻尔兹曼机的输出作为它的输入,执行有监督的训练,再将训练误差自顶向下地传播到每一个受限玻尔兹曼机当中,以实现对整个网络的微调。这也是为什么深度信念网络要在最顶上的两层进行无方向连接的原因。在实际的使用中,用来做微调的网络无需被局限在反向传播上,大部分用于分类的判别模型都能够胜任这个任务。
**其实相比于深度信念网络这个具体的模型,辛顿的贡献更大程度上在于对深度模型训练方法的改进。不夸张地说,正是这套训练策略引领了近十年深度学习的复兴。这种复兴不仅体现在训练效率的提升上,更体现在研究者对训练机制的关注上。**
**传统的反向传播方法应用于深度结构在原则上是可行的可实际操作中却无法解决梯度弥散gradient vanishing的问题**。所谓梯度弥散指的是当误差反向传播时,传播的距离越远,梯度值就变得越小,参数更新的也就越慢。这会导致在输出层附近,隐藏层的参数已经收敛;而在输入层附近,隐藏层的参数几乎没有变化,还是随机选择的初始值。在这种情况下,对网络整体的优化也就无从谈起了。
相比之下,基于预训练的训练方法就不会受梯度弥散的困扰。在梯度下降之前先执行无监督预训练能够在所有隐藏层上一视同仁实现良好的优化效果,并给深度结构带来强大的表达能力。这使得无监督预训练一度成为训练深度结构的不二法门。
但随着研究的不断深入,事实表明无监督预训练并没有人们想象地那么神奇。良好的初始化策略完全可以比逐层预训练更加高效,而梯度弥散的根源并不是反向传播算法的问题,而是在于非线性传递函数非理想的性质。**虽然目前深度信念网络的应用远不如卷积神经网络等其他模型广泛,但它却是一次吃螃蟹的成功尝试。如果没有这次尝试,也许我们依然在单个隐藏层的神经网络中兜兜转转,坐井观天**。
今天我和你分享了深度信念网络的基本概念和基本原理,其要点如下:
- 深度信念网络是一种生成模型,能够建立输入和输出的联合概率分布;
- 受限玻尔兹曼机是构成深度信念网络的基本单元,是由可见层和隐藏层构成的神经网络;
- 受限玻尔兹曼机的训练方法是对比散度法,通过可见层和隐藏层的多轮交互实现;
- 深度神经网络的通用训练方式是无监督逐层预训练和有监督微调的结合。
在前面介绍的自编码器中,稀疏性既可以降低运算量,也能提升训练效果,发挥着重要的作用。那么同样的原理能否应用在受限玻尔兹曼机和深度信念网络之中呢?
欢迎发表你的观点。
<img src="https://static001.geekbang.org/resource/image/6e/45/6ee015991274b820f056695c8b5f9e45.jpg" alt="">

View File

@@ -0,0 +1,60 @@
<audio id="audio" title="29 深度学习框架下的神经网络 | 见微知著:卷积神经网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/5c/18/5cc20e8a1528448b270052fb70a0f518.mp3"></audio>
2017年9月13日苹果公司推出了新一代智能手机iPhone X。相比于它的前辈们iPhone X的一项重要卖点就是引入了Face ID人脸识别技术用户直接刷脸就可以解锁手机。虽然目前看来Face ID的识别率远没有苹果声称的那么“高精度”但更加简单便捷的人脸识别无疑是未来的发展方向。而人脸识别乃至图像识别中的一项关键技术就是**卷积神经网络**。
诞生于1989年的卷积神经网络已近而立之年但它的首秀直到9岁才姗姗来迟。1998年今日的深度学习扛鼎者之一燕乐存提出了第一个卷积神经网络模型LeNet-5用来识别手写文本。遗憾的是这个小朋友因为胃口太大消耗计算资源多并不招人喜欢。直到2006年辛顿提出的逐层初始化训练算法才让韬光养晦的卷积神经网络一鸣惊人这个少年也渐渐成长为神经网络和深度学习队伍中的中坚力量。
顾名思义,**卷积神经网络convolutional neural network指的是至少在某一层中用卷积运算convolution来代替矩阵乘法的神经网络**。卷积运算的特性决定了神经网络适用于处理具有网格状结构的数据。最典型的网格型数据就是数字图像,不管是灰度图像还是彩色图像,都是定义在二维像素网格上的一组标量或向量。因而卷积神经网络自诞生以来,便广泛地应用于图像与文本识别之中,并逐渐扩展到自然语音处理等其他领域。
要介绍卷积神经网络,首先要从卷积运算说起。**卷积**是对两个函数进行的一种数学运算在不同的学科中有不同的解释方式。在卷积网络中两个参与运算的函数分别叫做输入和核函数kernel function。**本质上讲,卷积就是以核函数作为权重系数,对输入进行加权求和的过程**。为了突出这个本质,卷积神经网络中针对二维函数的卷积运算在原始的数学定义上做了一些调整,可以写成以下形式
$$ Y(i, j) = (X * H)(i, j) = $$
$$\sum\limits_m \sum\limits_n X(i + m, j + n)H(m, n) $$
用生活中的实例类比,卷积就可以看成是做菜,输入函数是原料,核函数则是菜谱。对于同一个输入函数鲤鱼来说,如果核函数中酱油的权重较大,输出的就是红烧鱼;如果核函数中糖和醋的权重较大,输出的就是杭帮菜的西湖醋鱼;如果核函数中辣椒的权重较大,输出的就是朝鲜族风味的辣鱼。不同的菜谱对应不同的口味,不同的核函数也对应不同的输出。
之所以将卷积运算应用于图像识别当中,是因为它具有一些优良的性质。**卷积神经网络的稀疏感知性、参数共享性和平移不变性都有助于将它应用在图像处理之中**。
**稀疏感知性sparse interaction指的是卷积层核函数的大小通常远远小于图像的大小**。输入图像可能在两个维度上都有几千个像素,但核函数最大也不会超过几十个像素。选择较小的核函数一方面有助于发现图像中细微的局部特征,另一方面也可以提升算法的存储效率和运行效率。核函数选取背后的原理在于对图像的全局感知可以通过将多个局部感知综合得到,这其实也符合人类的认知方式。
**参数共享性parameter sharing指的则是在一个模型中使用相同的参数**,说白了就是在每一轮训练中用单个的核函数去和图像的所有分块来做卷积,这无疑能够显著降低核函数参数的数目。在卷积神经网络中,参数共享的基础是对图像特征的提取与图像的位置无关。如果在图像的一个区域上,某些像素的组合构成一条直线,那么在图像的其他区域,具有相同灰度的像素组合仍然是直线,而不会变成一个圆。这说明图像的统计特性并不取决于空间位置,因而对于整个图像都可以使用同样的学习特征。
**平移不变性translational equivalence指的是当卷积的输入产生平移时其输出等于原始输出做出相同数量的平移这说明平移操作和核函数的作用是可以交换的**。从卷积的线性特性出发很容易推导出平移不变性。平移不变性其实可以看成是离散时间域上的线性移不变系统在二维空间上的扩展,它在只关心某些特征是否出现,而不考虑出现的位置时具有重要的作用。
卷积神经网络的结构并非卷积运算的简单组合,而是包含几个功能不同的层次。**当输入图像被送入卷积神经网络后,先后要循环通过卷积层、激活层和池化层,最后从全连接层输出分类结果**。每个层次各司其职,各负其责,都发挥着不可替代的作用。
卷积层无疑是卷积神经网络的核心部分,其参数是一个或者多个随机初始化的核函数。核函数就像探照灯一样,逐行逐列地扫描输入图像,对像素矩阵进行从左到右,从上到下的滑动覆盖。每一个被核函数的光圈覆盖的区域都是和核函数维度相同的像素组合,并且作为输入和核函数进行卷积。当核函数将输入图像全部扫描完毕后,计算出的所有卷积结果又可以构成一个矩阵,这个新矩阵就是**特征映射**feature map。卷积层得到的特征映射一般会送到激活层处理给系统添加非线性元素。激活层首选的传递函数是整流线性单元它可以激活特征映射中的负值。
为什么简单的卷积运算能完成图像的分类任务呢?解释这个问题还要回归到卷积的运算上。细心的你一定发现了,**虽然卷积的表达式具有二维的形式,可如果把二维的输入和核函数拉成一维向量的话,卷积计算的实际上就是两者的内积**!内积的作用是描述两个向量的关系,因而卷积的结果反映的正是输入像素和核函数之间的近似程度。卷积的输出越大表明两者之间的相似性越高,输出越小就意味着两者没什么共性。
正因如此,**通过合理设置核函数的性质,卷积层就能够提取出图像的特征**。如果选取的核函数表示一个直角,原始图像中的直角就会体现为特征映射中一个较大的数值,根据这个数的坐标就可以确定曲线在输入图像中的位置。所以在卷积神经网络的实际应用中,通常会同时训练多个不同的核函数,以提取输入图像中不同类型的特征。
卷积神经网络的卷积层之间通常周期性地会插入**池化层**pooling layer。池化层更恰当的名字是下采样层downsampling layer它的作用是对得到的特征映射矩阵进行筛选。卷积层给出了核函数和原始图像每个局部之间的近似关系但这里面真正对图像分析有帮助的只是取值较大也就是和核函数相似程度较高的部分。因而**常见的最大池化max pooling的做法就是将特征映射划分为若干个矩形区域挑选每个区域中的最大值也就是最明显的特征作为下采样的结果**。这样做在显著降低数据量的同时也能减少过拟合的风险。
直观来看,池化机制之所以能够发挥作用,其原因在于特征在图像中的绝对位置远不及它和其他特征的相对位置的关系来的重要。例如在判定一张图像中是否包含人脸时,我们需要在图像中找到左右对应地两只眼睛,但不需要确定这两只眼睛的精确位置。
**池化机制的应用也可以看成是参数共享的体现:在一个图像区域有用的特征极有可能在另一个区域同样适用**。因而对不同位置的特征进行聚合统计就是提取图像主要特征的有效方法。此外,池化操作还给图像带来了旋转不变性,因为无论图像如何旋转,每个区域的最大值都不会改变,因而池化并不会给图像结构造成影响。
卷积层和池化层的循环使用能够实现对图像特征的逐层提取而根据提取出的特征得到图像的分类与标记则要交给全连接层完成。由于全连接层中的神经元与前一层中的所有激活神经元都有连接因此它们的激活与否可以通过矩阵乘法计算这和常规的神经网络别无二致。全连接层可以使用softmax分类器得到原始图像属于不同类别的概率对应的损失函数通常选择交叉熵。
将前面介绍的卷积神经网络结构加以总结,就可以得到它的工作流程:输入层将待处理的图像转化为一个或者多个像素矩阵,卷积层利用一个或多个卷积核从像素矩阵中提取特征,得到的特征映射经过非线性函数处理后被送入池化层,由池化层执行降维操作。卷积层和池化层的交替使用可以使卷积神经网络提取出不同层次上的图像特征。最后得到的特征作为全连接层的输入,由全连接层的分类器输出分类结果。
在卷积神经网络的训练里,待训练的参数是卷积核,也就是卷积层中的权重系数矩阵。训练采用的也是反向传播的方法,参数的不断更新能够提升图像特征提取的精度。
最近两年,关于卷积神经网络的一项重要进展是**残差网络**的提出。将深度结构应用于卷积神经网络当中可以增强表达能力,在图像分类和目标检测等问题上表现出优异的性能。可是当网络的层数超过特定的阈值时,训练误差也会随着层数的增加而增加,网络的性能不仅不能提升,反而会出现显著的退化。残差网络正是通过残差结构单元解决了深度网络性能下降的问题,使网络层数可以达到千层以上。
今天我和你分享了卷积神经网络的原理与机制,受篇幅所限,诸如数据维度的变化和图像边界的策略设计等具体的技术细节并未涉及。其要点如下:
- 卷积神经网络是应用了卷积运算的神经网络,适用于处理网格化数据;
- 卷积神经网络具有稀疏感知性、参数共享性和平移不变性;
- 卷积神经网络的结构包括交替出现的卷积层、激活层和池化层,以及作为输出的全连接层;
- 卷积神经网络的作用是逐层提取输入对象的特征。
在卷积神经网络中,很多参数都会对性能产生影响。那么在设计卷积层和池化层时,需要考虑哪些具体的因素呢?
欢迎发表你的观点。
<img src="https://static001.geekbang.org/resource/image/4d/e7/4dce2701152a658ff621948a3ed26ce7.jpg" alt="">

View File

@@ -0,0 +1,72 @@
<audio id="audio" title="30 深度学习框架下的神经网络 | 昨日重现:循环神经网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/88/94/885a91201944adfc12b8077b5b731994.mp3"></audio>
今天是除夕,明天就是春节啦,在这里,给你拜个早年,祝你狗年大吉,新春快乐,在新的一年里,福旺运旺!
今天我们继续讨论深度学习框架下的神经网络,聊一聊**循环神经网络**。
2017年一本名叫《阳光失了玻璃窗》的诗集出版了。这本来是再普通不过的事情可诗集的作者是赫赫有名的网红机器人微软小冰或者更确切地说小冰背后的算法就让事情变得没那么简单了。
我在网上拜读了一些小冰的诗,实话实说,它们让我想起了几年前那些将简单的旋律和节奏随机排列组合而批量生产出来,至今仍在广场舞音乐中大行其道的网络歌曲。但小冰的诗显然技高一筹,循环神经网络和递归神经网络这些高大上的技术让它的排列组合更加难以捉摸。
在深度学习中RNN这个缩写有两层含义它既可以表示循环神经网络Recurrent Neural Network也可以表示递归神经网络Recursive Neural Network。巧的是这两个RNN之间的关系还很密切循环神经网络可以看成是递归神经网络的特例递归神经网络则可以视为循环神经网络的推广。
**循环神经网络和我们前面介绍的所有神经网络都不一样,它的独特之处在于引入了“时间”的维度,因而适用于处理时间序列类型的数据**。回忆一下上次分享的卷积神经网络,它具有空间上的参数共享的特性,也就是同样的核函数可以应用在图像的不同区域之上。如果把参数共享调整到时间的维度上,让神经网络使用相同的权重系数来处理具有先后顺序的数据,得到的就是循环神经网络。
从结构上看,使用神经网络处理可变长度的输入时,在时间上共享参数是非常有必要的。定义在空间上的数据不会无穷无尽地延伸,即使大如《清明上河图》也有确定的边界存在。在很多图像识别的任务中,输入图像的像素数目甚至是有特定要求的。但对于一个以时间为自变量的变长数据来说,很难说清楚数据的终点在哪里,抑或这个终点根本就不存在。
这种情况之下,如果对每一个时间点上的数据都计算一次神经网络的权重系数,无疑会带来极大的计算负荷。循环神经网络就是将长度不定的输入分割为等长度的小块,再使用相同的权重系数进行处理,从而实现对变长输入的计算与处理。
**从功能上看,时间维度上的参数共享可以充分利用数据之间的时域关联性**。在生活中你一定有这样的经验:前后文的语境能够对信息进行有效的补充。在大大小小的英语考试中都少不了一类叫做“完形填空”的题目,这类题目的要求就是根据上下文的语义选择用于填空的合适的词语。比方说妈妈在厨房里突然喊我:“菜炒好了,赶紧来......”,即使后面的话没有听清楚,也能猜到十有八九是让我赶紧吃饭,而不是洗衣服或者其他什么事情。这利用的就是数据的**时域关联**。
循环神经网络对时域的关联性的利用体现在时刻$t$的输出既取决于当前时刻的输入,也取决于网络在前一时刻$t - 1$甚至于更早的输出。从这个意义上讲,**循环神经网络引入了反馈机制,因而具有记忆的功能**。正是记忆功能使循环神经网络能够提取来自序列自身的信息,这是传统的前馈神经网络所无法做到的。
关于循环神经网络的记忆特性,可以做出进一步的解释:**其实前馈网络在某种程度上同样具有记忆,只要神经网络的参数经过最优化,优化的参数中就会包含着过往数据的踪迹**。但最优化的记忆只局限于训练数据集上。当训练出的模型应用到新的测试数据集上时,其参数并不会根据测试数据的表现做出进一步的调整,因而前馈神经网络的记忆其实是“冻结”的记忆。
相比之下,在循环神经网络中,记忆的作用更加宽泛。它的作用不是给每种类型的特征分配固定的权重,而是描述一系列时序事件之间的关系,即使这些事件之间可能没有明显而紧密的时间关联,但它们之间的相关性依然可能如草蛇灰线般伏延千里,而这正是循环网络的记忆要挖掘的对象。
两种网络代表了两种不同的知识类型。
前馈网络适用于表示客观性的知识。当我们学会分辨颜色之后,这项技能就会伴随我们一生,不会随时间或环境的变化而变化,就像一块红布不会因为放了几十年或者是拿到另一个城市而变成蓝色。
循环网络则适用于表示主观性的知识。每种语言中都有同音不同义的词汇,那么在听到一个&quot;jing&quot;的音节时,就要根据前后的其他音节来判断它到底是干净的“净”还是安静的“静”。很多主观性知识正隐藏在数据的顺序之中,而这种顺序恰恰可以由循环神经网络刻画。
具体来说,输入序列的内部信息存储在循环神经网络的隐藏层中,并随着时间的推移在隐藏层中流转。循环神经网络的记忆特性可以用以下公式表示
$$ \mathbf{h}_t = f(\mathbf{W} \mathbf{x}_t + \mathbf{U} \mathbf{h}_{t - 1} ) $$
这个式子的含义在于将时刻$t$的输入$\mathbf{x}_t$的加权结果和时刻$t - 1$的隐藏层状态$\mathbf{h}_{t - 1}$的加权结果共同作为传递函数的输入,得到的就是隐藏层在时刻$t$的输出$\mathbf{h}_t$。$\mathbf{W}$表示了从输入到状态的权重矩阵,$\mathbf{U}$则表示了从状态到状态的转移矩阵。直观地看起来,$\mathbf{h}_t$只取决于$\mathbf{h}_{t - 1}$,但由于$\mathbf{h}_{t - 1}$又取决于$\mathbf{h}_{t - 2}$$\mathbf{h}_{t - 2}$又取决于$\mathbf{h}_{t - 3}$,因而$\mathbf{h}_t$和之前所有时刻的隐藏层状态都是有关系的。
对循环神经网络的训练就是根据输出结果和真实结果之间的误差不断调整参数$\mathbf{W}$和$\mathbf{U}$,直到达到预设要求的过程,其目的是实现对输入序列的精确划分。**其训练方法也是基于梯度的反向传播算法,但和其他前馈网络不同的是,这里的反向传播是通过时间进行的**backpropagation through time
由于循环神经网络的每个状态都与之前的所有状态相关,因而在基于时间的反向传播中,对当前时刻的参数求偏导一定会涉及前一时刻的参数。这其实和原始的反向传播算法毫无区别,只不过在链式法则中添加了一组关于时间的中间变量。
在普通的循环神经网络中,记忆只会涉及到过去的状态。如果想让循环神经网络利用来自未来的信息,就要让当前的状态和以后时刻的状态同样建立起联系,得到的就是**双向循环神经网络**bidirectional recurrent neural network
双向循环网络包括正向计算和反向计算两个环节,在正向计算中,时刻$t$的隐藏层状态$\mathbf{h}_t$与过去的$\mathbf{h}_{t - 1}$相关;而在反向计算中,时刻$t$的隐藏层状态$\mathbf{h}_t$与未来的$\mathbf{h}_{t + 1}$相关。由于正向计算和反向计算的权重系数是不共享的,因而双向循环网络需要分别计算正向和反向的结果,并将两者的组合作为隐藏层的最终参数。
将深度结构引入双向循环神经网络就可以得到深度循环网络,它和其他深度结构一样,具有多个隐藏层。每个隐藏层的状态$\mathbf{h}_t^i$既取决于同一时刻前一隐藏层的状态$\mathbf{h}_t^{i - 1}$,也取决于同一隐藏层在前一时刻的状态$\mathbf{h}_{t - 1}^i$。
深度结构的作用在于建立更清晰的表示,这也可以用完形填空的例子来做类比,有些填空只需要根据它所在的句子便可以推断出来,这对应着单个隐藏层在时间维度上的依赖性;有些填空则可能要通读整段甚至全文才能确定它合适的意义,这就对应着深度结构在时间维度和空间维度上共有的依赖性。
循环神经网络的特点是在时间维度上共享参数,从而展开处理序列。如果换一种展开方式,将序列数据展开成树状结构,用到的就是**递归神经网络**。递归神经网络在处理数据使用的也是相同的权重系数,但这里的相同并非体现在时间上,而是体现在结构上。递归网络首先将输入数据转化为某种拓扑结构,再在相同的结构上递归使用相同的权重系数,通过遍历方式得到结构化的预测。
**在自然语言处理中,递归神经网络可以解决时间序列无法解决的问题**。比方说,“两个大学的老师”是个有歧义的句子,如果单纯地将它拆分为词序列是无法消解歧义性的,只有用语法解析树来表示才能表示出定语“两个”到底描述的是“大学”还是“老师”。
将数据用树状结构表示后,递归神经网络的作用是将它们进一步表示成向量,映射到表示语义的向量空间之中。在语义空间上既可以度量单个向量的尺度,比如判定句子的感情色彩到底是褒义还是贬义;也可以度量不同向量之间的关系,比如确定两个句子意义上的相似程度。
递归神经网络通过树状结构将一个完整的句子打散为若干分量的组合,生成的向量就是树结构的根节点。在训练中,递归网络使用的也是误差反向传播的方法,误差从树结构的根节点反向传播到每个叶子节点。但在实际应用中,递归神经网络远不如循环神经网络受欢迎,这是因为它的训练需要高度的人工干预,将训练集的每个句子标注为语法解析树的形式不仅需要人工完成,而且费时费力。从性价比的角度看,递归网络远不如循环网络来得实在。
今天我和你分享了循环神经网络和递归神经网络的基本原理与简要的工作机制。其要点如下:
- 循环神经网络是具有记忆的神经网络,适用于处理序列化数据;
- 循环神经网络引入反馈结构,能够在时间上共享参数,从而具有记忆;
- 循环神经网络的扩展包括双向循环网络和深度循环网络;
- 递归神经网络能够处理具有层次化结构的数据,可以看成循环神经网络的推广。
循环神经网络的记忆机制与人类的记忆机制颇为相似。那么人类记忆还有哪些特点可以借鉴到神经网络的设计当中呢?
欢迎发表你的观点。
<img src="https://static001.geekbang.org/resource/image/3b/05/3b35d656105e4d355b968f7f292d9a05.jpg" alt="">

View File

@@ -0,0 +1,66 @@
<audio id="audio" title="31 深度学习框架下的神经网络 | 左右互搏:生成式对抗网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/db/7a/dbad8693195519010cc7835d1fb7267a.mp3"></audio>
2016年10月谷歌大脑的研究者们做了一个有趣的实验使用三个并不复杂的神经网络执行保密通信的任务两个合法通信方共享的只有保密的密钥而没有商定的加解密算法第三个神经网络则作为窃听者出现。
这种配置显然颠覆了密码学的常识:无论是公钥体制还是私钥体制,加解密的算法都是已知的。如果合法通信双方不能统一加解密的方法,实现保密通信就是“巧妇难为无米之炊”。可谷歌偏偏不信这个邪,他们就是要让神经网络实现双盲的加密与解密。
实验的结果同样令人惊讶经过不断的试错与调整接收方可以精确恢复出发送方的明文而窃听者的错误率稳定在50%左右,意味着她的破译只是随机的猜测。**这个实验的意义在于展示出神经网络的潜能**:它们不仅能够在欠缺先验规则的条件下,通过对大量数据的无监督学习完成目标,甚至还能够在学习过程中根据实际条件的变化对完成目标的方式进行动态调整。
这个实验的环境,就是在最近两年名声大噪的**生成式对抗网络**。生成式对抗网络generative adversarial network由《深度学习》的第一作者伊安·古德菲洛提出**这是一类在无监督学习中使用的人工智能算法,由两个在零和游戏框架下相互竞争的神经网络实现**。“零和游戏”zero-sum game这个术语来自于博弈论意思是博弈双方的利益之和为零。由于一方的收益必然意味着另一方的损失因而双方不可能实现合作属于非合作博弈。
**生成式对抗网络里的两个玩家一个叫生成器generator一个叫判别器discriminator均可以采用深度神经网络实现这两者之间的对抗就是网络训练的主旋律**。生成器像是白骨精,想方设法从随机噪声中模拟真实数据样本的潜在分布,以生成以假乱真的数据样本;判别器则是孙悟空,凭一双火眼金睛来判断输入到底是人畜无害的真实数据还是生成器假扮的伪装者。零和博弈中的竞争促使双方不断进化,直到“假作真时真亦假”,真真假假不可区分为止。
两个玩家费这么大劲对抗的目的是什么呢?就是建立数据的生成模型,使生成器尽可能精确估测出数据样本的分布。从学习方式上看,对抗性学习固然属于无监督学习,但对抗的引入使学习可以利用来自判别器的反馈信息,因而又蕴含着某些监督学习的影子。
由于生成器和判别器处于零和博弈之中,因而对网络的训练就可以等效成对以下目标函数的**极大-极小问题**
$$ \arg \min_g \max_D { -\dfrac{1}{2} \int_x [p_{data}(x) \log (D(x)) + p_g(x) \log (1 - D(x))] {\rm d}x } $$
其中“极大”是让判别器区分真实数据和伪造数据的准确率最大化,“极小”则是让生成器生成的数据被判别器发现的概率最小化。对整体极大-极小问题的优化可以通过**交替迭代训练**的方式实现。
交替迭代训练通常从判别器开始,也就是在给定生成器的条件下来求解最优的判别器。由于生成式对抗网络使用的是基于对数几率函数的二分类判别器,因而使用交叉熵作为损失函数是合理的选择。
由于判别器要将来自真实分布的真样本标注为1因而对数几率函数的输出需要越大越好反过来对来自生成器的假样本要标注为0此时的输出就越小越好也就是输出的相反数越大越好。这样一来对判别器的优化就转化为求解以下目标函数的最小值
$$ f(x) = -\dfrac{1}{2} \int_x [p_{data}(x) \log (D(x)) + p_g(x) \log (1 - D(x))] {\rm d}x $$
式中的$p_{data}(x)$表示数据的真实分布,$p_g(x)$表示生成器的数据分布,$D(x)$则表示判别器对数据$x$的概率输出。在给定生成器的条件下可以求出,使以上函数取得最小值的最优解是
$$D^*_G(x) = \dfrac{p_{data}(x)}{p_{data}(x) + p_g(x)}$$
这表明生成式对抗网络估计的实际是两个概率分布密度的比值。
优化完判别器,就该轮到生成器了。对生成器的优化意味着希望判别器对假样本的输出越大越好,因而需要优化$p_g(x)$,以使前文目标函数中的第二项最小。当且仅当$p_{data}(x) = p_g(x)$时,整个网络的目标函数可以取得全局最优解。
这表明在算法收敛时生成器学到的分布和数据的真实分布完全一致而判别器对每个样本的输出都等于0.5。在生成式对抗网络的实际训练时,一般采用先更新多次判别器的参数,再对生成器的参数执行一次更新的方法。
既然都是学习数据的分布,那生成式对抗网络和其他生成模型又有什么区别呢?
首先,传统的生成模型是定义了模型的分布,进而去求解参数。比如说在已知数据满足正态分布的前提下,生成模型会通过最大似然估计等方法根据样本来求解正态的均值和方差。可要是生成人脸呢?没人知道人脸满足什么样的先验分布,只能通过不断尝试来逐渐逼近,这时传统的生成模型就无能为力了。**生成式对抗网络好就好在摆脱了对模型分布的依赖,也不限制生成的维度,因而大大拓宽了生成数据样本的范围**。
其次,**生成式对抗网络能够整合不同的损失函数,增加了设计的自由度**。生成式对抗网络是没有显式的损失函数的,之所以这么说是因为它训练的目标是生成器,判别器只是训练过程中的副产品。对于生成器来说,因为判别器被用来度量生成分布和真实分布之间的偏差,所以判别器其实就是它的损失函数。而作为损失函数的判别器又会随着真实分布的变化而变化。从这个角度看,生成式对抗网络可以自动学习潜在的损失函数,这是传统的生成模型没法做到的。
**除了优点之外,生成式对抗网络也有它的问题。最主要的一个问题就是缺乏理论基础**
回到文首那个密码学的例子:我们只是知道了合法通信方能够达成关于密码算法的共识,但这个共识的达成过程还是个黑箱。关于生成器为什么能够从随机样本出发学习到真实的数据分布也缺乏清晰的理论解释。凡此种种都让生成式对抗网络看起来更像是沙上之塔。没有坚实的理论基础,对算法的推广自然存在困难。除了在图像生成等少数领域表现突出,生成式对抗网络在大多数任务上还是乏善可陈。在算法的原理尚不清楚时,想要实现优化自然是空中楼阁。
**生成式对抗网络面临的另一个主要问题就是训练的难度**。对抗网络的训练目标是在连续分布的高维度参数下达到纳什均衡,也就是让生成器和判别器的损失函数同时取得最小值。但由于待优化的问题可能是个非凸的问题,直接追求纳什均衡可能会让算法难以收敛,从而引发模型的欠拟合,导致表示能力不足。生成式对抗网络的提出者古德菲洛针对训练难的问题也提出了一系列改进措施,并应用在了半监督学习问题上,取得了不错的效果。
**虽然优缺点都很明显,但生成式对抗网络的提出依然可以看成是深度学习的一次突破**。给定一只猫的图片,过往的神经网络算法只能区分出它到底是不是猫,还不一定分得准确。可生成式神经网络却能模仿现有的图片画出一只类似的猫。不管这是简单的数据拟合,还是更加高级的抽象特征重组,它都是由机器自己完成的再创作,这种行为方式无疑更加接近于真实的人类。
关于生成式对抗网络还有一个有趣的事实。自2014年诞生以来各种各样的对抗网络变体层出不穷其中有名有姓的就超过了200种给这些变体命名让拉丁字母都不够用了。可这些改进到底有多少效果呢谷歌公司近期的一项研究表明没有证据表明哪种变体能够带来实质上的改进。换句话说改来改去的结果是王小二过年一年不如一年。
出现这种问题的原因就在于理论基础的缺失。没有理论基础就没有明确的改进方向,因而只能像没头苍蝇一样,从应用问题出发盲目地摸索优化技巧。运气好的话,通过优化架构或是损失函数可以在特定任务上获得性能的提升,但提升表现的适用范围往往狭窄,换一个场合就不好用了。这其实不只是生成式对抗网络,更是整个深度学习所深陷的“炼金术”尴尬处境的体现。
今天我和你分享了生成式对抗网络的原理与机制。其要点如下:
- 生成式对抗网络是一类运行在零和博弈框架下的无监督学习算法,由生成器和判别器构成;
- 生成器的目的是精确模拟真实数据的分布,判别器的目的是精确区分真实数据和生成数据;
- 生成式对抗网络的主要优点是超越了传统神经网络分类和特征提取的功能,能够按照真实数据的特点生成新的数据;
- 生成式对抗网络的主要问题是理论基础的缺失。
生成式对抗网络的一个重要的潜在应用就是让人工智能在没有明确指导的情况下学习,使算法的学习方式向人类的学习方式转变。那么如何看待生成式对抗网络在通用人工智能研究中的前景呢?
欢迎发表你的观点。
<img src="https://static001.geekbang.org/resource/image/3f/7f/3f505cb5fd0b5f18eece1522718a707f.jpg" alt="" />

View File

@@ -0,0 +1,70 @@
<audio id="audio" title="32 深度学习框架下的神经网络 | 三重门:长短期记忆网络" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f6/87/f644fa571b4857da3b3714aac0aeff87.mp3"></audio>
在之前的专栏中,我和你分享了循环神经网络的原理,而今天要介绍的**长短期记忆网络**就是一类特殊的循环神经网络。这个词的断句方式是“长-短期记忆网络”,表达的含义是**一类可以持续很长时间的短期记忆模型**。对时隙长度的不敏感性是这种模型的优势,因而它适用于序列中信息之间的时滞不确定的情况。
循环神经网络通过在时间上共享参数引入了记忆特性,从而将先前的信息应用在当前的任务上,可这种记忆通常只有有限的深度。有追剧经历的都会知道,国外的电视剧通常是每周更新一集,可即使经历了一周的空窗期,我们依然能将前一集的内容和新一集的情节无缝衔接起来。但循环神经网络的记忆就没有这么强的延续性,别说是一个星期的断片儿,插播一段五分钟广告就足以让它的记忆脱节,造成理解上的混乱。
真实世界中的信息不是静止的而是不断经历着流转与跃变如果神经网络不能保存长期记忆的话它处理信息的能力就会大打折扣。长短期记忆网络long short-term memory的作用就是实现长期记忆更准确地说是实现任意长度的记忆。精巧的设计使记住长期的信息成为了长短期记忆网络的默认行为而不是需要付出很大代价才能获得的能力。
**从机制上讲,要实现长期记忆,神经网络既要学会记忆,也要学会遗忘**。长期记忆的基础是足够的存储,但宝贵的存储不能被滥用,它不是收集桶,有用的没用的都一股脑儿往里面扔。**长期记忆要求模型具备对信息价值的判断能力,结合自身的状态确定哪些信息应该保留,而哪些信息应该舍弃**。比方说电视剧里的一段支线情节结束了,模型就应当重置相关的信息,只需保留对应的结果。同理,当收到新的输入信息时,模型也要判断这些信息是否有用,以及是否需要保存。
除了添加遗忘机制之外,**长短期记忆单元还要能够将长期记忆聚焦成工作记忆,也就是哪一部分记忆需要立刻使用**。有用的信息也不会每时每刻都有用,因而记忆单元并不会始终使用所有的长期记忆,而是根据当前的相关性做出取舍,这就类似于人类注意力的工作方式。遗忘和选择使长短期记忆网络能够对记忆做出更细粒度的处理,它不同于循环神经网络一视同仁的方式,因而可以实现对信息进行长期而精确的跟踪。
长短期记忆网络是由相应的基本单元构成的。长短期记忆的基本单元的作用在需要时取出并聚焦记忆,通常包括**四个功能不同的隐藏层记忆模块memory cell、输入门input gate、输出门output gate和遗忘门forget gate**,这比只有一个激活函数的一般循环神经网络要复杂得多。
记忆模块的作用时存储数值或是状态,存储的时限既可以是长期也可以是短期。另外的“三重门”则用于控制信息的有选择通过,三者都使用对数几率函数作为传递函数。
在这“三重门”中,输入门决定哪些新信息被存放在记忆模块中,遗忘门决定哪些信息被从记忆模块中丢弃,输出门则决定记忆模块中的哪些信息被用于计算整个长短期记忆单元的输出。值得一提的是,长短期记忆网络的最初版本只有输入门和输出门,遗忘门是作为一项改进添加的。
下面来看看长短期记忆单元的工作流程:根据遗忘机制,记忆模块要根据时刻$t$的输入来更新现有的记忆这个过程首先由遗忘门来完成。如果网络处理的对象是这样一句话“李雷XXX韩梅梅XXX”那么当“韩梅梅”出现时遗忘门就能够察觉到主语的变化从而降低“李雷”在记忆单元中的权重。在很多种语言中主语性别的改变也意味着动词词形的变化。
当然,记忆单元的更新不一定意味着完全的替换,对新输入的部分信息和原始存储中的部分信息加以整合也是可以的。遗忘门的输入包括这个长短期记忆单元在时刻$t - 1$的输出$y(t - 1)$和时刻$t$的输入$x(t)$,两者的加权组合再送进对数几率函数计算输出,其表达式可以写成
$$ \mathbf{f}(t) = \sigma (\mathbf{W}_f \mathbf{x}(t) + \mathbf{R}_f \mathbf{y}(t - 1) + \mathbf{b}_f) $$
其中$\sigma{\cdot}$表示对数几率函数。如果遗忘门的输出为0意味着记忆单元的当前存储要被全部舍弃输出为1则意味着全部保留。
在决定哪些来自输入的信息进入到记忆模块中时,就轮到输入门发挥作用了。**遗忘门的作用是弃旧,输入门的作用则是图新**,将新来的“韩梅梅”添加到记忆模块之中。输入门的工作机制与遗忘门类似,但是更加复杂,它首先用对数几率函数对即时输入和上一时刻的输出的组合进行过滤,过滤的作用一方面在于确定哪些信息被保留,另一方面则在于确定这些信息以何种比例被添加到记忆单元之中。将待保留的结果与权重系数相乘,就得到了输入门的输出。过滤结果和权重的表达式分别为
$$ \mathbf{i}(t) = \sigma (\mathbf{W}_i \mathbf{x}(t) + \mathbf{R}_i \mathbf{y}(t - 1) + \mathbf{b}_i) $$
$$ \tilde{\mathbf C}(t) = \tanh (\mathbf{W}_z \mathbf{x}(t) + \mathbf{R}_z \mathbf{y}(t - 1) + \mathbf{b}_z)$$
遗忘门和输入门的工作完成后,记忆模块的状态就是“万事俱备,只欠更新”。更新操作是舍弃旧信息和添加新信息的组合,其表达式可以写成
$$ \mathbf{C}(t) =\mathbf{f}(t) \odot \mathbf{C}(t - 1) + \mathbf{i}(t) \odot \tilde{\mathbf C}(t)$$
式中的$\odot$代表外积计算。
更新了记忆模块的状态后,就要从当前的单元状态中选择有用的信息输出,这部分工作由输出门完成。由于主语已经由李雷变成了韩梅梅,那么谓语出现“化妆”地可能性就远大于出现“打球”的可能性。输出门同样利用对数几率函数对即时输入和上一时刻的输出的组合进行过滤,过滤的目的生成一组权重系数,其整体的表达式可以写成
$$ \mathbf{o}(t) = \sigma (\mathbf{W}_o \mathbf{x}(t) + \mathbf{R}_o \mathbf{y}(t - 1) + \mathbf{b}_o)$$
**输出门输出权重系数的作用是对记忆模块的状态进行加权。但加权对象不是记忆状态本身,而是记忆状态的双曲正切函数结果**。因而长短期记忆单元在时刻$t$的输出就可以表示为
$$ y(t) = \tanh(\mathbf C(t)) \odot \mathbf{o}(t) $$
这一输出又将作为记忆单元在$t + 1$时刻的输入出现。
前文介绍的是长短期记忆网络的基本结构,一种改进的方法是加入所谓的“**门镜连接**peephole connection”。设计门镜连接的出发点是语义信息的载体不仅包括具体的文字也包括文字之间的时序。即使在通信高度发达的今天某些民族依然保持着用具有明显节奏和模式的鼓声来传递消息的古老传统。这种思想有它的现实意义即事件之间的时间差也就是通常所说的“节奏”也可以作为模式而被识别。
与其临渊羡鱼,不如退而结网,门镜连接体现的就是这一古老的哲理。门镜连接的作用是让长短期记忆单元中的三重门都能接受来自记忆模块的输入,这就意味着每个门都能观察到模块当前的状态,并将状态信息应用到更新之中。这一改进的作用在于提升长短期记忆网络对时间的识别精度。
和原始的循环神经网络相比长短期记忆网络解决了梯度弥散的问题梯度弥散这种现象可以用复利计算做类比即使一个赌徒每轮只损失1%的赌本,一座金山也会很快输个精光。根据求导的链式法则,循环神经网络的层次和时间之间是通过连续的乘法运算关联起来的,正是这大量的乘法运算使梯度以指数方式下降,以至于小到无法用于网络学习。而长短期记忆网络通过门隐藏层的使用强制性地将误差转化为加法运算,从而避免了梯度快速消失的问题。
**目前,长短期记忆网络最著名的应用恐怕非谷歌翻译莫属**。谷歌公司于2016年发表的论文中提到谷歌的神经机器翻译系统Google Neural Machine Translation就是由带有 8 个编码器和 8 个解码器的深度长短期记忆网络组成还使用了额外的注意力机制和残差连接。相比于原来使用的基于短语的系统新系统的翻译误差平均降低了60%,这是非常明显的提升。
今天我和你分享了长短期记忆网络的基本原理与简单工作机制。其要点如下:
- 长短期记忆网络可以实现任意长度的记忆,对信息进行长期而精确的跟踪;
- 长短期记忆单元的组成包括记忆模块、输入门、遗忘门和输出门;
- 长短期记忆网络根据当前的输入、当前的记忆和前一时刻的输出确定当前的输出;
- 长短期记忆网络能够解决梯度弥散的问题。
长短期记忆网络的作用不仅在于做些阅读理解,它可以让人工智能理解事物之间的长序联系。那么长短期记忆网络会不会在训练机器的推理能力上带来突破呢?
欢迎发表你的观点。
<img src="https://static001.geekbang.org/resource/image/2e/14/2e463cd67177ecafb547c36d65524a14.jpg" alt="">