3

I want to compile my MATLAB application that uses neural networks to a stand-alone application, but as you know MATLAB can't compile training neural network as stand-alone and can only compile already trained neural networks.

The core of my application consists of training a neural network on an imported data. How can I do that? Is there an alternative way to do this? My MATLAB version is R2014a.

I tried using deploytool for compiling, but according to the MATLAB Compiler documentation:

THIS CAN BE COMPILED
  * Pre-trained network
  * command line functions

THIS CANNOT BE COMPILED
  * All other command line functionality
  * All GUIs provided with toolbox
  * Simulink blocks
  * gensim

So we get error after compiling the app if we have functions like newff or patternnet or other training functions in our code.

I know this is a limitation of the MATLAB Compiler and I searched for solutions for months but I didn't find any workarounds or alternative ways.

Apparently there is a function added to newer versions of MATLAB for using trained neural networks in MATLAB compiler: Deploy Neural Network Functions.

4

3 回答 3

10

底线是 MATLAB Compiler 仅支持部署预训练的神经网络。

神经网络工具箱

可以编译:

  • 预训练的网络命令行功能

无法编译:

  • 所有其他命令行功能
  • 应用程序和用户界面
  • Simulink 模块
  • gensim

这意味着您不能mcc- 编译具有训练功能的函数(任何包含TRAINADAPT等...),您只能部署评估/模拟已经训练的网络对象的函数(SIM函数等)。


对于支持的场景(部署预训练的网络),有几种方法可以解决:

1)将预训练的网络对象保存/加载到 MAT 文件中

在正常的 MATLAB 会话中,加载您拥有的训练数据,然后使用所需的设置创建和训练神经网络(不断调整网络参数,直到您对结果感到满意)。最后将网络对象保存到磁盘(导出为 MAT 文件中的变量)。

% sample regression dataset
[x,y] = simplefit_dataset();

% feed-forward neural network (one hidden layer with 4 neurons)
net = fitnet(4);
net = configure(net, x, y);            % configure net to match data
net.trainParam.showWindow = false;     % dont show training GUI
net.trainParam.showCommandLine = true; % display output in command line
net.trainParam.show = 1;               % display output every iteration

% train networks (data is divided into train/validation/test sets)
net = init(net);           % initialize network weights
[net,tr] = train(net, x, y);

% save pre-trained network to MAT-file
save('pretrained_network.mat', 'net')

接下来创建一个可部署的函数来加载保存的网络,并使用它来预测给定一些测试数据的输出(注意使用%#functionpragma行):

模拟SavedNet.m

function y_hat = simulateSavedNet(x)
    % this is a special pragma for MATLAB Compiler
    % used to declare "network" class as dependency in deployed mode
    %#function network

    % load pre-trained network
    S = load('pretrained_network.mat', 'net');
    net = S.net;

    % predict outcome given input data
    %y_hat = net(x);
    y_hat = sim(net, x);
end

2)从预训练的网络生成一个独立的 M-function

您可以使用 ,从预先训练的网络对象生成独立的 MATLAB 函数genFunction,然后可以使用该函数来模拟网络输出。此功能是在 MATLAB R2013b 中引入的。

它基本上将网络设置、结构和权重硬编码在一个 M 函数中。mcc生成的函数与 MATLAB Compiler (编译到支持的目标之一)以及 MATLAB Coder codegen(转换为独立的 C/C++ 代码)完全兼容。

% generate standalone M-function from the trained net
genFunction(net, 'simulateStandaloneNet.m', 'MatrixOnly','yes', 'ShowLinks','no')

下面是生成函数的代码:

模拟独立网络.m

3)手动模拟预训练的网络

对于简单的静态神经网络(前馈等),评估预训练网络并模拟其输出相对容易(困难的部分是训练它们!)。

我已经在之前的 答案中展示了如何做到这一点。您基本上从网络中提取学习的权重,然后将这些数字插入传递函数,为其提供输入,并计算传播的输出(一次一层)。您必须注意对数据进行任何预处理/后处理,并在每一层中使用相同的传递函数。

事实上,这基本上是genFunction前一种方法所做的,只是它是自动化的并处理所有情况(适用于各种神经网络,而不仅仅是前馈 ANN)。

这是上面训练的网络的一个例子:

模拟手册网.m

function y_hat = simulateManualNet(x)
    % pre-trained feed-forward neural network
    % contains one hidden layer with 4 neurons, 1D input, 1D output
    % We assume the default transfer functions, preprocessing, etc..

    % The following hardcoded values were obtained
    % from net.IW, net.LW, net.b properties using MAT2STR

    % hidden layer weights/biases
    b1 = [6.0358701949521; 2.72569392497815; 0.584267717191459; -5.1615078566383];
    W1 = [-14.0019194910639; 4.90641117353245; -15.2282807645331; -5.26420794868803];
    % output layer weights/biases
    b2 = -0.756207251486408;
    W2 = [0.548462643231606 -0.435802343861239 -0.085111261420613 -1.13679228253379];

    % scale input
    in = mapFcn(x);

    % hidden layer
    hid = hiddenLayerTransferFcn(bsxfun(@plus, W1*in, b1));

    % output layer
    out = outputLayerTransferFcn(W2*hid + b2);

    % inverse scale output
    y_hat = mapInverseFcn(out);
end

function xx = mapFcn(x)
    % linear mapping from [mn,mx] to [-1,1]
    mn = 0; mx = 9.97628374728129;
    xx = (x - mn)*2 / (mx - mn) - 1;
end
function x = mapInverseFcn(xx)
    % inverse linear mapping from [-1,1] to [mn,mx]
    mn = 0; mx = 10;
    x = (xx + 1) * (mx - mn)/2 + mn;
end
function out = hiddenLayerTransferFcn(in)
    % Hyperbolic tangent sigmoid transfer function
    out = tanh(in);
end
function out = outputLayerTransferFcn(in)
    % Linear transfer function
    out = in;
end

4)从预训练的网络生成 Simulink 模块,并使用 Simulink Coder 进行转换

这里的想法是使用 由预训练网络生成 Simulink 模块,然后使用Simulink Coder(以前称为 Real-Time Workshop)gensim将生成的模块转换为独立的 C/C++ 应用程序。在 R2010b 中引入了将神经网络编译为 Simulink 模块。

我不是 Simulink 专家,所以我将留给您探索这种方法

gensim(net)

在上述每种方法中(无论如何都是前三种),其想法是simulate通过 MATLAB 编译器(独立可执行文件、共享库、Java 包、.NET 程序集)将函数编译为支持的目标之一,然后部署生成的组件。

(其实方法#2和#3也可以使用MATLAB Coder转换成C/C++源代码codegen)。

mcc以下是如何使用命令将每个编译成共享库(deploytool如果您愿意,可以使用):

% 1) saved network
mcc -v -W cpplib:libANN -T link:lib -N -p nnet simulateSavedNet.m -a pretrained_network.mat

% 2) standalone simulation function (genFunction)
mcc -v -W cpplib:libANN -T link:lib -N simulateStandaloneNet

% 3) standalone simulation function (manual)
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

测试程序的代码:

测试网.cpp

#include <cstdlib>
#include <iostream>
#include "libANN.h"

// choose one!
//#define SIMFCN simulateSavedeNet
//#define SIMFCN simulateStandaloneNet
//#define SIMFCN simulateManualNet

int main()
{
    // initialize MCR and lib
    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 {
        // create input data (1x5 vector)
        double x[] = {1.0, 3.0, 5.0, 7.0, 9.0};
        mwArray in(1, 5, mxDOUBLE_CLASS, mxREAL);
        in.SetData(x, 5);

        // predict network output by simulating network
        mwArray out;
        SIMFCN(1, out, in);
        double y[5];
        out.GetData(y, 5);

        // show result
        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;
    } 

    // cleanup
    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

于 2014-08-06T03:27:06.403 回答
2

不幸的是,您不能通过 deploytool 创建独立的神经网络程序(因此使用 matlab 编译器)确实是正确的。

替代品

  1. 您可以先训练网络,然后构建独立程序,但似乎您想在创建后进行训练。
  2. 您可以查看 matlab 编码器;这基本上是从 matlab 创建程序的“另一种方式”。我无法找到它是否支持神经网络,但如果你正在考虑这个选项,你可以联系 mathworks。
  3. 考虑不制作独立程序。例如,根据您的需要,您可以从不同的程序或命令行调用 matlab 来完成其工作。
于 2014-08-05T12:12:32.257 回答
2

无法使用部署产品(MATLAB Compiler、MATLAB Builder 产品)或代码生成产品(MATLAB Coder 等)部署 Neural Network Toolbox 的网络训练功能。

您可能会考虑为神经网络使用第三方工具箱,例如Netlab。Netlab 不包括 Neural Network Toolbox 的所有神经网络功能,但它包括最常用的功能,以及 Statistics Toolbox 更好地涵盖的一些额外方法,例如 K-means 聚类。

我不知道在部署 Netlab 功能时有任何技术问题,而且我相信它是根据 BSD 开源许可证获得许可的,因此您应该能够毫无问题地在您的项目中包含和重新分发它。


编辑:从 R2016b 开始,现在可以从神经网络工具箱(或现在已知的深度学习工具箱)编译网络训练功能。

于 2014-08-05T16:39:27.070 回答