隐藏层的数量、隐藏层中的单元数以及神经网络开始在训练数据上表现良好的轮数

11
我正在尝试使用神经网络解决这个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

我曾尝试调整学习率、权重衰减、动量、隐藏单元数量、隐藏层数量、隐藏层类别和输出层类别等参数,以解决这个问题,但无论如何,如果输入来自训练数据,每次都会得到相同的输出。
我认为我应该运行超过8000次,因为当我为“XOR”构建神经网络时,至少需要700次迭代才能开始在纳米级别上出现错误。在“XOR”上的训练数据大小仅为4,而在这种情况下它是892。因此,我在原始数据的10%上运行了8000次迭代(现在训练数据的大小为89),即使这样,它仍然对训练数据中的每个输入都给出相同的输出。并且,由于我想将输入分类为“0”或“1”,如果我使用Softmax作为输出层的类别,则始终会输出“1”。
无论我在“XOR”中使用哪种配置(隐藏单元数、输出层类别、学习率、隐藏层类别、动量),它更多或少地在每种情况下开始收敛。
是否可能存在某些配置最终会产生较低的误差率?至少有一些配置,使其不会对训练数据中的所有输入都产生相同的输出吗?
我对其进行了80000次迭代(训练数据大小为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)内。

1
为什么报告的错误与|out-correct|不匹配?此外,您是否尝试过进行超过8000次迭代的训练?您尝试过的最大隐藏节点数量是多少? - Junuxx
看起来是一个明显的改进。但我有这样的印象,权重开始非常低,可能为零,这意味着数据集中的标签应该是-1和1,而不是0和1。另一件事是,在每次训练迭代之后打印平均误差,以查看其如何演变。 - Junuxx
@Junuxx 我正在尝试。同时,这么多次迭代跑起来需要三个多小时,这正常吗?我还需要改变其他配置,比如隐藏节点的数量或层级分类吗? - Jack Smith
@Stan 学习率为0.04。应该调整为多少?权重是随机初始化的。我还没有运行任何数据归一化。但特征值在范围内。 - Jack Smith
1
尝试以学习率0.2-0.4开始,并使其随着当前epoch成比例下降(LR * (N - i)/N)。它们的范围是多少?我想它们对于不同的特征是不同的吧?然后将它们归一化为相同的范围内。在所有的网络中使用Sigmoid或Tanh层。如果您使用Sigmoid,则保留0和1。如果您使用Tanh,则使用[-1, +1]作为输出。 - Stan
显示剩余9条评论
1个回答

6
还有一种神经网络的度量标准你没有提到——可适应权重数量。我从这里开始回答是因为它与隐藏层及其中的单位数有关。
为了得到良好的泛化效果,权重数量必须要远小于Np/Ny(其中Np为模式数量,Ny为网络输出数量)。"远小于"具体指多少可以商榷,我建议取数值相差几倍,比如10。对于大约1000个模式和1个输出的问题,这将意味着100个权重。
使用两个隐藏层是没有意义的。在大多数涉及非线性的任务中,一个隐藏层就已足够了。在你的情况下,额外的隐藏层只会通过影响整体表现而产生差异。因此,如果只使用1个隐藏层,则其中的神经元数量可以近似为权重数除以输入数,即100/7 = 14。
建议在所有神经元中都使用相同的激活函数,无论是Hypertanh还是Sigmoid。事实上,你的输出值已经对Sigmoid进行了归一化处理。无论如何,你可以通过将输入数据归一化到所有维度的[0,1]范围内来提高神经网络的性能。当然,要对每个特征进行单独的归一化处理。
如果你能使用Pybrain库,就要以更高的学习速率开始学习,然后将其平滑地降低到当前步骤成比例的值(LR * (N - i)/N),其中i是当前步骤,N是限制,LR是初始学习速率。
如@Junuxx所建议的,每M步输出当前误差(如果可以的话),以确保程序按预期工作。如果连续几步中误差的差异小于一个阈值,则停止学习。对于初步估计合适的NN参数的选择,将阈值设置为0.1-0.01即可(不需要"纳米级别")。
在80000个步骤中运行89个模式的网络并获得你的结果的事实很奇怪。请再次确认是否向NN传递了正确的数据,并检查提供的错误值的含义。可能是错误或输出显示来自错误的位置。我认为10000个步骤应该足以获得89个模式的可接受结果。
至于具体任务,我认为SOM网可能是另一种选择(也许比BP更适合)。
顺便说一下,我不熟悉Pybrain,但已经用C ++和其他语言编写过一些NN,所以你的时间看起来非常超出预期。

我以0.2的学习率开始,每次迭代后它会乘以0.999,经过20,000次迭代,输出仍然相同。我再次检查了数据,它是正确的。 - Jack Smith
@JackSmith,那么可能是Pybrain特定的问题,超出了我的范围。但你应该尝试理解错误在哪里。尝试使用纯BP而不是softmax。你尝试过输入数据归一化吗? - Stan
我之前尝试过不用Softmax,但使用了Softmax后,每个输出都是“1”。而且归一化也没有起作用。 - Jack Smith
请在您的问题中提供输入数据的摘录(实际向网络传递的向量)。如果可能,请尝试使用另一个神经网络工具,例如http://neuroph.sourceforge.net。我希望有人能告诉我Pybrain设置在给定任务中出了什么问题,并如何解释您的错误值。 - Stan
@JackSmith,抱歉,我没有看到归一化。所有的值都应该在[0,1]范围内。 - Stan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接