Softmax 损失-梯度计算

本文介绍Softmax运算、Softmax损失函数及其反向传播梯度计算, 内容上承接前两篇博文 损失函数 & 手推反向传播公式

Softmax 梯度

设有K类, 那么期望标签y形如\([0,0,...0,1,0...0]^T\)的one-hot的形式. softmax层的输出为\([a_1,a_2,...,a_j,...a_K]^T\), 其中第j类的softmax输出为:

\[ \begin{align} a_{j} &= \frac{\exp(z_{j})}{\sum_{k=1}^K \exp(z_{k})} \forall j\in 1...K \\ {\partial a_{j}\over \partial z_{j} } &= {\exp(z_{j})\cdot(\Sigma - \exp(z_{j}) )\over \Sigma^2} = a_j(1 - a_j) \\ {\partial a_{k}\over \partial z_{j} } &= { - \exp(z_{k}) \cdot \exp(z_{j}) \over \Sigma^2} = -a_j a_k \tag{$k\ne j$} \end{align} \]

如果是全连接的DNN,那么有: \(z_{j}^{l+1}=\sum_i w_{ij} a_{i}^{l}+b_j^{l+1}\)
\(a_j^{l+1}\)可以解释成观察到的数据 \(a^l\) 属于类别 j 的概率,或者称作似然 (Likelihood)。

求输出对输入的梯度\(\partial a\over \partial z\):

\[ \begin{align} {\partial a\over \partial z_k}= \begin{bmatrix} {\partial a_1\over \partial z_k} \\ \vdots \\ {\partial a_k\over \partial z_k} \\ \vdots \\ {\partial a_K\over \partial z_k} \end{bmatrix} = \begin{bmatrix} -a_1 \\ \vdots \\ (1-a_k) \\ \vdots \\ -a_K \end{bmatrix}a_k = (\begin{bmatrix} 0 \\ \vdots \\ 1 \\ \vdots \\ 0 \end{bmatrix} -a)a_k \end{align} \]

因此损失对输入的梯度为\({\partial E\over \partial z}\):

\[ {\partial E\over \partial z_k}={\partial E\over \partial a}{\partial a\over \partial z_k}=({\partial E\over \partial a_k} - [{\partial E\over \partial a}]^T a)a_k \\ {\partial E\over \partial z}={\partial E\over \partial a}{\partial a\over \partial z}=({\partial E\over \partial a} - [{\partial E\over \partial a}]^T a)⊙ a \]

对应的 Caffe 中的SoftmaxLayer的梯度反向传播计算实现代码为:

# dot 表示矩阵乘法, * 表示按对应元素相乘
bottom_diff = (top_diff - dot(top_diff, top_data)) * top_data

Softmax loss 梯度

单样本的损失函数为:

\[ E = -\sum^K_{k}y_k\log(a_{k}) \\ {\partial E\over \partial a_j} = -\sum^K_{k}{y_k\over a_k}\cdot {\partial a_k\over \partial a_j}=-{y_j\over a_j} \]

接下来求E对w,b的梯度, 过程与反向传播的通用梯度计算公式相同, 这里指定了具体的激活函数(softmax)与损失函数:

\[ \begin{align} {\partial E\over \partial b_j^{l+1}} &= {\partial E\over \partial z_j^{l+1}} = \sum_k{\partial E\over \partial a_k^{l+1}} \cdot {\partial a_k^{l+1}\over \partial z_j^{l+1}} \\ &=-{y_j^{l+1}\over a_j^{l+1}} \cdot a_j^{l+1}(1 - a_j^{l+1})+\sum_{k\ne j}[-{y_k^{l+1}\over a_k^{l+1}} \cdot -a_j^{l+1} a_k^{l+1}] \\ &= -y_j^{l+1}+y_j^{l+1} a_j^{l+1} +\sum_{k\ne j}y_k^{l+1}a_j^{l+1} \\ &= a_j^{l+1}-y_j^{l+1} \\ {\partial E\over \partial w_{ij}^{l+1}} &= {\partial E\over \partial z_j^{l+1}} \cdot {\partial z_j^{l+1}\over w_{ij}^{l+1}}=(a_j^{l+1}-y_j^{l+1})a_i^l \end{align} \]

对应的 Caffe 中的SoftmaxWithLossLayer的梯度反向传播计算实现为(\({\partial E\over \partial z}\)):

# prob_data 为前向传播时softmax的结果, label_data 是标签的one-hot表示
bottom_diff = prob_data - label_data

参考123


  1. softmax的log似然代价函数(公式求导) https://blog.youkuaiyun.com/u014313009/article/details/51045303

  2. Softmax与SoftmaxWithLoss原理及代码详解 https://blog.youkuaiyun.com/u013010889/article/details/76343758

  3. 数值计算稳定性 http://freemind.pluskid.org/machine-learning/softmax-vs-softmax-loss-numerical-stability/

转载于:https://www.cnblogs.com/makefile/p/softmax.html

### 朴素 Softmax 损失函数及其梯度计算 #### 背景介绍 在机器学习领域,尤其是分类任务中,Softmax 函数被广泛用于将未归一化的分数转换为概率分布。它通过指数运放大较大值的影响,并使较小值趋于零[^2]。对于一个多类别分类问题,假设输入是一个长度为 \( K \) 的向量 \( z=[z_1,z_2,...,z_K]^T \),则 Softmax 函数可以定义为: \[ S(z_i)=\frac{e^{z_i}}{\sum_{j=1}^K e^{z_j}} \] 此函数的作用是将原始得分转化为一个有效的概率分布。 #### 损失函数定义 为了衡量模型预测的概率分布与真实标签之间的差异,通常采用交叉熵作为损失函数。设真实的标签为独热编码形式的一维数组 \( y=[y_1,y_2,...,y_K]^T \),其中仅有一个位置上的值为1其余均为0,则交叉熵损失可写成如下形式: \[ L=-\sum_{i=1}^K y_i \log(S(z_i)) \] 由于 \( y \) 是独热编码,在大多数情况下只有当某个特定索引 \( k \) 对应的真实类别时 \( y_k=1 \),其他地方皆为0。因此上述公式简化为: \[ L =-\log(S(z_k))=-\log(\frac{e^{z_k}}{\sum_{j=1}^K e^{z_j}}) \] 这便是所谓的 **朴素 Softmax 损失函数** 表达式[^1]。 #### 梯度计算过程 下面展示如何针对参数矩阵 W 计算损失函数关于每个权重 w_ij 的偏导数。假定我们的网络结构是从输入层到隐藏层再到输出层的标准全连接神经网路架构,那么最终的线性变换结果 Z 可由下述关系给出: \[ Z=XW+b \] 这里 X 是 mini-batch 数据张量 (形状 NxD),D 维特征空间维度大小; b 偏置项矢量(长度等于 C 类别数目); W 权重系数矩阵(DxC). 现在我们来具体看每一个元素 w_pq 上面的变化情况。注意到整个表达式的复杂程度较高,所以我们采取链式法则逐步拆解开来分析: 1. 首先是 S 关于 Z 的变化率 dS/dZ; 2. 接下来考虑 L 关于 S 的敏感度 dL/dS; 3. 最终组合起来得到完整的梯度信息 dL/dW. ##### Step 1: Derivative of S with respect to Z 根据前面提到过的 softmax 定义可知, \[ \frac{\partial S}{\partial z_m}=S(z_m)(I[m=k]-S(z_k)), m,k ∈ {1..C} \] 此处 I[] 符号代表指示函数(indicator function),如果条件成立返回1否则返回0。 ##### Step 2: Derivative of Loss Function With Respect To Output Probabilities 继续回到之前的损失函数表述里头去寻找答案吧! \[ \frac{\partial L}{\partial s_c}=\begin{cases}-\frac{1}{s_t}, & c=t \\ 0,& otherwise.\end{cases} \] t 即为目标类别的编号。 ##### Step 3: Combine Everything Together For Final Gradient Computation On Weights Matrix. 利用以上两步的结果以及初始设定的关系链条,我们可以得出结论说: \[ \nabla_W J(W,b;x,y)=(X^T)\odot (\delta), \] 这里的 δ 向量包含了所有节点处误差信号累积后的总效果,即: \[ δ=(∇_aJ(a;y))^TS'(z). \] 注意这里是逐元操作符⊙表示按位相乘而非普通的矩阵乘法哦!另外补充一句,b 的更新规则也类似只是少了那个转置而已啦~ 😊 ```python import numpy as np def compute_softmax_loss_and_gradient(X, Y_true, scores): """ Compute the loss and gradient using naive implementation Args: X (numpy.ndarray): Input data matrix shape(N,D) Y_true (numpy.ndarray): Ground truth labels one-hot encoded shape(N,C) scores (numpy.ndarray): Unnormalized score vectors from model output shape(N,C) Returns: tuple(float,numpy.ndarray): Tuple containing computed loss value and gradients wrt weights respectively """ num_train = X.shape[0] # Calculate probabilities via applying softmax activation over raw scores exp_scores = np.exp(scores - np.max(scores,axis=1,keepdims=True)) probs = exp_scores / np.sum(exp_scores,axis=1,keepdims=True) # Cross entropy error calculation per training example averaged across all samples correct_logprobs = -np.log(probs[np.arange(num_train),Y_true.argmax(axis=1)]) loss = np.mean(correct_logprobs) # Backpropagate into weight parameters computing delta term first then full grad dscores = probs.copy() dscores[np.arange(num_train),Y_true.argmax(axis=1)] -= 1 dscores /= num_train dw = np.dot(X.T,dscores) return loss,dw ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值