【问题标题】:Vectorized SVM gradient矢量化 SVM 梯度
【发布时间】:2018-05-16 09:50:59
【问题描述】:

我正在查看 SVM 损失和导数的代码,我确实了解损失,但我无法理解梯度是如何以矢量化方式计算的

def svm_loss_vectorized(W, X, y, reg):

loss = 0.0
dW = np.zeros(W.shape) # initialize the gradient as zero
num_train = X.shape[0]

scores = X.dot(W)
yi_scores = scores[np.arange(scores.shape[0]),y] 
margins = np.maximum(0, scores - np.matrix(yi_scores).T + 1)
margins[np.arange(num_train),y] = 0
loss = np.mean(np.sum(margins, axis=1))
loss += 0.5 * reg * np.sum(W * W)

了解到这里,在这里之后我不明白为什么我们要在二进制矩阵中逐行求和并减去它的总和

binary = margins
binary[margins > 0] = 1
row_sum = np.sum(binary, axis=1)
binary[np.arange(num_train), y] = -row_sum.T
dW = np.dot(X.T, binary)

# Average
dW /= num_train

# Regularize
dW += reg*W

return loss, dW

【问题讨论】:

    标签: python numpy svm


    【解决方案1】:

    让我们先回顾一下场景和损失函数,所以我们在同一页上:

    PxN 矩阵X 的形式给定N 维空间中的P 样本点,因此这些点是该矩阵的行。 X 中的每个点都分配给M 类别中的一个。这些以向量Y 的形式给出,长度为P,其整数值介于0 和M-1 之间。

    目标是通过M线性分类器(每个类别一个)预测所有点的类别,以权重矩阵W的形式给出NxM,所以分类器是@的列987654334@。为了预测所有样本X的类别,形成所有点和所有权重向量之间的标量积。这与矩阵乘以XW 产生一个得分矩阵Y0 的排列方式相同,该矩阵的行排列顺序与Y 的h 个元素类似,每一行对应一个样本。每个样本的预测类别就是得分最高的类别。

    没有偏差项,所以我假设存在某种对称性或零均值假设。

    现在,为了找到一组好的权重,我们需要一个损失函数,对于好的预测来说小而对于坏的预测来说大,并且可以让我们进行梯度下降。最直接的方法之一是惩罚每个样本i 每个大于该样本正确类别分数的分数,并让惩罚随差值线性增长。因此,如果我们为得分高于正确类别Y0[i, j] > Y0[i, Y[i]] 的类别集jA[i],则样本i 的损失可以写为

    sum_{j in A[i]} (Y0[i, j] - Y0[i, Y[i]])

    或者等效地,如果我们将#A[i] 写成A[i] 中的元素数

    (sum_{j in A[i]} Y0[i, j]) - #A[i] Y0[i, Y[i]]

    关于分数的偏导数因此很简单

                        | -#A[i]      if j == Y[i]
    dloss / dY0[i, j] = {      1      if j in A[i]
                        |      0      else
    

    这正是你说你不理解的前四行计算。

    下一行应用链式法则dloss/dW = dloss/dY0 dY0/dW

    仍然需要除以样本数以获得每个样本的损失,并添加正则化项的导数,正则化只是一个分量二次函数很容易。

    【讨论】:

    • 逻辑我明白了,从非向量化的代码中我明白了,你能解释一下1,0(margin>0)的矩阵是怎么用的,在非向量化的时候我们实际上是用值的在 [i][j] 中,即(不四舍五入到 1 或 0),这里是 'margin = scores[j] - correct_class_score + 1',但在矢量化中,我们四舍五入到 1 或 0,不会'二进制[margins > 0] = (actual values which are > 0, not 1, else 0) ' 更有意义?
    • 没有非矢量化代码我只能评论矢量化。正如我试图在答案中解释的那样,对于导数 使用 1 和 0,而不是实际值,是数学上正确的做法。因为如果i=k,j=ldY0[i,j]/dY0[k,l] 为 1,否则为 0。
    • 他们在做同样的事情:if margin > 0: ...dW[j, :] += X[:, i].T。请务必注意margin 的实际值不会在更新中使用。您可以将其写成dW[j, :] += (margin > 0) * X[:, i].T,避免if 语句。这是矢量化代码的基础。
    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 2018-06-05
    相关资源
    最近更新 更多