最近拜读大神Karpathy的经验之谈 A Recipe for Training Neural Networks https://karpathy.github.io/2019/04/25/recipe/,这个秘籍对不少深度学习算法训练过程当中遇到的各自问题进行了总结,并提出了不少很好的建议,翻译于此,但愿可以帮助更多人学到这些内容。python
译文以下:git
几周前,我发布了一条关于“最多见的神经网络错误”的推文,列出了一些与训练神经网络相关的常见问题。这条推文获得了比我预期的要多得多的认同(包括网络研讨会:))。显然,不少人我的遇到了“卷积层是这样工做的”和“咱们的卷积网络达到最早进结果”之间的巨大差距。github
因此我认为若是清空我尘土飞扬的博客并将这个推文扩展到这个主题应该获得的长篇形式应该是有趣的事情。然而,与其列举常见的错误或深刻分析它们,我更想深刻挖掘并讨论如何避免出现这些错误(或者很是快速地修复它们)。这样作的关键是遵循某个过程,据我所知,这个过程并无文档记录下来。让咱们从促使我作这个的两个重要发现开始吧。算法
据称很容易开始训练神经网络。许多图书和框架都以展现了若是采用30行代码解决您的数据问题,并以此而自豪。这给你们一个很是错误的印象,即这些东西是即插即用。常见的示例代码以下:api
>>> 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。 咱们但愿对其进行训练,可视化损失,任何其余指标(例如准确度),模型预测,并在此过程当中使用明确的假设进行一系列实验。
这个阶段的须要注意的地方和建议主要包括: