Fork me on GitHub

深度学习的实用层面

介绍深度学习实现层面所需要理解的一些概念以及基本方法,包括正则化、梯度消失与梯度爆炸。

训练集/交叉验证集/测试集

通常情况下我们将数据分为三部分

  • 训练集:训练模型
  • 交叉验证集:考查模型性能,一些情况是将训练集里的一部分数据取出验证训练集误差
  • 测试集:进行无偏评估模型,是对模型泛化能力的评估

验证集与测试集的区别常常让人一头雾水,简要来说,验证集用于进一步确定模型中的超参数(例如正则项系数、ANN中隐含层的节点个数等)而测试集只是用于评估模型的精确度(即泛化能力)。在传统时代常常将训练集与测试集按70%/30%的比例分开,或者是训练集/交叉验证集/测试集按60%/20%/20%分开。而在大数据时代通常三者的比例是:98%/1%/1%,甚至前者所占的比例更大。

尽管有些时候会出现训练集与交叉验证集以及测试集不匹配的情况,例如训练集可能是从网上下载的猫片,测试集以及交叉验证集可能是用户上传的猫片。不论如何一定要保证交叉验证集和测试集来自同样的数据分布,这样的评估才是最准确的。

偏差/方差

方差与偏差的指标情况决定了模型是过拟合还是欠拟合或是适度拟合

我们也把过拟合叫做高方差,欠拟合成为高偏差

在模型建立的过程中首先通过训练集的表现来判断是否发生了高偏差并采取一些相应的手段进行处理,之后通过对验证集的表现来确定是否是高方差,进而进行一些处理。

因为有许多手段(例如图中)能够保证我们在降低一个指标的同时而不影响另外一个指标,所以权衡两者的问题显得没有那么重要。

正则化

加入正则项是为了避免过拟合

正则化常用技术

  • 参数约束
  • 训练集合扩充
  • dropout

过多的变量(特征),同时只有非常少的训练数据,会导致出现过度拟合的问题。因此为了解决过度拟合,有以下两个办法。

  • 尽量减少选取的变量:具体而言,我们可以人工检查每一项变量,并以此来确定哪些变量更为重要,然后,保留那些更为重要的特征变量。
  • 正则化:正则化中我们将保留所有的特征变量,但是会减小特征变量的数量级(参数数值的大小θ(j))。

参数惩罚

通过将参数减小数量级,我们可以将模型简单化,进而减少过拟合。通常情况下,深度学习中只对仿射参数添加约束,对偏置项不加约束。主要原因是偏置项一般需要较少的数据就能精确的拟合。如果添加约束常常会导致欠拟合。

左图的拟合效果已经比较让人满意,但倘若我们用一个更高次的函数去拟合,拟合效果会更好,但是这个模型对新数据的拟合效果可能不如左图。这时候我们将$\theta_3$和$\theta_4$的数量级减少,使其接近0,整个函数也就接近于二次函数,其拟合效果也就更好。

实际上,这些参数的值越小,通常对应于越光滑的函数,也就是更加简单的函数。因此 就不易发生过拟合的问题。

但是在实际过程中,我们可能对拟合的结果没有一个清晰的认识,也不太清楚需要去缩小哪几个函数。因此,我们需要修改代价函数,在这后面添加一项,就像我们在方括号里的这项。当我们添加一个额外的正则化项的时候,我们收缩了每个参数。按照惯例,通常情况下我们还是只从 θ1 到 θn 进行正则化。$\theta_0$的数量级保持不变。

dropout

Dropout是一类通用并且计算简洁的正则化方法,在2014年被提出后广泛的使用。 简单的说,Dropout在训练过程中,随机的丢弃一部分输入,此时丢弃部分对应的参数不会更新。相当于Dropout是一个集成方法,将所有子网络结果进行合并,通过随机丢弃输入可以得到各种子网络。

Dropout以概率p舍弃神经元并让其它神经元以概率q=1-p保留。每个神经元被关闭的概率是相同的。在标准神经网络中,每个参数的导数告诉其应该如何改变,以致损失函数最后被减少。因此神经元元可以通过这种方式修正其他单元的错误。但这可能导致复杂的协调,反过来导致过拟合,因为这些协调没有推广到未知数据。Dropout通过使其他隐藏单元存在不可靠性来防止共拟合。

经验:原始输入每一个节点选择概率0.8,隐藏层选择概率为0.5

梯度消失与梯度爆炸

  • 梯度消失:前面的层比后面的层梯度变化更小,故变化更慢,从而引起了梯度消失问题。
  • 梯度爆炸:当权值过大,前面层比后面层梯度变化更快,会引起梯度爆炸问题。

用形象化的方式解释就是,倘若每层梯度的值都小于1,那么在反向传播中,多了小于1的量相乘,最终到了最浅层的梯度结果可能是一个趋于0的值,这时候就是梯度消失。反过来,假若是很多大于1的值相乘,到了最浅层就是一个很大的值,甚至可能导致溢出,这就是梯度爆炸

解决方法

  • 使用relu函数代替sigmoid函数
  • 重新设计网络,尝试减少层数

调试处理

在确定超参数的过程中,我们往往需要很多尝试。一个比较有用的经验就是在超参数组成的空间内,均匀的取一些值,然后在表现较好的超参数附件在细致的取一些值,为了方便说明,以两个超参数举例。当我们反正右下角的取值表现比较好时,我们将超参数的取值范围确定在左下角,然后进一步选取表现好的值。

线性轴与log轴

若我们想在0.0001到1之前均匀的选参数进行尝试,我们第一个想法可能是采用传统的坐标轴去直接进行均匀的划分,但事实上这样的效果可能并不好。

我们可能要将坐标轴转化为log轴的形式,然后均匀取点进行尝试可能会有意想不到的效果。

参考

1.网易云课堂. 深度学习工程师微专业

2.大佬博客:https://www.cnblogs.com/jianxinzhou/p/4083921.html

3.大佬博客:https://blog.csdn.net/liujiandu101/article/details/55103831

4.云栖社区:https://yq.aliyun.com/articles/68901

5.大佬博客:https://blog.csdn.net/cppjava_/article/details/68941436

-------------The End-------------