svm 损失函数以及其梯度推导

一般而言,score_matrix=WX

W是系数矩阵,X是data_matrix,这儿是学习cs231n的笔记,为了与其代码内w,x的含义保持一致,

以下统一使用XW来计算score_matrix。背景是用svm实现图片分类,输入参数如下:

N 代表样品个数,D 代表像素个数,C代表一共的种类数。

X=(N, D)

    注:如果原输入为(500,32,32,3)[即有500个样品(图片),每个图像32行,32列,并有3个color chanel],那么应该进行预处理,转变为(500,32*32*3)的结构。

W=(D, C)

损失函数

损失函数的计算方法为:L_i={\sum_{}^{j\neq{y_i}}}max(0,s_j -s_y_i + \Delta ),其中i代表第i个样品,j代表第j个种类,那么y_i代表第i个样品的真实种类。

其中,常用的数学表达式为:s_j=w_{T}^{j}x_i,但为了与代码中的统一,从而稍微变动以下s_j=x_iw_j,对于y_i来说同理。

具体的例子如下:

                  w
                 cat  duck frog
             |p1 0.1  0.2  0.2
n_i=第i个样品 |p2 0.2  0.3  0.1
p=pixel      |p3 0.5  0.1  0.1
-------------------------
      x      |      score
    p1  p2 p3|   cat  duck  frog
n1  10  14 10|   8.8 [7.2]  4.4  -->第一个样品得分
n2  5   10  8|   6.5  4.8  2.8  -->第二个样品
n3  10  5   5|   4.5  4.0  3.0  -->第三个样品

[7.2]代表第一个样品的真实类别为duck,分数是7.2


那么按照损失函数的计算方法:
L_i=max(0,8.8-7.2+1)+max(0,4.4-7.2+1)
   =1.8+0=1.8

梯度推导 

现在需要计算梯度,因为最开始的w是随机生成的很小的值(注意,这样做是有原因的,因为若w都大致为0,那么第一步计算出的score矩阵的每一个元素也约等于0,因此按照损失函数的计算方法,每个i样品的L_i=1*(N-1),即最后的平均损失函数为N-1,这样可以作为debug的依据),我们需要知道让w怎样变化才能让损失最少,

以数值分析为例:

对于第一个样品,我们想知道若w在cat种类上的数增加一点点,损失会改变多少

                  w
                 cat      duck frog
             |p1 0.1+0.01  0.2  0.2
n_i=第i个样品 |p2 0.2       0.3  0.1
p=pixel      |p3 0.5       0.1  0.1
-------------------------
      x      |      score
    p1  p2 p3|   cat      duck  frog
n1  10  14 10|   8.8+0.1  [7.2]  4.4  -->第一个样品得分
n2  5   10  8|   6.5      4.8    2.8  -->第二个样品
n3  10  5   5|   4.5      4.0    3.0  -->第三个样品

因此,按照数值的分析方法,L_1对cat种类的偏导数为:   \frac{df(x)}{dx}=\lim_{h \to 0} {\frac{f(x+h)-f(x)}{h}}==>\frac{\partial }{\partial w_{cat}}L_1=\frac{8.9-8.8}{0.1}=1

但这样计算会很慢,因此我们借助于微分公式,可以方便用分析的方式计算出L_i对各个种类的偏导数,也就是计算梯度。

\nabla_wL_1=\begin{bmatrix} \frac{dL_1 }{d_{w_1}}& \frac{dL_1 }{d_{w_2}} & \frac{dL_1 }{d_{w_2}} \end{bmatrix}=\begin{bmatrix} \frac{dL_1 }{d_{w_{11}}}& \frac{dL_1 }{d_{w_{21}}}& \frac{dL_1 }{d_{w_{31}}}\\ \frac{dL_1 }{d_{w_{12}}}& \frac{dL_1 }{d_{w_{22}}}& \frac{dL_1 }{d_{w_{32}}}\\ \frac{dL_1 }{d_{w_{13}}}& \frac{dL_1 }{d_{w_{23}}}& \frac{dL_1 }{d_{w_{33}}} \end{bmatrix}

又因为L_i如下,注意,这儿w的下标为实际含义,而不是行、列

L_i=max(0,x_{i1}w_{11}+x_{i2}w_{12}+\cdots +x_{iD}w_{1D}-x_{i1}w_{y_{i}1}-x_{i2}w_{y_{i}2}-x_{iD}w_{y_{i}D}+\Delta)+\\ \qquad max(0,x_{i1}w_{21}+x_{i2}w_{22}+\cdots +x_{iD}w_{2D}-x_{i1}w_{y_{i}1}-x_{i2}w_{y_{i}2}-x_{iD}w_{y_{i}D}+\Delta)+\\ \qquad \cdots\\ \qquad max(0,x_{i1}w_{C1}+x_{i2}w_{C2}+\cdots +x_{iD}w_{CD}-x_{i1}w_{y_{i}1}-x_{i2}w_{y_{i}2}-x_{iD}w_{y_{i}D}+\Delta)

因此if(x_iw_1-x_iw_{y_i}+\Delta)>0 \qquad then \frac{dL_i}{d_{w_{11}}}=x_{i1}

最后,上面的梯度矩阵就变成了(注意,若j=yi时为负)

\begin{bmatrix} x_{i1} & x_{i1} & \cdots &x_{i1} \\ x_{i2} & x_{i2} & \cdots &x_{i2} \\ \qquad \cdots \\ x_{i3} & x_{i3} & \cdots &x_{i3} \end{bmatrix}

更新:看了两篇文章之后理解更深了,之前的东西自己其实是模凌两可的。

这儿的梯度,实质上已经不是我们熟悉的scalar,标量了,而是基于vector或matrix的,因此,需要先探究关于matrix的derivative。

为了与下面代码一致,同样:Y=XW,Y即为scores矩阵,L=f(Y),损失函数是关于Y的取max函数。

X=(2,2) W=(2,3) Y=(2,3) L为计算后的一个标量。

根据矩阵的乘法,可知:Y_{i,j}=\sum_{k=1}^{D}X_{i,k}W_{k,j},所以\frac{\partial Y_{a,b}}{\partial X_{c,d}} 全为零,除非a=c。因此\frac{\partial Y_{i,j}}{\partial X_{i,k}}=W_{k,j}

同理,\frac{\partial Y_{a,b}}{\partial W_{c,d}} 全为零,除非b=d。因此\frac{\partial Y_{i,j}}{\partial W_{k,j}}=X_{i,k} \quad (1)

根据链式法则,\frac{\partial L}{\partial W_{1,1}}=\frac{\partial L}{\partial Y}\frac{\partial Y}{\partial W_{1,1}} \quad (2)

L是标量,Y=(2,3),因此L对Y的梯度也是(2,3)        \frac{\partial L}{\partial Y}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}

根据公式(1),\frac{\partial Y}{\partial W_{1,1}}=\begin{pmatrix} X_{1,1}& 0& 0\\ X_{2,1}& 0& 0 \end{pmatrix} \quad (4)

注意,因为L是标量,W11也是标量,因此对于公式(2)来说,是dot product,而不是矩阵乘法。

公式(2)最后写成:

\frac{\partial L}{\partial W_{1,1}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} X_{1,1}& 0& 0\\ X_{2,1}& 0& 0 \end{pmatrix} = \frac{\partial L}{\partial Y_{1,1}}X_{1,1}+\frac{\partial L}{\partial Y_{2,1}}X_{2,1} \quad (5)

同理,

\frac{\partial L}{\partial W_{1,2}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} 0& X_{1,1}& 0\\ 0& X_{2,1}& 0 \end{pmatrix} = \frac{\partial L}{\partial Y_{1,2}}X_{1,1}+\frac{\partial L}{\partial Y_{2,2}}X_{2,1} \quad (6)

\frac{\partial L}{\partial W_{1,3}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} 0& 0& X_{1,1}\\ 0& 0& X_{2,1}\end{pmatrix} = \frac{\partial L}{\partial Y_{1,3}}X_{1,1}+\frac{\partial L}{\partial Y_{2,3}}X_{2,1} \quad (7)

\frac{\partial L}{\partial W_{2,1}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} X_{1,2}& 0& 0\\ X_{2,2}& 0& 0 \end{pmatrix} = \frac{\partial L}{\partial Y_{1,1}}X_{1,2}+\frac{\partial L}{\partial Y_{2,1}}X_{2,2} \quad (8)

\frac{\partial L}{\partial W_{2,2}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} 0& X_{1,2}& 0\\ 0& X_{2,2}& 0 \end{pmatrix} = \frac{\partial L}{\partial Y_{1,2}}X_{1,2}+\frac{\partial L}{\partial Y_{2,2}}X_{2,2} \quad (9)

\frac{\partial L}{\partial W_{2,3}}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}& \frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}& \frac{\partial L}{\partial Y_{2,3}} \end{pmatrix}\begin{pmatrix} 0& 0& X_{1,2}\\ 0& 0& X_{2,2} \end{pmatrix} = \frac{\partial L}{\partial Y_{1,3}}X_{1,2}+\frac{\partial L}{\partial Y_{2,3}}X_{2,2} \quad (10)

根据公式(5)~(10)

\frac{\partial L}{\partial W}=\begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}X_{1,1}+\frac{\partial L}{\partial Y_{2,1}}X_{2,1}& \frac{\partial L}{\partial Y_{1,2}}X_{1,1}+\frac{\partial L}{\partial Y_{2,2}}X_{2,1}& \frac{\partial L}{\partial Y_{1,3}}X_{1,1}+\frac{\partial L}{\partial Y_{2,3}}X_{2,1}\\ \frac{\partial L}{\partial Y_{1,1}}X_{1,2}+\frac{\partial L}{\partial Y_{2,1}}X_{2,2} & \frac{\partial L}{\partial Y_{1,2}}X_{1,2}+\frac{\partial L}{\partial Y_{2,2}}X_{2,2}& \frac{\partial L}{\partial Y_{1,3}}X_{1,2}+\frac{\partial L}{\partial Y_{2,3}}X_{2,2} \end{pmatrix} \\ = \begin{pmatrix} X_{1,1}& X_{1,2}\\ X_{2,1}& X_{2,2} \end{pmatrix} \begin{pmatrix} \frac{\partial L}{\partial Y_{1,1}}& \frac{\partial L}{\partial Y_{1,2}}&\frac{\partial L}{\partial Y_{1,3}}\\ \frac{\partial L}{\partial Y_{2,1}}& \frac{\partial L}{\partial Y_{2,2}}&\frac{\partial L}{\partial Y_{2,3}} \end{pmatrix} \\=X^T\cdot \frac{\partial L}{\partial Y}

其中的\frac{\partial L}{\partial Y}其实就是代码里的判断条件,因为对于max函数而言,结果只能为0,1,-1。

代码表示如下

方式一:Non-vectorized implementation

 dW = np.zeros(W.shape) # initialize the gradient as zero
  
 # compute the loss and the gradient
   ...
  for i in xrange(num_train):
    ...
    for j in xrange(num_classes):
      ...
      if margin > 0:
          ...
          dW[:,y[i]] -= X[i,:] 
          dW[:,j] += X[i,:] 

方式二:Vectorized implementation

从方式一中不难发现,对于每一个样品而言,最后的梯度就是X的转置,只不过若分类正确,乘以0,分类错误时,为当前类别乘以-1,否则乘以1。对于第二种方式而言,可以理解为一次性算出梯度。因为最后的梯度结果即为X的转置进行几次加几次减的操作,方式二的核心在于如何得到分类错误的矩阵描述。

损失函数进行二值化处理,即可得到分类错误的情况,但分类错误时有两种操作:yi=j时,系数需要为-1,否则为1,因此需要一点小技巧。

下面具体举例说明:

#假设scores为我们得到的分数,scores=(N,C)
scores=np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
#y表示每一个样本真正的类别
y=np.array([2,1,1])
#这儿选出每行,对应的y的值
#https://mlxai.github.io/2017/01/06/vectorized-implementation-of-svm-loss-and-#
yi_scores = scores[np.arange(scores.shape[0]),y]
# yi_scores=>array([3, 5, 8])
#计算边界函数
margins = np.maximum(0, scores - np.matrix(yi_scores).T + 1)
"""
matrix([[0, 0, 1],
        [0, 1, 2],
        [0, 1, 2]])
"""
#这儿就是一个小技巧,因为若j=yi时,系数是需要为-1的
margins[np.arange(3),y] = 0
"""
matrix([[0, 0, 0],
        [0, 0, 2],
        [0, 0, 2]])
"""
loss = np.mean(np.sum(margins, axis=1))
binary = margins
#二值化处理
binary[margins > 0] = 1
"""
matrix([[0, 0, 0],
        [0, 0, 1],
        [0, 0, 1]])
"""
#计算每个样本分类错误的个数
row_sum = np.sum(binary, axis=1)
"""
matrix([[0],
        [1],
        [1]])
"""
#这儿的技巧同上面的技巧结合起来,就可以实现分类错误时,系数可以根据yi是否等于j
#进行梯度-(X转置),或梯度+(X转置)的操作
binary[np.arange(3), y] = -row_sum.T
"""
matrix([[ 0,  0,  0],
        [ 0, -1,  1],
        [ 0, -1,  1]])
"""
#相当于一次性做完方式一的循环操作
dW = np.dot(X.T, binary)

 

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值