总之,MATLAB Compiler仅支持部署预训练神经网络。
神经网络工具箱
可编译:
不可编译:
- 所有其他命令行功能
- 应用程序和用户界面
- Simulink块
gensim
这意味着您无法mcc
-编译具有训练功能的函数(任何包含TRAIN,ADAPT等内容的函数),您只能部署评估/模拟已经训练过的网络对象的函数(如SIM函数等)。
对于支持的场景(部署预训练网络),有几种方法可以实现:
在正常的MATLAB会话中,加载您拥有的训练数据,然后使用所需的设置创建和训练神经网络(不断调整网络参数,直到满意为止)。最后将网络对象保存到磁盘上(作为MAT文件中的变量导出)。
[x,y] = simplefit_dataset();
net = fitnet(4);
net = configure(net, x, y);
net.trainParam.showWindow = false;
net.trainParam.showCommandLine = true;
net.trainParam.show = 1;
net = init(net);
[net,tr] = train(net, x, y);
save('pretrained_network.mat', 'net')
接下来创建一个可部署的函数,加载保存的网络,并使用它来预测给定一些测试数据的输出(请注意使用%#function
pragma行):
simulateSavedNet.m
function y_hat = simulateSavedNet(x)
S = load('pretrained_network.mat', 'net');
net = S.net;
y_hat = sim(net, x);
end
您可以使用genFunction
从预训练网络对象生成一个独立的MATLAB函数,该函数可用于模拟网络输出。此功能在MATLAB R2013b中引入。
它基本上会将网络设置、结构和权重全部硬编码到一个M函数中。生成的函数与MATLAB编译器mcc
(编译为支持的目标之一)以及MATLAB Codercodegen
(转换为独立的C/C++代码)完全兼容。
genFunction(net, 'simulateStandaloneNet.m', 'MatrixOnly','yes', 'ShowLinks','no')
这是生成函数的代码:
simulateStandaloneNet.m
3) 手动模拟预训练网络
对于简单的静态神经网络(如前馈网络等),评估预训练网络并模拟其输出相对容易(难点在于训练它们!)。
我已经在previous answers中展示了如何做到这一点。你基本上需要从网络中提取学习到的权重,然后将这些数字插入到转移函数中,输入数据,计算传播输出(逐层计算)。你需要注意对数据进行任何预处理/后处理,并在每个层中使用相同的转移函数。
事实上,这基本上就是上一种方法中genFunction
所做的,只不过是自动化的,可以处理所有情况(适用于各种神经网络,而不仅仅是前馈人工神经网络)。
以下是上述训练网络的一个示例:
simulateManualNet.m
function y_hat = simulateManualNet(x)
b1 = [6.0358701949521; 2.72569392497815; 0.584267717191459; -5.1615078566383];
W1 = [-14.0019194910639; 4.90641117353245; -15.2282807645331; -5.26420794868803];
b2 = -0.756207251486408;
W2 = [0.548462643231606 -0.435802343861239 -0.085111261420613 -1.13679228253379];
in = mapFcn(x);
hid = hiddenLayerTransferFcn(bsxfun(@plus, W1*in, b1));
out = outputLayerTransferFcn(W2*hid + b2);
y_hat = mapInverseFcn(out);
end
function xx = mapFcn(x)
mn = 0; mx = 9.97628374728129;
xx = (x - mn)*2 / (mx - mn) - 1;
end
function x = mapInverseFcn(xx)
mn = 0; mx = 10;
x = (xx + 1) * (mx - mn)/2 + mn;
end
function out = hiddenLayerTransferFcn(in)
out = tanh(in);
end
function out = outputLayerTransferFcn(in)
out = in;
end
这里的想法是使用gensim
从预先训练的网络生成一个Simulink块,然后使用Simulink Coder(以前称为Real-Time Workshop)将生成的块转换为独立的C/C++应用程序。将神经网络编译成Simulink块是在R2010b中引入的。
我不是Simulink专家,所以我会留给你去探索这种方法:
gensim(net)
在上述每种方法中(前三种),其思想是将
simulate
函数编译为MATLAB Compiler支持的目标之一(独立可执行文件,共享库,Java包,.NET程序集),然后部署生成的组件。
(实际上,方法#2和#3也可以使用MATLAB Coder
codegen
转换为C/C++源代码)。
以下是如何使用
mcc
命令将每个方法编译为共享库(如果您喜欢,可以使用
deploytool
):
mcc -v -W cpplib:libANN -T link:lib -N -p nnet simulateSavedNet.m -a pretrained_network.mat
mcc -v -W cpplib:libANN -T link:lib -N simulateStandaloneNet
mcc -v -W cpplib:libANN -T link:lib -N simulateManualNet
为了检查生成的DLL文件,下面是一个链接到所生成共享库的C++测试程序:
% 1)
mbuild -output test_savedNet -DSIMFCN=simulateSavedNet -I. test_net.cpp libANN.lib
% 2)
mbuild -output test_standaloneNet -DSIMFCN=simulateStandaloneNet -I. test_net.cpp libANN.lib
% 3)
mbuild -output test_manualNet -DSIMFCN=simulateManualNet -I. test_net.cpp libANN.lib
测试程序的代码:
test_net.cpp
#include <cstdlib>
#include <iostream>
#include "libANN.h"
int main()
{
if (!mclInitializeApplication(NULL,0)) {
std::cerr << "could not initialize the application" << std::endl;
return EXIT_FAILURE;
}
if(!libANNInitialize()) {
std::cerr << "Could not initialize the library" << std::endl;
return EXIT_FAILURE;
}
try {
double x[] = {1.0, 3.0, 5.0, 7.0, 9.0};
mwArray in(1, 5, mxDOUBLE_CLASS, mxREAL);
in.SetData(x, 5);
mwArray out;
SIMFCN(1, out, in);
double y[5];
out.GetData(y, 5);
std::cout << "y = net(x)" << std::endl;
std::cout << "y = \n" << out << std::endl;
} catch (const mwException& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
} catch (...) {
std::cerr << "Unexpected error thrown" << std::endl;
return EXIT_FAILURE;
}
libANNTerminate();
mclTerminateApplication();
return EXIT_SUCCESS;
}
以下是生成程序的输出结果,与原始网络对象和源M函数进行了比较:
>> net([1 3 5 7 9])
ans =
9.5620 7.7851 7.2716 6.1647 2.4073
>> simulateSavedNet([1 3 5 7 9])
ans =
9.5620 7.7851 7.2716 6.1647 2.4073
>> simulateStandaloneNet([1 3 5 7 9])
ans =
9.5620 7.7851 7.2716 6.1647 2.4073
>> simulateManualNet([1 3 5 7 9])
ans =
9.5620 7.7851 7.2716 6.1647 2.4073
>> !test_savedNet.exe
y = net(x)
y =
9.5620 7.7851 7.2716 6.1647 2.4073
>> !test_standaloneNet.exe
y = net(x)
y =
9.5620 7.7851 7.2716 6.1647 2.4073
>> !test_manualNet.exe
y = net(x)
y =
9.5620 7.7851 7.2716 6.1647 2.4073
这篇文章有点长,但我想涵盖所有可能的情况,包括这个问题和未来的问题 :) HTH
##
符号,MATLAB无法读取。问题出在哪里? - Eghbal