神经网络在测试数据上的预测准确率仅为50%

我创建了一个神经网络,用于将输入数据(每个输入数据有400个特征)分类为五种阿拉伯方言之一。我将训练数据分为“训练数据”、“验证数据”和“测试数据”,使用net.divideFcn = 'dividerand';。我使用trainbr作为训练函数,这导致了长时间的训练,因为我的训练数据中有9000个元素。对于网络架构,我使用了两层,第一层有10个感知器,第二层有5个,因为我使用了一对多策略。网络训练通常以达到最小梯度结束,而不是最小误差。

如何让网络预测得更好?这是否是泛化问题(网络很好地学习了训练数据,但在新数据上的测试往往失败)?我是否应该在第一层增加更多的感知器?我问这个问题是因为当第一层有10个感知器时,训练网络需要大约一个小时,所以时间会增加。

这是我的网络代码:

[Test] = load('testData.mat');[Ex] = load('trainData.mat');Ex.trainVectors = Ex.trainVectors';Ex.trainLabels = Ex.trainLabels';net = newff(minmax(Ex.trainVectors),[10 5] ,{'logsig','logsig'},'trainlm','learngdm','sse');net.performFcn = 'mse';net.trainParam.lr = 0.01;net.trainParam.mc = 0.95;net.trainParam.epochs = 1000;net.trainParam.goal = 0;net.trainParam.max_fail = 50;net.trainFcn = 'trainbr';   net.divideFcn = 'dividerand';net.divideParam.trainRatio = 0.7;net.divideParam.valRatio = 0.15;net.divideParam.testRatio = 0.15;net = init(net);net = train(net,Ex.trainVectors,Ex.trainLabels);

谢谢!


回答:

与神经网络打交道是一种创造性的工作。因此,没有人能给你唯一正确的答案。但我可以根据自己的经验提供一些建议。

  1. 首先 – 检查训练结束时的网络误差(在训练和验证数据集上。在你开始使用测试数据集之前)。你说它是最小的,但它的实际值是多少?如果也是50%,那么我们可能有坏数据或错误的网络架构。
  2. 如果训练数据集的误差是可以接受的。下一步 – 让我们检查在验证步骤中你的网络系数的变化情况。以及这里的误差情况如何。如果它们发生了显著变化,那就是我们的架构有问题的信号:网络没有泛化能力,并且会在每个新数据集上重新训练。
  3. 在改变架构之前我们还能做些什么?我们可以改变训练轮数。有时我们可以得到好的结果,但这有点随机 – 我们必须确保在训练的最后几个步骤中系数的变化很小。但我记得nntool会自动检查这一点,所以我们可能可以跳过这一步。
  4. 我还想推荐你改变训练数据集。也许你知道rand在Matlab启动时总是给你相同的数字,所以如果你只创建了一次数据集,你可能会一直使用相同的集合。这个问题也与数据的非均匀性有关。可能你的数据的某些部分比其他部分更重要。所以如果一些不同的随机集合给出大致相同的误差,数据是可以的,我们可以继续。如果不是 – 我们需要处理数据并更仔细地分割它。有时我会避免使用dividerand,而是手动分割数据。
  5. 有时候我会尝试改变激活函数的类型。但你这里使用的是感知器…所以我的建议是 – 尝试使用sigma-或线性-神经元代替感知器。这很少会带来显著的改进,但可能会有所帮助。
  6. 如果所有这些步骤都不能给你足够的帮助,你就必须改变网络架构。首先要做的就是改变第一层的神经元数量。通常,当我处理神经网络时,我会花很多时间尝试不仅仅是不同数量的神经元,还有不同类型的网络。例如,我发现了一篇关于你这个话题的有趣文章Alberto Simões的文章链接。他们是这样说的:

关于隐藏层中单元的数量,有一些经验法则:在所有隐藏层中使用相同数量的单元,并且至少使用与类别数量和特征数量中的最大值相同的单元数量。但可以是该值的三倍。鉴于特征数量较多,我们选择在隐藏层中保持相同数量的单元。


来自评论的一些建议:数据分割方法(用于训练和测试数据集)取决于你的数据。例如,我处理过工业数据,发现数据集的最后部分技术参数(某些设备的压力)发生了变化。所以我必须获取两种操作模式的数据来训练数据集。但对于你的情况,我认为不会有相同的问题…我建议你尝试几个随机集合(只需确保它们确实不同!)。

为了测量网络误差,我通常会计算完整的误差向量 – 我训练网络,然后检查它对所有值的处理以获得完整的误差向量。这对于获得一些有用的视图(如直方图等)很有用,我可以看到我的网络在哪里出错了。将sse(或mse)接近零并不是必要的,甚至可能是有害的 – 通常这意味着你已经过度训练了网络。对于初步的近似,我通常会尝试在训练数据集上获得80-95%的正确值,然后在测试数据集上尝试网络。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注