3、前向和反向传播
1. 单个神经元的前向和反向计算
众所周知,神经网络是由一系列的神经元组成,那具体长什么样呢?可以看下面的图。
所以,对于一个神经元来说,其前向计算公式如下:
其中:为神经网络的激励函数。
为什么要使用激励函数呢?
激活函数是用来加入非线性因素的,增加线性模型的非线性表达能力。
如果没有激活函数,那么我们最终得到只是一系列直线/平面包围的学习区域,如下图:
最终得到的结果还是线性的, 最多不过是复杂的线性组合罢了,当然你可以说我们可以用无限条直线去逼近一条曲线。
但是如果加入激活函数,如sigmoid函数,这是一个不折不扣的非线性函数,如下图。最终我们得到的就是一个非线性的线\曲面。
既然知道了激活函数的好处,那么我们常用的激活函数有哪些呢?这里就不一一列举了,有兴趣的可以查看第一个参考链接中的常见激励函数介绍。在本程序中我们主要使用relu激活函数,该函数的公式为:,其具体形状如下:
这里,我们用c++实现了相关函数:
void NN::relu(Mat &X)
{
//生成大于零的模板并归一化
Mat mask = (X > 0) / 255;
//将矩阵转化为float类型
Mat mask2f;
mask.convertTo(mask2f, CV_32FC1);
//relu计算输出
multiply(X, mask2f, X);
}
参考链接:
【机器学习】神经网络-激活函数-面面观(Activation Function)
这时我们很容易得到单个神经元的梯度,通过分别对w,b求导得到如下公式:
令:,,则:
其中:,,,根据链式法则,最终得到单个神经元得反向传播得计算公式如下:
2. 多层神经网络的前向和反向传播的计算
是不是很简单,答案必须是的。但是如果有多个神经元连接在一起的时候,就会蒙逼了,这时候相对来说对于前向传播可能还比较简单,但反向传播,也就是求各个层的参数的导数,可能无从下手了。当然,这里我们先不着急进行反向传播得计算,先搞清楚前向传播得过程再说。我们假设有如下所示得一个神经网络: