cs231n assignments學習心得
cs231n是斯坦福的一門以計算機視覺為載體的深度學習課程,由李飛飛和她的幾個博士生上課吓著。這門課親測好評。下面是我完成這些assignment的一些疑問點和解決辦法送挑。
首先先貼代碼:https://github.com/oubindo/cs231n-cnn
歡迎star和fork绑莺。感謝支持!
Assignment1:KNN惕耕,SVM纺裁,Softmax,Neuron Network
總體來說,這個assignment難度適中欺缘,但是對于numpy的要求還挺高的栋豫,要比較純熟的使用才能完成一些諸如矢量化一樣的操作。比較困難的地方在于梯度的計算谚殊。作為初學者的我一開始是非常懵逼的丧鸯,(現(xiàn)在好一點了也還有點懵逼)÷缭洌看了官方給出的一些說明双藕,還有慕課學院講解課以后才理解了一些。現(xiàn)在嘗試對于一些問題給出自己的理解乳幸。圖片部分出自上面內(nèi)容
1.KNN
KNN主要的考察點就是兩重循環(huán)抓谴,一重循環(huán)和全向量化。
先介紹一下背景怨愤,給出n維的測試點和訓練點派敷,要求出它們之間的距離。使用兩重循環(huán)的話就是通過索引到這兩個數(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之間的相減功能篮愉,單獨的算出所有訓練點到一個測試點的距離,再一次便利即可差导。
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計算颠蕴。
這里的1是margin。SVM使用的是hinge loss助析。hinge loss圖形如下:
我們之前學習到SVM的代價函數(shù)是這個樣子
調(diào)轉(zhuǎn)一下約束項的位置犀被,就成了e >= 1 - ywx了⊥饧剑可以看出來SVM損失函數(shù)可以看作是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求導:
注意上面的計算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函數(shù)。下面是Softmax的定義
單個測試數(shù)據(jù)的損失就是這樣計算膀跌,最后求總和要加起來所有的才行遭商。
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。求導很重要的一點就是要分清求導對象
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的項都給去掉了。所以反向?qū)radient傳回來的時候,這些小于0的位是沒有貢獻的祠汇。
下面是殘差分布仍秤,這里對于后向傳播的gradient計算做了一些解釋。梯度計算與反向傳播對梯度計算給出了一個很好的實例可很。
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章節(jié)的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纳鼎,并對這些行為的實現(xiàn)加以封裝俺夕。
1.Affine Layer仿射層。其實也就是fully-connected layer. Affine Layer其實就是y=wx+b的實現(xiàn)贱鄙。這一層的backward梯度也比較好求
2.ReLU層劝贸。這一層運用了ReLU函數(shù),對于前面?zhèn)鱽淼男∮?的輸入都置零逗宁,大于0的輸入照常輸出映九。引入這種非線性激勵函數(shù)的作用是避免線性情況下輸出永遠都是輸入的線性組合,從而與沒有隱藏層效果相當瞎颗。在求backward梯度時要注意氯迂,只有輸出為正數(shù)的才有梯度,輸出的梯度應該等于dout*x言缤。
除了講解上面的層級,還引入了模塊化編程的概念禁灼,使用Solver來控制整個訓練過程管挟,將模型常用的參數(shù)都傳給Solver,然后Solver內(nèi)部進行訓練弄捕。斯坦福大學學生編程能力真的強僻孝。
然后給出了幾種更新規(guī)則的區(qū)別,SGD+momentum守谓,RMSProp穿铆,Adam等,這些算法只要知道個原理斋荞,都不是很難荞雏。
2.BatchNormalization
這一部分難點主要在于
1.test模式下BN的操作:由于我們在訓練時候已經(jīng)得到了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。為了實現(xiàn)高效率哪替,我們直接對訓練時除以p即可栋荸。具體的原因請看上面的參考文章:深度學習筆記二。在這里凭舶,我們并不是簡單的去除以p晌块,而是除以1-p。因為這樣可以避免后續(xù)的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時候從后面?zhèn)鱽淼纳嫌蝕radient穴翩。
$$ \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} $
然后我們進行一下排列組合。
第二個難點是在fast_layer的時候丰介,會出現(xiàn)col2im_6d_cython isn't defined的問題背蟆,這時候需要刪除cs231n文件夾下面除im2col_cython.pyx以外所有以im2col_cython開頭的文件鉴分,然后重新編譯。
第三個難點是在Spatial Batch Normalization處理圖片時淆储,這里的輸入是(N,C,H,W)冠场,我們需要先轉(zhuǎn)換為(N,H,W,C)再reshape成(N*H*W, C),最后再轉(zhuǎn)換回來本砰,這樣才能保留住channel進行Spatial BN操作碴裙。
然后我們就可以愉快的組裝layer成一個完整的convolutional network了。
5.Pytorch和TensorFlow
這里就沒啥好講的了点额。
Assignment3: RNN, Network visualization, style transfer, GAN
1.RNN
RNN是種十分強大的網(wǎng)絡舔株,尤其是改進版LSTM,更是讓人嘆為觀止还棱。這個作業(yè)寫了一個文本標注的例子载慈,只要注意到了rnn的模型架構,一般不會有問題珍手。我放在這里來办铡。
特別注意LSTM的模型中,$c_t$的梯度來源有兩個琳要,dc_t和tanh寡具。所以要把兩個相加。
Network visualization
Style transfer
GAN
這幾個專題感覺都是偏應用型的稚补,代碼沒什么難度童叠,而且我的代碼注釋比較詳細。直接跟著代碼看就行了课幕。