![00156fa129e5e1fde3bfa60dc8bba59c.png](https://i-blog.csdnimg.cn/blog_migrate/39d9045becfb0c3622bd8ba3024d1aa6.jpeg)
写这篇文章的动机来源于计算机视觉课最近的一次编程作业,要手写CNN的前向传播和反向传播。特地准备把用到的一些技巧以及数学推导都记录下来。该篇此属系列文章之一。另一篇请见:
清流:卷积加速im2col和梯度反向传播zhuanlan.zhihu.com![d0025b24027fc388ea84a240abf8c425.png](https://i-blog.csdnimg.cn/blog_migrate/6f3cb590d984bb9351e33617748acca2.jpeg)
Softmax的数值稳定性
Softmax函数
其输入是一个
交叉熵损失函数(Cross Entropy Loss)经常和Softmax一起使用,定义如下:
在编程实现的时候容易发现直接用Softmax容易出现各种损失函数爆炸、梯度爆炸的问题,这是因为浮点数的范围是有限的。在做指数运算
然后简单验证一下这个均值迁移操作不影响Softmax后的概率分布。
记
由此可见,对输入
但是迁移会带来另外一个问题,如果
Softmax的梯度反向传播
计算损失函数(Cross Entropy Loss)相对于Softmax输入的梯度。
直接算导数需要分情况讨论后半部分导数的问题,所以考虑直接把两部分都别写成Jacobian形式然后直接算矩阵乘积即可,具体地,由链式法则
其中
对
若为对角单元(
若为非对角单元(
有了上面的公式,
算出
实现代码:
def loss_cross_entropy_softmax(x, y):
# TO DO
'''
Compute the cross entropy loss.
Args:
x: The input to the softmax layer, of size [m,1]
y: The ground truth
Returns:
l: The loss
dl_dx: The loss derivative with respect to x
'''
x_shift = x - np.max(x) # [m,1]
x_exp = np.exp(x_shift) # [m,1]
y_tilde = x_exp / np.sum(x_exp) # [m,1]
y_log = np.log(y_tilde+1e-9) # [m,1]
l = -np.sum(np.multiply(y_log, y)) # [1,1]
dl_dy_tilde = -np.multiply(1/(y_tilde+1e-9), y) # [m,1]
dy_dx = -np.dot(y_tilde, y_tilde.T) + np.diag(y_tilde.flatten()) # [m,m]
dl_dx = np.dot(dl_dy_tilde.T, dy_dx)
return l, dl_dx
本篇完结 _(:з」∠)_