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