基本概念
- 权重 表示相应输入对于输出重要性的实数
- 偏置 看作一种表示让感知器输出1(或者用生物学的术语,即激活感知器)有多容易的估算。
- S型神经元(逻辑神经元)
σ(wx+b)
σ(z)=11+e−z - 代价函数(损失函数 目标函数)
C(w,b)=12n∑x||y(x)−a||2
这里 w 表示所有的网络中权重的集合, b 是所有的偏置, n 是训练输入数据的个数, a 是表示当输入为 x 时输出的向量,求和则是在总的训练输入 x 上进行的。
C称为二次代价函数(均方误差 MSE)
我们训练神经网络的目的是找到能最小化二次代价函数 C(w, b) 的权重和偏置。
定义 ∆v 为 v 变化的向量(例子两个变量,可以多变量)
定义 C 的梯度为偏导数的向量 梯度向量∇C
函数C的变动如下(方程9)
假设我们选取 (方程10)
这里的 η 是个很小的正数(称为 学习速率)。
如果我们按照方程 (10) 的规则去改变 v,那么 C 会
一直减小,不会增加。(当然,要在方程 (9) 的近似约束下)。
在真正的实现中, η 通常是变化的,
以至方程 (9) 能 保持很好的近似度,但算法又 不会太慢。
证实了我们可以通过仅仅计算随机选取的小批量数据(mini-batch)的梯度来估算整体的梯度。
递增学习(在线、online学习,极端情况,相当于把batchsize设置为1) 相对于小批量随机梯度下降法
验证数据 它对于解决如何去设置某些神经网络中的超参数是很有用的——例如学习速率等,这些参数不被我们的学习算法直接选择。
然后对于每一个 mini_batch我们应用一次梯度下降
超参数 训练的迭代期数量,小批量数据大小和学习速率 η
复杂的算法 ≤ 简单的学习算法 + 好的训练数据
反向传播算法如何工作
首先给出网络中权重、偏置的清晰定义。
wljk 表示从(L-1)层的第k个神经元到 L层的第j个神经元的链接上的权重;
blj 表示在L 层第 j个神经元的偏置(为什么j、k的顺序是这样的?解释如下)
表在L 层第 j个神经元的激活值
其中求和是在 (L − 1) 层的所有 k 个神经元上进行的。
为了用矩阵的形式重写这个表达式,我们对 每一层 L 都定义一个权重矩阵 wl 。权重矩阵 wl 的元素正是连接到L层神经元的权重,更确切地说,在 第j行第k列的元素是 wljk 。
权重矩阵 偏置向量 激活向量(上到下)
L层神经元的带权输入
zlj 就是 第L层第j个神经元的激活函数的带权输入。
为了应用反向传播,需要对代价函数C做如下前提假设:
第一个假设:代价函数可以被写成一个在每个训练样本 x 上的代价函数
Cx
的均值
这个假设对书中提到的其他任何一个代价函数也都是必须满足的。二次代价函数的例子,其中对每个独立的训练样本其代价是
需要这个假设的原因是反向传播实际上是对一个独立的训练样本计算了 ∂Cx/∂w 和 ∂Cx/∂b 。
然后我们通过在所有训练样本上进行平均化获得 ∂C/∂w 和 ∂C/∂b 。
第二个假设:代价可以写成神经网络输出的函数
将 C 看成仅有输出激活值 aL 的函数才是合理的,而y 仅仅是帮助定义函数的参数而已。
Hadamard 乘积(Schur 乘积) s ⊙ t 表示按元素的乘积
反向传播其实是对权重和偏置变化影响代价函数过程的理解。
首先引入一个中间量
这个我们称为在 L 层第 j 个神经元上的 误差。
在 L 层的第 j 个神经元上。当输入进来时,增加很小的变化
在神经元的带权输入上,使得神经元输出由
变成
这个变化会向网络后面的层行传播,最终导致整个代价产生
的 改变
这里有一种启发式的认识,
是神经元的误差的度量。
(因为如果这个值很大(或正或负),选择相反符号的 Δzlj (很小才能满足)来降低代价;相反,如果这个值接近0,并不能通过扰动带权输入来改善太多代价,这时神经元已接近最优了)
按照上面的描述,我们定义L层的第j个神经元上的误差
δlj
为:
之所以用 带权输入而不用 输出激活值做分母,是因为用输出激活值做分母会让反向传播在 代数运算上变的比较复杂
(误差的度量选择这个的原因)
反向传播关键点
关于 BP2的推导详见与草稿.
通过组合(BP1)和(BP2),我们可以计算任何层的误差 δL 。首先使用(BP1)计算 δL ,然后应用方程 (BP2) 来计算 δL−1 ,然后再次用方程 (BP2) 来计算 δL−2 ,如此一步一步地反向传播完整个网络。(反向推导的由来,从最后一层往前推导)
误差 δLj 和偏导数值 ∂C∂blj 完全一致(BP3)。
BP3 BP4 推导见草稿 BP4理解如下
其中 ain 是 输入给权重w的神经元的激活值, δout 是 输出自权重w的神经元的误差。
(BP4)的一个结果就是来自低激活值神经元的权重学习会非常缓慢。表示在梯度下降的时候,这个权重不会改变太多。
总结一下,我们已经学习到,如果输入神经元激活值很低,或者输出神经元已经饱和了(过高或者过低的激活值),权重会学习缓慢。
改进神经网络的学习方法
更好的代价函数的选择 —交叉熵代价函数;
四种称为“规范化”的方法(L1 和 L2 规范化,弃权和训练数据的人为扩展),这会让我们的网络在训练集之外的数据上更好地泛化;
更好的权重初始化方法;
还有帮助选择好的超参数的启发式想法。
交叉熵代价函数(单个神经元):
其中 n 是训练数据的总数,求和是在所有的 训练输入 x 上进行的, y 是对应的 目标输出。
交叉熵为何能够解释成一个代价函数。
第一,它是非负的, C > 0。可以看出:(a)公式中的
求和的所有独立的项都是负数的,因为对数函数的定义域是 (0; 1);(b)求和前面有一个负号。
第二,如果对于所有的训练输入x,神经元实际的输出接近目标值,那么交叉熵将接近 0。
交叉熵代价函数有一个比二次代价函数更好的特性就是它避免了学习速度下降的问题。
交叉熵代价函数关于权重的偏导数推导之后的结果:
这是一个优美的公式。它告诉我们权重学习的速度受到 σ(z) − y,也就是输出中的误差的控制。更大的误差,更快的学习速度。
特别地,这个代价函数还避免了像在二次代价函数中类似过程中 σ′(z) 导致的学习缓慢。当我们使用交叉熵的时候, σ′(z) 被约掉了,所以我们不再需要关心它是不是变得很小。
交叉熵代价函数(多个神经元):
针对 回归问题(原来的论断其实是和y只等于1或者0有关,这在分类问题一般是可行的,但是对其他的问题(如回归问题) y 可以取 0 和 1 之间的中间值的。)证明,交叉熵对所有训练输在σ(z) = y 时仍然是最小化的。
而其中−[y ln y + (1 − y) ln(1 − y)]有时候被称为 二元熵。
如果输出神经元是线性的那么二次代价函数不再会导致学习速度下降的问题。
那么交叉熵直觉含义又是什么?粗略地说, 交叉熵是“不确定性”的一种度量。
softmax
柔性最大值的想法其实就是为神经网络定义一种新式的输出层。应用一种叫做柔性最大值函数在带权输入上。根据这个函数,第j个神经元的激活值 aLj 就是
其中, 分母中的求和是在所有的输出神经元上进行的。
根据定义,输出的激活值加起来正好为1我们可以证明:
柔性最大值层的输出可以被看做是一个概率分布。
对比一下,如果输出层是S型层,那么我们肯定不能假设激活值形成了一个概率分布。
柔性最大值层会怎么样解决学习缓慢问题。
对数似然代价函数
这些方程其实和我们前面对交叉熵得到的类似。而且,正如前面的分析,这些表达式确保我们不会遇到学习缓慢的问题。事实上,把一个具有 对数似然代价的 柔性最大值输出层,看作与一个具有 交叉熵代价的 S型输出层非常相似,这是很有用的。实际上,在很多应用场景中,这 两种方式的效果都不错*。
使用这个表达式,我们可以在使用 柔性最大值层和 对数似然代价的网络上应用 反向传播。
过拟合和规范化(正则化)
从一个实践⻆度,我们真的关心的是提升测试数据集上的分类准确率,而测试集合上的代价不过是分类准确率的一个反应。
过拟合是神经网络的一个主要问题。这在现代网络中特别正常,因为网络权重和偏置数量巨大。为了有效地训练,我们需要一种检测过度拟合是不是发生的技术,这样我们不会过度训练。并且我们也想要找到一些技术来降低过度拟合的影响。
方法 —— 跟踪测试数据集合上的准确率随训练变化情况。
这个一般的策略就是使用validation_data来衡量不同的超参数(如迭代期,学习速率,最好的网络架构等等)的选择的效果。
有一个更加一般的问题,就是为何用validation_data取代 test_data来设置更好的超参数?为了理解这点,想想当设置超参数时,我们想要尝试许多不同的超参数选择。如果我们设置超参数是基于test_data的话,可能最终我们就会得到过度拟合于test_data的超参数。也就是说,我们可能会找到那些符合test_data特点的超参数,但是网络的性能并不能够泛化到其他
数据集合上。我们借助validation_data来克服这个问题。然后一旦获得了想要的超参数,最终我们就使用test_data进行准确率测量。这给了我们在test_data上的结果是一个网络泛化能力真正的度量方式的信心。
你可以将验证集看成是一种特殊的训练数据集能够帮助我们学习好的超参数。这种寻找好的超参数的方法有时候被称为hold out方法,因为validation_data是从traning_data 训练集中留出或者“拿出”的一部分。
一般来说,最好的降低过度拟合的方式之一就是增加训练样本的量。
规范化(正则化)
最为常用的规范化手段——有时候被称为权重衰减(weightdecay)或者L2 规范化。
L2 规范化的想法是增加一个额外的项到代价函数上,这个项叫做规范化项。形式如下:
就是所有权重的平方的和。然后使用一个因子 λ2n 进行量化调整,其中λ>0可以称为 规范化参数,而n就是训练集合的大小。需要注意的是, 规范化项里并不包含偏置。
规范化可以当做一种寻找小的权重和最小化原始的代价函数之间的折中。
这两部分之前相对的重要性就由λ的值来控制了:λ越小,就偏向于最小化原始代价函数,反之,倾向于小的权重。
把规范化描述为一种减轻过拟合和提高分类准确率的方法。实际上,这不是仅有的好处。
实践表明,在使用不同的(随机)权重初始化进行多次MNIST网络训练的时候,我发现无规范化的网络会偶然被限制住,明显困在了代价函数的局部最优值处。结果就是不同的运行会给出相差很大的结果。对比看来,规范化的网络能够提供更容易复制的结果。
权重向量的长度?
为何规范化可以帮助减轻过度拟合?
记住这一点,规范化的神经网络常常能够比非规范化的泛化能力更强,这只是一种实验事实(empirical fact)。
发展出更加强大的技术来规范化神经网络,最终这些技术会让神经网络甚至在小的训练集上也能够学到强大的泛化能力。
允许大的偏置能够让网络更加灵活——因为,大的偏置让神经元更加容易饱和,这有时候是我们所要达到的效果。所以,我们通常不会对偏置进行规范化。
规范化的其他技术
三种减轻过拟合的其他的方法:L1规范化、弃权和人为增加训练样本。
L1 规范化:这个方法是在未规范化的代价函数上加上一个权重绝对值的和:
在L1规范化中,权重通过一个常量向0进行缩小。在L2规范化中,权重通过一个和w成比例的量进行缩小的。所以,当一个特定的权重绝对值|w|很大时,L1规范化的权重缩小得远比L2规范化要小得多。相反,当一个特定的权重绝对值|w|很小时,L1规范化的权重缩小得要比L2规范化大得多。
结果:L1规范化倾向于聚集网络的权重在相对少量的高重要度连接上,而其他权重就会被驱使向 0 接近。
弃权
随机(临时)地删除网络中的一半的隐藏神经元开始,同时让输入层和输出层的神经元保持不变。我们前向传播输入x,通过修改后的网络,然后反向传播结果,同样通过这个修改后的网络。在一个小批量数据集上进行这些步骤后,我们对有关的权重和偏置进行更新。然后重复这个过程,首先重置弃权的神经元,然后选择一个新的随机的隐藏神经元的子集进行删除,估计对一个不同的小批量数据的梯度,然后更新权重和偏置。
通过不断地重复,我们的网络会学到一个权重和偏置的集合。当然,这些权重和偏置也是在一半的隐藏神经元被弃权的情形下学到的。当我们实际运行整个网络时,是指两倍的隐藏神经元将会被激活。为了补偿这个,我们将从隐藏神经元出去的权重减半。所以,弃权过程就如同大量不同网络的效果的平均那样。不同的网络会以不同的方式过拟合了,所以,弃权过的网络的效果会减轻过拟合。
弃权技术在训练大规模深度网络时尤其有用,这样的网络中过拟合问题经常特别突出。
人为扩展训练数据(数据扩增)
旋转 转换 扭曲 弹性扭曲
权重初始化
最简单直接:归一化的高斯分布 均值为 0,标准差 1。
前面我们讨论过输出神经元在错误的值上饱和导致学习的下降。我们之前通过代价函数的选择解决了前面的问题。不幸的是,尽管那种方式在输出神经元上有效,但对于隐藏神经元的饱和却一点作用都没有。
改进做法:假设我们有一个有 nin 个输入权重的神经元。我们会使用均值为0标准差为 1/nin−−−√ 的高斯随机分布初始化这些权重。也就是说,我们会向下挤压高斯分布,让我们的神经元更不可能饱和。继续使用之前的方式对偏置进行初始化,就是使用均值为0标准差为1的高斯分布来对偏置进行初始化。
不仅仅能够带来训练速度的加快,有时候在最终性能上也有很大的提升。(在迭代初期得到的效果比原来的初始化方法好,准确率提升速度快,但在大部分例子最后准确率都重合了,但是改进方法经历更少的迭代次数?)
如何选择神经网络的超参数
1宽泛策略
2学习速率
3使用提前停止来确定训练的迭代期数量
4学习速率调整
5规范化参数: 我建议,开始时不包含规范化(λ=0.0),确定η的值。使用确定出来的η,我们可以使用验证数据来选择好的λ。从尝试λ=1.0开始,然后根据验证集上的性能按照因子10增加或减少其值。一旦我已经找到一个好的量级,你可以改进λ的值。这里搞定后,你就可以返回再重新优化η。
6小批量数据大小
可以使用矩阵技术来对所有在一批量数据中的样本同时计算梯度更新,而不是进行循环。
7自动技术 网格搜索(grid search)贝叶斯观点自动优化超参数
其它技术
随机梯度下降的变化形式
Hessian 技术
Hessian 矩阵
证明右式表达式可以进行最小化,选择:
这就给出了一种优化代价函数的可能的算法:
• 选择开始点, w
• 更新 w 到新点 w′=w−H−1∇C ,其中 Hessian H 和 ∇C 在 w 处计算出来的
• 更新 w′ 到新点 w′=w′−H′−1∇′C ,其中 Hessian H′ 和 ∇′C 在 w′ 处计算出来的
• …
实际应用中,(105)是唯一的近似,并且选择更小的步长会更好。我们通过重复地使用改变量 Δw=−ηH−1∇C 来改变w,其中η就是学习速率。
在理论上和实践中的结果都表明Hessian方法比标准的梯度下降方法收敛速度更快。特别地,通过引入代价函数的二阶变化信息,可以让Hessian方法避免在梯度下降中常碰到的多路径(pathologies)问题。而且,反向传播算法的有些版本也可以用于计算 Hessian。
尽管Hessian优化有很多可取的特性,它其实还有一个不好的地方:在实践中很难应用。这个问题的部分原因在于Hessian矩阵的太大了。
基于momentum的梯度下降
momentum 技术修改了梯度下降的两处使之类似于这个物理场景。首先,为我们想要优化的参数引入了一个称为速度(velocity)的概念。梯度的作用就是改变速度,而不是直接的改变位置,就如同物理学中的力改变速度,只会间接地影响位置。第二,momentum方法引入了一种摩擦力的项,用来逐步地减少速度。
梯度下降更新规则
改成
µ是用来控制阻碍或者摩擦力的量的超参数。当µ=1时,没有摩擦,速度完全由梯度∇C决定。相反,若是µ=0,就存在很大的摩擦,速度无法叠加,公式 (107) (108)就变成了通常的梯度下降, w → w′ = w − η∇C。在实践中,使用0和1之间的µ值可以给我们避免过量而又能够叠加速度的好处。我们可以使用hold out**验证数据集**来选择合适的µ值,就像我们之前选择η和λ那样。
µ 的标准命名:moment coefficient
关于 momentum 技术的一个很好的特点是它基本上不需要改变太多梯度下降的代码就可以实现。我们可以继续使用反向传播来计算梯度,就和前面那样,使用随机选择的minibatch的方法。这样的话,我们还是能够从 Hessian 技术中学到的优点的 —— 使用梯度如何改变的信息。也仅仅需要进行微小的调整。实践中, momentum 技术很常用,也能够带来学习速度的提升。
其他优化代价函数的方法
共轭梯度下降 和 BFGS 方法、 limited memory BFGS
Nesterov 的加速梯度技术 这个技术对 momentum 技术进行了改进。
人工神经元的其他模型
tanh神经元
tanh(发音为“tanch”)神经元,使用双曲正切(hyperbolic tangent)函数替换了 S 型函数。
进行简单的代数运算,我们可以得到
这两个函数之间的一个差异就是 tanh 神经元的输出的值域是 (−1,1) 而非 (0,1)。这意味着如果你构建基于tanh神经元,你可能需要正规化最终的输出(取决于应用的细节,还有你的输
入),跟 sigmoid 网络略微不同。
反向传播和随机梯度下降这样的想法也能够轻松地用在 tanh 神经元构成的网络上的。
修正线性神经元ReLU
修正线性神经元(rectified linear neuron)或者修正线性单元(rectified linear unit),简记为 ReLU。
输入为 x,权重向量为 w,偏置为 b 的 ReLU神经元的输出是:
在这章我们也反复看到了问题就是σ′降低了梯度,减缓了学习。 Tanh 神经元也有类似的问题。对比一下, 提高ReLU的带权输入并不会导致其饱和,所以就不存在前面那样的学习速度下降。另外,当带权输入是负数的时候,梯度就消失了,所以神经元就完全停止了学习。
神经网络可以计算任何函数的可视化证明
神经网络拥有一种普遍性
包含一个隐藏层的神经网络可以被用来按照任意给定的精度来近似任何连续函数。
阶跃点 s=−bw
h=xw1=xw2=−x
S型神经元的延伸
如果我们考虑一个不同类型的神经元,它使用其它激活函数,比如如下的 s(z),会怎样?更确切地说,我们假定如果神经元有输⼊ x1; x2; ···,权重 w1; w2; ···,和偏置b,那么输出为 s(∑jwjxj+b) 。我们可以使用这个激活函数来得到一个阶跃函数,正如用 S 型函数做过的一样。
s(z)需要什么样的性质来满足这样的结果呢?我们确实需要假定s(z)在z→负无穷和z→正无穷时是定义明确的。这两个界限是在我们的阶跃函数上取的两个值。我们也需要假定这两个界限彼此不同。如果它们不是这样,就没有阶跃,只是一个简单的平坦图形!但是如果激活函数s(z)满足这些性质,基于这样一个激活函数的神经元可普遍用于计算。
普遍性告诉我们神经网络能计算任何函数;而实际经验依据提示深度网络最能适用于学习能够解决许多现实世界问题的函数。
深度神经网络为何很难训练
基于梯度下降的学习方法本身存在着内在不稳定性。这种不稳定性使得先前或者后面的层的学习过程阻滞。
梯度消失问题 (vanishing gradient problem)
梯度激增问题 (exploding gradient problem)
什么导致了梯度消失问题?深度神经网络中的梯度不稳定性
为了弄清楚为何会出现消失的梯度,来看看一个极简单的深度神经网络:每一层都只有一个的神经元。
除了最后一项,该表达式是一系列形如 wjσ′(zj) 的乘积。
sigmoid 函数导数的图像(关键) 在0时取到最大值0.25
该导数在σ′(0)= 1/4时达到最大。现在,如果我们使用标准方法来初始化网络中的权重,那么会使用一个均值为 0 标准差为 1 的高斯分布。因此所有的权重通常会满足 |wj|<1 。有了这些信息,我们发现会有 wjσ′(zj)<1/4 。并且在我们进行了所有这些项的乘积时,最终结果肯定会指数级下降:项越多,乘积的下降的越快。这里我们敏锐地嗅到了梯度消失问题的合理解释。
特别地,我们想要知道权重 wj 在训练中是否会增长。如果会,项 wjσ′(zj) 会不会不再满足之前 wjσ′(zj)<1/4 的约束。事实上,如果权重变得很大——超过1,那么我们将不再遇到消失的梯度问题。实际上,这时候梯度会在我们BP的时候发生指数级地增长。也就是说,我们遇到了梯度激增问题。
不稳定的梯度问题:根本的问题其实并非是梯度消失问题或者梯度激增问题,而是在前面的层上的梯度是来自后面的层上项的乘积。当存在过多的层次时,就出现了内在本质上的不稳定场景。唯一让所有层都接近相同的学习速度的方式是所有这些项的乘积都能得到一种平衡。如果没有某种机制或者更加本质的保证来达成平衡,那网络就很容易不稳定了。简而言之,真实的问题就是神经网络受限于不稳定梯度的问题。所以,如果我们使用标准的基于梯度的学习算法,在网络中的不同层会出现按照不同学习速度学习的情况。
在更加复杂网络中的不稳定梯度
其它深度学习的障碍
深度学习
全连接:如果一开始就使用全连接层,拿全连接层分类图像是很奇怪的。原因是这样的一个网络架构不考虑图像的空间结构。例如,它在完全相同的基础上去对待相距很远和彼此接近的输入像素。这样的空间结构的概念必须从训练数据中推断。
卷积神经网络
局部感受野/域(local receptive fields) 跨距
共享权重(shared weights)
混合/池化(pooling)
用稍微更抽象的术语,卷积网络能很好地适应图像的平移不变性:例如稍稍移动一幅猫的图像,它仍然是一幅猫的图像。
因为这个原因,我们有时候把从输入层到隐藏层的映射称为一个特征映射。我们把定义特征映射的权重称为共享权重。我们把以这种方式定义特征映射的偏置称为共享偏置。共享权重和偏置经常被称为一个卷积核或者滤波器。
详细地说,一个混合层取得从卷积层输出的每一个特征映射并且从它们准备一个凝缩的特征映射。例如,混合层的每个单元可能概括了前一层的一个(比如)2×2的区域。作为一个具体的例子,一个常见的混合的程序被称为最大值混合(max-pooling)。在最大值混合中,一个混合单元简单地输出其2×2输入区域的最大激活值。
我们可以把最大值混合看作一种网络询问是否有一个给定的特征在一个图像区域中的哪个地方被发现的方式。然后它扔掉确切的位置信息。直观上,一旦一个特征被发现,它的确切位置并不如它相对于其它特征的大概位置重要。一个很大的好处是,这样可以有很多被更少地混合的特征,所以这有助于减少在以后的层所需的参数的数目。另一个常用的方法是L2混合(L2 pooling)。这里我们取2×2区域中激活值的平方和的平方根,而不是最大激活值。
为什么我们只对全连接层应用弃权:如果你仔细看上面的代码,你会注意到我们只在网络的全链接部分应用了弃权,而不是卷积层。原则上我们可以在卷积层上应用一个类似的程序。但
是,实际上那没必要:卷积层有相当大的先天的对于过度拟合的抵抗。原因是共享权重意味着卷积滤波器被强制从整个图像中学习。这使他们不太可能去选择在训练数据中的局部特质。于是就很少有必要来应用其它规范化,例如弃权。
利用充分大的数据集(为了避免过度拟合);使用正确的代价函数(为了避免学习减速);使用好的权重初始化(也是为了避免因为神经元饱和引起的学习减速);以算法形式扩展训练数据。
其他的深度学习模型
递归神经网络(RNN)
长短期记忆单元(Long short-term memory units,LSTMs)
深度信念网络,生成式模型和 Boltzmann 机