cs231n学习有疑惑? 看这一篇或许能搞定

cs231n assignments学习心得

cs231n是斯坦福的一门以计算机视觉为载体的深度学习课程,由李飞飞和她的几个博士生上课。这门课亲测好评。下面是我完成这些assignment的一些疑问点和解决办法。

首先先贴代码:https://github.com/oubindo/cs231n-cnn
欢迎star和fork。感谢支持!

Assignment1:KNN,SVM,Softmax,Neuron Network

总体来说,这个assignment难度适中,但是对于numpy的要求还挺高的,要比较纯熟的使用才能完成一些诸如矢量化一样的操作。比较困难的地方在于梯度的计算。作为初学者的我一开始是非常懵逼的,(现在好一点了也还有点懵逼)。看了官方给出的一些说明,还有慕课学院讲解课以后才理解了一些。现在尝试对于一些问题给出自己的理解。图片部分出自上面内容

1.KNN

KNN主要的考察点就是两重循环,一重循环和全向量化。
先介绍一下背景,给出n维的测试点和训练点,要求出它们之间的距离。使用两重循环的话就是通过索引到这两个数据再处理。

    for i in xrange(num_test):
      for j in xrange(num_train):
        distances = np.sqrt(np.sum(np.square(self.X_train[j] - X[i])))
        dists[i,j]=distances

使用一重循环是借助了numpy ndarry之间的相减功能,单独的算出所有训练点到一个测试点的距离,再一次便利即可。

for i in xrange(num_test):
      distances = np.sqrt(np.sum(np.square(self.X_train - X[i]),axis = 1))
      dists[i, :] = distances

使用全向量化就比较有技术了,这里通过(X-Y)2=X2-2XY+Y^2来计算。

    num_test = X.shape[0]
    num_train = self.X_train.shape[0]
    dists = np.zeros((num_test, num_train))
    
    a = -2 * np.dot(X, self.X_train.T)
    b = np.sum(np.square(self.X_train), axis = 1)
    c = np.transpose([np.sum(np.square(X), axis=1)])
    dists = np.sqrt(a + b + c)

2.SVM

SVM这里我想介绍一下背景知识。首先介绍一下SVM的loss计算。

2018-04-18-07-32-19

这里的1是margin。SVM使用的是hinge loss。hinge loss图形如下:

2018-04-18-07-37-27

我们之前学习到SVM的代价函数是这个样子

2018-04-18-07-38-14

调转一下约束项的位置,就成了e >= 1 - ywx了。可以看出来SVM损失函数可以看作是L2-norm和Hinge Loss之和。

在这里我们只需要计算hinge loss就行了。

  num_train = X.shape[0]
  num_classes = W.shape[1]
  scores = X.dot(W)
  correct_class_scores = scores[range(num_train), list(y)].reshape(-1,1) #(N, 1)
  margins = np.maximum(0, scores - correct_class_scores + 1)
  margins[range(num_train), list(y)] = 0
  loss = np.sum(margins) / num_train + 0.5 * reg * np.sum(W * W)

至于gradient,我们需要对这个loss进行w求导:

2018-04-18-07-45-53

注意上面的计算l(*)只有在符合相应条件的时候才进行。

  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].T
        dW[:,y[i]] += -X[i].T

  loss /= num_train
  dW /= num_train

  # vectorized操作
  coeff_mat = np.zeros((num_train, num_classes))
  coeff_mat[margins > 0] = 1
  coeff_mat[range(num_train), list(y)] = 0
  coeff_mat[range(num_train), list(y)] = -np.sum(coeff_mat, axis=1)

  dW = (X.T).dot(coeff_mat)
  dW = dW/num_train + reg*W

3.Softmax

Softmax也是常见的non-linearity函数。下面是Softmax的定义

2018-04-18-07-57-33

单个测试数据的损失就是这样计算,最后求总和要加起来所有的才行。

  num_classes = W.shape[1]
  num_train = X.shape[0]
  scores = X.dot(W)
  softmax_output = np.exp(scores)/np.sum(np.exp(scores), axis = 1).reshape(-1,1)
  loss = -np.sum(np.log(softmax_output[range(num_train), list(y)]))
  loss /= num_train 
  loss +=  0.5* reg * np.sum(W * W)

再求gradient。求导很重要的一点就是要分清求导对象

2018-04-18-08-01-49

  dS = softmax_output.copy()
  dS[range(num_train), list(y)] += -1
  dW = (X.T).dot(dS)
  dW = dW/num_train + reg* W 

4.Two-layer NN

从题目可以知道这里的结构是Input--FC--ReLU--FC--Softmax+loss的结构。由于我们引入了ReLU层,将输入中所有小于0的项都给去掉了。所以反向将gradient传回来的时候,这些小于0的位是没有贡献的。

下面是残差分布,这里对于后向传播的gradient计算做了一些解释。梯度计算与反向传播对梯度计算给出了一个很好的实例。

2018-04-18-08-06-36
    dscores = softmax_output.copy()   # how this come from please see http://cs231n.github.io/neural-networks-case-study/ 
    dscores[range(N), list(y)] -= 1
    dscores /= N
    grads['W2'] = h_output.T.dot(dscores) + reg * W2
    # 以上通过Softmax章节的w求导就可以得到
    grads['b2'] = np.sum(dscores, axis = 0)
    
    dh = dscores.dot(W2.T)
    dh_ReLu = (h_output > 0) * dh
    grads['W1'] = X.T.dot(dh_ReLu) + reg * W1
    grads['b1'] = np.sum(dh_ReLu, axis = 0)

5.feature

这个涉及到图片的直方图之类的,感觉用处不大,懒得看了

Assignment2: FC-NN, BatchNormalization, Dropout, cnn, Pytorch

Assignment2相对Assignment1来说知识程度更深了,但是因为有了Assignment1中对梯度和backpropagate的学习,所以相对来说都能触类旁通。唯一比较复杂的就只有卷积层梯度的求解了。所以这部分我先总结一下自己所学到的东西,然后针对题目中的相关问题给出一些讲解。

1.Fully-connected Neural Network

这一部分介绍了几种常见的层的forward/backward,并对这些行为的实现加以封装。

1.Affine Layer仿射层。其实也就是fully-connected layer. Affine Layer其实就是y=wx+b的实现。这一层的backward梯度也比较好求

2.ReLU层。这一层运用了ReLU函数,对于前面传来的小于0的输入都置零,大于0的输入照常输出。引入这种非线性激励函数的作用是避免线性情况下输出永远都是输入的线性组合,从而与没有隐藏层效果相当。在求backward梯度时要注意,只有输出为正数的才有梯度,输出的梯度应该等于dout*x。

除了讲解上面的层级,还引入了模块化编程的概念,使用Solver来控制整个训练过程,将模型常用的参数都传给Solver,然后Solver内部进行训练。斯坦福大学学生编程能力真的强。

然后给出了几种更新规则的区别,SGD+momentum,RMSProp,Adam等,这些算法只要知道个原理,都不是很难。

2.BatchNormalization

这一部分难点主要在于
1.test模式下BN的操作:由于我们在训练时候已经得到了running_mean和running_var,这两个值将用在test模式下替换原有的sample_mean和sample_var。再带入公式即可。

2.backward梯度的计算:这里有一篇非常好的文章Understanding the backward pass through Batch Normalization Layer。简单来说就是当我们没办法一下子看出梯度来时,画出计算图,逐层递推。这和cs231n课程讲到的也是一个意思。最后得到梯度后直接计算,可以比逐层递推有更高的效率。

具体怎么搞就去看代码吧。

3.Dropout

Dropout相对比较简单,但是要注意训练模式和测试模式下的不同。测试模式下我们可以使用Dropout,但是测试模式下为了避免随机性不能使用Dropout。为了实现高效率,我们直接对训练时除以p即可。具体的原因请看上面的参考文章:深度学习笔记二。在这里,我们并不是简单的去除以p,而是除以1-p。因为这样可以避免后续的normalize操作。并且这里要把Dropout的mask记住,然后在backward的时候需要。这是和BN一样的原理。

4.Convolutional Network

最难的应该是这部分了。
首先,第一个难点就是backward梯度的推导。这里我推导了一次。好难过啊,不知道怎么显示latex。这里的推导大家如果看不懂就去慕课学院讲解课这里看吧。

假设我们有一个原来的图片。用3*3的简化
$$ \begin{Bmatrix} a_{11} & a_{12} & a_{12} \ a_{21} & a_{22} & a_{23}\ a_{31} & a_{32} & a_{33} \end{Bmatrix} $$

我们的filter是这样的:
$$ \begin{Bmatrix}
w_{11} & w_{12}\
w_{21} & w_{22}
\end{Bmatrix} $$

最后的结果是:
$$ \begin{Bmatrix}
z_{11} & z_{12}\
z_{21} & z_{22}
\end{Bmatrix} $$

容易得到:
$ z_{11}=a_{11}w_{11}+a_{12}w_{12}+a_{21}w_{21}+a_{22}w_{22} $

$ z_{12}=a_{12}w_{11}+a_{13}w_{12}+a_{22}w_{21}+a_{23}w_{22} $

$ z_{21}=a_{21}w_{11}+a_{22}w_{12}+a_{31}w_{21}+a_{32}w_{22} $

$ z_{22}=a_{22}w_{11}+a_{23}w_{12}+a_{32}w_{21}+a_{33}w_{22} $

又因为我们可以计算出{z}的gradient。也就是backpropagate时候从后面传来的上游gradient。
$$ \begin{Bmatrix}
\delta_{11} & \delta_{12}\
\delta_{21} & \delta_{22}
\end{Bmatrix} $$

这样当我们对$ a_{ij} $求导的时候,由于同一个$ a_{ij} $可能参与了多个$ z_{ij} $的计算,所以求导的时候要加起来。例如:
$ \triangledown a_{11} = \delta_{11}w_{11} $
$ \triangledown a_{12} = \delta_{11}w_{12} + \delta_{12}w_{11} $
...
$ \triangledown a_{33} = \delta_{22}w_{22} $
然后我们进行一下排列组合。

2018-04-27-12-26-59

第二个难点是在fast_layer的时候,会出现col2im_6d_cython isn't defined的问题,这时候需要删除cs231n文件夹下面除im2col_cython.pyx以外所有以im2col_cython开头的文件,然后重新编译。

第三个难点是在Spatial Batch Normalization处理图片时,这里的输入是(N,C,H,W),我们需要先转换为(N,H,W,C)再reshape成(N*H*W, C),最后再转换回来,这样才能保留住channel进行Spatial BN操作。

然后我们就可以愉快的组装layer成一个完整的convolutional network了。

5.Pytorch和TensorFlow

这里就没啥好讲的了。

Assignment3: RNN, Network visualization, style transfer, GAN

1.RNN

RNN是种十分强大的网络,尤其是改进版LSTM,更是让人叹为观止。这个作业写了一个文本标注的例子,只要注意到了rnn的模型架构,一般不会有问题。我放在这里来。

2018-04-26-23-45-12

特别注意LSTM的模型中,$c_t$的梯度来源有两个,dc_t和tanh。所以要把两个相加。

Network visualization

Style transfer

GAN

这几个专题感觉都是偏应用型的,代码没什么难度,而且我的代码注释比较详细。直接跟着代码看就行了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,333评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,812评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,016评论 0 246
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,293评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,650评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,788评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,003评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,741评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,462评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,681评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,168评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,528评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,169评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,119评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,902评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,846评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,719评论 2 274

推荐阅读更多精彩内容