cs231n學(xué)習(xí)有疑惑? 看這一篇或許能搞定

cs231n assignments學(xué)習(xí)心得

cs231n是斯坦福的一門以計(jì)算機(jī)視覺(jué)為載體的深度學(xué)習(xí)課程,由李飛飛和她的幾個(gè)博士生上課。這門課親測(cè)好評(píng)。下面是我完成這些assignment的一些疑問(wèn)點(diǎn)和解決辦法。

首先先貼代碼:https://github.com/oubindo/cs231n-cnn
歡迎star和fork。感謝支持!

Assignment1:KNN,SVM,Softmax,Neuron Network

總體來(lái)說(shuō),這個(gè)assignment難度適中,但是對(duì)于numpy的要求還挺高的,要比較純熟的使用才能完成一些諸如矢量化一樣的操作。比較困難的地方在于梯度的計(jì)算。作為初學(xué)者的我一開(kāi)始是非常懵逼的,(現(xiàn)在好一點(diǎn)了也還有點(diǎn)懵逼)??戳斯俜浇o出的一些說(shuō)明,還有慕課學(xué)院講解課以后才理解了一些?,F(xiàn)在嘗試對(duì)于一些問(wèn)題給出自己的理解。圖片部分出自上面內(nèi)容

1.KNN

KNN主要的考察點(diǎn)就是兩重循環(huán),一重循環(huán)和全向量化。
先介紹一下背景,給出n維的測(cè)試點(diǎn)和訓(xùn)練點(diǎn),要求出它們之間的距離。使用兩重循環(huán)的話就是通過(guò)索引到這兩個(gè)數(shù)據(jù)再處理。

    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

使用一重循環(huán)是借助了numpy ndarry之間的相減功能,單獨(dú)的算出所有訓(xùn)練點(diǎn)到一個(gè)測(cè)試點(diǎn)的距離,再一次便利即可。

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

使用全向量化就比較有技術(shù)了,這里通過(guò)(X-Y)2=X2-2XY+Y^2來(lái)計(jì)算。

    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這里我想介紹一下背景知識(shí)。首先介紹一下SVM的loss計(jì)算。

2018-04-18-07-32-19

這里的1是margin。SVM使用的是hinge loss。hinge loss圖形如下:

2018-04-18-07-37-27

我們之前學(xué)習(xí)到SVM的代價(jià)函數(shù)是這個(gè)樣子

2018-04-18-07-38-14

調(diào)轉(zhuǎn)一下約束項(xiàng)的位置,就成了e >= 1 - ywx了。可以看出來(lái)SVM損失函數(shù)可以看作是L2-norm和Hinge Loss之和。

在這里我們只需要計(jì)算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,我們需要對(duì)這個(gè)loss進(jìn)行w求導(dǎo):

2018-04-18-07-45-53

注意上面的計(jì)算l(*)只有在符合相應(yīng)條件的時(shí)候才進(jìn)行。

  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也是常見(jiàn)的non-linearity函數(shù)。下面是Softmax的定義

2018-04-18-07-57-33

單個(gè)測(cè)試數(shù)據(jù)的損失就是這樣計(jì)算,最后求總和要加起來(lái)所有的才行。

  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。求導(dǎo)很重要的一點(diǎn)就是要分清求導(dǎo)對(duì)象

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

從題目可以知道這里的結(jié)構(gòu)是Input--FC--ReLU--FC--Softmax+loss的結(jié)構(gòu)。由于我們引入了ReLU層,將輸入中所有小于0的項(xiàng)都給去掉了。所以反向?qū)radient傳回來(lái)的時(shí)候,這些小于0的位是沒(méi)有貢獻(xiàn)的。

下面是殘差分布,這里對(duì)于后向傳播的gradient計(jì)算做了一些解釋。梯度計(jì)算與反向傳播對(duì)梯度計(jì)算給出了一個(gè)很好的實(shí)例。

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
    # 以上通過(guò)Softmax章節(jié)的w求導(dǎo)就可以得到
    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

這個(gè)涉及到圖片的直方圖之類的,感覺(jué)用處不大,懶得看了

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

Assignment2相對(duì)Assignment1來(lái)說(shuō)知識(shí)程度更深了,但是因?yàn)橛辛薃ssignment1中對(duì)梯度和backpropagate的學(xué)習(xí),所以相對(duì)來(lái)說(shuō)都能觸類旁通。唯一比較復(fù)雜的就只有卷積層梯度的求解了。所以這部分我先總結(jié)一下自己所學(xué)到的東西,然后針對(duì)題目中的相關(guān)問(wèn)題給出一些講解。

1.Fully-connected Neural Network

這一部分介紹了幾種常見(jiàn)的層的forward/backward,并對(duì)這些行為的實(shí)現(xiàn)加以封裝。

1.Affine Layer仿射層。其實(shí)也就是fully-connected layer. Affine Layer其實(shí)就是y=wx+b的實(shí)現(xiàn)。這一層的backward梯度也比較好求

2.ReLU層。這一層運(yùn)用了ReLU函數(shù),對(duì)于前面?zhèn)鱽?lái)的小于0的輸入都置零,大于0的輸入照常輸出。引入這種非線性激勵(lì)函數(shù)的作用是避免線性情況下輸出永遠(yuǎn)都是輸入的線性組合,從而與沒(méi)有隱藏層效果相當(dāng)。在求backward梯度時(shí)要注意,只有輸出為正數(shù)的才有梯度,輸出的梯度應(yīng)該等于dout*x。

除了講解上面的層級(jí),還引入了模塊化編程的概念,使用Solver來(lái)控制整個(gè)訓(xùn)練過(guò)程,將模型常用的參數(shù)都傳給Solver,然后Solver內(nèi)部進(jìn)行訓(xùn)練。斯坦福大學(xué)學(xué)生編程能力真的強(qiáng)。

然后給出了幾種更新規(guī)則的區(qū)別,SGD+momentum,RMSProp,Adam等,這些算法只要知道個(gè)原理,都不是很難。

2.BatchNormalization

這一部分難點(diǎn)主要在于
1.test模式下BN的操作:由于我們?cè)谟?xùn)練時(shí)候已經(jīng)得到了running_mean和running_var,這兩個(gè)值將用在test模式下替換原有的sample_mean和sample_var。再帶入公式即可。

2.backward梯度的計(jì)算:這里有一篇非常好的文章Understanding the backward pass through Batch Normalization Layer。簡(jiǎn)單來(lái)說(shuō)就是當(dāng)我們沒(méi)辦法一下子看出梯度來(lái)時(shí),畫出計(jì)算圖,逐層遞推。這和cs231n課程講到的也是一個(gè)意思。最后得到梯度后直接計(jì)算,可以比逐層遞推有更高的效率。

具體怎么搞就去看代碼吧。

3.Dropout

Dropout相對(duì)比較簡(jiǎn)單,但是要注意訓(xùn)練模式和測(cè)試模式下的不同。測(cè)試模式下我們可以使用Dropout,但是測(cè)試模式下為了避免隨機(jī)性不能使用Dropout。為了實(shí)現(xiàn)高效率,我們直接對(duì)訓(xùn)練時(shí)除以p即可。具體的原因請(qǐng)看上面的參考文章:深度學(xué)習(xí)筆記二。在這里,我們并不是簡(jiǎn)單的去除以p,而是除以1-p。因?yàn)檫@樣可以避免后續(xù)的normalize操作。并且這里要把Dropout的mask記住,然后在backward的時(shí)候需要。這是和BN一樣的原理。

4.Convolutional Network

最難的應(yīng)該是這部分了。
首先,第一個(gè)難點(diǎn)就是backward梯度的推導(dǎo)。這里我推導(dǎo)了一次。好難過(guò)啊,不知道怎么顯示latex。這里的推導(dǎo)大家如果看不懂就去慕課學(xué)院講解課這里看吧。

假設(shè)我們有一個(gè)原來(lái)的圖片。用3*3的簡(jiǎn)化
$$ \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} $$

最后的結(jié)果是:
$$ \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} $

又因?yàn)槲覀兛梢杂?jì)算出{z}的gradient。也就是backpropagate時(shí)候從后面?zhèn)鱽?lái)的上游gradient。
$$ \begin{Bmatrix}
\delta_{11} & \delta_{12}\
\delta_{21} & \delta_{22}
\end{Bmatrix} $$

這樣當(dāng)我們對(duì)$ a_{ij} $求導(dǎo)的時(shí)候,由于同一個(gè)$ a_{ij} $可能參與了多個(gè)$ z_{ij} $的計(jì)算,所以求導(dǎo)的時(shí)候要加起來(lái)。例如:
$ \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} $
然后我們進(jìn)行一下排列組合。

2018-04-27-12-26-59

第二個(gè)難點(diǎn)是在fast_layer的時(shí)候,會(huì)出現(xiàn)col2im_6d_cython isn't defined的問(wèn)題,這時(shí)候需要?jiǎng)h除cs231n文件夾下面除im2col_cython.pyx以外所有以im2col_cython開(kāi)頭的文件,然后重新編譯。

第三個(gè)難點(diǎn)是在Spatial Batch Normalization處理圖片時(shí),這里的輸入是(N,C,H,W),我們需要先轉(zhuǎn)換為(N,H,W,C)再reshape成(N*H*W, C),最后再轉(zhuǎn)換回來(lái),這樣才能保留住channel進(jìn)行Spatial BN操作。

然后我們就可以愉快的組裝layer成一個(gè)完整的convolutional network了。

5.Pytorch和TensorFlow

這里就沒(méi)啥好講的了。

Assignment3: RNN, Network visualization, style transfer, GAN

1.RNN

RNN是種十分強(qiáng)大的網(wǎng)絡(luò),尤其是改進(jìn)版LSTM,更是讓人嘆為觀止。這個(gè)作業(yè)寫了一個(gè)文本標(biāo)注的例子,只要注意到了rnn的模型架構(gòu),一般不會(huì)有問(wèn)題。我放在這里來(lái)。

2018-04-26-23-45-12

特別注意LSTM的模型中,$c_t$的梯度來(lái)源有兩個(gè),dc_t和tanh。所以要把兩個(gè)相加。

Network visualization

Style transfer

GAN

這幾個(gè)專題感覺(jué)都是偏應(yīng)用型的,代碼沒(méi)什么難度,而且我的代碼注釋比較詳細(xì)。直接跟著代碼看就行了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容