【问题标题】:why is my Neural Network stuck at high loss value after the first epochs为什么我的神经网络在第一个时期后仍停留在高损失值
【发布时间】:2020-03-27 21:52:53
【问题描述】:

我正在使用神经网络进行回归。这对 NN 来说应该是一项简单的任务,我有 10 个特征和 1 个输出要预测。我在项目中使用 pytorch,但我的模型学习不好。损失从一个非常高的值(40000)开始,然后在前 5-10 个时期之后,损失迅速下降到 6000-7000,然后不管我做什么,它都卡在那里。我什至尝试更改为 skorch 而不是 pytorch,以便我可以使用交叉验证功能,但这也无济于事。我尝试了不同的优化器并向网络添加层和神经元,但这并没有帮助,它停留在 6000,这是一个非常高的损失值。我在这里做回归,我有 10 个特征,我试图预测一个连续值。这应该很容易做到,这就是为什么它让我更加困惑。

这是我的网络: 我在这里尝试了从制作更复杂的架构(例如添加层和单元到批量标准化、更改激活等)的所有可能性。没有任何效果

class BearingNetwork(nn.Module):
    def __init__(self, n_features=X.shape[1], n_out=1):
        super().__init__()
        self.model = nn.Sequential(

            nn.Linear(n_features, 512), 
            nn.BatchNorm1d(512),
            nn.LeakyReLU(),
            nn.Linear(512, 64),
            nn.BatchNorm1d(64),
            nn.LeakyReLU(),
            nn.Linear(64, n_out),
#             nn.LeakyReLU(),
#             nn.Linear(256, 128),
#             nn.LeakyReLU(),
#             nn.Linear(128, 64),
#             nn.LeakyReLU(),
#             nn.Linear(64, n_out)
        )

    def forward(self, x):
        out = self.model(x)
        return out

这是我的设置: 使用 skorch 比 pytorch 更容易。在这里,我还监控 R2 指标,并将 RMSE 作为自定义指标来监控模型的性能。我还为 Adam 尝试了 amsgrad,但这并没有帮助。

R2 = EpochScoring(r2_score, lower_is_better=False, name='R2')
explained_var_score = EpochScoring(EVS, lower_is_better=False, name='EVS Metric')
custom_score = make_scorer(RMSE)
rmse = EpochScoring(custom_score, lower_is_better=True, name='rmse')

bearing_nn = NeuralNetRegressor(

    BearingNetwork,
    criterion=nn.MSELoss,
    optimizer=optim.Adam,
    optimizer__amsgrad=True,
    max_epochs=5000,
    batch_size=128,
    lr=0.001,
    train_split=skorch.dataset.CVSplit(10),
    callbacks=[R2, explained_var_score, rmse, Checkpoint(), EarlyStopping(patience=100)],
    device=device

)

我还将输入值标准化。

我的输入具有以下形状:

torch.Size([39006, 10])

输出的形状是:

torch.Size([39006, 1])

我使用 128 作为我的 Batch_size,但我也尝试了其他值,如 32、64、512 甚至 1024。虽然标准化输出不是必需的,但我也尝试过,当我预测值时它不起作用,损失很高。请有人帮助我,我将不胜感激每一个有用的建议。我还将添加我的训练和验证损失以及 epoch 上的指标的屏幕截图,以可视化损失在前 5 个 epoch 中是如何减少的,​​然后它永远保持在 6000 的值,这是一个非常高的损失值。

【问题讨论】:

  • 您可以尝试添加一个nn.BatchNorm1d 层作为模型的第一层吗?这种变化对训练过程有什么影响吗?
  • @Shai 谢谢你的建议,我试过了,但没用
  • 您是否尝试过在单个示例上过度拟合您的模型并查看它是否有效(即您的损失为 0 或关闭)?
  • @ZaccharieRamzi 你说的单个例子是什么意思?如果您的意思是单一功能,是的,我这样做了,但没有用。损失一直停留在高值
  • 不不,只是对 10 个特征的一次观察,基本上你的x 的大小是(1, 10)。通过这种方式,您可以查看您的模型是否甚至能够过度拟合单个示例。如果它不能做到这一点,它就不太可能预测更多。

标签: neural-network deep-learning regression pytorch skorch


【解决方案1】:

随着您的损失从 40000 减少到 6000,这意味着您的 NN 模型已经学习了普遍的关系,但不是全部。您可以通过转换预测变量然后将它们作为派生变量提供给您的模型来帮助这种学习,看看是否有帮助。您可以尝试通过首先添加最有影响力的预测变量来逐步向您的 NN 模型添加特征。在每次迭代中评估模型性能(即训练损失)。

如果第一步没有帮助,并且您对其他方法持开放态度,那么假设您的数据动态、高斯过程回归或分位数回归应该会有所帮助,因为这些方法不受线性回归技术等假设的影响。它还应该有助于探索自变量和因变量之间关系的不同方面。

【讨论】:

    【解决方案2】:

    您应该查看的指标是 R^2,而不是损失函数的大小。损失函数的目的只是让优化器知道它是否朝着正确的方向前进——它不是一个可在数据集和学习设置之间进行比较的拟合度量。这就是 R^2 的用途。

    您的 R^2 分数表明您解释了输出中总方差的大约三分之一,对于只有 10 个特征的数据集,这通常是一个非常好的结果。实际上,鉴于您的数据的形状,您的隐藏层更有可能比必要的大得多,并且存在过度拟合的风险。

    要真正评估此模型,您需要知道 (1) R^2 分数与 OLS 等更简单的回归方法相比如何,以及 (2) 为什么您应该确信超过 30% 的输出方差应由输入变量捕获。

    对于#1,至少 R^2 不应该更糟。至于#2,请考虑规范数字分类示例。我们知道以非常高的准确度(即 R^2 接近 1)识别数字所需的所有信息,因为人类可以做到。其他数据集不一定是这种情况,因为有一些重要的方差来源没有在源数据中捕获。

    【讨论】:

    • 什么是OLS?它是 scikit learn 中的简单线性回归模型吗?我尝试了其他 ML 方法,只有 RandomForestRegressor 提供了更好的性能,但它也过度拟合了数据。在训练数据上,它给了我很小的损失和 88% 的分数(R2 分数),但对于验证数据,它给出了 48% 的分数,这比神经网络分数要好,而且损失值也更好,但我无法防止即使使用交叉验证也会过度拟合
    • 是的,OLS 是 ordinary least squares,通常用于简单的线性回归模型。这是一个很好的基线比较,应该避免过度拟合。训练时 0.88 的 R^2 到验证时 0.48 的 R^2 非常差,表明极度过拟合。随机森林或遗传编程方法可能会比 NN 预测得更好,但对于这个有限的数据集,应用显着的简约压力来解决过拟合问题会很有用。
    • 感谢您的回答,您能详细说明一下吗?我尝试了一个简单的线性回归,但它表现出很差的性能,训练数据上的 r2=0.006 和测试数据上的 0.004。我认为,由于它是线性回归,因此无济于事,因为我的数据具有很强的非线性。随机森林更好,但正如你所说,它过度拟合了数据。在你看来我接下来应该怎么做?
    • 要将 OLS 用于非线性数据,您需要对输入特征进行转换,例如 log(x)、sqrt(x),然后对这些特征进行回归。可视化残差通常有助于解决这个问题。然而,虽然生成的模型更易于理解,但这不会捕获/建模不连续性和特征间交互。
    • 如果您的数据不仅是非线性的,而且还具有不连续性和复杂的交互作用,那么随机森林和genetic programming 方法可能更合适。为了减少过度拟合,减少树的数量或应用“简约压力”。您还需要考虑在哪里停止,因为无法保证从数据集中提取更准确的预测是可能的,因为通常有许多未捕获的因果因素。但是,如果不知道数据是什么,就不可能对此发表评论。
    【解决方案3】:

    考虑到您的训练和开发损失随着时间的推移而减少,您的模型似乎正在正确训练。关于您对训练和开发损失值的担忧,这完全取决于您的目标值的规模(您的目标值有多大?)以及用于计算训练和开发损失的指标。如果您的目标值很大并且您想要更小的训练和开发损失值,您可以对目标值进行归一化。

    根据我收集到的关于您的实验和 R2 分数的信息,您似乎在错误的领域寻找解决方案。对我来说,考虑到您的 R2 分数很低,您的功能似乎不够强大,这可能意味着您有数据质量问题。这也可以解释为什么您的架构调整没有提高模型的性能,因为问题不是您的模型。所以如果我是你,我会考虑我可以添加哪些有用的新功能,看看是否有帮助。在机器学习中,一般规则是模型只与训练它们的数据一样好。我希望这有帮助!

    【讨论】:

    • 训练和开发损失正在减少,但是当它们达到 6000 时,即使经过 5000 个 epoch,它们仍会停留在那里,当它们改善时,速度会非常缓慢。标准化目标是不必要的,我会得到相同的损失值,但在其他尺度。那不会有任何改善!我的 R2 分数很低,因为我的模型不适合数据,也许你是对的,我的数据没有很强的关系,但据我所知,神经网络也可以适应如此复杂的非线性,还是我错了?我无法添加功能,这是我为这个项目拥有的唯一数据集,我必须忍受它
    • 你是对的,标准化不会改善你的模型。但这不是我提出它的原因。我提到它是因为您多次表示您的训练损失很高。这可能是因为目标值有多大。因此,通过标准化您的目标数据,您可以使用更小的值。可能有用的是将您的模型与同一任务中的其他模型进行比较,或者使用基线来查看您的模型与它的比较情况。只是看看你的模型实际上是否表现不佳。
    • 是的,我知道你是这个意思。我的目标值在 [0-360] 范围内,所以不是那么大。归一化目标可能会给出 [0-1] 或其他值之间的损失值,但在这种情况下,值 1 将非常糟糕。我不知道我还能做什么,我想我尝试了所有我可以尝试的事情。也许我可以尝试权重初始化,否则我不知道
    • 所有功能的缩放比例都相似吗?如果不是,我会将您的所有特征标准化为 0 到 1 之间,并对您的目标数据执行相同的操作。在评估预测时,您可以对预测进行非标准化。
    • 我试过了,但没有用。在缩放数据和目标之后,损失从 1.04 开始,然后开始减少,直到 0.7,然后卡在那里
    猜你喜欢
    • 2021-08-30
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 2020-10-17
    相关资源
    最近更新 更多