Softmax层 输出&梯度推导及Python实现
详细代码在这里,存在于Layer.py中的Softmax类里面
推导
太长不看 下面有结论及代码

结论
约定:Input = I 输入,Output = O 输出
- Softmax层的前向传播非常简单,就是输入向量的每个分量取指数,再除以所有分量的指数和即可
- 反向传播需要计算输出向量对输入向量的导数,输出向量i分量(Oi)对输入向量的分量j(Ij)的导数分为两种情况:
- i=j 时,其值等于 Oi * (1 - Oi)
- i≠j 时,其值等于 -1 * Oi * Ij
- 整个输出向量O,欲求O对于 Ii 的导数,必须依次计算 O1,O2, O3 …On 对 Ii的导数,再将他们加和,作为 O 对 Ii 的导数
代码
# Forward propagation
# param x : last layer's output
# 前向传播
# x 是当前层的输入
def FP(self, x):
self.input = x.copy()
self.expi = np.exp(self.input)
self.sum = np.sum(self.expi)
self.output = self.expi / self.sum
self.next_layer.FP(x=self.output)
# Back propagation
# param gradient : last layer's gradient
# param lr : learning rate
# 反向传播,gradient是当前层输出对损失函数的梯度, lr是学习率
def BP(self, gradient, lr):
self.gradient = gradient.copy()
self.tp = self.expi/self.sum
self.last_layer_gradient = np.zeros(shape=self.input_shape, dtype=np.float64)
for i in range(self.input_shape[0]):
# gradient for Input[i]
# 输入向量 Input 的第 i 个位置的梯度
self.gradient_for_Ii = np.zeros(shape=self.input_shape, dtype=np.float64)
for j in range(self.input_shape[0]):
if i == j:
self.gradient_for_Ii[j] = self.output[i]*(1 - self.output[i])
else:
self.gradient_for_Ii[j] = -1 * self.output[i] * self.output[j]
self.last_layer_gradient[i] = np.sum(self.gradient_for_Ii * self.gradient)
self.last_layer.BP(gradient=self.last_layer_gradient, lr=lr)