防止过拟合和提高泛化能力的技巧.

深度学习是一个很奇怪的过程,有人说它是“深度炼丹”,有人说它是一个黑盒,超参调整就是玄学。

事实上,我们不可能在深度学习中寻找到所谓的“最优解”,我们只能够在自己的能力范围之内寻找到局部的最优解,而如何提高自己网络模型的分类或者生成能力也自然有着许多的技巧。

数据

深度学习最需要的,就是数据,一个好的数据集可以让神经网络的训练事半功倍。在我看来,数据在保证质量的前提下多多益善,样本数据越多,模型拟合的效果就会越好。因此首先,尽可能多地寻找优质数据集

Data Augmentation

而如果在数据集不够时,对数据的预处理就显得十分重要,对原先数据的处理扩增被称作 data augmentation,方法主要是下面的几种:

  1. 对于语音或者图像,可以在原本的数据上加噪声,或者进行缩放,镜像等操作;
  2. 对于数值类向量,可以在原先的数据基础上进行随机;
  3. 文字类数据,我觉得并不会缺少数据集(笑)。

在数据中添加噪声,或者平移缩放等操作在很多比赛以及网络中已经证明了,可以很好地提高模型的泛化能力

数据归一化

这是一个老生常谈的问题了,提前把数据进行归一化可以很好地防止梯度爆炸。在网络中,我们也可以设置激活函数(sigmoid、tanh等)对数据进行归一化。而激活函数也容易造成梯度消失的问题,我们可以更换激活函数,或者进行 normalize,这会在另一篇文章里面讨论。

数据本身

最后还有一个方法,就是从数据本身寻找问题。举个例子,老师职位和性别有关吗?车速和天气有关系吗?答案是否定的,所以要检查数据集中的某些特征是不是与我们要预测或分类的特征毫无关联,如果是的话就尽量抛弃。

另外,如果有其他的特征或者更加适合的方法,也需要对数据进行调整。

算法

其实在我的很多情况下,当无法采取某种特定的算法去进行数据处理的时候,便会采用深度学习其训练拟合(笑)。

选择算法

什么算法对于特定的问题效果最好,我们是没有办法也不可能知道的,只能取范围内最优,即当前使用的算法并不一定适合当前的问题。

如果没有头绪的话,可以从下面几点进行尝试:

  • 线性算法,如逻辑回归和线性判断分析
  • 树模型,如 CART、随机森林等
  • SVM 或 KNN 等算法
  • 神经网络模型,如 CNN、RNN、LSTM

然后根据经验和结果综合判断,选择目标模型进行调参或者优化,从而进一步提升效果。

之前比赛的时候有一个大佬的解法是训练两个网络进行对抗,这个算法拿了准确率第一,当时印象挺深刻的。

算法调优

调参是一个算法调优的必经之路,主要分为以下几点:

  • 模型可诊断性,模型总是处于两种状态,即欠拟合和过拟合之间,只是程度不同罢了。我们可以把 accuracy 和 loss 输出在图表中,从而作为一个有价值的诊断工具。
  • 权重的初始化,用小的随机数初始化权重。
  • 学习率,学习率决定了梯度下降时的范围,如果添加了更多的神经节点和网络层,就可加大学习率。这一点并不是独立的,与 batch size 等都有关系。
  • 激活函数,激活函数其实有很多种,而且每一种激活函数都有一段流行的时间,如今一般都会使用 ReLU 函数,但 ReLU 本身存在着死神经元的问题,然后又诞生了 Leaky ReLU。尝试不同的激活函数可能会有不同的效果。
  • 网络结构,网络的结构设计也会很大程度影响性能,在一般情况下,最好使用成熟的网络,或者尝试发表论文中的网络。
  • batch size 和 epoch,batch size 决定了梯度值以及权重的更新频率,一般设置的越大计算的速度就越快,反之越慢;epoch 则是样本参与训练的循环次数。
  • 正则项,这可以很好地解决过拟合,如 dropout。
  • 优化方法和损失函数,现在在梯度下降的过程中有许多优化器。默认的梯度下降方法是得到一个结果,然后调整动量值、学习率进行优化,而复杂的优化器则会有更多的参数设置,这需要多尝试去积累经验。
  • 提早结束训练,一旦效果变差了,可以及时停止优化训练。而这一部分可以直接通过 TensorFlow 或者 Pytorch 框架中的 checkpoint 功能,自动选择和保存相应的模型训练点。

宏观调整

最后边是调出神经网络这个视角,从宏观的角度出发,把神经网络作为一个个体去看待问题。

比如上文中所说的,通过两个网络之间的对抗提高准确率(GAN 网络就是这样的),以及最近有大神的网络暴力行为监测网络也一样,在神经网络外面套上了一个连坐的算法,即有暴力倾向的人其朋友圈的人也会有更大的概率有暴力倾向,说人话就是近朱者赤,近墨者黑。

所以,从宏观上进行调整,比如切换观察视角,加上限制条件的网络或者其他算法,甚至是想随机森林一样,通过多神经网络投票进行融合等。

尾巴

这是我的一些在学习过程中的小结,希望对大家有用。其实神经网络,或者说深度学习这方面,我们一直时站在巨人的肩膀上,不停有大佬创造出了更有效和更强大的网络模型,我们能够做的更多是择善而从。

我觉得最好能够把网络或者是算法做的更加模块化或者是耦合度更高,从而可以更加灵活多变。