前面一部分主要介绍了深度神经网络的优化算法。包括对原始数据集进行分割,使用mini-batch gradient descent。然后介绍了指数加权平均(Exponentially weighted averages)的概念以及偏移校正(bias correction)方法。接着,我们着重介绍了三种常用的加速神经网络学习速度的三种算法:动量梯度下降、RMSprop和Adam算法。其中,Adam结合了动量梯度下降和RMSprop各自的优点,实际应用中表现更好。然后,我们介绍了另外一种提高学习速度的方法:learning rate decay,通过不断减小学习因子,减小步进长度,来减小梯度振荡。最后,我们对深度学习中local optima的概念作了更深入的解释。本节课,我们将重点介绍三个方面的内容:超参数调试、Batch正则化和深度学习编程框架。
一、超参数调试处理(Tuning Process)
1. 重要程度排序
目前已经讲到过的超参数中,重要程度依次是(仅供参考):
2. 调参技巧
如何选择和调试超参数?传统的机器学习中,我们对每个参数等距离选取任意个数的点,然后,分别使用不同点对应的参数组合进行训练,最后根据验证集上的表现好坏,来选定最佳的参数。例如有两个待调试的参数,分别在每个参数上选取5个点,这样构成了5x5=25中参数组合,如下图所示:
这种做法在参数比较少的时候效果较好。但是在深度神经网络模型中,我们一般不采用这种均匀间隔取点的方法,比较好的做法是使用随机选择。也就是说,对于上面这个例子,我们随机选择25个点,作为待调试的超参数,如下图所示:
随机化选择参数的目的是为了尽可能地得到更多种参数组合。 还是上面的例子,如果使用均匀采样的话,每个参数只有5种情况;而使用随机采样的话,每个参数有25种可能的情况,因此更有可能得到最佳的参数组合。
这种做法带来的另外一个好处就是对重要性不同的参数之间的选择效果更好。假设hyperparameter1为 α α α,hyperparameter2为 ε ε ε,显然二者的重要性是不一样的。如果使用第一种均匀采样的方法, ε ε ε的影响很小,相当于只选择了5个 α α α值。而如果使用第二种随机采样的方法, ε ε ε和 α α α都有可能选择25种不同值。这大大增加了 α α α调试的个数,更有可能选择到最优值。其实,在实际应用中完全不知道哪个参数更加重要的情况下,随机采样的方式能有效解决这一问题,但是均匀采样做不到这点。
在经过随机采样之后,我们可能得到某些区域模型的表现较好。然而,为了得到更精确的最佳参数,我们应该继续对选定的区域进行由粗到细的采样(coarse to fine sampling scheme)。 也就是放大表现较好的区域,再对此区域做更密集的随机采样。 例如,对下图中右下角的方形区域再做25点的随机采样,以获得最佳参数。
3. 选择合适的范围
上一部分讲的调试参数使用随机采样,对于某些超参数是可以进行尺度均匀采样的,但是某些超参数需要选择不同的合适尺度进行随机采样。
什么意思呢?例如对于超参数#layers和#hidden units,都是正整数,是可以进行均匀随机采样的,即超参数每次变化的尺度都是一致的(如每次变化为1,犹如一个刻度尺一样,刻度是均匀的)。
但是,对于某些超参数,可能需要非均匀随机采样(即非均匀刻度尺)。 例如超参数 α α α,待调范围是[0.0001, 1]。如果使用均匀随机采样,那么有90%的采样点分布在[0.1, 1]之间,只有10%分布在[0.0001, 0.1]之间。这在实际应用中是不太好的,因为最佳的 α α α值可能主要分布在[0.0001, 0.1]之间,而[0.1, 1]范围内 α α α值效果并不好。因此我们更关注的是区间[0.0001, 0.1],应该在这个区间内细分更多刻度。
通常的做法是将linear scale转换为log scale,将均匀尺度转化为非均匀尺度,然后再在log scale下进行均匀采样。 这样,[0.0001, 0.001],[0.001, 0.01],[0.01, 0.1],[0.1, 1]各个区间内随机采样的超参数个数基本一致,也就扩大了之前[0.0001, 0.1]区间内采样值个数。
一般解法是,如果线性区间为[a, b],令m=log(a),n=log(b),则对应的log区间为[m,n]。对log区间的[m,n]进行随机均匀采样,然后得到的采样值r,最后反推到线性区间,即
1
0
r
10^r
10r。
1
0
r
10^r
10r就是最终采样的超参数。相应的Python语句为:
m = np.log10(a)
n = np.log10(b)
r = np.random.rand() # 对log区间的[m,n]进行随机均匀采样,然后得到的采样值r
r = m + (n-m)*r
r = np.power(10,r) # 最终采样的超参数
除了
α
α
α之外,动量梯度因子
β
β
β也是一样,在超参数调试的时候也需要进行非均匀采样。一般
β
β
β的取值范围在[0.9, 0.999]之间,那么
1
−
β
1-β
1−β的取值范围就在[0.001, 0.1]之间。那么直接对
1
−
β
1-β
1−β在[0.001, 0.1]区间内进行log变换即可。
4. Hyperparameters tuning in practice: Pandas vs. Caviar
经过调试选择完最佳的超参数并不是一成不变的,一段时间之后(例如一个月),需要根据新的数据和实际情况,再次调试超参数,以获得实时的最佳模型。
在训练深度神经网络时,一种情况是受计算能力所限,我们只能对一个模型进行训练,调试不同的超参数,使得这个模型有最佳的表现。我们称之为Babysitting one model。另外一种情况是可以对多个模型同时进行训练,每个模型上调试不同的超参数,根据表现情况,选择最佳的模型。我们称之为Training many models in parallel。
因为第一种情况只使用一个模型,所以类比做Panda approach;第二种情况同时训练多个模型,类比做Caviar approach。使用哪种模型是由计算资源、计算能力所决定的。一般来说,对于非常复杂或者数据量很大的模型,使用Panda approach更多一些。
二、批标准化(Batch Normalization)
Sergey Ioffe和Christian Szegedy两位学者提出了Batch Normalization方法。Batch Normalization不仅可以让调试超参数更加简单,而且可以让神经网络模型更加“健壮”。也就是说较好模型可接受的超参数范围更大一些,包容性更强,使得更容易去训练一个深度神经网络。接下来,我们就来介绍什么是Batch Normalization,以及它是如何工作的。
之前,我们对输入特征
x
x
x 使用了标准化处理。我们也可以用同样的思路处理隐藏层的激活值
a
a
a[
l
l
l],以加速
W
W
W[
l
+
1
l+1
l+1]和
b
b
b[
l
+
1
l+1
l+1]的训练。在实践中,经常选择标准化
z
z
z[
l
l
l]。
其中,m 是单个 mini-batch 所包含的样本个数,
ϵ
ϵ
ϵ 是为了防止分母为零,通常取
10
10
10
−
8
-8
−8。
这样,我们使得所有的输入
z
z
z(
i
i
i) 均值为 0,方差为 1。但我们不想让隐藏层单元总是含有平均值 0 和方差 1,也许隐藏层单元有了不同的分布会更有意义。因此,我们计算
其中,
γ
γ
γ 和
β
β
β 都是模型的学习参数,所以可以用各种梯度下降算法来更新
γ
γ
γ 和
β
β
β 的值,如同更新神经网络的权重一样。
设置 γ 和 β 的原因是,如果各隐藏层的输入均值在靠近 0 的区域,即==处于激活函数的线性区域,不利于训练非线性神经网络,从而得到效果较差的模型。==因此,需要用 γ 和 β 对标准化后的结果做进一步处理。
1. 将 BN 应用于神经网络(Fitting Batch Norm into a neural network)
我们已经知道了如何对某单一隐藏层的所有神经元进行Batch Norm,接下来将研究如何把Bath Norm应用到整个神经网络中。
对于L层神经网络,经过Batch Norm的作用,整体流程如下:
实际上,Batch Norm经常使用在mini-batch上,这也是其名称的由来。
使用 Batch Normalization 时,因为标准化处理中包含减去均值的一步,因此b 实际上没有起到作用,其数值效果交由 β 来实现。因此,在 Batch Normalization 中,可以省略 b 或者暂时设置为 0。
在使用梯度下降算法时,分别对 W W W[ l l l], β β β[ l l l] 和 γ γ γ[ l l l] 进行迭代更新。除了传统的梯度下降算法之外,还可以使用之前学过的动量梯度下降、RMSProp 或者 Adam 等优化算法。
2. BN 有效的原因(Why does Batch Norm work?)
Batch Normalization 效果很好的原因有以下两点:①通过对隐藏层各神经元的输入做类似的标准化处理,提高神经网络训练速度;②可以使前面层的权重变化对后面层造成的影响减小,整体网络更加健壮。
假如用一个浅层神经网络(类似逻辑回归)来训练识别猫的模型。如下图所示,提供的所有猫的训练样本都是黑猫。然后,用这个训练得到的模型来对各种颜色的猫样本进行测试,测试的结果可能并不好。其原因是训练样本不具有一般性(即不是所有的猫都是黑猫),这种训练样本(黑猫)和测试样本(猫)分布的变化称之为covariate shift(即实际应用样本和训练样本的数据分布不同)。发生了covariate shift,一般是要对模型重新进行训练的。
Batch Normalization 的作用就是减小 Covariate Shift 所带来的影响,让模型变得更加健壮,鲁棒性(Robustness)更强。 Batch Norm减少了各层
W
W
W[
l
l
l]、
b
b
b[
l
l
l] 之间的耦合性,让各层更加独立,实现自我训练学习的效果。也就是说,如果输入发生covariate shift,那么因为Batch Norm的作用,对个隐藏层输出
z
z
z[
l
l
l] 进行均值和方差的归一化处理,
W
W
W[
l
l
l] 和
b
b
b[
l
l
l] 更加稳定,使得原来的模型也有不错的表现。针对上面这个黑猫的例子,如果我们使用深层神经网络,使用Batch Norm,那么该模型对花猫的识别能力应该也是不错的。
从另一个方面来说,Batch Norm也起到轻微的正则化(regularization)效果。 具体表现在:
- 每个mini-batch都进行均值为0,方差为1的归一化操作
- 每个mini-batch中,对各个隐藏层的 z z z[ l l l]添加了随机噪声,效果类似于Dropout
- mini-batch越小,正则化效果越明显
但是,Batch Norm的正则化效果比较微弱,正则化也不是Batch Norm的主要功能。因为 Batch Normalization 只有微弱的正则化效果,因此可以和 dropout 一起使用,以获得更强大的正则化效果。通过应用更大的 mini-batch 大小,可以减少噪声,从而减少这种正则化效果。
最后,不要将 Batch Normalization 作为正则化的手段,而是当作加速学习的方式。正则化只是一种非期望的副作用,Batch Normalization 解决的还是反向传播过程中的梯度问题(梯度消失和爆炸)。
3. 测试时的 Batch Normalization(Batch Norm at test time)
训练过程中,Batch Norm是对单个mini-batch进行操作的,但在测试过程中,如果是单个样本,该如何使用Batch Norm进行处理呢?
Batch Normalization 将数据以 mini-batch 的形式逐一处理,但在测试时,可能需要对每一个样本逐一处理,这样无法得到
μ
μ
μ 和
σ
2
σ^2
σ2。
三、Softmax回归
对于多分类问题,用C表示种类个数,神经网络中输出层就有C个神经元,即 n n n[ L L L] = C =C =C。其中,每个神经元的输出依次对应属于该类的概率,即 P ( y = c ∣ x ) P(y=c|x) P(y=c∣x)。为了处理多分类问题,我们一般使用Softmax回归模型。
1. Softmax回归模型
Softmax回归模型输出层的激活函数如下所示:
其中,for i in range(L),有:
输出层每个神经元的输出,对应属于该类的概率,满足:
一个直观的计算例子如下:
下面给出几个简单的线性多分类的例子:
如果使用神经网络,特别是深层神经网络,可以得到更复杂、更精确的非线性模型。
2. Training a softmax classifier
Softmax classifier的训练过程与我们之前介绍的二元分类问题有所不同。先来看一下softmax classifier的loss function。举例来说,假如C=4,某个样本的预测输出和真实输出为:
预测输出为:
真实输出为:
从预测的值来看,
P
(
y
=
4
∣
x
)
=
0.4
P(y=4|x)=0.4
P(y=4∣x)=0.4 ,概率最大。但是真实样本属于第2类,因此该预测效果不佳。我们定义softmax classifier的loss function为:
然而,由于只有当
j
=
2
j=2
j=2 时,
y
2
=
1
y_2 = 1
y2=1 ,其他情况下
y
j
=
0
y_j = 0
yj=0。所以,上式可以简化为:
要让
L
L
L 更小,就应该让
y
2
y_2
y2 的预测输出越大越好,其输出反映的是概率,完全符合我们之前的定义。
所有m个样本的cost function为:
其预测输出向量的维度为(4,m)。
拓展到一般情况,定义损失函数为:
当
i
i
i 为样本真实类别,则有:
y
j
=
0
,
j
≠
i
y_j = 0 , j ≠ i
yj=0,j=i。
因此,损失函数可以简化为:
所有m个样本的成本函数为:
3. 梯度下降法
softmax classifier的反向传播过程仍然使用梯度下降算法,其推导过程与二元分类有一点点不一样。因为只有输出层的激活函数不一样,我们先推导
d
z
dz
dz[
L
L
L]:
对于所有m个训练样本:
可见
d
z
dz
dz[
L
L
L]的表达式与二元分类结果是一致的,虽然推导过程不太一样。然后就可以继续进行反向传播过程的梯度下降算法了,推导过程与二元分类神经网络完全一致。
四、深度学习框架
深度学习的框架有很多,比较著名的框架有如下:
一般选择深度学习框架的基本准则是:
- 便于编程:包括神经网络的开发和迭代、配置产品;
- 运行速度:特别是训练大型数据集时;
- 是否真正开放:不仅需要开源,而且需要良好的管理,能够持续开放所有功能。
实际应用中,我们应该根据自己的需求选择最合适的深度学习框架。
最后的视频中,吴恩达老师介绍了最近几年比较火的深度学习框架:TensorFlow。Tensorflow 框架内可以直接调用梯度下降算法,极大地降低了编程人员的工作量。笔记请看:深度学习笔记。
关于TensorFlow更多的原理和编程技巧这里就不在赘述了,感兴趣的朋友可以关注TensorFlow官方文档。