2013-03-20 99 views
10

與MATLAB訓練的神經網絡我訓練使用MATLAB神經網絡工具箱神經網絡,特別是使用命令nprtool,它提供了一個簡單的GUI使用工具箱功能,並導出net包含關於NN生成的信息的對象。出口在其他編程語言

以這種方式,我創建了一個工作的神經網絡,我可以作爲分類使用,並且代表它的圖如下:

Diagram representing the Neural Network

有200個輸入,20個神經元在第一隱藏層和最後一層提供二維輸出的2個神經元。

我想要做的是在一些其他編程語言(C#,Java,...)中使用網絡。

爲了解決這個問題,我嘗試使用以下代碼在MATLAB:

y1 = tansig(net.IW{1} * input + net.b{1}); 
Results = tansig(net.LW{2} * y1 + net.b{2}); 

假設input是200種元素的單維陣列中,如果net.IW{1}是20x200矩陣前面的代碼將工作(20個神經元,200個重量)。

的問題是,我注意到,size(net.IW{1})返回意外的值:

>> size(net.IW{1}) 

    ans = 

    20 199 

我得到了同樣的問題與10000輸入網絡。在這種情況下,結果不是20x10000,而是20x9384(我不記得確切的值)。

所以,問題是:我怎樣才能獲得每個神經元的權重?之後,有人可以解釋我如何使用它們來產生相同的MATLAB輸出?

+0

某些權重可能已設置爲0,因此會從矩陣中刪除。希望如果我是正確的,有一個設置可以避免這種行爲。 – CTZStef 2013-03-20 14:50:43

+0

我看不到任何設置來改變這種選擇......你能幫我找到它們嗎? – 2013-03-20 14:52:35

回答

13

我解決了上面描述的問題,我認爲分享我學到的東西很有用。

房地

首先,我們需要一些定義。

A scheme of Neural Network

在上述圖中,IW代表初始權重:它們代表在層1神經元的的權重,每個讓我們考慮下面的圖像,從[1]取其中與每個輸入端連接,如下面的圖像示出了[1]:

All neurons are connected with all inputs

所有其它權重,被稱爲層權重LW在第一個圖中),它們也與前一層的每個輸出相連接。在我們的研究案例中,我們使用只有兩層的網絡,因此我們將只使用一個LW陣列來解決我們的問題。

解決方案中的問題

的上述引入後,我們可以在兩個步驟中通過將所述問題進行:

  • 強制初始權重的數量以匹配輸入數組長度
  • 使用權重來實現和使用剛剛在其他編程語言中訓練過的神經網絡

A - 強制初始權重的數量以匹配輸入數組長度

使用nprtool,也可以培養我們的網絡,並在該過程結束時,我們也可以導出在工作區中的一些信息整個培訓過程。特別是,我們需要導出:

  • 表示神經網絡創建
  • 用於訓練網絡
  • 用於訓練網絡
目標陣列的輸入陣列的MATLAB網絡對象

另外,我們需要生成一個M文件,其中包含MATLAB用於創建神經網絡的代碼,因爲我們需要修改它並更改一些訓​​練選項。

下圖顯示瞭如何執行這些操作:

The nprtool GUI to export data and generate the M-code

產生的將是類似於以下一個的M碼:

function net = create_pr_net(inputs,targets) 
%CREATE_PR_NET Creates and trains a pattern recognition neural network. 
% 
% NET = CREATE_PR_NET(INPUTS,TARGETS) takes these arguments: 
% INPUTS - RxQ matrix of Q R-element input samples 
% TARGETS - SxQ matrix of Q S-element associated target samples, where 
%  each column contains a single 1, with all other elements set to 0. 
% and returns these results: 
% NET - The trained neural network 
% 
% For example, to solve the Iris dataset problem with this function: 
% 
% load iris_dataset 
% net = create_pr_net(irisInputs,irisTargets); 
% irisOutputs = sim(net,irisInputs); 
% 
% To reproduce the results you obtained in NPRTOOL: 
% 
% net = create_pr_net(trainingSetInput,trainingSetOutput); 

% Create Network 
numHiddenNeurons = 20; % Adjust as desired 
net = newpr(inputs,targets,numHiddenNeurons); 
net.divideParam.trainRatio = 75/100; % Adjust as desired 
net.divideParam.valRatio = 15/100; % Adjust as desired 
net.divideParam.testRatio = 10/100; % Adjust as desired 

% Train and Apply Network 
[net,tr] = train(net,inputs,targets); 
outputs = sim(net,inputs); 

% Plot 
plotperf(tr) 
plotconfusion(targets,outputs) 

啓動前的訓練過程中,我們需要刪除MATLAB在輸入和輸出上執行的所有預處理和後處理功能。這是可以做到只% Train and Apply Network行之前添加以下行:

net.inputs{1}.processFcns = {}; 
net.outputs{2}.processFcns = {}; 

這些更改create_pr_net()功能後,只要我們可以用它來創建我們最後的神經網絡:

net = create_pr_net(input, target); 

其中inputtarget是我們通過nprtool輸出的值。

通過這種方式,我們確信權重的數量等於輸入數組的長度。而且,這個過程對於簡化移植到其他編程語言非常有用。

乙 - 實施與使用只訓練有素的其他編程語言

隨着這些變化的神經網絡,我們可以這樣定義一個函數:

function [ Results ] = classify(net, input) 
    y1 = tansig(net.IW{1} * input + net.b{1}); 

    Results = tansig(net.LW{2} * y1 + net.b{2}); 
end 

在這段代碼中,我們使用上面提到的IW和LW陣列,還有偏差 b,用於nprtool的網絡架構。在這方面,我們不在乎role of biases;簡單地說,我們需要使用它們,因爲nprtool這樣做。

現在,我們可以使用上面所定義的classify()函數或sim()功能同樣,獲得相同的結果,如顯示在下面的例子:

>> sim(net, input(:, 1)) 

ans = 

    0.9759 
    -0.1867 
    -0.1891 

>> classify(net, input(:, 1)) 

ans = 

    0.9759 
    -0.1867 
    -0.1891 

顯然,classify()功能可以被解釋爲一僞代碼,然後在每一種編程語言中實現,其中可以定義函數[2]和數組之間的基本操作。

參考

[1] Howard Demuth, Mark Beale, Martin Hagan: Neural Network Toolbox 6 - User Guide, MATLAB

[2] Mathworks, tansig - Hyperbolic tangent sigmoid transfer function, MATLAB Documentation center

其他備註

看一看到robott's answerSangeun Chi's answer的更多細節。

+1

謝謝你的回答。這對我幫助很大。但我需要processFcns。我只用'[inputs,PSi] = mapminmax(輸入);'在我的輸入數據上保存到minmaxParams.mat'save('minmaxParams','PSi')'。然後在我的分類函數中,我添加了'load minmaxParams.mat; input = mapminmax('apply',input,PSi);' – 2013-11-26 10:16:20

+0

我已經合併了所有評論,更正了一些錯別字,並給出了一個適用於單個隱藏層ANN。它包括Sangeun Chi的改進和更正。 – fermat4214 2017-03-11 03:57:27

2

這是偉大的Vito Gentile的答案的一個小改進。

如果你想使用預處理和後處理「mapminmax功能,你有因爲「mapminmax」在Matlab由行標準化,而不是由列關注!

這是你需要添加到上面的「分類」功能,以保持一個連貫的前/後處理的內容:

[m n] = size(input); 
ymax = 1; 
ymin = -1; 
for i=1:m 
    xmax = max(input(i,:)); 
    xmin = min(input(i,:)); 
    for j=1:n 
    input(i,j) = (ymax-ymin)*(input(i,j)-xmin)/(xmax-xmin) + ymin; 
    end 
end 

這在函數的末尾:

ymax = 1; 
ymin = 0; 
xmax = 1; 
xmin = -1; 
Results = (ymax-ymin)*(Results-xmin)/(xmax-xmin) + ymin; 

這是Matlab代碼,但它可以很容易地讀爲僞代碼。 希望這會有所幫助!

3

感謝VitoShadow和robott的答案,我可以將Matlab神經網絡值導出到其他應用程序。

我真的很感激他們,但我發現他們的代碼中有一些微不足道的錯誤,並希望糾正它們。

1)在VitoShadow碼,

Results = tansig(net.LW{2} * y1 + net.b{2}); 
-> Results = net.LW{2} * y1 + net.b{2}; 

2)在預處理robott碼, 它將從淨可變比計算它們提取XMAX和XMIN更容易。

xmax = net.inputs{1}.processSettings{1}.xmax 
xmin = net.inputs{1}.processSettings{1}.xmin 

3)在robott後處理代碼,

xmax = net.outputs{2}.processSettings{1}.xmax 
xmin = net.outputs{2}.processSettings{1}.xmin 

Results = (ymax-ymin)*(Results-xmin)/(xmax-xmin) + ymin; 
-> Results = (Results-ymin)*(xmax-xmin)/(ymax-ymin) + xmin; 

可以手動檢查並確認值如下:

p2 = mapminmax('apply', net(:, 1), net.inputs{1}.processSettings{1}) 

- >預處理的數據

y1 = purelin (net.LW{2} * tansig(net.iw{1}* p2 + net.b{1}) + net.b{2}) 

- >神經網絡親cessed數據

y2 = mapminmax('reverse' , y1, net.outputs{2}.processSettings{1}) 

- >後處理數據

參考: http://www.mathworks.com/matlabcentral/answers/14517-processing-of-i-p-data

0

我試圖使用的OpenCV實現一個簡單的2層NN在C++中,然後導出的權重的Android其工作安靜以及。我寫了一個小腳本,它生成一個帶有學習權重的頭文件,並在以下代碼中使用。

// Map Minimum and Maximum Input Processing Function 
Mat mapminmax_apply(Mat x, Mat settings_gain, Mat settings_xoffset, double settings_ymin){ 

    Mat y; 

    subtract(x, settings_xoffset, y); 
    multiply(y, settings_gain, y); 
    add(y, settings_ymin, y); 

    return y; 


    /* MATLAB CODE 
    y = x - settings_xoffset; 
    y = y .* settings_gain; 
    y = y + settings_ymin; 
    */ 
} 




// Sigmoid Symmetric Transfer Function 
Mat transig_apply(Mat n){ 
    Mat tempexp; 
    exp(-2*n, tempexp); 
    Mat transig_apply_result = 2 /(1 + tempexp) - 1; 
    return transig_apply_result; 
} 


// Map Minimum and Maximum Output Reverse-Processing Function 
Mat mapminmax_reverse(Mat y, Mat settings_gain, Mat settings_xoffset, double settings_ymin){ 

    Mat x; 

    subtract(y, settings_ymin, x); 
    divide(x, settings_gain, x); 
    add(x, settings_xoffset, x); 

    return x; 


/* MATLAB CODE 
function x = mapminmax_reverse(y,settings_gain,settings_xoffset,settings_ymin) 
x = y - settings_ymin; 
x = x ./ settings_gain; 
x = x + settings_xoffset; 
end 
*/ 

} 


Mat getNNParameter (Mat x1) 
{ 

    // convert double array to MAT 

    // input 1 
    Mat x1_step1_xoffsetM = Mat(1, 48, CV_64FC1, x1_step1_xoffset).t(); 
    Mat x1_step1_gainM = Mat(1, 48, CV_64FC1, x1_step1_gain).t(); 
    double x1_step1_ymin = -1; 

    // Layer 1 
    Mat b1M = Mat(1, 25, CV_64FC1, b1).t(); 
    Mat IW1_1M = Mat(48, 25, CV_64FC1, IW1_1).t(); 

    // Layer 2 
    Mat b2M = Mat(1, 48, CV_64FC1, b2).t(); 
    Mat LW2_1M = Mat(25, 48, CV_64FC1, LW2_1).t(); 

    // input 1 
    Mat y1_step1_gainM = Mat(1, 48, CV_64FC1, y1_step1_gain).t(); 
    Mat y1_step1_xoffsetM = Mat(1, 48, CV_64FC1, y1_step1_xoffset).t(); 
    double y1_step1_ymin = -1; 



    // ===== SIMULATION ======== 


    // Input 1 
    Mat xp1 = mapminmax_apply(x1, x1_step1_gainM, x1_step1_xoffsetM, x1_step1_ymin); 

    Mat temp = b1M + IW1_1M*xp1; 

    // Layer 1 
    Mat a1M = transig_apply(temp); 

    // Layer 2 
    Mat a2M = b2M + LW2_1M*a1M; 

    // Output 1 
    Mat y1M = mapminmax_reverse(a2M, y1_step1_gainM, y1_step1_xoffsetM, y1_step1_ymin); 

    return y1M; 
} 

例如在頭部偏置可能是這樣的:

static double b2[1][48] = { 
     {-0.19879, 0.78254, -0.87674, -0.5827, -0.017464, 0.13143, -0.74361, 0.4645, 0.25262, 0.54249, -0.22292, -0.35605, -0.42747, 0.044744, -0.14827, -0.27354, 0.77793, -0.4511, 0.059346, 0.29589, -0.65137, -0.51788, 0.38366, -0.030243, -0.57632, 0.76785, -0.36374, 0.19446, 0.10383, -0.57989, -0.82931, 0.15301, -0.89212, -0.17296, -0.16356, 0.18946, -1.0032, 0.48846, -0.78148, 0.66608, 0.14946, 0.1972, -0.93501, 0.42523, -0.37773, -0.068266, -0.27003, 0.1196}}; 

現在,谷歌公佈的Tensorflow,這成爲過時。

0

因此,溶液變成(修正所有部件後)

在這裏,我給在Matlab的解決方案,但如果你有正切()函數,你可以很容易地將其轉換爲任何編程語言。它僅用於顯示來自網絡對象和您需要的操作的字段。

  • 假設你有,你要導出
  • 假設訓練有素的安的名稱trained_ann

這裏訓練有素的安(網絡對象)是用於出口和測試腳本。 測試腳本相比之下,my_ann_evaluation)原網絡的結果(導致

% Export IT 
exported_ann_structure = my_ann_exporter(trained_ann); 

% Run and Compare 
% Works only for single INPUT vector 
% Please extend it to MATRIX version by yourself 
input = [12 3 5 100]; 
res1 = trained_ann(input')'; 
res2 = my_ann_evaluation(exported_ann_structure, input')'; 

,你需要以下兩個功能

首先my_ann_exporter

function [ my_ann_structure ] = my_ann_exporter(trained_netw) 
% Just for extracting as Structure object 
my_ann_structure.input_ymax = trained_netw.inputs{1}.processSettings{1}.ymax; 
my_ann_structure.input_ymin = trained_netw.inputs{1}.processSettings{1}.ymin; 
my_ann_structure.input_xmax = trained_netw.inputs{1}.processSettings{1}.xmax; 
my_ann_structure.input_xmin = trained_netw.inputs{1}.processSettings{1}.xmin; 

my_ann_structure.IW = trained_netw.IW{1}; 
my_ann_structure.b1 = trained_netw.b{1}; 
my_ann_structure.LW = trained_netw.LW{2}; 
my_ann_structure.b2 = trained_netw.b{2}; 

my_ann_structure.output_ymax = trained_netw.outputs{2}.processSettings{1}.ymax; 
my_ann_structure.output_ymin = trained_netw.outputs{2}.processSettings{1}.ymin; 
my_ann_structure.output_xmax = trained_netw.outputs{2}.processSettings{1}.xmax; 
my_ann_structure.output_xmin = trained_netw.outputs{2}.processSettings{1}.xmin; 
end 

二my_ann_evaluation:

function [ res ] = my_ann_evaluation(my_ann_structure, input) 
% Works with only single INPUT vector 
% Matrix version can be implemented 

ymax = my_ann_structure.input_ymax; 
ymin = my_ann_structure.input_ymin; 
xmax = my_ann_structure.input_xmax; 
xmin = my_ann_structure.input_xmin; 
input_preprocessed = (ymax-ymin) * (input-xmin) ./ (xmax-xmin) + ymin; 

% Pass it through the ANN matrix multiplication 
y1 = tanh(my_ann_structure.IW * input_preprocessed + my_ann_structure.b1); 

y2 = my_ann_structure.LW * y1 + my_ann_structure.b2; 

ymax = my_ann_structure.output_ymax; 
ymin = my_ann_structure.output_ymin; 
xmax = my_ann_structure.output_xmax; 
xmin = my_ann_structure.output_xmin; 
res = (y2-ymin) .* (xmax-xmin) /(ymax-ymin) + xmin; 
end 
+0

此導出功能專爲簡單情況而設計:僅適用於1輸入,1輸出和1隱藏層的ANN。人們可以很容易地將其擴展到更多層次的ANN – fermat4214 2017-03-11 03:52:56