softmax梯度矩阵向量化实现推导

前言

前面的SVM梯度矩阵向量化实现,其实不能算是推导出来的,应该算是“凑出来的”,由结果推过程,今天又遇到了softmax的梯度矩阵,我觉得不能再逃避了,思考了很久,终于算真正地把这个搞明白

预备知识

向量偏微分

引自我之前写的博客《CS231n学习笔记》里关于数学基础补充的向量偏微分部分:
https://blog.csdn.net/lt1103725556/article/details/89291335#_95

单个数值对向量求偏导
易得应是数值对向量中的每个元素分别求偏导:
∂ y / ∂ x ⃗ = [ ∂ y / ∂ x 1 , ∂ y / ∂ x 2 , … … , ∂ y / ∂ x m ] {\partial y}/{\partial{\vec{x}}}=\left[ \partial{y}/\partial{x_1},\partial{y}/\partial{x_2},……,\partial{y}/\partial{x_m}\right]y/x=[y/x1,y/x2,,y/xm]
向量对向量求偏导
由上式易得应是第一个向量中的每个元素对第二个向量求偏导,从而组成一个矩阵,第一行为y 1 y_1y1x ⃗ \vec{x}x求偏导,第二行为y 2 y_2y2,以此类推:
∂ y ⃗ / ∂ x ⃗ = [ ∂ y 1 / ∂ x 1 ∂ y 1 / ∂ x 2 ⋯ ∂ y 1 / ∂ x n ∂ y 2 / ∂ x 1 ∂ y 2 / ∂ x 2 ⋯ ∂ y 2 / ∂ x 3 ⋮ ⋮ ⋱ ⋮ ∂ y m / ∂ x 1 ∂ y m / ∂ x 2 ⋯ ∂ y m / ∂ x n ] \partial{\vec{y}}/\partial{\vec{x}}= \left [ \begin{matrix} \partial{y_1}/\partial{x_1}&\partial{y_1}/\partial{x_2}&\cdots&\partial{y_1}/\partial{x_n}\\ \partial{y_2}/\partial{x_1}&\partial{y_2}/\partial{x_2}&\cdots&\partial{y_2}/\partial{x_3}\\ \vdots&\vdots&\ddots&\vdots\\ \partial{y_m}/\partial{x_1}&\partial{y_m}/\partial{x_2}&\cdots&\partial{y_m}/\partial{x_n} \end{matrix}\right ]y/x=y1/x1y2/x1ym/x1y1/x2y2/x2ym/x2y1/xny2/x3ym/xn
即雅克比矩阵

分清公式中哪些是向量,哪些是标量,哪些是矩阵

(1)L i L_iLi是一个标量,即第i个样本X i X_iXi带入计算后的损失值
(2)X i X_iXi是一个向量,包含3073个值
(3)W j W_jWj是一个向量,即一个class_j对应的权重向量,也有3073个值
(4)同理W y i W_{y_i}Wyi也是一个向量

各个变量的维度

(1)W:3073 × 10 3073\times103073×10
(2)X:N × 3073 N\times3073N×3073
(3)dW:3073 × 10 3073\times103073×10
(4)Scores=X.dot(W):N × 10 N\times10N×10

各个公式

L i = − l o g ( e S y i / ∑ e S j ) L_i=-log(e^{S_{y_i}}/\sum{e^{S_j}})Li=log(eSyi/eSj):第i个样本的损失值
S y i = X i ∗ W y i S_{y_i}=X_i*W_{y_i}Syi=XiWyi :第i个样本正确分类的得分
S j = X i ∗ W j S_{j}=X_i*W_jSj=XiWj :第i个样本错误分类的得分
d W y i = ( e S y i / ∑ e S j − 1 ) ∗ X i dW_{y_i}=(e^{S_{y_i}}/\sum{e^{S_j}}-1)*X_idWyi=(eSyi/eSj1)Xi :第i个样本正确分类的梯度
d W j = e S j / ∑ e S j ∗ X i dW_{j}=e^{S_j}/\sum{e^{S_j}}*X_idWj=eSj/eSjXi:第i个样本对错误分类的梯度

开始

(1)从上面公式我们可以看见,第i个样本对错误分类的梯度和正确分类的梯度公式类似,因为当j = y i j=y_ij=yie S j = e S y i e^{S_j}=e^{S_{y_i}}eSj=eSyi
(2)我们先计算一个样本的梯度矩阵:
由上文向量偏微分可得,L 1 L_1L1是一个标量,W j W_jWj是一个向量,即标量对向量求导,应是如下形式:
d L 1 / d W j ( j ! = y i ) = ( ∂ L 1 ∂ W j , 1 , ∂ L 1 ∂ W j , 2 , … … ∂ L 1 ∂ W j , 3073 ) T dL_1/dW_j(j!=y_i)=\left(\frac{\partial{L_1}}{\partial{W_{j,1}}},\frac{\partial{L_1}}{\partial{W_{j,2}}},……\frac{\partial{L_1}}{\partial{W_{j,3073}}}\right)^TdL1/dWj(j!=yi)=(Wj,1L1,Wj,2L1,Wj,3073L1)T

W j , 1 W_{j,1}Wj,1W j W_jWj的第一个分量,共3073个分量

带入d W j dW_jdWj的公式:
= ( e S j ∑ ( e x p ) ∗ X 1 , 1 , e S j ∑ ( e x p ) ∗ X 1 , 2 , … … e S j ∑ ( e x p ) ∗ X 1 , 3073 ) T =\left(\frac{e^{S_j}}{\sum(exp)}*X_{1,1},\frac{e^{S_j}}{\sum(exp)}*X_{1,2},……\frac{e^{S_j}}{\sum(exp)}*X_{1,3073}\right)^T=((exp)eSjX1,1,(exp)eSjX1,2,(exp)eSjX1,3073)T
而当j = y i j=y_ij=yi时,其实就是把X前的系数-1,j jj换成y i y_iyi而已
当j遍历从1到10,我们就有了第1个样本对所有梯度的贡献,即第一个样本得到的梯度矩阵dW
每个样本都会有一个梯度矩阵,我们把它们全部加起来就是总的梯度矩阵

注:变量exp为np.exp(本行)的结果

观察

观察第一个样本的梯度矩阵,我们可以发现:

第一行每个单位都有一个X 1 , 1 X_{1,1}X1,1,第二行都有一个X 1 , 2 X_{1,2}X1,2……最后一行都有一个X 1 , 3073 X_{1,3073}X1,3073
若将所有样本的梯度矩阵相加,以第一行第一个元素为例,应该是(X 1 , 1 , X 2 , 1 , … … X n , 1 X_{1,1},X_{2,1},……X_{n,1}X1,1,X2,1,Xn,1)的线性组合,第二个元素同理。
因此第一个元素可以分解为两个向量的乘积,同理所有元素可以分解为两个矩阵的乘积,其中左边矩阵第一行应为(X 1 , 1 , X 2 , 1 , … … X n , 1 X_{1,1},X_{2,1},……X_{n,1}X1,1,X2,1,Xn,1),因此左边矩阵应为X.T。

再看与左边矩阵相乘的右边第一列,当j ! = y i j!=y_ij!=yi时,系数为e S j ∑ ( e x p ) \frac{e^{S_j}}{\sum(exp)}(exp)eSjj = y i j=y_ij=yi时-1即可,即对应该样本的正确分类时,对应的得分np.exp/sum(本行)后-1,其余得分np.exp/sum(本行)即可
因此有代码:

dS = softmax_output.copy()
dS[range(num_train), list(y)] += -1
dW = (X.T).dot(dS)

版权声明:本文为lt1103725556原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。