c++调用matlab神经网络,BP神经网络原理及C++实战

前一段时间做了一个数字识别的小系统,基于BP神经网络算法的,用MFC做的交互。在实现过程中也试着去找一些源码,总体上来讲,这些源码的可移植性都不好,多数将交互部分和核心算法代码杂糅在一起,这样不仅代码阅读困难,而且重要的是核心算法不具备可移植性。设计模式,设计模式的重要性啊!于是自己将BP神经网络的核心算法用标准C++实现,这样可移植性就有保证的,然后在核心算法上实现基于不同GUI库的交互(MFC,QT)是能很快的搭建好系统的。下面边介绍BP算法的原理(请看《数字图像处理与机器视觉》非常适合做工程的伙伴),边给出代码的实现,最后给出基于核心算法构建交互的例子。

人工神经网络的理论基础

1.感知器

感知器是一种具有简单的两种输出的人工神经元,如下图所示。

99cce85e8a622dc87d1726074a6d9967.png

2.线性单元

只有1和-1两种输出的感知器实际上限制了其处理和分类的能力,下图是一种简单的推广,即不带阈值的感知器。

de76eed1762f2f4c59b97023cbdf221c.png

3.误差准则

使用的是一个常用的误差度量标准,平方误差准则。公式如下。

95732e0ea88892cd264ff7a38d9b5437.png

其中D为训练样本,td为训练观测值d的训练输出,ot为观测值d的实际观测值。如果是个凸函数就好了(搞数学的,一听到凸函数就很高兴,呵呵!),但还是可以用梯度下降的方法求其参数w。

4.梯度下降推导

在高等数学中梯度的概念实际上就是一个方向向量,也就是方向导数最大的方向,也就是说沿着这个方向,函数值的变化速度最快。我们这里是做梯度下降,那么就是沿着梯度的负方向更新参数w的值来快速达到E函数值的最小了。这样梯度下降算法的步骤基本如下:

1)初始化参数w(随机,或其它方法)。

2)求梯度。

3)沿梯度方向更新参数w,可以添加一个学习率,也就是按多大的步子下降。

4)重复1),2),3)直到达到设置的条件(迭代次数,或者E的减小量小于某个阈值)。

梯度的表达式如下:

cf8a73942b54f4e65f9fad99412b57a6.png

那么如何求梯度呢?就是复合函数求导的过程,如下:

4a9fe3ad0ebd3d88d2bd478fdf1f2734.png

其中xid为样本中第d个观测值对应的一个输入分量xi。这样,训练过程中参数w的更新表达式如下(其中添加了一个学习率,也就是下降的步长):

96ab829757812fafd84066d4df7b63c1.png

于是参数wi的更新增量为:

d69ba0ef81427f30e26b852a0c22fadf.png

对于学习率选择的问题,一般较小是能够保证收敛的,看下图吧。

a04dc2b5df4f93bd9a373c2e7cb4258f.png

5.增量梯度下降

对于4中的梯度下降算法,其缺点是有时收敛速度慢,如果在误差曲面上存在多个局部极小值,算法不能保证能够找到全局极小值。为了改善这些缺点,提出了增量梯度下降算法。增量梯度下降,与4中的梯度下降的不同之处在于,4中对参数w的更新是根据整个样本中的观测值的误差来计算的,而增量梯度下降算法是根据样本中单个观测值的误差来计算w的更新。

6.梯度检验

这是一个比较实用的内容,如何确定自己的代码就一定没有错呢?因为在求梯度的时候是很容易犯错误的,我就犯过了,嗨,调了两天才找出来,一个数组下表写错了,要是早一点看看斯坦福大学的深度学习基础教程就好了,这里只是截图一部分,有时间去仔细看看吧。

25d252c4064fcf57e3bd6a7c9d35d18e.png

多层神经网络

好了有了前面的基础,我们现在就可以进行实战了,构造多层神经网络。

1.Sigmoid神经元

Sigmoid神经元可由下图表示:

4059a1b036d6d0df072468e0c458372f.png

2.神经网络层

一个三层的BP神经网络可由下图表示:

7b8493753d253b725bf5c74cb702a9a4.png

3.神经元和神经网络层的标准C++定义

由2中的三层BP神经网络的示意图中可以看出,隐藏层和输出层是具有类似的结构的。神经元和神经网络层的定义如下:

// Neuron.h

#ifndef __SNEURON_H__

#define __SNEURON_H__

#define NEED_MOMENTUM //if you want to addmomentum, remove the annotation

#define MOMENTUM 0.6 //momentumcoefficient, works on when defined NEED_MOMENTUM

typedef double WEIGHT_TYPE; // definedatatype of the weight

struct SNeuron{//neuron cell

/******Data*******/

intm_nInput; //number of inputs

WEIGHT_TYPE*m_pWeights;  //weights array of inputs

#ifdef NEED_MOMENTUM

WEIGHT_TYPE*m_pPrevUpdate; //record last weights update when momentum is needed

#endif

doublem_dActivation; //output value, through Sigmoid function

doublem_dError; //error value of neuron

/********Functions*************/

voidInit(int nInput){

m_nInput= nInput + 1; //add a side term,number of inputs is actual number of actualinputs plus 1

m_pWeights= new WEIGHT_TYPE[m_nInput];//allocate for weights array

#ifdef NEED_MOMENTUM

m_pPrevUpdate= new WEIGHT_TYPE[m_nInput];//allocate for the last weights array

#endif

m_dActivation= 0; //output value, through SIgmoid function

m_dError= 0;  //error value of neuron

}

~SNeuron(){

//releasememory

delete[]m_pWeights;

#ifdef NEED_MOMENTUM

delete[]m_pPrevUpdate;

#endif

}

};//SNeuron

struct SNeuronLayer{//neuron layer

/************Data**************/

intm_nNeuron; //Neuron number of this layer

SNeuron*m_pNeurons; //Neurons array

/*************Functions***************/

SNeuronLayer(intnNeuron, int nInputsPerNeuron){

m_nNeuron= nNeuron;

m_pNeurons= new SNeuron[nNeuron];  //allocatememory for nNeuron neurons

for(inti=0; i

m_pNeurons[i].Init(nInputsPerNeuron);  //initialize neuron

}

}

~SNeuronLayer(){

delete[]m_pNeurons;  //release neurons array

}

};//SNeuronLayer

#endif//__SNEURON_H__

代码中定义了一个NEED_MOMENTUM,它是用来解决局部极小值的问题的,其含义是本次权重的更新是依赖于上一次权重更新的。另外还有一种解决局部极小值问题的方法是,将w初始化为接近于0的随机数。

4.反向传播(BP)算法

前面虽然有了神经元和神经网络层的定义,但要构造一个三层的BP神经网络之前,还要搞清楚BP算法是如何来学习神经网络的参数的。它仍采用梯度下降算法,但不同的是这里的输出是整个网络的输出,而不再是一个单元的输出,所有对误差函数E重新定义如下:

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值