2013-03-20 66 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