前言
前面的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_1 y1对 x ⃗ \vec{x} x求偏导,第二行为 y 2 y_2 y2,以此类推:
∂ 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/∂x1∂y2/∂x1⋮∂ym/∂x1∂y1/∂x2∂y2/∂x2⋮∂ym/∂x2⋯⋯⋱⋯∂y1/∂xn∂y2/∂x3⋮∂ym/∂xn⎦⎥⎥⎥⎤
即雅克比矩阵
分清公式中哪些是向量,哪些是标量,哪些是矩阵
(1)
L
i
L_i
Li是一个标量,即第i个样本
X
i
X_i
Xi带入计算后的损失值
(2)
X
i
X_i
Xi是一个向量,包含3073个值
(3)
W
j
W_j
Wj是一个向量,即一个class_j对应的权重向量,也有3073个值
(4)同理
W
y
i
W_{y_i}
Wyi也是一个向量
各个变量的维度
(1)W:
3073
×
10
3073\times10
3073×10
(2)X:
N
×
3073
N\times3073
N×3073
(3)dW:
3073
×
10
3073\times10
3073×10
(4)Scores=X.dot(W):
N
×
10
N\times10
N×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=Xi∗Wyi :第i个样本正确分类的得分
S
j
=
X
i
∗
W
j
S_{j}=X_i*W_j
Sj=Xi∗Wj :第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_i
dWyi=(eSyi/∑eSj−1)∗Xi :第i个样本正确分类的梯度
d
W
j
=
e
S
j
/
∑
e
S
j
∗
X
i
dW_{j}=e^{S_j}/\sum{e^{S_j}}*X_i
dWj=eSj/∑eSj∗Xi:第i个样本对错误分类的梯度
开始
(1)从上面公式我们可以看见,第i个样本对错误分类的梯度和正确分类的梯度公式类似,因为当
j
=
y
i
j=y_i
j=yi时
e
S
j
=
e
S
y
i
e^{S_j}=e^{S_{y_i}}
eSj=eSyi。
(2)我们先计算一个样本的梯度矩阵:
由上文向量偏微分可得,
L
1
L_1
L1是一个标量,
W
j
W_j
Wj是一个向量,即标量对向量求导,应是如下形式:
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)^T
dL1/dWj(j!=yi)=(∂Wj,1∂L1,∂Wj,2∂L1,……∂Wj,3073∂L1)T
W j , 1 W_{j,1} Wj,1即 W j W_j Wj的第一个分量,共3073个分量
带入
d
W
j
dW_j
dWj的公式:
=
(
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)eSj∗X1,1,∑(exp)eSj∗X1,2,……∑(exp)eSj∗X1,3073)T
而当
j
=
y
i
j=y_i
j=yi时,其实就是把X前的系数-1,
j
j
j换成
y
i
y_i
yi而已
当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_i
j!=yi时,系数为
e
S
j
∑
(
e
x
p
)
\frac{e^{S_j}}{\sum(exp)}
∑(exp)eSj,
j
=
y
i
j=y_i
j=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)