我正在查看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
答案 0 :(得分:1)
让我们首先回顾一下场景和损失函数,所以我们在同一页面上:
鉴于P
维度空间中的N
个采样点是PxN
矩阵X
的形式,因此这些点是此矩阵的行。 X
中的每个点都分配给M
个类别中的一个。它们以长度为Y
的向量P
给出,其整数值介于0和M-1
之间。
目标是通过M
线性分类器(每个类别一个)以形状W
的权重矩阵NxM
的形式预测所有点的类别,因此分类器是W
的列。为了预测所有样本X
的类别,形成所有点和所有权重向量之间的标量积。这与矩阵乘以X
和W
相同,产生得分矩阵Y0
,其排列方式使得其行的排序方式与Y
的h元素相同,每行对应于一个样本。每个样本的预测类别只是得分最高的。
没有偏见术语所以我认为存在某种对称性或零均值假设。
现在,为了找到一组好的权重,我们想要一个损失函数,这个函数对于良好的预测来说很小,对于糟糕的预测来说很大,这让我们可以进行梯度下降。最直接的方法之一就是惩罚每个样本i
每个分数大于该样本的正确类别的分数,并使惩罚与差异线性增长。因此,如果我们为得分超过正确类别A[i]
的类别集j
写Y0[i, j] > Y0[i, Y[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
。
它仍然要除以每个样本损失的样本数,并加上正则化项的导数,正则化只是一个分量二次函数。