一個簡單的BP神經網路matlab程式(附函式詳解)
說明:20180604更新
2、本人對其中涉及到的函式進行了詳細說明。
3、此程式中部分函式的使用方式是高版本Matlab中不推薦的
文中給出了當前高版本Matlab中的使用方式,並給出了相關部落格地址,具體如下:
4、使用過程中,可能出現的問題
5、所需的IRIS資料集
具體程式如下:
詳細說明:%讀取訓練資料 [f1,f2,f3,f4,class] = textread('trainData.txt' , '%f%f%f%f%f',150); %特徵值歸一化 [input,minI,maxI] = premnmx( [f1 , f2 , f3 , f4 ]') ; %構造輸出矩陣 s = length( class) ; output = zeros( s , 3 ) ; for i = 1 : s output( i , class( i ) ) = 1 ; end %建立神經網路 net = newff( minmax(input) , [10 3] , { 'logsig' 'purelin' } , 'traingdx' ) ; %設定訓練引數 net.trainparam.show = 50 ; net.trainparam.epochs = 500 ; net.trainparam.goal = 0.01 ; net.trainParam.lr = 0.01 ; %開始訓練 net = train( net, input , output' ) ; %讀取測試資料 [t1 t2 t3 t4 c] = textread('testData.txt' , '%f%f%f%f%f',150); %測試資料歸一化 testInput = tramnmx ( [t1,t2,t3,t4]' , minI, maxI ) ; %模擬 Y = sim( net , testInput ) %統計識別正確率 [s1 , s2] = size( Y ) ; hitNum = 0 ; for i = 1 : s2 [m , Index] = max( Y( : , i ) ) ; if( Index == c(i) ) hitNum = hitNum + 1 ; end end sprintf('識別率是 %3.3f%%',100 * hitNum / s2 )
1、文字檔案讀取函式
textread() 讀取檔案中資料,%f表示讀取單浮點數,按列依次將資料存入f1、f2、f3……。這裡f1—f4代表四個特徵,class代表每組資料所屬的類別。
這裡的每列是一個屬性/特徵的所有輸入值,並不是後面函式中輸入的一組樣本資料。
而在程式中 premnmx、newff、train、tramnmx都是以列的形式輸入每組樣本資料,故在歸一化時需要轉置。
2、歸一化處理函式
premnmx()將原始資料歸一化到-1到1之間,該函式在高版本的MATLAB中已被廢棄。
[input,minI,maxI] = premnmx(P)
premnmx()對行歸一化,故需要將textread讀取的原始資料進行轉置,此時矩陣P是4行75列的(4個屬性,75組訓練樣本)。
minI,maxI均是4行1列,這兩個是為了後面的測試資料的歸一化。
input是歸一化後的矩陣4行75列。後面神經網路建立的newff函式的第一個引數是一個Rx2的矩陣以定義R個輸入向量(即輸入層節點個數-輸入特徵值個數)的最小值和最大值。
推薦使用mapminmax進行歸一化:該函式也是對行歸一化!!!
http://blog.csdn.net/lkj345/article/details/50352385
https://blog.csdn.net/ckzhb/article/details/72871140
例子:[inputn,setting]=mapminmax(input_train);
3、輸出矩陣
%構造輸出矩陣 s = length( class ) ; output = zeros( s , 3 ) ; %zeros(s,3)生成s乘3的全零陣。即75行3列 for i = 1 : s output( i , class( i ) ) = 1 ; end
output是75行3列。class矩陣是75行1列,前幾列是1,中間是2,最後是3.(即三種花的型別)。資料集中第一種花標記為1,第二種花記為2,第三種花記為3,這樣經過迴圈後,output依然是75行3列,第一列的前幾行全為1,第二列的中間幾行全為1,第三列的最後幾行全為1,其餘均為0.
目的是:神經網路輸出需要根據類別數量進行一定的處理,有幾種類別輸出層便含有幾個結點,即第一種花輸出為[1 0 0],第二種花輸出為[0 1 0],第三種花輸出為[0 0 1]。這裡output每一行對應一組樣本的輸出類別,通過一個for迴圈,將所述的類所在的列置為1,此時output是75行3列的。後續train()函式所需的輸出標籤要求每一列對應一組資料的類別,故後續需要將output轉置。
4、神經網路構建
net = newff( minmax(input) ,[10 3] , { 'logsig' 'purelin' } , 'traingdx' )
(此例是老版本的使用http://blog.sina.com.cn/s/blog_64b046c70101cko4.html)
舊版newff函式的格式為:
net=newff(PR,[S1S2 ...SN],{TF1 TF2...TFN},BTF,BLF,PF),函式newff建立一個可訓練的前饋網路。輸入引數說明:
PR:Rx2的矩陣以定義R個輸入向量的最小值和最大值;
Si:第i層神經元個數;
TFi:第i層的傳遞函式,預設函式為tansig函式;
BTF:訓練函式,預設函式為trainlm函式;
traingdx表示學習率自適應並附加動量因子的最速下降法
BLF:權值/閾值學習函式,預設函式為learngdm函式;
PF:效能函式,預設函式為mse函式。
minmax()函式用於獲取陣列中每一行的最小值和最大值
新版newff函式格式:
net =newff(P,T,[S1 S2...S(N-l)],{TF1 TF2...TFNl}, BTF,BLF,PF,IPF,OPF,DDF)
例如:net=newff(inputn,output_train,6,{'tansig','purelin'},'traingda');
P和T:輸入和輸出矩陣;每一列代表一組樣本資料。
Si:第i層神經元個數,輸出層不用寫,根據T決定;
TFi:第i層的傳遞函式,隱含層預設函式為tansig函式,輸出層預設為’purelin’;
BTF:訓練函式,預設函式為trainlm函式,表示採用LM法進行訓練;
BLF:權值/閾值學習函式,預設函式為learngdm函式;
PF:效能函式,預設函式為mse函式即均方誤差。
IPF:指定輸入資料歸一化函式的細胞陣列。
OPF:指定輸出資料反歸一化函式的細胞陣列
DDF:資料劃分函式。
(後5個一般用不到)
舊版本:舊用法訓練次數多,但精度高
新版本:新用法訓練次數少,但精度可能達不到要求
造成上述原因是:
程式裡面的權值、閾值的初始值是隨機賦值的,所以每次執行的結果都會不一樣,有好有壞。你可以把預測效果不錯的網路的權值和閾值作為初始值。具體可以檢視net.iw{1,1}、net.lw{2,1}、net.b{1,1}、net.b{2,1}的值。
5、訓練函式
net = train( net, input ,output' ) ;
這裡input是4行75列,output經轉置後是3行75列。
即每組資料是以列的形式輸入到構建的神經網路模型,共75組。相應的,輸出層與之對應,組數保持一致。
6、測試
Y = sim( net, testInput )
sim模擬,Y是訓練好的網路net對輸入testInput的實際輸出。
若使用mapminmax()函式,測試資料歸一化方法為:inputn_test=mapminmax('apply',input_test,setting);