最近拜读大神Karpathy的经验之谈 A Recipe for Training Neural Networks https://karpathy.github.io/2019/04/25/recipe/,这个秘籍对很多深度学习算法训练过程中遇到的各自问题进行了总结,并提出了很多很好的建议,翻译于此,希望能够帮助更多人学到这些内容。
译文如下:
几周前,我发布了一条关于“最常见的神经网络错误”的推文,列出了一些与训练神经网络相关的常见问题。这条推文得到了比我预期的要多得多的认同(包括网络研讨会:))。显然,很多人个人遇到了“卷积层是这样工作的”和“我们的卷积网络达到最先进结果”之间的巨大差距。
所以我认为如果清空我尘土飞扬的博客并将这个推文扩展到这个主题应该得到的长篇形式应该是有趣的事情。然而,与其列举常见的错误或深入分析它们,我更想深入挖掘并讨论如何避免出现这些错误(或者非常快速地修复它们)。这样做的关键是遵循某个过程,据我所知,这个过程并没有文档记录下来。让我们从促使我做这个的两个重要发现开始吧。
据称很容易开始训练神经网络。许多图书和框架都以展示了如果采用30行代码解决您的数据问题,并以此而自豪。这给大家一个非常错误的印象,即这些东西是即插即用。常见的示例代码如下:
>>> your_data = # 导入数据 >>> model = SuperCrossValidator(SuperDuper.fit, your_data, ResNet50, SGDOptimizer) # 由此征服世界这些
这些库和示例激活了我们大脑里面熟悉标准软件的部分 - 通常它们认为干净和抽象的API是可以轻易获得的。 比如,后面的功能可以采用如下调用:
>>> r = requests.get(‘https://api.github.com/user‘, auth=(‘user‘, ‘pass‘)) >>> r.status_code 200
这很酷! 一个勇敢的开发人员已经承担了理解查询字符串,URL,GET / POST请求,HTTP连接等等的负担,并且在很大程度上隐藏了几行代码背后的复杂性。 这恰恰是我们熟悉和期待的。 不幸的是,神经网不是那样的。 它们不是“现成的”技术,第二个与训练ImageNet分类器略有不同。 我试图在我的帖子“是的你应该理解反向传播”中通过反向传播的例子说明这一点,并将其称为“漏洞抽象”,但不幸的是情况更加可怕。 Backprop + SGD并没有神奇地让你的网络正常工作。 Batch Norm也不会神奇地使其收敛得更快。RNN不会神奇地让你“插入”文本。 只是因为你可以将你的问题采用增强学习来建模,并不意味着你应该如此。 如果您坚持使用该技术而不了解其工作原理,则可能会失败。 这让我想到......
当您写错或错误配置代码时,您通常会遇到某种异常。你输入了一个整数,但这本来应该是一个字符串的!某函数只需要3个参数!导入失败!键值不存在!两个列表中的元素个数不相等。此外,通常不会为特定功能创建单元测试。
解决了这些问题,也只是训练神经网络的开始。一切都可以在语法上正确,但整个训练没有妥善安排,而且很难说清楚。 “可能的错误面”是很大的,逻辑(与语法相反)层面的问题,并且对单元测试非常棘手。例如,在数据增强期间左右翻转图像时,您可能忘记翻转数据标签。您的网络仍然可以(令人震惊地)工作得非常好,因为您的网络可以在内部学习检测翻转的图像,然后左右翻转其预测。或许你的自回归模型会因为一个偶然错误而意外地将它想要预测的东西作为输入。或者你想要修剪你的梯度但是修剪了损失,导致在训练期间异常样本被忽略。或者您从预训练模型初始化了您的权重,但没有使用原始均值。或者你只是用错了正则化权重,学习率,衰减率,模型大小等。因此,错误设置的神经网络只有在你运气好的时候才会抛出异常;大部分时间它会训练,但默默地输出看起来有点糟糕的结果。
因此,“快速和激烈”方法训练的神经网络并不能发挥其作用,我们只会遭受其痛苦。 现在,痛苦是让神经网络运作良好的一个非常自然的过程,但可以通过对训练过程中的所有细节了然于胸来减轻训练过程的折磨。 在我的经验中,与深度学习成功最相关的品质是耐心和对细节的关注。
鉴于上述两个事实,我已经为自己开发了一个特定的过程,使我能够将神经网络应用于新问题。稍后我会竭力描述如何做到的。 你会发现它非常重视上述两个原则。 特别是,它遵循从简单到复杂的规律,并且在每一步我们对将要发生的事情做出具体假设,然后通过实验验证它们或进行检查直到我们发现了问题。 我们试图防止的是同时引入了许多复杂“未经验证的”问题,这必然会导致需要花很多时间去查找的错误/错误配置。 如果编写您的神经网络代码就像训练一样,您需要使用非常小的学习速率并猜测,然后在每次迭代后评估整个的测试集。
训练神经网络的第一步是根本不是接触任何神经网络代码,而是从彻底检查数据开始。这一步至关重要。我喜欢花费大量时间(以小时为单位)扫描数千个示例,了解它们的分布并寻找模式。幸运的是,你的大脑非常擅长这一点。有一次我发现了数据中包含重复的例子。另一次我发现了错误的图像/标签对。我通常会寻找不均衡的数据,也会关注自己对数据的分类过程,这些过程暗示了我们最终会尝试的各种架构。例如 -我们需要局部特征还是全局上下文?数据有多少变化,这些变化采取什么形式?什么变化是假的,是可以预处理的?空间位置是否重要,或者我们是否想要将其平均化?细节有多重要,我们可以在多大程度上对图像进行下采样?标签有多少噪声?
此外,由于神经网络实际上可以看作压缩/编译的数据集,因此您将能够查看网络的(错误)预测并了解它们的来源。如果你的网络给你的预测看起来与你在数据中看到的内容不一致,那么就会有所收获。
一旦获得定性的感知,编写一些简单的代码来搜索/过滤/排序也是一个好主意,无论你能想到什么(例如标签的类型、大小、数量等),并可视化它们的分布,和沿任何坐标轴的异常值。异常值尤其能揭示数据质量或预处理中的一些错误。
当我们了解了数据之后,我们可以采用我们超级精彩的多尺度ASPP FPN ResNet训练牛X的模型吗? 答案是不。 这是一条充满痛苦的道路。 我们的下一步是建立一个完整的训练+评估框架,并通过一系列实验验证其正确性。在这个阶段,最好选择一些你能正确使用的简单模型 - 例如 线性分类器,或非常小的ConvNet。 我们希望对其进行训练,可视化损失,任何其他指标(例如准确度),模型预测,并在此过程中使用明确的假设进行一系列实验。
这个阶段的需要注意的地方和建议主要包括:
A Recipe for Training Neural Networks [中文翻译, part 1]
原文:https://www.cnblogs.com/xueliangliu/p/10775751.html