softMax层反向传播图如图所示,这里我们将图中-ti/yi的反向传播泛化为Li,方便我们的推导。
这里我们规定S=exp(a1)+...+exp(an) , yi=exp(ai)/S
-
"乘"节点
有两个分支,对于向上的分支:Li*exp(ai) 然后将所有分支相加: ∑Li*exp(ai)
对于向下分支:Li/S
-
"除"节点
对除法求导后乘上前面传递过来的梯度:
(-1/S^2)∑Li*exp(ai)
-
"加”节点
加法直接传递过去
-
“exp”节点
y=exp(x) -> y'=exp(x) 从而:
对于上面的分支:
(-1/S^2)*exp(ai)*∑Lj*exp(aj)=exp(ai)/S*∑(Lj*exp(aj)/S)=yi*∑(Lj*yj)
下面的分支(对应之前的乘节点):
Li*exp(ai)/S=Li*yi
将两个分支结果相加:
dxi= Li*yi+yi*∑(Lj*yj)
代码实现为:
class Softmax:
def __init__(self):
self.params, self.grads = [], []
self.out = None
def forward(self, x):
self.out = softmax(x)
return self.out
def backward(self, dout): #?
dx = self.out * dout
sumdx = np.sum(dx, axis=1, keepdims=True)
dx -= self.out * sumdx
return dx