在学习cs231n,在做到SVM这一课作业时,被梯度的代码难住了,再次翻看网上的课程笔记,细致推导才逐渐清晰。理解能力有限,这里做个简单的记录,防止以后忘记也便于温习。
https://zhuanlan.zhihu.com/p/20945670?refer=intelligentunit线性分类笔记(中)中详细介绍了多累支持向量机损失函数,该函数定义如下:
cs231n svm这一课后作业中对于求梯度的代码如下:
# 估算损失函数的梯度
def svm_loss_naive(W, X, y, reg):
dW = np.zeros(W.shape) # initialize the gradient as zero
# compute the loss and the gradient
num_classes = W.shape[1] # C
num_train = X.shape[0] # N
loss = 0.0
# 对于一个minibatches
for i in xrange(num_train):
scores = X[i].dot(W)
correct_class_score = scores[y[i]]
# 下面这个for循环计算损失函数,loss为该训练图像输入后的损失,注意这里的loss有叠加,最后是这个minibatches的loss
for j in xrange(num_classes):
if j == y[i]:
continue
margin = scores[j] - correct_class_score + 1 # note delta = 1
if margin > 0:
loss += margin
dW[:, j] += X[i] # 数据分类错误时的梯度
dW[:, y[i]] -= X[i] # 数据分类正确时的梯度
# Right now the loss is a sum over all training examples, but we want it
# to be an average instead so we divide by num_train.
loss /= num_train
dW /= num_train
# Add regularization to the loss.
loss += reg * np.sum(W * W)
dW += reg*np.sum(W) # 这里正则化项没有除以num_train是因为这里把reg当成 lamda/num_train
return loss, dW
该代码中需要添加的是 dW[:,j] += X[i], 和 dW[:,y[i]] -= X[i], 这两行代码保存了代价函数对W求梯度的值,注意他们所在的条件语句为if margin > 0, 即对于每个训练样本(每幅图),该代码很可能执行不止一遍。起初看网上提供的代码答案并不太懂这样的做法,后来根据损失函数似乎看出来点什么,但一直不太明朗。
这里我们做个假设,假设该分类器有六种分类,分别是 A,B,C,D,E,F,计算得到:
假设正确分类, 那么上面式子里的五个数分别对应 j=1,3,4,5,6,(假设j从0开始),也就是说对应的是 W[1]*X,W[3]*X,W[4]*X,W[5]*X,W[6]*X所得到的结果。W为权值矩阵,具体介绍见课程笔记,其维度为K*D,K为分类数目,D为图像维度(即像素点数),W[1]表示第1行的向量,维度为 1*D。
上述Li对W求导数,既然这里的Li有五个数子相加,我们依次求导相加。
j=1时,max(0,1-2)=0,0的导数肯定为0;
j=3时,导数只有两种情况下有值,即 和,其他情况下因为分子部分没有对应的W[i],i=1,4,5,6项,因而均不做更新
j=5时,max(0,-2)=0,权值不更新
j=6时,同样不更新
最后将W[2]的两个梯度相加就是W[2]的梯度,W[3]和W[4]的梯度也已经求出。上述分析默认△为0,且是在分类出错的情况下计算所得。分类正确情况下Li=0,梯度为0,权值不做更新。
这对应着代码中以下部分
# 对于一个minibatches
for i in xrange(num_train):
scores = X[i].dot(W)
correct_class_score = scores[y[i]]
for j in xrange(num_classes):
if j == y[i]:
continue
margin = scores[j] - correct_class_score + 1 # note delta = 1
if margin > 0:
loss += margin
dW[:, j] += X[i] # 数据分类错误时的梯度
dW[:, y[i]] -= X[i] # 数据分类正确时的梯度
对于每个图片,分别遍历分类器输出向量的每个元素,即对应上文累加和公式的每个项,倘若loss不为0,则计算该项对应W[i]的偏导和W[yi]的偏导,并在每次循环的时候都做更新。
仍在学习过程中,理解和表述可能都不尽人意,再接再厉,希望能给予帮助。