使用神经网络:调试清单

使用神经网络:调试清单

机器学习软件产品的代码通常很复杂并且相当混乱。 检测并消除其中的错误是一项资源密集型任务。 即使是最简单的 前馈神经网络 需要认真对待网络架构、权重初始化和网络优化。 一个小错误可能会导致不愉快的问题。

本文介绍的是一种用于调试神经网络的算法。

技能箱推荐: 实践课程 从零开始的Python开发者.

我们提醒: 对于“Habr”的所有读者 - 使用“Habr”促销代码注册任何 Skillbox 课程可享受 10 卢布的折扣。

该算法由五个阶段组成:

  • 轻松开始;
  • 确认损失;
  • 检查中间结果和连接;
  • 参数诊断;
  • 对工作的控制。

如果您觉得某些内容比其他内容更有趣,您可以立即跳到这些部分。

轻松开始

具有复杂架构、正则化和学习率调度器的神经网络比常规网络更难调试。 我们在这里有点棘手,因为这一点本身与调试间接相关,但这仍然是一个重要的建议。

一个简单的开始是创建一个简化的模型并在一组(点)数据上对其进行训练。

首先我们创建一个简化的模型

为了快速开始,我们创建一个具有单个隐藏层的小型网络,并检查一切是否正常工作。 然后我们逐渐使模型复杂化,检查其结构的每个新方面(附加层、参数等),然后继续。

我们在一组(点)数据上训练模型

作为对项目的快速健全性检查,您可以使用一两个数据点进行训练,以确认系统是否正常工作。 神经网络必须在训练和测试中表现出 100% 的准确性。 如果情况并非如此,则要么模型太小,要么您已经存在错误。

即使一切顺利,也要在继续之前为一个或多个时期准备好模型。

损失评估

损失估计是完善模型性能的主要方法。 您需要确保损失适合问题,并且损失函数按照正确的尺度进行评级。 如果您使用多种损失类型,请确保它们的阶数相同并且比例正确。

注意初始损失很重要。 如果模型以随机猜测开始,请检查实际结果与预期结果的接近程度。 在 安德烈·卡帕蒂 (Andrey Karpathy) 的研究表明::“当您从少量参数开始时,请确保获得预期的结果。 最好立即检查数据丢失情况(将正则化程度设置为零)。 例如,对于具有 Softmax 分类器的 CIFAR-10,我们预计初始损失为 2.302,因为每个类别的预期扩散概率为 0,1(因为有 10 个类别),而 Softmax 损失是正确类别的负对数似然as − ln (0.1) = 2.302。”

对于二进制示例,只需对每个类进行类似的计算。 例如,这里的数据是:20% 为 0,80% 为 1。 预期初始损失将高达 –0,2ln (0,5) –0,8ln (0,5) = 0,693147。 如果结果大于1,则可能表明神经网络权重未适当平衡或数据未标准化。

检查中间结果和连接

要调试神经网络,有必要了解网络内过程的动态以及各个中间层连接时的作用。 以下是您可能遇到的常见错误:

  • gradle 更新的表达式不正确;
  • 不应用权重更新;
  • 梯度爆炸。

如果梯度值为零,这意味着优化器中的学习速率太慢,或者您遇到更新梯度的不正确表达式。

此外,还需要监控每一层的激活函数、权重和更新的值。 例如,参数更新的幅度(权重和偏差) 应该是 1-e3.

有一种现象称为“Dying ReLU”或 “梯度消失问题”,当 ReLU 神经元在学习其权重的大负偏差值后将输出零。 这些神经元在数据中的任何点都不会再次被激发。

您可以使用梯度检查来通过使用数值方法近似梯度来识别这些错误。 如果它接近计算的梯度,则反向传播已正确实现。 要创建梯度检查,请查看 CS231 中的这些优秀资源 这里 и 这里以及 安德鲁·恩加(Andrew Nga)谈到了这个话题。

费赞·谢赫 表示可视化神经网络的三种主要方法:

  • 预备部分是简单的方法,向我们展示训练模型的一般结构。 其中包括神经网络各层的形状或滤波器的输出以及每层内的参数。
  • 基于激活。 在其中,我们破译单个神经元或神经元组的激活以了解它们的功能。
  • 基于梯度。 这些方法倾向于操纵由模型训练的前向和后向传递形成的梯度(包括显着性图和类激活图)。

有几种有用的工具可用于可视化各个层的激活和连接,例如 康克斯 и 张量板.

使用神经网络:调试清单

参数诊断

神经网络有很多相互影响的参数,这使得优化变得复杂。 实际上,本节是专家们积极研究的主题,因此以下建议仅应被视为建议和构建的起点。

包装尺寸 (批量大小)- 如果您希望批量大小足够大以获得准确的误差梯度估计,但又足够小以便随机梯度下降 (SGD) 能够正则化您的网络。 小批量会由于训练过程中的噪声而导致快速收敛,从而导致优化困难。 这有更详细的描述 这里.

学习率 - 太低将导致收敛缓慢或陷入局部最小值的风险。 同时,高学习率会导致优化发散,因为你可能会跳过损失函数深而窄的部分。 在训练神经网络时尝试使用速度调度来减少它。 已更新至 CS231n 有很大一部分专门讨论这个问题.

渐变剪裁  — 在反向传播期间以最大值或边际范数修剪参数梯度。 对于解决第三点中可能遇到的任何梯度爆炸问题很有用。

批量归一化 - 用于对每一层的输入数据进行归一化,这使我们能够解决内部协变量偏移的问题。 如果您同时使用 Dropout 和 Batch Norma, 查看这篇文章.

随机梯度下降 (SGD) — SGD 有多种使用动量、自适应学习率和 Nesterov 方法的变体。 然而,它们在学习效率和泛化能力方面都没有明显的优势(详情在这里).

正则化 - 对于构建可推广的模型至关重要,因为它会增加模型复杂性或极端参数值的惩罚。 这是一种减少模型方差而不显着增加其偏差的方法。 更多的 详细信息 - 这里.

要自己评估一切,您需要禁用正则化并自己检查数据丢失梯度。

辍学 是简化网络以防止拥塞的另一种方法。 在训练期间,仅通过以一定概率p(超参数)维持神经元的活动或在相反情况下将其设置为零来进行dropout。 因此,网络必须为每个训练批次使用不同的参数子集,从而减少某些成为主导参数的变化。

重要提示:如果您同时使用 dropout 和批量归一化,请注意这些操作的顺序,甚至将它们一起使用。 这一切仍在积极讨论和补充中。 以下是关于该主题的两个重要讨论 在 Stackoverflow 上 и Arxiv.

工作控制

这是关于记录工作流程和实验。 如果您不记录任何内容,您可能会忘记例如使用的学习率或类别权重。 通过控制,您可以轻松查看和重现以前的实验。 这可以让您减少重复实验的数量。

然而,在工作量很大的情况下,手动记录可能会成为一项艰巨的任务。 这就是像 Comet.ml 这样的工具可以帮助您自动记录数据集、代码更改、实验历史记录和生产模型的地方,包括有关模型的关键信息(超参数、模型性能指标和环境信息)。

神经网络可能对微小的变化非常敏感,这将导致模型性能下降。 跟踪和记录您的工作是标准化您的环境和建模的第一步。

使用神经网络:调试清单

我希望这篇文章可以成为您开始调试神经网络的起点。

技能箱推荐:

来源: habr.com

添加评论