感知器和神经网络训练(公式推导及C++实现)

感知器

感知器是一个二元线性分类器,其目标是找到一个超平面将训练样本进行分隔(分类),其表示为
感知器和神经网络训练(公式推导及C++实现)_第1张图片
一般使用的激活函数不是阶跃函数,常用的有sigmoid函数(其导数: σ=σ(1σ) )
感知器和神经网络训练(公式推导及C++实现)_第2张图片
在1个样本的训练集上代价函数(最小均方误差)通常为

C=12|ay|2

训练过程中步长(学习速率)为 α w b 的新值为
wib=wiαwiC=bαbC

分别求其梯度,由于在神经元中,上一步的输出是下一步的输入,也就是下一步中的自变量,根据链式法则可以得到
CwiCb=Czzwi=Czzb

其中
Czzwizb=Caaz=12a|ay|2az=(ay)σ(1σ)=wi(i=0n1wixi+b)=xi=wi(i=0n1wixi+b)=1

最终可得
CwiCb=Czzwi=Caazzwi=(ay)σ(z)(1σ(z))xi=Czzb=Caazzb=(ay)σ(z)(1σ(z))

最终对有k个训练样本的感知机的迭代函数为

wib=wiα1kk=0k1(akyk)σ(z)(1σ(z))xi=bα1kk=0k1(akyk)σ(z)(1σ(z))

多层神经网络

感知器可以看成一个最简单的二层神经网络,作为一个线性分类器它使用的局限性太大,而多层神经网络可以弥补它的缺点,并且训练原理与其类似
感知器和神经网络训练(公式推导及C++实现)_第3张图片
上图的三层神经网络多了一个隐含层,其中隐含层和输出层均为左下角的神经元,这个神经网络在训练过程时需要训练两层的神经网络,并且隐层的误差无法直接获取,而输出层的误差则和感知器相同:
同样在1个样本的训练集上代价函数(均方误差)通常为

C=12i=0n1|ajiyji|2

也就是输出层每个神经元的输出和对应的目标值误差的平方和。

训练输出层

因为只有输出层的误差可以获取,所以训练从输出层开始,对第三层的第一个来说

Cw31iCb31=Ca31a31z31z31w31i=Ca31a31z31x31i=Ca31a31z31a21i=Ca31a31z31z31b31=Ca31a31z31

反向传播,训练隐含层

隐含层的训练也就是BP神经网络的重点,即误差的反向传播过程,因为隐含层的误差无法直接获取,所以才从输出层开始调整参数,然后误差向出入层开始传播,一层一层的进行训练
感知器和神经网络训练(公式推导及C++实现)_第4张图片
以训练隐含层的第一个神经元为例

Cw21i=Cz21z21w1i2=Ca21a21z21z21w1i2=Cz31z31a21a21z21z21w21i+Cz32z32a21a21z21z21w21i=Ca31a31z31z31a21a21z21z21w21i+Ca32a32z32z32a21a21z21z21w21i

这里写图片描述
式子中红色部分即为输出层两个神经元计算过的,蓝色部分
z31=w31a2i+b

z31a21=w31z32a21=w32

weight这些值都是确定的,最后黄色部分也很容易求得。
Cw21iCb21=Ca31a31z31z31a21a21z21a11i+Ca32a32z32z32a21a21z21a11i=Ca31a31z31z31a21a21z21+Ca32a32z32z32a21a21z21

如果有更多层,则都是在后一层计算完成的基础上进行更新。

K个训练样本

同感知器的K个同理,使用k个样本的平均误差进行更新

批随机梯度下降

因为样本的巨大,所以一次不会使用所有的样本进行训练,而是将训练样本分为比较小的部分进行分批训练。

实现

使用三层神经网络识别手写数字。

语言:C++
数据:Mnist

具体实现在我的图像处理库:zMatrix中的zml中。仅做参考

你可能感兴趣的:(计算机视觉,机器学习)