当前位置: 首页 > 科技观察

小心训练模型,少数据也能玩深度学习

时间:2023-03-17 21:56:53 科技观察

最近,JeffLeek在SimplyStats上发表了一篇题为“Don'tusedeeplearningifyourdatavolumeisnotlargeenough”的文章(Don'tusedeeplearningyourdataisn'tthatbig)一文(见文末链接),相信只有获得了谷歌和Facebook这种规模数据的人才有资格进行深度学习。AndrewL.Beam(本文作者)并不反对这一点,他认为这让我们清醒地认识到深度学习并不是万能的;很多东西都不清楚或不清楚,Beam认为深度学习只要认真训练模型,就可以用在小数据设置中。机器之心对本文进行了整理,原文链接在文末。JeffLeek基于MNIST数据集使用两种方法对手写字体进行分类。他比较了五层神经网络系统(激活函数使用双曲正切)和Leekasso,后者仅使用10个边缘p值最小的像素块。他令人惊讶地表明,Leekasso在使用少量样本时优于神经网络。是不是如果你的样本量小于100,你就不能使用深度学习,因为模型会过度拟合并给出很差的性能?可能是这样,深度学习模型非常复杂,训练技巧很多,我总感觉模型收敛性/复杂度训练不足可能是性能差的原因,不是过拟合。深度学习VS。LeekassoRedux的第一件事就是使用这个数据集构建深度学习模型,它是现代版的多层感知器(MLP)和卷积神经网络(CNN)。如果Leek的文章是正确的,那么当只有少量样本时,这些模型应该严重过拟合。我们构建了一个带有RELU激活函数的简单MLP和一个像VGG这样的卷积模型,然后我们将它们的性能与Leekasso进行了比较。所有代码都可以下载:https://github.com/beamandrew/deep_learning_works/blob/master/mnist.pyMLP模型非常标准:CNN模型也与上一个非常相似:供参考,MLP大约有12万个参数,而CNN大约有20万个参数。按照最初的假设,当我们有这么多参数和少量样本时,模型似乎真的会出错。为了尽可能接近原始分析,我们使用了5折交叉验证,但使用标准MNIST测试集进行评估(约2000个测试样本)。我们将测试集分为两部分,上半部分用于评估训练过程的收敛性,而下半部分用于衡量样本外预测的准确性。我们甚至没有调整模型,只是对大多数超参数使用了合理的默认值。我们尽可能地从原始论文中重构了Leekasso和MLP的Python版本。代码可以在这里下载:https://github.com/beamandrew/deep_learning_works/blob/master/mnist.py以下是每个模型的样本精度:这两个模型的精度与原始分析有很大不同,使用原始分析中针对小样本的MLP仍然表现不佳,但我们的神经网络在广泛的样本大小范围内实现了非常好的准确性。为什么是这样?众所周知,深度学习模型的训练往往对细节要求极高,懂得“调参”是一项非常重要的技能。调整许多超参数是一个非常具体的问题(尤其是关于SGD超参数),错误地调整参数会导致整个模型的性能大幅下降。如果您正在构建深度学习模型,请务必记住模型的细节非常重要,您需要小心任何看起来像深度学习的黑盒模型。以下是我对原模型问题的猜测:激活函数很重要,tanh神经网络很难训练。这就是为什么激活函数在很大程度上转而使用像“RELU”这样的函数。确保随机梯度下降是收敛的。在最初的比较中,模型只训练了20个epoch,这可能还不够。因为当n=10个样本时,20个epoch只有20*10=200次梯度迭代更新。遍历整个MNIST数据集相当于大约60,000次梯度更新,更常见的是数百到数千次遍历(大约数百万次梯度更新)。如果我们只进行200次梯度更新,那么我们需要比较大的学习率,否则模型不会收敛。h2o.deeplearning()的默认学习率为0.005,对于少量更新来说太小了。而我们使用的模型需要训练200个epoch,在前50个epoch内,我们可以看到样本准确率有了很大的提高。所以我猜测模型缺乏收敛性可以解释两者样本精度的巨大差异。始终检查超参数的默认值。Keras之所以这么好,是因为它的默认参数值通常反映了当前最好的训练,但同时我们也需要保证选择的参数适合我们的问题。不同的框架可能会产生截然不同的结果。我尝试使用原始R代码来查看是否可以得到类似的结果。但是,我无法使用h2o.deeplearning()函数获得良好的结果。我猜想可能和它使用的优化过程有关。好像是用elasticmeanSGD来计算多个节点来加速训练。当你只有一小部分数据样本时,我不知道这是否是一个小故障,但我认为这很有可能。幸运的是,RStudio的优秀人员刚刚发布了一个与Keras的R接口:https://rstudio.github.io/keras/所以我可以在R中完全重建我的Python代码。我们之前在R中使用MLP完成了这个:我将其放入Jeff的R代码中并重新生成了原始图形。我稍微修改了Leekasso。原始代码使用lm()(即线性回归),我觉得这很奇怪,所以我切换到glm()(即逻辑回归)。新图看起来像这样:深度学习真棒!类似的现象可以解释Leekasso的Python和R版本之间的差异。逻辑回归的Python版本使用liblinear作为其求解器,我认为它比R的默认求解器更可靠。这可能会产生影响,因为Leekasso选择的变量是高度共线的。这个问题太简单了,无法说明任何有意义的事情。我重新运行了Leekasso,但只使用了最好的预测器,结果几乎与完整的Leekasso相同。事实上,我确信我可以在不使用数据的情况下做出高精度的分类器。只要取它的中心像素,如果它是黑色就预测1,否则预测0,正如DavidRobinson指出的那样:David还指出,大多数数字对都可以通过单个像素进行分类。所以,这个问题很可能不会让我们对“真实”的小数据场景有任何洞察,我们应该对其结论持适当的怀疑态度。关于为什么深度学习有效的误解最终,我想回到Jeff在文章中提出的观点,尤其是这个陈述:问题是只有少数企业实际上有足够的数据来进行深度学习,[...]但我认为经常想到的是,在更简单的模型上使用深度学习的主要优势是,如果你有很多数据,你可以拟合很多参数。这篇文章,尤其是第一部分,在我看来并不完整。很多人似乎认为深度学习是一个巨大的黑盒子,里面有大量的参数,只要你有足够的数据,它就可以学习任何功能。神经网络当然非常灵活,这种灵活性是它们成功的部分原因,但不是全部,不是吗?毕竟,这种超级灵活的模型在机器学习和统计领域已有70多年的历史。我不认为神经网络是先验的,也不认为它们比相同复杂度的其他算法更灵活。这是我对其成功原因的总结:一切都是偏差/方差权衡的练习。更明确地说,我认为Jeff真正在做的是关于模型复杂性和偏差/方差权衡。如果您没有大量数据,训练简单模型(高偏差/低方差)可能比复杂模型(低偏差/高方差)效果更好。客观地说,这在大多数情况下是个好建议,但是……神经网络有很多防止过度拟合的技术。神经网络有很多参数,根据Jeff的说法,如果我们没有足够的数据来可靠地估计这些参数值,就会导致高方差。我们很清楚这个问题,并开发了许多减少方差的技术。例如,dropout与随机梯度下降相结合会导致像bagging这样的糟糕过程,但这发生在网络参数上,而不是输入变量上。诸如dropout之类的方差减少技术以其他模型难以复制的方式融入到训练过程中。这允许您训练非常大的模型,即使没有太多数据。深度学习允许您轻松地将特定于问题的约束直接合并到模型中以减少方差。这是我想说的最重要的一点,也是我们之前经常忽略的一点。由于它们的模块化,神经网络允许您真正集成强约束(先验),从而大大减少模型的方差。一个很好的例子是卷积神经网络。在CNN中,我们实际上将图像的属性编码到模型本身中。例如,当我们指定一个大小为3x3的过滤器时,我们实际上是在直接告诉网络,局部连接像素的小簇将包含有用的信息。此外,我们还可以直接将图像的平移和旋转不变性编码到模型中。所有这些都使模型偏向于图像属性,以大大减少方差并提高预测性能。您不需要拥有Google的海量数据。以上意味着即使每人100到1000个样本也可以从深度学习中获益。使用所有这些技术,我们可以改进方差问题并仍然受益于它的灵活性。您甚至可以通过迁移学习创造其他工作。总而言之,我认为上述原因很好地解释了为什么深度学习在实践中有效,打破了深度学习需要大量参数和数据的假设。***,本文并不是说Jeff的观点是错误的,而是提供一个不一样的新视角,给读者以启发。原文:http://beamandrew.github.io/deeplearning/2017/06/04/deep_learning_works.html【本文为《机器之心》专栏原文翻译,微信公众号《机器之心》(id:almosthuman2014)》】点此阅读该作者更多好文