我需要解决前馈网络的回归问题,并且我一直在尝试使用PyBrain来完成它。由于没有关于pybrain参考的回归的例子,我试图改编它的回归分类示例,但没有成功(分类示例可以在这里找到:http://pybrain.org/docs/tutorial/fnn.html)。以下是我的代码:
第一个函数将我的numpy数组形式的数据转换为pybrain SupervisedDataset。我使用SupervisedDataset,因为根据pybrain的参考,它是在问题回归时使用的数据集。参数是一个包含特征向量(数据)及其预期输出(值)的数组:
def convertDataNeuralNetwork(data, values):
fulldata = SupervisedDataSet(data.shape[1], 1)
for d, v in zip(data, values):
fulldata.addSample(d, v)
return fulldata
接下来,是运行回归的功能。 train_data和train_values是列车特征向量及其预期输出,test_data和test_values是测试特征向量及其预期输出:
regressionTrain = convertDataNeuralNetwork(train_data, train_values)
regressionTest = convertDataNeuralNetwork(test_data, test_values)
fnn = FeedForwardNetwork()
inLayer = LinearLayer(regressionTrain.indim)
hiddenLayer = LinearLayer(5)
outLayer = GaussianLayer(regressionTrain.outdim)
fnn.addInputModule(inLayer)
fnn.addModule(hiddenLayer)
fnn.addOutputModule(outLayer)
in_to_hidden = FullConnection(inLayer, hiddenLayer)
hidden_to_out = FullConnection(hiddenLayer, outLayer)
fnn.addConnection(in_to_hidden)
fnn.addConnection(hidden_to_out)
fnn.sortModules()
trainer = BackpropTrainer(fnn, dataset=regressionTrain, momentum=0.1, verbose=True, weightdecay=0.01)
for i in range(10):
trainer.trainEpochs(5)
res = trainer.testOnClassData(dataset=regressionTest )
print res
当我打印res时,它的所有值都是0.我尝试使用buildNetwork函数作为构建网络的快捷方式,但它不能正常工作。我还在隐藏层中尝试了不同类型的层和不同数量的节点,没有运气。
有人知道我做错了什么吗?此外,一些pybrain回归示例真的会有所帮助!我看的时候找不到任何东西。
提前致谢
答案 0 :(得分:5)
答案 1 :(得分:5)
正如Ben Allison最初指出的那样,为了使网络能够逼近任意值(即不一定在0..1
范围内),使用激活函数非常重要不在最后一层中输出范围有限。例如,线性激活功能应该很好。
这是一个从pybrain的基本元素构建的简单回归示例:
#----------
# build the dataset
#----------
from pybrain.datasets import SupervisedDataSet
import numpy, math
xvalues = numpy.linspace(0,2 * math.pi, 1001)
yvalues = 5 * numpy.sin(xvalues)
ds = SupervisedDataSet(1, 1)
for x, y in zip(xvalues, yvalues):
ds.addSample((x,), (y,))
#----------
# build the network
#----------
from pybrain.structure import SigmoidLayer, LinearLayer
from pybrain.tools.shortcuts import buildNetwork
net = buildNetwork(1,
100, # number of hidden units
1,
bias = True,
hiddenclass = SigmoidLayer,
outclass = LinearLayer
)
#----------
# train
#----------
from pybrain.supervised.trainers import BackpropTrainer
trainer = BackpropTrainer(net, ds, verbose = True)
trainer.trainUntilConvergence(maxEpochs = 100)
#----------
# evaluate
#----------
import pylab
# neural net approximation
pylab.plot(xvalues,
[ net.activate([x]) for x in xvalues ], linewidth = 2,
color = 'blue', label = 'NN output')
# target function
pylab.plot(xvalues,
yvalues, linewidth = 2, color = 'red', label = 'target')
pylab.grid()
pylab.legend()
pylab.show()
侧面注释(因为在您的代码示例中,您有一个带有线性激活函数的隐藏层):在任何隐藏层中,线性函数都没有用,因为:
可以减少到单个线性变换,即它们也可以被消除,而不会减少可以近似的函数集。神经网络的一个重点是激活函数在隐藏层中是非线性的。
答案 2 :(得分:4)
我认为这里可能会发生一些事情。
首先,我建议使用不同于您正在使用的图层激活配置。特别是,对于初学者,尝试对网络中的隐藏层使用S形非线性,并对输出层使用线性激活。这是迄今为止典型监督网络最常见的设置,应该可以帮助您入门。
引起我注意的第二件事是你的训练师weightDecay
参数的值相对较大(虽然构成“相对较大”的值取决于输入和输出值的自然比例)。我会为初学者删除该参数,或将其值设置为0.重量衰减是一个有助于防止网络过度拟合的正则化器,但如果你过多地增加该参数的值,你的网络权重将全部变为0很快(然后你的网络的梯度基本上是0,所以学习将停止)。如果在培训期间验证数据集的性能开始下降,则仅将weightDecay
设置为非零值。
答案 3 :(得分:0)
正如Andre Holzner所解释的那样,隐藏层应该是非线性的。 Andre的代码示例很棒,但是当您拥有更多功能而不是那么多数据时,它不能很好地工作。在这种情况下,由于隐藏层很大,我们得到了很好的近似,但是当你处理更复杂的数据时,输出层中只有线性函数是不够的,你应该将特征和目标规范化到范围[0..1]