本文将Matlab训练好的神经网络参数导出,在Visual Studio中导入,对数据重新计算。本文的方法可以用于C++调用离线训练好的神经网络。作为神经网络学习之路的一个小小记录

Matlab训练神经网络

首先在Matlab中训练神经网络,本文使用了Matlab的神经网络工具箱中的House Pricing示例模型。

在Matlab命令行界面中键入nnstart进入神经网络工具箱,导入数据,默认隐含层有10个神经元,一路next到这里,导出矩阵参数的神经网络匹配函数

matlab 神经网络训练有弹窗 matlab中神经网络训练_matlab

得到myNeuralNetworkFunction函数,例如下面这个:

matlab 神经网络训练有弹窗 matlab中神经网络训练_matlab 神经网络训练有弹窗_02

可见里面有很多的数据矩阵,那些就是神经网络的权值和偏置参数

写一小段代码,用于测试生成的神经网络,例如:

i=1:15;
predict = myNeuralNetworkFunction(houseInputs(:,i))
result = houseTargets(i);
plot(predict,'b');hold on;
plot(result,'g');

该代码用了生成的神经网络重新计算前15组输入数据,并与真实结果plot在同一幅图像中,可见该神经网络还是比较令人满意的

matlab 神经网络训练有弹窗 matlab中神经网络训练_visual studio_03

导出Matlab的神经网络参数

上文生成的神经网络函数中包含了很多的网络权值和偏移参数,下面将这些参数矩阵导出供Visual Studio读取

  1. myNeuralNetworkFunction退出的地方放置一个断点,让程序跑到这里停止,方便导出数据
  2. matlab 神经网络训练有弹窗 matlab中神经网络训练_matlab_04

  3. 将结构体中的矩阵分别复制出来
x1_xoffset = x1_step1.xoffset
x1_gain = x1_step1.gain
%...方法类似,在此不赘述
  1. 将矩阵保存到文件中
save('x1_gain.txt','x1_gain','-ascii')
save('x1_xoffset.txt','x1_xoffset','-ascii')
%...方法类似,不赘述

注意保存的时候要使用-ascii参数

  1. 可见,Matlab的工作目录中生成了一系列的文件,里面就是响应的矩阵数据,将他们复制到Visual Studio工程目录中

此处我新建了一个data文件夹以免混乱

Visual Studio工程中调用参数

参考本博客文章Visual Studio使用Armadillo线性代数运算库添加Armadillo线性代数库,新建工程,编写代码

注意:貌似LAPACK和BLAS库有点问题,因此到Armadillo的config.hpp中注释掉

#define ARMA_USE_LAPACK #define ARMA_USE_BLAS

这两句,调试阶段,牺牲一点速度吧

代码中矩阵的初始化使用load方法读取文件,如下:

layer1.bias.load("data\\b1.txt", raw_ascii);
layer1.weight.load("data\\IW1_1.txt", raw_ascii);

测试代码

OffLineNeuralNet.hpp

#pragma once
#ifndef _OFFLINE_NEURAL_
#define _OFFLINE_NEURAL_

#include "stdafx.h"
#include <armadillo>

using namespace arma;
using namespace std;

enum Method method;

class Setting
{
public:
    mat xoffset;
    mat gain;
    mat ymin;
};

class Layer
{
public:
    mat bias;
    mat weight;
};

mat mapminmax_apply(mat x, Setting setting)
{
    mat y;
    mat temp = x;
    y = x - setting.xoffset;
    y = y % setting.gain;

    temp.fill(setting.ymin(0, 0));
    y = y + temp;
    return y;
}

mat tansig_apply(mat n)
{
    mat a;
    a = 2 / (1 + exp(-2 * n)) - 1;
    return a;
}

mat mapminmax_reverse(mat y, Setting setting)
{
    mat x;
    mat temp = y;

    temp.fill(setting.ymin(0, 0));
    x = y - temp;

    temp.fill(setting.gain(0, 0));
    x = x / temp;

    temp.fill(setting.xoffset(0, 0));
    x = x + setting.xoffset;
    return x;
}

#endif // !_OFFLINE_NEURAL_

main.cpp

// HousePrizeModel.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <armadillo>
#include "OffLineNeuralNet.h"

#define TOTAL_TEST 15

using namespace arma;

const mat x1_ymin = { -1 };
const mat y1_ymin = { -1 };
const mat y1_gain = { 0.0444444444444444 };
const mat y1_xoffset = { 5 };
const mat layer2_b = { 0.91848175916311114 };

int main()
{

    Setting x1_step1, y1_step1;
    Layer layer1, layer2;

    x1_step1.xoffset.load("data\\x1_xoffset.txt", raw_ascii);
    x1_step1.gain.load("data\\x1_gain.txt", raw_ascii);
    x1_step1.ymin = x1_ymin;

    y1_step1.ymin = y1_ymin;
    y1_step1.gain = y1_gain;
    y1_step1.xoffset = y1_xoffset;

    layer1.bias.load("data\\b1.txt", raw_ascii);
    layer1.weight.load("data\\IW1_1.txt", raw_ascii);

    layer2.bias = layer2_b;
    layer2.weight.load("data\\LW2_1.txt", raw_ascii);

    mat houseInputs;
    vec result(TOTAL_TEST);
    houseInputs.load("data\\houseInputs.txt", raw_ascii);

    for (int i = 0; i < TOTAL_TEST; i++)
    {
        mat x1 = houseInputs.col(i);

        mat xp1 = mapminmax_apply(x1, x1_step1);
        mat a1 = tansig_apply(layer1.bias + layer1.weight * xp1);
        mat a2 = layer2.bias + layer2.weight*a1;

        double result_temp = mapminmax_reverse(a2, y1_step1)(0);
        result.at(i) = result_temp;


    }

    result.print("Target = ");

    system("pause");

    return 0;
}

同样测试了数据集的前15组数据,结果如下:

matlab 神经网络训练有弹窗 matlab中神经网络训练_matlab 神经网络训练有弹窗_05