Pybrain學習筆記-4 基於前饋神經網路的分類器
阿新 • • 發佈:2019-02-13
話不多說,直接上程式碼:
5.test_pybrian_5
#!usr/bin/env python
#_*_coding:utf-8_*_
'''
Created on 2017年4月14日
Topic:Classification with Feed-Forward Neural Networks
@author: Stuart斯圖爾特
'''
from pybrain.datasets import ClassificationDataSet #分類資料專用資料集工具包
from pybrain.utilities import percentError #以列表和陣列的形式返回誤差的百分比工具包
from pybrain.tools.shortcuts import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.structure.modules import SoftmaxLayer
#下面是一些圖形介面以及矩陣運算和隨機陣列運算的工具包,可暫時忽略具體應用,後續會講到
from pylab import ion , ioff , figure , draw , contourf , clf , show , hold , plot
from scipy import diag , arange , meshgrid , where
from numpy.random import multivariate_normal
#建立一個有二維空間點組成的列表
means = [(-1,0),(2,4),(3,1)]
#建立一個由對角矩陣形成的列表
cov = [diag([1,1]), diag([0.5,1.2]), diag([1.5,0.7])]
#ClassificationDataSet:Specialized data set for classification data. Classes are to be numbered from 0 to nb_classes-1.
#定義資料集:輸入目標是2維,目標的target的維數是1,資料可被分為3類
alldata = ClassificationDataSet(2, 1, nb_classes=3)
for n in xrange(400): #外層迴圈400次
for klass in range(3): #內層迴圈三次
input = multivariate_normal(means[klass],cov[klass]) #理解成把輸入資料進行正態分佈的處理,得到更好的資料集
alldata.addSample(input, [klass]) #得到二維輸入資料
#按照3:1的比例劃分測試集和訓練集
#tstdata, trndata = alldata.splitWithProportion( 0.25 )
#報錯:AttributeError: 'SupervisedDataSet' object has no attribute '_convertToOneOfMany'
#將這條語句改成下面程式碼段:
tstdata_temp, trndata_temp = alldata.splitWithProportion(0.25)
#定義測試集,輸入維度是2,target是1,有三類,均是2d向量
tstdata = ClassificationDataSet(2, 1, nb_classes=3)
for n in xrange(0, tstdata_temp.getLength()):
tstdata.addSample( tstdata_temp.getSample(n)[0], tstdata_temp.getSample(n)[1] )
#定義訓練集, 輸入維度是2,target是1,有三類,均是2d向量
trndata = ClassificationDataSet(2, 1, nb_classes=3)
for n in xrange(0, trndata_temp.getLength()):
trndata.addSample( trndata_temp.getSample(n)[0], trndata_temp.getSample(n)[1] )
#將target轉化成一維的輸出,注意網路的output有三層,在分類器中我們想得到的結果是某一明確的分類
#通過convertToOneOfMany()實現target的降維,並把'target'欄位轉存在'class'欄位中
trndata._convertToOneOfMany( )
tstdata._convertToOneOfMany( )
print "Number of training patterns: ", len(trndata) #Number of training patterns: 900
print "Input and output dimensions: ", trndata.indim, trndata.outdim #Input and output dimensions: 2 3
print "First sample (input, target, class):"
print trndata['input'][0], trndata['target'][0], trndata['class'][0] #[ 0.7295122 0.37413538] [0 0 1] [2]
#呼叫buildNetwork建立前饋神經網路,輸入層是2,隱含層是5,輸出層是3
fnn = buildNetwork( trndata.indim, 5, trndata.outdim, outclass=SoftmaxLayer )
#呼叫反向誤差訓練器
trainer = BackpropTrainer( fnn, dataset=trndata, momentum=0.1, verbose=True, weightdecay=0.01)
#這個網路已經可以進行測試了,但由於想做出一個漂亮易懂的分類器,因此下面將自定義資料範圍,用訓練好的網路進行分類並將分類結果視覺化
#下面為了把分類器控制在一個可繪製方格中,因此隨機生成方格內的二維點
#從-3到6建立一維陣列,間隔為0.2,顯然維度是60
#生成矩陣X , Y,矩陣均為60*60的方陣
ticks = arange(-3.,6.,0.2)
X, Y = meshgrid(ticks, ticks)
# need column vectors in dataset, not arrays 定義分類資料集並從X Y矩陣中取樣
griddata = ClassificationDataSet(2,1, nb_classes=3)
for i in xrange(X.size):
griddata.addSample([X.ravel()[i],Y.ravel()[i]], [0])
#同樣要把target對映成一維資料放到class例項中
griddata._convertToOneOfMany()
for i in range(20):
trainer.trainEpochs( 1 ) #訓練網路一次,之所以要訓練一次是想得到每次的訓練結果
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
out = fnn.activateOnDataset(griddata)
#下面是輸出視覺化的分類結果,涉及pylab模組的使用,後續會講到
out = out.argmax(axis=1) # the highest output activation gives the class
out = out.reshape(X.shape)
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()
程式碼說明:
有關程式碼的解釋都已在註釋中給出,下面主要對標記轉化函式_convertToOneOfMany( )報出的AttributeError進行分析與解釋
在官方的說明書中,訓練集與測試集按照3:1劃分,並將標記轉化為一維輸出,語句是:
tstdata, trndata = alldata.splitWithProportion( 0.25 )tstdata, trndata = alldata.splitWithProportion( 0.25 ) trndata._convertToOneOfMany( ) tstdata._convertToOneOfMany( )