如何在MATLAB中编译训练神经网络作为独立应用程序?

如何在MATLAB中编译训练神经网络作为独立应用程序?,matlab,neural-network,matlab-deployment,matlab-compiler,mcc,Matlab,Neural Network,Matlab Deployment,Matlab Compiler,Mcc,我想将我的MATLAB应用程序用于一个独立的应用程序,但正如大家所知,MATLAB不能将训练神经网络编译为独立的,只能编译已经训练过的神经网络 我的应用程序的核心是在导入的数据上训练神经网络。我该怎么做?有没有其他方法可以做到这一点?我的MATLAB版本是R2014a 我尝试使用deploytool进行编译,但根据MATLAB编译器文档: THIS CAN BE COMPILED * Pre-trained network * command line functions THIS C

我想将我的MATLAB应用程序用于一个独立的应用程序,但正如大家所知,MATLAB不能将训练神经网络编译为独立的,只能编译已经训练过的神经网络

我的应用程序的核心是在导入的数据上训练神经网络。我该怎么做?有没有其他方法可以做到这一点?我的MATLAB版本是R2014a

我尝试使用
deploytool
进行编译,但根据MATLAB编译器文档:

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
因此,如果我们的代码中有类似于
newff
patternnet
的函数或其他训练函数,那么编译应用程序后就会出错

我知道这是MATLAB编译器的一部分,几个月来我一直在寻找解决方案,但我没有找到任何解决方法或替代方法


显然,新版本的MATLAB中增加了一个函数,用于在MATLAB编译器中使用经过训练的神经网络:。

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

备选方案

  • 您可以先训练一个网络,然后构建独立的程序,但似乎您希望在创建网络后进行训练
  • 你可以看看matlab编码器;这基本上是从matlab创建程序的“另一种方式”。我还没有找到它是否支持神经网络,但是如果你正在考虑这个选项,你可以联系mathworks
  • 考虑不要制作一个独立的程序。例如,根据您的需要,您可以从不同的程序或命令行调用matlab来完成其工作

  • 使用部署产品(MATLAB编译器、MATLAB Builder产品)或代码生成产品(MATLAB编码器等)部署神经网络工具箱的网络训练功能是不可能的

    您可以考虑为神经网络使用第三方工具箱,例如。Netlab不包括神经网络工具箱的所有神经网络功能,但它包括最常用的功能,以及统计工具箱更好地涵盖的许多额外方法,如K-均值聚类

    我不知道在部署Netlab功能时会出现任何技术问题,而且我相信它是在BSD开源许可下获得许可的,因此您应该能够在项目中包含并重新发布它,而不会出现任何问题



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

    底线是MATLAB编译器只部署预训练的神经网络

    神经网络工具箱

    可编辑:

    • 预先培训的网络命令行功能
    无法编译:

    • 所有其他命令行功能
    • 应用程序和用户界面
    • 模拟块
    • gensim
    这意味着您不能使用训练功能(包含的任何内容等)编译函数,只能部署评估/模拟已训练的网络对象(函数等)的函数


    对于受支持的场景(部署预先培训的网络),有两种方法:

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

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

    simulateSavedNet.m 2) 您可以使用从预先训练的网络对象生成一个独立的MATLAB函数,然后可以使用该函数模拟网络输出。该功能是在MatlabR2013B中引入的

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

    以下是生成的函数的代码:

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

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

    事实上,这基本上是
    genFunction
    在前面的方法中所做的,只是它是自动化的,并且可以处理所有情况(适用于所有类型的神经网络,而不仅仅是前馈神经网络)

    以下是上述培训网络的一个示例:

    模拟器UALNET.m 4) 这里的想法是使用预先训练的网络生成Simulink块,然后使用(以前称为Real Time Workshop)将生成的块转换为独立的C/C++应用程序。R2010b中介绍了将神经网络编译为Simulink块

    我不是Simulink专家,所以我将让您来探索:


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

    (实际接近#2和#
    % 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')
    
    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
    
    % generate standalone M-function from the trained net
    genFunction(net, 'simulateStandaloneNet.m', 'MatrixOnly','yes', 'ShowLinks','no')
    
    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
    
    gensim(net)
    
    % 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
    
    % 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
    
    #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;
    }
    
    >> 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