在mlpack中实现极其高效的前馈神经网络(C++)

strint 2018-11-06

MLPACK是一个用C ++编写的快速,灵活的机器学习库,为用户提供各种强大的机器学习模型和高度优化的常用ML任务中使用的数学函数实现。有关它提供的高级功能列表,请查看此链接(https://www.mlpack.org/about.html)。

在本教程中,我想向您展示实现一个简单的多层神经网络模型。本文侧重于更深入地了解它的实现方面,而不是深度学习本身的理论方面。

前提条件:

  • 您现在已在系统上安装了MLPACK。
  • 您对前馈神经网络以及简单的FFN模型包含的内容有基本的了解(输入层,输出层,损失函数和中间的一堆隐藏层,以及您选择的激活函数)
  • 您的系统上安装了python3。{5 | 6}。(用于生成数据,可选)

示例数据集

使用python脚本生成一些人工(非线性可分离)数据。

import numpy as np
import math
# number of data points to generate
size = 400
# data points generated using this func
# given X, radius R return Y = SquareRoot(R^2 - X^2)
def circle(x,r):
 return math.sqrt(r**2-x**2)
# Generate 400 random datapoints for X between [-3.0,3.0] 
X = np.random.uniform(low=-3.0,high=3.0,size=size)
Y = []
# Generate 400 random labels = (1,0)
O = np.random.randint(low=0,high=2,size=size) # [low,high)
# Find Y for each given X
for x,o in zip(X,O): 
 if o == 1 :
 Y.append(circle(x,3.5)) 
 else: 
 Y.append(circle(x,4.0))
data = []
for x,y,o in zip(X,Y,O):
 data.append([x,y,int(o)])
np.savetxt("foo.csv", data, delimiter=",")

在mlpack中实现极其高效的前馈神经网络(C++)

foo.csv的格式:

  • 第0,1列=特征0,特征1
  • 第2列=标签

绘制数据,如下图所示。数据点属于2个单独的标签,如不同颜色所示。

在mlpack中实现极其高效的前馈神经网络(C++)

在mlpack中实现极其高效的前馈神经网络(C++)

请注意,MLPACK使用Armadillo库(C ++ lib for linear algebra),它以 column-major ordering存储矩阵,因为它在内存带宽使用和缓存性能方面更有效,可以访问数组的元素,顺序是按照它们在内存中的排列顺序排列的。

神教网络型概述

我们在这里遇到的问题是二进制分类。

  • 损失函数: 均方误差
  • 输入层: 8个感知器(2个输入),每个(2x8),Sigmoid激活函数。
  • 隐藏层: 8个感知器(8个输入),每个(8x8),Sigmoid激活函数。
  • 输出层: 1个感知器(8个输入),每个(8x1),Sigmoid激活函数。

编码,(C ++ 11)

我们将从从mlpack导入必需的.hpp文件开始

#include <mlpack/core.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/loss_functions/mean_squared_error.hpp>
#include <mlpack/methods/ann/ffn.hpp>

接下来,我们将使用mlpack、armadillo和stdlib,声明我们将使用的命名空间

using namespace mlpack;
using namespace mlpack::ann;
using namespace mlpack::optimization;
using namespace arma;
using namespace std;

启动main()并加载数据

int main(){
 
 mat data;
 data::Load("foo.csv",data,true);

mat数据类型是在armadillo库中定义的,它是密集矩阵的存储类,元素以column-major顺序存储。MLPACK定义了一个load函数,用于将数据从csv文件加载到mat变量中。

将数据拆分为火车和测试集

mat traindata = data.submat(0, 0,
 data.n_rows-2,data.n_cols-6);
mat trainlabels = data.submat(data.n_rows-1,0,
 data.n_rows-1,data.n_cols-6);
mat testdata = data.submat(0, data.n_cols-5,
 data.n_rows-2,data.n_cols-1);
mat testlabels = data.submat(data.n_rows-1,data.n_cols-5,
 data.n_rows-1,data.n_cols-1);

在mlpack中实现极其高效的前馈神经网络(C++)

在上面给出的代码中,我们将数据点总数分为2组,train (number of points-5)和test set(5个数据点)。你可以随意调整数字(5)。

在mlpack中实现极其高效的前馈神经网络(C++)

神经网络模型

FFN<MeanSquaredError<>, RandomInitialization> model;
 model.Add<Linear<> >(traindata.n_rows,8);
 model.Add<SigmoidLayer<> >();
 model.Add<Linear<> >(8,8);
 model.Add<SigmoidLayer<> >();
 model.Add<Linear<> >(8,1);
 model.Add<SigmoidLayer<> >();

在mlpack中实现极其高效的前馈神经网络(C++)

通过训练函数循环4个epochs

for (int i = 0; i < 4; ++i)
 {
 model.Train(traindata, trainlabels);
 }

经过训练,对测试数据进行预测,

mat assignments;
 model.Predict(testdata, assignments);
 cout<<"Predictions : "<<assignments<<endl;
 cout<<"Correct Labels : "<<testlabels<<endl;
 return 0;
}

在mlpack中实现极其高效的前馈神经网络(C++)

这就是代码的结尾。

编译和运行代码

假设文件名是mlp-mlpack.cpp,使用以下命令编译并运行代码。

g++ mlp-mlpack.cpp -o mlp-mlpack -std=c++11 -larmadillo -lmlpack

./mlp-mlpack

输出

c++代码应该给出以下输出

在mlpack中实现极其高效的前馈神经网络(C++)

正如所见,这些预测相当准确。

相关推荐