赞
踩
BP神经网络算法部分原理推导(梯度下降法)
20160715xujie
以下图所示网络为例,来源于网上某位大神的BP网络C代码,根据C代码源码进行理解。
上图显示的是一个只含有一个隐含层的网络,(对于一个刚接触ANN的人,好吓人的说,不要怕,看完后面你就不怕他了),隐层和输出层的神经元激活函数都是Sigmod函数:
每一个神经元的输入加权求和之后作为Sigmod函数的输入:
其中,Wji是上一层第i个神经元与当前层第j个神经元之间的系数(权值),这样就构成的整个网络的前向传播,那么后向传播的参数调整是如何实现的呢?
已知,每一个训练样本的输入(X[n][0],X[n][1], X[n][2], X[n][3],)都对应着一个期望的输出(d[n][0], d[n][1], d[n][2]);那么,网络实际上的输出值(y[n][0],y[n][1],y[n][2])与期望值之间就会存在差异,这个差值就作为梯度下降法的损失函数E:(这个损失函数指的是针对单个样本):
我先这样来理解一下神经网络,在神经网络中,从输入开始,每一层的输入都是上一层所有神经元的计算结果,也就是说总是先计算上一层,在计算下一层,数据经过每一层都会有相应的输出,回忆一下高等数学中的嵌套函数,不也是一样的吗?总是先计算内函数(上一层),在把内函数的计算结果(上一层的输出)当做自变量继续计算。
好了,如果我们把网络比喻成了嵌套函数,那么,网络中的参数也就好理解了,比如说有一个嵌套函数:
P(x,y,z)=f(w0*g(w3*x,w4*y),w1*u(w5*y,w6*t(w7*x,w8*z)),w2*q(w9*y,w10*z));
我们可以宏观的理解为P函数由三个自变量x,y,z和w0---w10这十一个系数构成的,如果我们已知这个函数的若干个点(xi,yi,zi)和对应的P函数值P(xi,yi,zi),要拟合这个函数的话,就是已知x,y,z去求解其中的系数嘛,这时每一个系数成了自变量,我的天,11个自变量的大函数哦,P(w0,w1,w2,w3,...,w10)。
好了,回到神经网络,在BP神经网络中,我们想要求解 来修正Wji(看一下梯度下降法就知道为啥了),但是损失函数E的定义中并没有Wji,只有yj和dj(这里j代表输出层,所以E得定义中用的是下标j),又因为dj不是自变量,所以针对输出层的第n个神经元,目前我们只能得到
for(k=0;k<nk;k++)/*单样本循环*/
{
for(i=0;i<ni;i++)//计算隐层
{
t=0;
for(h=0;h<nh;h++)
t+=whi[h][i]*x[k][h];
xi[i]=t+thi[i]; //thi应该是偏置
yi[i]=sigmoid(xi[i]);//激活函数输出
}
for(j=0;j<nj;j++)//计算输出层
{
t=0;
for(i=0;i<ni;i++)
t+=wij[i][j]*yi[i];
xj[j]=t+thj[j];
yj[j]=sigmoid(xj[j]);
}
for(j=0;j<nj;j++)/*输出层单样本点误差变化*/ //这里是变化率,而不是偏微分,所以少了一项yi,是为了方便下一步计算;其实在更新Wji时,是会补上这个yi的。
pxj[j]=yj[j]*(1-yj[j])*(yj[j]-d[k][j]);//
for(i=0;i<ni;i++)/*隐层单样本点误差变化率*/
{
t=0;
for(j=0;j<nj;j++)
t+=pxj[j]*wij[i][j];
pxi[i]=yi[i]*(1-yi[i])*t;
}
for(j=0;j<nj;j++)
{
thj[j]=thj[j]-nr*pxj[j];//因为偏置没有输入,输出就是其本身,也就是说相当于输入为a1,输出为thj=Wij,输出为xj=Wij=thj;
for(i=0;i<ni;i++)
wij[i][j]=wij[i][j]-nr*pxj[j]*yi[i];
}
for(i=0;i<ni;i++)
{
thi[i]=thi[i]-nr*pxi[i];
for(h=0;h<nh;h++)
whi[h][i]=whi[h][i]-nr*pxi[i]*x[k][h];//这个x[k][h]相当于yh[h],因为已经到了输入层,所以就是x了
}
t=0;
for(j=0;j<nj;j++)
t+=(yj[j]-d[k][j])*(yj[j]-d[k][j])/2.0;
error[k]=t;
gerror+=error[k];/*全局误差 g(lobal)error*/
}/*单样本循环结束*/
注:具体参考的代码来源想不起来了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。