http://www.pybrain.org/docs/tutorial/fnn.html
3.Classification with Feed-Forward Neural Networks
本节会手把手教你为分类建立一个数据集,训练相应的网络并且在线公布可视化训练结果。
首先我们需要从PyBrain导入必要的组件。
frompybrain.datasets import ClassificationDataSet
frompybrain.utilities import percentError
frompybrain.tools.shortcuts import buildNetwork
frompybrain.supervised.trainersimport BackpropTrainer
frompybrain.structure.modules import SoftmaxLayer
进一步,需要导入pylab进行图形化输出。
frompylabimport ion, ioff, figure, draw, contourf, clf, show, hold, plot
fromscipyimport diag, arange, meshgrid, where
fromnumpy.randomimport multivariate_normal
为了可视化展示效果好,我们生成一组2D的从属于三个不同类型的点。同时,需要一个将数据从一个文件中读入的工具,e.g. 使用pylab.load()。
means= [(-1,0),(2,4),(3,1)]
cov= [diag([1,1]), diag([0.5,1.2]), diag([1.5,0.7])]
alldata= ClassificationDataSet(2,1, nb_classes=3)
for n inxrange(400):
for klass inrange(3):
input= multivariate_normal(means[klass],cov[klass])
alldata.addSample(input, [klass])
随机将数据集分为75%的训练集和25%的测试集。当然,我们也可以在一开始创建不同的数据集。
tstdata, trndata = alldata.splitWithProportion(0.25 )
对神经网络分类而言,十分建议编译类别时,每一个输出神经元对应一个类别。注意这个操作复制原先的目标,并存到一个名为‘class’的(整数)场。(?Forneural network classification, it is highly advisable to encode classes withone output neuron per class. Note that this operation duplicates the originaltargets and stores them in an (integer) field named ‘class’.)
trndata._convertToOneOfMany( )
tstdata._convertToOneOfMany( )
通过打印部分信息来测试我们的数据集。
print"Number of training patterns: ",len(trndata)
print"Input and output dimensions: ", trndata.indim, trndata.outdim
print"First sample (input, target, class):"
print trndata['input'][0], trndata['target'][0], trndata['class'][0]
现在搭建一个有5个隐藏单元的向前传递网络。我们用快捷键buildNetwork()来实现。输入和输出的层大小必须和数据集输入和目标维数保持一致。你可以在给定层大小的基础上加入更多的隐藏层。
我们在解决分类问题,所以输出层使用一个softmax函数。PyBrain提供更多的选择,e.g.试着将隐藏层的转换函数从sigmoid(默认的)变为linear的。
fnn= buildNetwork( trndata.indim,5, trndata.outdim, outclass=SoftmaxLayer )
建立一个训练器基本上可以说是以网络和数据集作为输入。查看trainers可以看到训练器列表。这里我们使用BackpropTrainer。
trainer= BackpropTrainer( fnn, dataset=trndata, momentum=0.1, verbose=True, weightdecay=0.01)
现在生成一个数据点的正方形网格,并放入数据集中,从而在可视化分类结果时可以得到更好的等值线图。因此,这个数据集的目标值可以被忽略。
ticks= arange(-3.,6.,0.2)
X, Y = meshgrid(ticks, ticks)
# need column vectors in dataset, not arrays
griddata= ClassificationDataSet(2,1, nb_classes=3)
for i inxrange(X.size):
griddata.addSample([X.ravel()[i],Y.ravel()[i]], [0])
griddata._convertToOneOfMany() # this is still needed to make the fnn feel comfy
开始迭代训练。对网络训练一定时间。通常你会设定为5,但是为了可视化目的,我们一次只做一个epoch。
for i in range(20):
trainer.trainEpochs( 1 )
网络在训练集和测试集上进行评估。有许多种方法来做,例如可以查看pybrain.tools.validation模块。 这里我们让训练器来做这个测试。
...
trnresult = percentError( trainer.testOnClassData(),
trndata['class'] )
tstresult = percentError( trainer.testOnClassData(
dataset=tstdata ), tstdata['class'] )
print "epoch: %4d" % trainer.totalepochs, \
" train error: %5.2f%%" % trnresult, \
" test error: %5.2f%%" % tstresult
在FNN上运行我们的grid data,得到最近似的分类并且将它们再次组合成一个正方形数组。
...
out = fnn.activateOnDataset(griddata)
out = out.argmax(axis=1) # the highest output activation gives the class
out = out.reshape(X.shape)
现在plot测试数据和填充颜色等值线作为背景。
...
figure(1)
ioff() # interactive graphics off
clf() # clear the plot
hold(True) # overplot on
for c in [0,1,2]:
here, _ = where(tstdata['class']==c)
plot(tstdata['input'][here,0],tstdata['input'][here,1],'o')
if out.max()!=out.min(): # safety check against flat field
contourf(X, Y, out) # plot the contour
ion() # interactive graphics on
draw() # update the plot
最后,会一直展示图直到用户停止。
ioff()
show()