最近碰到这样一个问题:为什么ReLU函数作为激活函数不会有梯度消失问题,明明当x<=0时函数的梯度为0,当他往回传的时候与前面梯度相乘,不就全部为0了吗,而sigmoid激活函数虽然x很远时梯度特别特别小,但是至少还是有值的啊。sigmoid函数有梯度消失,而ReLU函数竟然没有梯度消失,真是太奇怪了。
原因请看下图:
假设最后一层relu层是输出,误差error取(y*-y)的平方。当这层某个神经元的relu的输入小于等于0时,梯度为0,x2*w2+b的误差为此时的梯度乘以这个神经元的输出的error,也就是为0了。当这层某个神经元的relu的输入大于0时,梯度为1,x2*w2+b的误差为它的梯度1乘以这个神经元的error,等于error。找到了后面一层relu函数的输入的误差之后,再来寻找前面一层relu函数的输出的误差,也就是x2的误差,因为是找x2的误差所以用x2*w2+b对x2求偏导,得到w2,这个w2就是梯度,也是斜率,用它乘以后面传来的误差就是x2的误差(相当于在坐标系中斜率乘deltx得到delty,这里的deltx就相当于后面传来的error,这里也可以将error看成是权重,error大的,往前传的时候使前面w改变大),用矩阵的形式表示就如上图的Delt(X2),而当用sigmoid函数时就如下面的那个式子一样,W2是一个矩阵,它乘以向量里面是做加法,而不是想象的0乘以所有的梯度都为0,这个时候relu函数的优势就出来了,假设取随机的一半为0一半为1,Delt(X2)还是有较大更新;而对于sigmoid函数,W2要与后面每个很小的数相乘,所以累加后还是很小,Delt(X2)更新较小。当网络层数特别深的时候relu的优势就是巨大的。当层数很浅的时候还是sigmoid函数的性能比较好,因为它毕竟有非常好的非线性能力(比relu函数强太多了),抵消了它的梯度消失问题,而且层数浅时梯度消失问题也不是很严重。得到x2的误差之后可以求前面一层relu函数的输入也就是x1*w1+b1的误差,这个误差的求法是跟前面一层一样,当x1*w1+b1小于等于0时,梯度为0,乘以delt(x2)为0,当神经元 的输入大于0时,x1*w1+b1的误差为delt(x2),有了x1*w1+b1的误差又能求x1的误差就是w1乘以delt(x2)或者0,就这样误差一步一步向前传递。再更新w时就要求w的误差,同样就是用x*w+b对w偏导就是x,用x乘以后面面的误差(也是类似于斜率乘以deltx得到y的变化量,这里的误差就是deltx,就是类似误差带来的权重)得到deltw,就是这层w需要变化的量。