摘要
在Matlab R2010a版中,如果要創建一個具有兩個隱含層、且神經元數分別爲5、3的前向BP網絡,使用舊的語法可以這樣寫:
net1 = newff(minmax(P), [5 3 1]);
注意minmax()函數的使用,還有對輸出層神經元數(1)的指定。
當然也可以採用新的語法,更簡潔(請留意差異):
net2 = newff(P, T, [5 3]);
不用求minmax,也不用人工指定輸出層神元數了(newff會根據參數T自行推導)。
不過,爲了得到與書本示例接近的結果,接下來需要清除net2.divideFcn等屬性再訓練,否則結果相去甚遠,且遠不止一個數量級。
net2.divideFcn = '';
net2.inputs{1}.processFcns = {}; % 1是輸入層所在網絡層編號
net2.outputs{3}.processFcns = {}; % 3 是輸出層所在網絡層編號
正文
最近在看朱凱的《精通Matlab神經網絡》,到第10章例10-3時,發現newff()的新舊用法得到的結果相去甚遠。
書中例10-3採用了舊式寫法,代碼如下:
% 例10-3,舊式寫法
clear all P = [-1 -1 2 2; 0 5 0 5]; T = [-1 -1 2 2];
%% 舊式語法 net1 = newff(minmax(P),[5 1],{'tansig', 'purelin'}, 'traingd'); % 隱含層有5個神經元
net1.trainParam.goal = 1e-5; net1.trainParam.epochs = 300; net1.trainParam.lr = 0.05; net1.trainParam.showWindow = 1; net1= train(net1,P,T);
Y1 = sim(net1,P); disp(['舊式語法 mse: ' num2str(mse(T-Y1))]); |
訓練窗口最終如下:
程序輸出如下:
Warning: NEWFF used in an obsolete way. > In nntobsu at 18 In newff at 86 See help for NEWFF to update calls to the new argument list.
舊式語法 mse: 9.8073e-006 |
很明顯,達到了設定的1e-5的目標。
不過我們也收到了警告,建議我們採用新的參數列表。於是查幫助,改成新的寫法,代碼如下:
% 例10-3,新式寫法
clear all P = [-1 -1 2 2; 0 5 0 5]; T = [-1 -1 2 2];
%% 新式語法 net2 = newff(P,T,5,{'tansig', 'purelin'}, 'traingd'); % 隱含層有5個神經元
net2.trainParam.goal = 1e-5; net2.trainParam.epochs = 300; net2.trainParam.lr = 0.05; net2.trainParam.showWindow = 1; net2 = train(net2,P,T);
Y2 = sim(net2,P); disp(['新式語法 mse: ' num2str(mse(T-Y2))]); |
訓練窗口:
程序輸出:
可見,遠遠沒有達到1e-5的目標。
這是爲什麼呢?QQ羣諮詢無果,無奈之下自行研究源碼。
newff.m分成三大塊:主程序、新版實現子函數 new_5p1()、舊版實現子函數 new_5p0()。通過仔細比較新舊這兩個子函數,發現新版設置了 net.divideFcn 屬性,其值爲'dividerand'。該函數把樣本數據三分爲訓練集、驗證集和測試集,默認比例是6:2:2。於是在我的程序中清除該屬性再訓練:
% 例10-3,新寫法,改進
clear all P = [-1 -1 2 2; 0 5 0 5]; T = [-1 -1 2 2];
%% 新式語法 net2 = newff(P,T,5,{'tansig', 'purelin'}, 'traingd'); % 隱含層有5個神經元
net2.trainParam.goal = 1e-5; net2.trainParam.epochs = 300; net2.trainParam.lr = 0.05; net2.trainParam.showWindow = 1; net2.divideFcn = ''; % 爲和書本一致,對於樣本極少的情況,不要再三分了 net2 = train(net2,P,T);
Y2 = sim(net2,P); disp(['新式語法,改進 mse: ' num2str(mse(T-Y2))]); |
訓練窗口:
程序輸出:
新式語法,改進 mse: 9.8129e-006 |
也達到了預期目標。
其實,新舊兩次的訓練窗口和Performance窗口也可以發現端倪的,此處不再細說,請各位看官自行對比。
當然,至於新版爲什麼要引入divideFcn必有其道理,我是初學者,有所揣測暫不表,先跟着書走。