【问题标题】:What is the reason for very high variations in val accuracy for multiple model runs?多个模型运行的 val 准确度差异很大的原因是什么?
【发布时间】:2020-10-26 11:13:17
【问题描述】:

我有一个 2 层神经网络,我正在对大约 10000 个特征(基因组数据)进行训练,我的数据集中有大约 100 个样本。现在我意识到,无论何时我运行我的模型(即编译和拟合),即使我保持训练/测试/验证拆分不变,我也会得到不同的验证/测试准确性。有时约为 70%,有时约为 90%。

由于 NN 的随机性,我预计会有一些变化,但这些强烈的波动是否可能是其他迹象?

【问题讨论】:

  • 当您尝试不同的优化器时,这种行为会改变吗?
  • 你的模型训练了多少个 epoch?如果只是少数,您可能看到的差异可能是由于随机初始化造成的。另一个候选者是优化器的学习率。对于具有数万个参数的神经网络来说,100 个样本是非常少的。因此,您可能需要以相对较高的学习率(例如 1e-2 左右)运行 500 个 epoch,才能看到运行之间的一致性。
  • @MichaelJanz 优化器究竟如何影响 val acc 的变化?我尝试了一些不同的优化器,但没有发现差异。验证 acc 至少波动 +/-8。
  • @Addy 根据学习率,我在 epoch 上尝试了不同的数字,以避免训练准确度一直上升到 100%。学习率高则少,反之亦然。我也运行了 50 个 epoch,但仍然看到波动。如果我以高学习率尝试 500,我不会严重过度拟合神经网络吗?或者你是什么意思?
  • 你能分享一下训练/验证/测试数据集的大小吗?你的层的大小(我想那些是密集层)和你的输出是多少?此外,您是否实现了一致的训练精度?

标签: tensorflow neural-network training-data genome


【解决方案1】:

您的验证准确性出现如此大的不稳定性是因为与您训练它的数据相比,您的神经网络非常庞大。

即使每层只有 12 个神经元,您的第一层仍然有 12 * 10000 + 12 = 120012 参数。现在想想神经网络在幕后做了什么。它需要您的 10000 个输入,它将每个输入乘以某个权重,然后将所有这些输入相加。现在您只提供了 64 个训练示例,训练算法应该在这些示例上决定正确的输入权重。仅凭直觉,从纯组合的角度来看,将有大量的权重分配在您的 64 个训练样本上表现良好。而且您无法保证训练算法会选择在您的样本外数据上表现良好的权重分配。

鉴于神经网络能够表示多种函数(已证明在某些假设下它可以逼近任何函数,这称为一般逼近)。要选择您想要的函数,您需要为训练算法提供数据,以将网络可以表示的所有可能函数的空间限制为适合您的数据的函数子空间。然而,这样的函数并不能保证代表输入和输出之间真正的潜在关系。特别是如果参数的数量大于样本的数量(在这种情况下是几个数量级),您几乎可以保证看到您的网络只是简单地记住了训练数据中的样本,这仅仅是因为它具有容量这样做,你没有足够的约束。

换句话说,您看到的是过度拟合。在 NN 中,一般的经验法则是,您需要的样本至少比您拥有的参数多几倍(查看 Hoeffding 不等式以了解其理论原理),实际上,您拥有的样本越多,您的样本就越少。又怕过拟合。

所以这里有几个可能的解决方案:

  1. 使用更适合输入维度高、样本数少的情况的算法,例如 Kernel SVM(支持向量机)。由于样本数如此之低,Kernel SVM 算法很有可能实现更好、更一致的验证准确度。 (你可以很容易地对此进行测试,它们在 scikit-learn 包中,非常易于使用)

  2. 如果您坚持使用 NN - 使用正则化。鉴于您已经有工作代码,这很容易,只需将 kernel_regularizer 添加到您的所有层,我会尝试 L1 和 L2 正则化(可能分别)。 L1 正则化倾向于将权重推到零,因此它可能有助于减少问题中的参数数量。 L2 只是试图使所有的权重都变小。使用您的验证集来确定每个正则化的最佳值。您可以优化验证数据的最佳平均准确度和最低准确度方差(对 L1 和 L2 正则化的每个参数值进行 20 次训练运行,通常只尝试不同的数量级就足够了,例如 1e- 4、1e-3、1e-2、1e-1、1、1e1)。

  3. 如果您的大多数输入特征不是真正具有预测性或高度相关,则可以使用 PCA(主成分分析)将您的输入投影到低得多的维度空间(例如从 10000 到 20),您可以在其中d 有更小的神经网络(我仍然会使用 L1 或 L2 进行正则化,因为即使那样你的权重也会比训练样本多)

最后一点,测试集的重点是非常稀疏地使用它(理想情况下只使用一次)。在完成所有研究和模型调整后,它应该是最终报告的指标。你不应该优化它的任何值。您应该在验证集上执行所有这些操作。为避免过度拟合您的验证集,请查看 k 折交叉验证。

【讨论】:

  • 这里有高质量的答案
  • 非常感谢您的详尽回答和解释!!我确实需要一个NN。不幸的是,我已经尝试过 PCA 并且得到了更差的训练准确度,而验证准确度的变化没有改变。刚刚尝试了正则化,但这也没有带来任何真正的改进。当我进行 k 折交叉验证以避免过度拟合 val 数据时,我观察到第一折中的 vadliation 准确度始终是迄今为止最低的(例如 30% 与 85% 的平均值甚至更差)。您可能知道这可能是由于什么原因吗?
  • 这是因为您在每个拆分中的数据非常少,我希望看到验证准确度出现如此巨大的变化,所以没关系。当您说您尝试过正则化但没有帮助时,您的意思是什么?你到底试过什么?我基本上会增加正则化常数,直到我在训练和验证数据上看到类似的准确性。只要您在训练集上看到 100%,就可以确定自己过度拟合(如果数据是真实世界的数据,而不是合成数据)。
  • 实际上我的数据没有被洗牌有问题。但我仍然看到相当大的变化。通过 20 折交叉验证,我得到基本模型所有折叠的平均验证准确度为 81% +/- 17%。我尝试了 l1 和 l2 从 1 到 0,00001 的惩罚,甚至尝试将 l2 与 dropout 层相结合,但我得到相似或更差的验证准确度。波动/发展范围从 +/-11% 到 +/-22%。即使在相同参数配置的多次交叉验证运行之间,+/- dev 也会出现波动。
  • 正如我所说,您看到的变化与样本数量一致,我希望这样的结果。通过 20 次运行,我并不是指 20 倍的 CV,而是例如4 倍 CV 运行 20 次。 20 倍的 CV 是不合理的,因为如果你有 81 个训练样本,这意味着你在每个验证拆分中有 2 个样本,这太少了。想一想你实际测量的是什么以及有多少样本,当然这些指标会很嘈杂。你能报告你的批量大小、历元数、优化器和学习率吗?事实上,你可以发布你的训练脚本吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
  • 2020-07-14
  • 2016-12-26
  • 2021-03-17
  • 2020-02-12
  • 2018-07-20
相关资源
最近更新 更多