前面主要是理论学习,从这节课开始我们会涉及更多实战的内容,毕竟只有理论是不够的嘛。
更新历史
- 2019.10.16: 完成初稿
训练/验证/测试集 Train/Dev/Test sets
当我们真正要开始训练一个神经网络的时候,我们需要选择:
- 网络层数
- 每层的隐藏单元个数
- 学习速度
- 每层的激活函数
但是因为目前没有一个绝对的标准辅助我们做选择,基本上我们的能做的就是不听的尝试,看看哪个效果好。
在小数据集时代,常用的比例为:
- 70% 训练集,30% 测试集
- 60% 训练集,20% 验证集,20% 测试集
对于数据量大于百万的应用,训练集可以占据 99.5%,验证和测试集各占 0.25%。
简单来说,验证集和测试集能够加速神经网络的优化过程,提供我们具体的指标来辅助判断最佳的超参数
偏差/方差 Bias/Variance
- 不能很好拟合数据 -> 高偏差 high bias -> 欠拟合 underfitting
- 网络非常复杂 -> 高方差 high vairiance -> 过拟合 overfitting
- 复杂程度适中 -> 适度拟合 just right
理解偏差和方差的两个关键数据:训练集误差(Train set error)和验证集误差(Dev set error),让我们来看看下面几个情况
- 训练集误差 1%,验证集误差 11% -> 可能过拟合 -> 高方差
- 训练集误差 15%,验证集误差 16% -> 人的误差约为 0% -> 欠拟合 -> 算法偏差性高 -> 高偏差
- 训练集误差 15%,验证集误差 30% -> 既高方差,又高偏差
- 训练集误差 0.5%,验证集误差 30% -> 方差和偏差都很低
总结一下,训练集误差告诉我们算法偏差情况,再加上验证集误差可以判断方差是否过高
机器学习基础方法 Basic Recipe for Machine Learning
按照下列步骤进行
- 训练初始模型,看训练集误差。如果训练集误差很高(就是准确率很低),再评估测试集数据。如果测试集误差依然很高 -> 选择新的网络结构(更多隐藏层/隐藏单元,其他优化算法等)
- 如果训练集误差比较低,同样评估测试集。如果测试集误差高,那么考虑采用更多的数据;如果无法获得更多数据,通过正则化减少过拟合;如果都不行,换神经网络框架
注意以下两点
- 高偏差和高方差是两种不同的情况。比如,算法如果偏差高,说明算法本身不适合,添加更多数据也没用。我们要根据实际情况去做判断决定下一步的行动
- 只要正则适度,通常构建一个更大的网络就可以做到不影响偏差的同时减少方差。
正则化 Regularization
解决过拟合问题(高方差)一般有两种方法:1)正则化。2)准备更多数据。考虑到数据有时候并不是要多少有多少,所以正则化是比较简单易行的方法。
L2 正则化是最常见的正则化类型。L1 正则化会使得 w 向量中有很多零,模型变得稀疏但是没有降低多少内存占用,所以一般使用 L2 正则化。L2 正则化的公式如下:
关于新增的 L2 正则化项的反向传播这里就不具体讨论,因为在实际的编程中,这些都是由框架帮忙完成的。
为啥正则化可以减少过拟合 Why regularization reduces overfitting
我们先来再回顾一下高偏差(high bias)与高方差(high variance)
正则项的影响不断增加,神经网络的所有隐藏单元依然存在,但是它们的影响变得更小了,神经网络变得更简单了。
更详细的说就是,如果正则化参数变得很大,那么参数 W 就会变得很小,于是通过激活函数的 z 也会变得很小,这使得激活函数(比如 tanh)会相对更接近于线性函数,众所周知,线性函数的表达能力有限,不会发生过拟合。也就是说正则化参数会让算法表现由高方差向高偏差移动(从右往左),于是我们可以利用这一点,找到一个比较好的取值,以达到中间 just right 这种比较好的结果。
Dropout 正则化
除了 L2 正则化之外,还有一种非常实用的方法 —— Dropout,简单来说就是随机丢弃一些节点。
具体到实现上,我们最常用的方法是反向随机失活(inverted dropout),这里有一个很关键的参数叫做 keep-prob
,表示保留某个隐藏单元的概率。
理解 Dropout
直观上理解,引入 Dropout 相当于告诉神经网络:你不要依赖某个特定的特征,因为它可能分分钟消失不见。这样一波操作,dropout 将产生收缩权重的平方范数的效果,就和 L2 正则化类似了。与 L2 不同的是,dropout 会对网络带来变化,甚至更能提高网络的泛化能力。
注意:目前来说在计算机视觉中 dropout 用得比较多,其他领域不一定是最有效的方法。另外 dropout 的一大缺点是代价函数 J 不再是明确定义的,比较难以复查结果。
其他正则化方法 Other regularization methods
这里介绍几种其他方法
Data Augmentation: 顾名思义,不多解释,下图可说明
Early Stopping: 当验证集误差不再下降(甚至开始上升时),停止训练。但一个坏处就是,如果验证集误差开始上升时,代价函数 J 还没有优化好,就比较麻烦。
归一化输入 Normalizing Inputs
归一化输入可以有效加速模型训练的速度,步骤为:1)零均值。2)归一化方差。具体可以参考下图
为啥归一化方差会有效呢?简单来说就是通过归一化我们重塑了搜索优化空间,于是我们对于代价函数 J 的优化(梯度下降)会更加简单,参考下图:
梯度消失/爆炸 Gradients Vanishing/Exploding
简单来说,就是训练神经网络的时候导数变得过大/过小,导致训练难度增加。在深度神经网络中,激活函数将以指数级增长/减少,具体参考下图,这里不再赘述(其实只要了解这个情况即可)
为了应对这样的情况,我们需要谨慎选择随机初始化权重。
权重初始化 Weight Initialization
我们先来看看只有一个神经元的情况,我们先忽略 b,主要看 w,得到的公式为:
如果想要 z 不大不小,那么 n 越大, w 应该越小,所以一个合理的方法就是设置 $w_i=\frac{1}{n}$,比如,针对 tanh 函数,具体实现的时候是:
如果是使用 Relu 函数,那么应该使用下面的公式(注意分子是 2)
一个合理的初始权重使得权重矩阵不会增长过快,也不会太快归零,这也是一个加速训练的技巧。
写在后面
最后三节的内容为梯度数值逼近、梯度检验和应用注意事项,这里因为我们不自己实现反向传播的部分(直接用现成的框架),所以就不赘述了,感兴趣的同学可以自行学习。