在神经网络开始在训练数据上表现可接受之前的隐藏层数、隐藏层中的单元数和历元数

Posted

技术标签:

【中文标题】在神经网络开始在训练数据上表现可接受之前的隐藏层数、隐藏层中的单元数和历元数【英文标题】:No. of hidden layers, units in hidden layers and epochs till Neural Network starts behaving acceptable on Training data 【发布时间】:2012-09-28 08:38:13 【问题描述】:

我正在尝试使用神经网络解决这个Kaggle Problem。我正在使用 Pybrain Python 库。

这是一个经典的监督学习问题。在以下代码中:“数据”变量是 numpy 数组(892*8)。 7 个字段是我的特征,1 个字段是我的输出值,可以是“0”或“1”。

from pybrain.datasets import ClassificationDataSet
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.tools.shortcuts import buildNetwork

dataset = ClassificationDataSet(7,1)
for i in data:
    dataset.appendLinked(i[1:],i[0])
net = buildNetwork(7,9,7,1, bias = True,hiddenclass = SigmoidLayer, outclass = TanhLayer)
trainer = BackpropTrainer(net, learningrate = 0.04, momentum = 0.96, weightdecay = 0.02, verbose = True)
trainer.trainOnDataset(dataset, 8000)
trainer.testOnData(verbose = True)

训练我的神经网络后,当我在训练数据上对其进行测试时,它总是为所有输入提供一个输出。喜欢:

Testing on data:
out:     [  0.075]
correct: [  1.000]
error:  0.42767858
out:     [  0.075]
correct: [  0.000]
error:  0.00283875
out:     [  0.075]
correct: [  1.000]
error:  0.42744569
out:     [  0.077]
correct: [  1.000]
error:  0.42616996
out:     [  0.076]
correct: [  0.000]
error:  0.00291185
out:     [  0.076]
correct: [  1.000]
error:  0.42664586
out:     [  0.075]
correct: [  1.000]
error:  0.42800026
out:     [  0.076]
correct: [  1.000]
error:  0.42719380
out:     [  0.076]
correct: [  0.000]
error:  0.00286796
out:     [  0.076]
correct: [  0.000]
error:  0.00286642
out:     [  0.076]
correct: [  1.000]
error:  0.42696969
out:     [  0.076]
correct: [  0.000]
error:  0.00292401
out:     [  0.074]
correct: [  0.000]
error:  0.00274975
out:     [  0.076]
correct: [  0.000]
error:  0.00286129

我尝试改变 learningRate、weightDecay、动量、隐藏单元的数量、隐藏层的数量、隐藏层的类别、输出层的类别以便解决它,但在每种情况下,如果输入,它会为每个输入提供相同的输出来自训练数据。

我认为我应该运行它超过 8000 次,因为当我为“异或”构建神经网络时,它至少需要 700 次迭代才能开始给出纳米级的错误。 'XOR' 上的训练数据大小仅为 4,而在本例中为 892。所以我在 10% 的原始数据上运行了 8000 次迭代(现在训练数据的大小为 89),即使这样它为每个输入提供相同的输出在训练数据中。而且由于我想将输入分类为'0'或'1',如果我使用输出层的类作为Softmax,那么它总是给出'1'作为输出。

无论我在“异或”中使用哪种配置(隐藏单元的数量、输出层的类别、学习率、隐藏层的类别、动量),它在每种情况下都或多或少地开始收敛。

有可能某些配置最终会产生较低的错误率。至少进行一些配置,这样它就不会为训练数据中的所有输入提供相同的输出。

我运行了 80,000 次迭代(训练数据大小为 89)。输出样本:

Testing on data:
out:     [  0.340]
correct: [  0.000]
error:  0.05772102
out:     [  0.399]
correct: [  0.000]
error:  0.07954010
out:     [  0.478]
correct: [  1.000]
error:  0.13600274
out:     [  0.347]
correct: [  0.000]
error:  0.06013008
out:     [  0.500]
correct: [  0.000]
error:  0.12497886
out:     [  0.468]
correct: [  1.000]
error:  0.14177601
out:     [  0.377]
correct: [  0.000]
error:  0.07112816
out:     [  0.349]
correct: [  0.000]
error:  0.06100758
out:     [  0.380]
correct: [  1.000]
error:  0.19237095
out:     [  0.362]
correct: [  0.000]
error:  0.06557341
out:     [  0.335]
correct: [  0.000]
error:  0.05607577
out:     [  0.381]
correct: [  0.000]
error:  0.07247926
out:     [  0.355]
correct: [  1.000]
error:  0.20832669
out:     [  0.382]
correct: [  1.000]
error:  0.19116165
out:     [  0.440]
correct: [  0.000]
error:  0.09663233
out:     [  0.336]
correct: [  0.000]
error:  0.05632861

平均误差:0.112558819082

('最大误差:',0.21803000849096299,'中值误差:',0.096632332865968451)

它给出范围内的所有输出(0.33, 0.5)。

【问题讨论】:

为什么报告的错误不匹配|out-correct|?此外,您是否尝试过训练超过 8000 次迭代?您尝试过的隐藏节点数量最多是多少? 我尝试了 2 个隐藏层,每个隐藏层有 11 个节点。它无法进行 8000 次迭代。现在我正在使用具有 9 个和 7 个节点的 2 个隐藏层并运行 80,000 次迭代,它已经运行了大约 3 个小时,一旦完成就会报告结果,虽然看着 Total Error,我真的不认为它会是好点。很抱歉,我不知道为什么报告的错误与 |out-correct| 不匹配。 我已经用运行 80,000 次迭代的结果更新了问题。 似乎是一个明显的改进。我得到的印象是权重开始时非常低,可能为零,这意味着数据集中的标签应该是 -1 和 1,而不是 0 和 1。你可以做的另一件事是打印平均误差在每 x 次训练迭代之后,看看它是如何演变的。 尝试从 0.2-0.4 的学习率开始,时间减少与当前 epoch (LR * (N - i)/N) 成正比。界限是什么?我想它们因不同的功能而有所不同?然后将它们归一化到相同的范围内。在所有网络中使用 Sigmoid 或 Tanh 层。如果您将使用 Sigmoid - 保留 0 和 1。如果您将使用 Tanh - 使用 [-1, +1] 作为输出。 【参考方案1】:

还有另一个神经网络指标,你没有提到 - 自适应权重的数量。我从这个开始回答,因为它与隐藏层的数量和其中的单元有关。

为了更好的泛化,权重的数量必须比 Np/Ny 少得多,其中 Np 是模式的数量,Ny 是净输出的数量。究竟什么是“多”是可以讨论的,我建议相差几倍,比如 10。对于您的任务中大约 1000 个模式和 1 个输出,这将意味着 100 个权重。

使用 2 个隐藏层没有意义。对于大多数涉及非线性的任务,1 就足够了。在您的情况下,额外的隐藏层只会通过影响整体性能来发挥作用。因此,如果使用 1 个隐藏层,则其中的神经元数量可以近似为权重数量除以输入数量,即 100/7 = 14。

我建议在所有神经元中使用相同的激活函数,无论是 Hypertanh 还是 Sigmoid。您的输出值实际上已经针对 Sigmoid 进行了标准化。无论如何,您可以通过输入数据归一化以适应所有维度的 [0,1] 来提高 NN 性能。当然,请自行规范化每个特征。

如果您可以使用 Pybrain 库,则以更高的学习率开始学习,然后与当前步骤 (LR * (N - i)/N) 成比例地平滑减小,其中 i 是当前步骤,N - 是限制,LR - 初始学习率。

正如@Junuxx 建议的那样,每 M 步输出当前错误(如果可能的话),以确保您的程序按预期工作。如果连续步骤中的错误差异小于阈值,则停止学习。只是为了开始和粗略估计适当的 NN 参数选择,将阈值设置为 0.1-0.01(“纳米尺度”中不需要)。

以 80000 步在 89 种模式上运行网络并获得您所拥有的结果的事实很奇怪。请仔细检查您将正确的数据传递给 NN,并检查您提供的错误值是什么意思。显示的错误或输出可能来自错误的位置。我认为 10000 步必须足够远才能获得 89 种模式的可接受结果。

至于具体任务,我认为 SOM net 可能是另一种选择(可能比 BP 更适合)。

作为旁注,我不熟悉 Pybrain,但我用 C++ 和其他语言编写了一些 NN,所以你的时间看起来非常大。

【讨论】:

我从 0.2 的学习率开始,每次迭代后它乘以 0.999 进行 20,000 次迭代,仍然输出相同。我再次检查了数据,它是正确的。 @JackSmith,那么它可能是 Pybrain 特定的东西,这超出了我的范围。您仍然应该尝试了解错误是什么。尝试没有 softmax 的纯 BP。您是否尝试过输入数据规范化? 我之前尝试不使用Softmax,使用Softmax,每个输出都是'1'。并且规范化不起作用。 请在您的问题中提供输入数据的摘录(您传递到网络中的实际向量)。如果可能,请尝试其他 NN 工具,例如,neuroph.sourceforge.net。我希望有人能告诉给定任务的 Pybrain 设置有什么问题,以及如何解释你的错误值。 数据切片:array([['1', '2', '0', '55', '0', '0', '16', '1'], [' 0'、'3'、'1'、'2'、'4'、'1'、'29.125'、'2']、['1'、'2'、'1'、'28.0'、' 0', '0', '13', '1'], ['0', '3', '0', '31', '1', '0', '18', '1'], ['1', '3', '0', '28.0', '0', '0', '7.225', '0'], ['0', '2', '1', '35' , '0', '0', '26', '1'],输出值在索引 0 处,其余是我的特征向量。

以上是关于在神经网络开始在训练数据上表现可接受之前的隐藏层数、隐藏层中的单元数和历元数的主要内容,如果未能解决你的问题,请参考以下文章

深度学习篇--神经网络中的调优

神经网络模型训练

深度学习——ResNet超详细讲解,详解层数计算各层维度计算

如何选择神经网络中的隐藏层数和节点数? [关闭]

一:输入层隐藏层输出层;二隐藏层的层数

在 Keras/Tensorflow 中实现可训练的广义 Bump 函数层