CS231n Assignment 1(一)

@[TOC](CS231n Assignment 1(一))
这篇文章就用来说说CS231n A1 Q1-Q3主要教的东西,还有计算SVM、Softmax损失函数和梯度的全矢量化(fully-vectorized)代码吧。

0.图像识别的简单分类器

CS231n是讲卷积神经网络(Convolutional Neural Network,CNN)图像识别的,当然,不可能一开始就来讲CNN(可能也可以吧),所以前面的几个lecture从简单的图像识别器开始讲起。

A1前三问主要讲了两大类图像识别分别器:KNN (nonlinear classifier中的一种) 和 linear classifier,linear classifier 根据Loss的不同又可以再分成svm loss linear classifer 和 softmax loss linear classfier。

1.KNN (Q1)

KNN分类器比较简单。它的基本逻辑是,在训练的时候记住所有的训练样本,包括样本的特征和标签。在预测的时候,它计算测试样本到各个训练样本的“距离”,然后根据前 K K K 个最近的训练样本的标签来决定预测的标签是什么。

好比说,我们取 K = 3 K=3 K=3,然后计算出来离测试样本最近的3个样本的标签分别为 1 , 1 , 2 1,1,2 1,1,2,由于这里面 1 1 1 最多,所以测试样本的预测标签是1。

这个算法最关键的地方是计算距离矩阵,也就是各个测试样本到训练样本的距离。如果测试样本的数目是 N t e N_{te} Nte,训练样本的数目是 N t r N_{tr} Ntr,那这个距离矩阵的维度是 N t e × N t r N_{te}×N_{tr} Nte×Ntr,其中 ( i , j ) (i,j) (i,j)位置的元素代表测试样本 i i i与训练样本 j j j的距离。

比如说我们要用 L 2 L^2 L2 范数来表征距离。最简单的计算方法是写两个loop,一个循环test set,一个循环training set,逐一计算距离。当然,这种办法的计算速度是贼慢。

我们可以使用fully-vectorized的代码来加快速度,因为numpy的库已经为我们优化过矩阵运算的速度了。Python代码如下:

    X_te_square=np.sum(X**2,axis=1).reshape(num_test,1)
    X_tr_square=np.sum(self.X_train**2,axis=1).reshape(1,num_train)
	X_te_tr_cross=np.dot(X,self.X_train.T)
    dists+=X_te_square
    dists+=X_tr_square
    dists-=2*X_te_tr_cross
    dists=np.sqrt(dists)

原理就是将平方项展开为二次项、交叉项,然后用pyhton numpy自带的broadcast功能将二次项和交叉项拼接回去。

2.Linear Classifier (Q2 & Q3)

我们可以把每张图片拉长成一个长向量 x ∈ R D x\in R^D xRD,这里 D D D是图片的像素点数乘上RGB通道数。一般来说,我们希望训练一个分类器,把图片分为 { 0 , 1 , . . . , C − 1 } \{0,1,...,C-1\} { 0,1,...,C1}中的一类,这里 C C C 是图片的总类别数。我们的想法是通过一个线性变换 W ∈ R C × D W\in R^{C×D} WRC×D,使得
f ( W , x ) = W T x ∈ R C f(W,x)=W^Tx \in R^C f(W,x)=WTxRC 也就是说,我们通过参数矩阵 W W W 将样本映射成了对应到 C C C 类的分数。如果我们能找到一个很好的 W W W,使得映射的分数 f ( W , x ) f(W,x) f(W,x) 刚好在每个样本label对应的得分很高,那我们就可以通过这个参数矩阵 W W W 进行图像识别了。

我们怎么评判参数矩阵的好坏呢?直观来说,如果参数矩阵能让 W T x W^Tx WTx 在样本真实标签维度的得分特别高,在其他维度的得分比较低,那这个矩阵 W W W 是不错的。为了定量衡量 W W W 的好坏,下面介绍两种损失函数。

2.1 SVM损失函数

对于某个样本 ( x i , y i ) (x_i,y_i) (xi,yi),它对应的SVM损失是
L i ( W , x i ) = ∑ j ≠ y i m a x ( 0 , W j T x − W y i T x + 1 ) L_i(W,x_i)=\sum \limits_{j\neq y_i} max(0,W_j^Tx-W_{y_i}^Tx+1) Li(W,xi)=j=yimax(0,WjTxWyiTx+1)
导数是:
CS231n Assignment 1(一)_第1张图片
对应的求loss和grad的代码是:

Inputs:
- W: A numpy array of shape (D, C) containing weights.
- X: A numpy array of shape (N, D) containing a minibatch of data.
- y: A numpy array of shape (N,) containing training labels; y[i] = c means
  that X[i] has label c, where 0 <= c < C.
- reg: (float) regularization strength
Returns a tuple of:
- loss as single float
- gradient with respect to weights W; an array of same shape as W
'''

N=X.shape[0]
score=X.dot(W)# N*D D*C = N*C
listr=range(0,N)
margin=score-score[listr,y].reshape(N,1)+1
margin[listr,y]=0
cnt=(margin>0).astype(int)
sum_cnt=np.sum(cnt,axis=1)
margin=margin[margin>0] #N*C
cnt[listr,y]-=sum_cnt
dW=(X.T).dot(cnt)#D*N N*C = D*N
dW/=N
dW+=reg*2*W
loss=np.sum(margin)
loss/=N
loss+=reg * np.sum(W * W)

Return loss,dW

有空再来补解释。

2.2 Softmax损失函数

对于某个样本 ( x i , y i ) (x_i,y_i) (xi,yi),它对应的Softmax损失是
L i = − log ⁡ ( e f y i ∑ j e f j ) L_i = - \log \left( \frac{e^{f_{y_i}}}{\sum_j e^{f_j}} \right) Li=log(jefjefyi)
导数是:
{ ∇ w y i L i = − x i + e f y i ∑ j e f j x i j = y i ∇ w j L i = e f j ∑ j e f j x i j ≠ y i \left\{\begin{aligned} \nabla_{w_{y_i}} L_i = & -x_i + \frac{e^{f_{y_i}}}{\sum_j e^{f_j}} x_i & j = y_i \\ \nabla_{w_j} L_i = & \frac{e^{f_j}}{\sum_j e^{f_j}} x_i & j \ne y_i \end{aligned}\right. wyiLi=wjLi=xi+jefjefyixijefjefjxij=yij=yi

对应的求loss和grad的代码是:

 Inputs:
- W: A numpy array of shape (D, C) containing weights.
- X: A numpy array of shape (N, D) containing a minibatch of data.
- y: A numpy array of shape (N,) containing training labels; y[i] = c means
  that X[i] has label c, where 0 <= c < C.
- reg: (float) regularization strength
Returns a tuple of:
- loss as single float
- gradient with respect to weights W; an array of same shape as W
'''

N=X.shape[0]
listr=range(0,N)
probs=X.dot(W)
probs-=np.max(probs,axis=1).reshape(N,1)
probs=np.exp(probs)/np.sum(np.exp(probs),axis=1).reshape(N,1)
log_probs_on_label=np.log(probs[listr,y])
loss+=-np.sum(log_probs_on_label)
loss/=N
loss+=reg * np.sum(W * W)
probs[listr,y]-=1
dW+=(X.T).dot(probs)
dW/=N
dW+=reg*2*W

Return loss,dW

有空再来补+1。

你可能感兴趣的:(图像识别)