我试图让一个网络(PyBrain)学习二进制。这是我的代码,它总是返回大约8的值,但当我用这个目标激活时,它应该返回9。
from pybrain.tools.shortcuts import buildNetworkfrom pybrain.structure import *from pybrain.datasets import *from pybrain.supervised.trainers import BackpropTrainerfrom matplotlib.pyplot import *trains = 3000hiddenLayers = 4dim = 4target = (1, 0, 0, 1)ds = SupervisedDataSet(dim, 1)ds.addSample((0, 0, 0, 0), (0,))ds.addSample((0, 0, 0, 1), (1,))ds.addSample((0, 0, 1, 0), (2,))ds.addSample((0, 0, 1, 1), (3,))ds.addSample((0, 1, 0, 0), (4,))ds.addSample((0, 1, 0, 1), (5,))ds.addSample((0, 1, 1, 0), (6,))ds.addSample((0, 1, 1, 1), (7,))ds.addSample((1, 0, 0, 0), (8,))net = buildNetwork(dim, hiddenLayers, 1, bias=True, hiddenclass=SigmoidLayer)trainer = BackpropTrainer(net, ds)tests = []for i in range(trains): trainer.train() tests.append(net.activate(target))plot(range(len(tests)), tests)print net.activate(target)show()
我尝试调整了隐藏层的数量,将隐藏类从TanhLayer改为SigmoidLayer,并改变了训练次数,但它总是在大约500次训练后(对数据集进行网络训练)收敛。我应该使用不同于反向传播的训练器吗?如果是,为什么?
回答:
你构建了一个具有4个输入节点、4个隐藏节点和1个输出节点的网络,以及2个偏置项。
考虑到每个字母代表该节点的激活,我们可以说每个隐藏节点计算其激活为sigmoid(w0*1 + w1*A + w2*B + w3*C + w4*D),而输出节点计算其激活为(w0*1 + w1*E + w2*F + w3*G + w4*H)(没有sigmoid)。图中的线条数量代表模型中在学习过程中调整的权重参数的数量。
由于有如此多的参数,但只有9个样本进行训练,网络可以收敛到许多局部最优但不完全正确的解决方案。
解决这个问题的一种方法是增加你的训练样本数量。你可以推广到1和0之外,提供如((0, 0, 1.0, 0.5), (2.5,))和((0, 1.2, 0.0, 1.0), (5.8,))这样的样本。
另一种选择是简化你的模型。完美的解决方案只需要4个输入直接连接到输出,没有偏置或sigmoid。该模型只有4个权重,训练会将其设置为1、2、4和8。最终计算将是1*A + 2*B + 4*C + 8*D。