1. 程式人生 > >一個簡單的BP神經網路matlab程式(附函式詳解)

一個簡單的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代表每組資料所屬的類別。

這裡的每列是一個屬性/特徵的所有輸入值,並不是後面函式中輸入的一組樣本資料。

而在程式中 premnmxnewfftraintramnmx都是以列的形式輸入每組樣本資料,故在歸一化時需要轉置

2、歸一化處理函式

premnmx()將原始資料歸一化到-1到1之間,該函式在高版本的MATLAB中已被廢棄。

[input,minI,maxI] = premnmx(P)

premnmx()對歸一化,故需要將textread讀取的原始資料進行轉置,此時矩陣P是4行75列的(4個屬性,75組訓練樣本)。

minI,maxI均是4行1列,這兩個是為了後面的測試資料的歸一化。

input是歸一化後的矩陣475列。後面神經網路建立的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建立一個可訓練的前饋網路。輸入引數說明:

PRRx2矩陣以定義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);