CS231N Assignment3 SoftMaxpython
Beginapp
本文主要介紹CS231N系列課程的第三項做業,寫一個SoftMax損失的線形訓練模型。dom
課程主頁:網易雲課堂CS231N系列課程機器學習
語言:Python3.6函數
系統:Windows10學習
1 SoftMax分類器測試
簡單介紹SoftMax,它和SVM都是比較經常使用的線形分類器,SoftMax最終獲得的損失是spa
反應每一個分類的機率大小。以下所示:blog
最左邊藍色框爲每一個分類的分數,咱們取exp能夠獲得紅色框,再歸一化獲得最右邊綠色it
的框,標準化的值就反應它的機率狀況,咱們再取它的-log獲得咱們要的損失值。
softmax到底什麼含義呢?我查了一下,通常直接max取值使直接取最大值,softmax將
其轉變爲機率問題,這樣就會考察機率狀況,更加合理~~~emmm機器學習知識還不太好,等
我再看看書多補充點解釋。
2 softmax梯度
前文解釋了前向傳播,計算損失,訓練一個模型,還須要找到梯度,如何計算梯度呢?
下圖是我寫的一個計算,emmm懶得敲公式
而後在網易雲課堂上,寫了說要考慮一個穩定性問題~~~讓每個分數值都減去最大值,
那麼每一個分數都變爲了複數,也就到了左半軸,這樣指數函數變化率就會減少。emmm
大概使考慮這樣就穩定了
3 代碼部分
因爲都是線形分類器,因此代碼的訓練、預測部分都是同樣的,不一樣的在於損失函數
的求解以及梯度的計算。以下爲損失函數的計算部分
def loss(self,W,X,Y,reg): loss = 0.0 num_train = X.shape[0] dW = np.zeros(W.shape) #計算分數 scores = X.dot(W) scores = scores - np.max(scores,axis=1,keepdims=True) #取score的exp exp_scores = np.exp(scores) #求行和,獲得Pk的底 sum_row = np.sum(exp_scores,axis = 1,keepdims=True) #相除獲得Pk P = exp_scores / sum_row #計算Loss loss = -1.0 / num_train * np.log(P[np.arange(num_train),Y]).sum() loss += 0.5 * reg * np.sum(W*W) #計算Dw梯度 grad = np.zeros_like(P)#生成一個和P同樣的0矩陣 grad[np.arange(num_train),Y] = 1#對矩陣中Y所對應的部分加一個1,由於一會要剪 dW = X.T.dot(P - grad) #上文剛說要減,如今就減去,只有Y對應的地方有變化 dW = dW / num_train#加正則 dW += 0.5 * reg * np.sum(W*W) return loss,dW
測試:損失爲2.5589,梯度以下
其餘代碼以下
class Softmax(): def __init__(self): self.W = None pass def loss(self,W,X,Y,reg): loss = 0.0 num_train = X.shape[0] dW = np.zeros(W.shape) #計算分數 scores = X.dot(W) scores = scores - np.max(scores,axis=1,keepdims=True) #取score的exp exp_scores = np.exp(scores) #求行和,獲得Pk的底 sum_row = np.sum(exp_scores,axis = 1,keepdims=True) #相除獲得Pk P = exp_scores / sum_row #計算Loss loss = -1.0 / num_train * np.log(P[np.arange(num_train),Y]).sum() loss += 0.5 * reg * np.sum(W*W) #計算Dw梯度 grad = np.zeros_like(P)#生成一個和P同樣的0矩陣 grad[np.arange(num_train),Y] = 1#對矩陣中Y所對應的部分加一個1,由於一會要剪 dW = X.T.dot(P - grad) #上文剛說要減,如今就減去,只有Y對應的地方有變化 dW = dW / num_train#加正則 dW += 0.5 * reg * np.sum(W*W) return loss,dW def train(self,X,Y,learning_rate=1e-3,reg=1e-5,num_iters=100,batch_size=200,verbose=False): ''' 隨機梯度降低法訓練分類器 輸入參數: -learning_rate學習率 -reg正則化強度 -num_iters步長值 -batch_size每一步使用的樣本數量 -verbose若爲真則打印過程 輸出參數: list損失值 ''' num_train,dim = X.shape num_classes = np.max(Y) + 1 #if self.W is None: #初始化W矩陣 self.W = 0.001 * np.random.randn(dim,num_classes) loss_history = [] #開始訓練num_iters步 for it in range(num_iters): X_batch = None Y_batch = None ######################## # 選取部分訓練樣本 # 隨機生成一個序列 batch_inx = np.random.choice(num_train,batch_size) X_batch = X[batch_inx,:] Y_batch = Y[batch_inx] ######################### # 計算損失與梯度 loss,grade = self.loss(self.W,X_batch,Y_batch,reg) loss_history.append(loss) ######################## # 參數更新 # 梯度爲正表示損失增大,應該減小,成負相關 self.W = self.W - learning_rate * grade #打印結果 if verbose and it % 100 == 0: print('iteration %d / %d : loss %f'%(it ,num_iters,loss)) return loss_history def predict(self,X_train): y_predict = np.zeros(X_train.shape[1]) #根據訓練後的W矩陣計算分數 scores = X_train.dot(self.W) #找到得分中最大的值做爲類別 y_predict = np.argmax(scores,axis = 1)#計算每一行最大值 return y_predict
接下來咱們作一步測試,訓練咱們用到的數據。
############################################################## # step4 調參 # 兩個參數,學習率;正則化強度 learning_rate = [1e-7,2e-7,5e-7] regularization_strengths = [3e4,3.25e4,3.5e4] results = {} best_val = 0 best_svm = None ###################################### # 循環執行代碼 # 對不一樣的學習率以及正則化強度進行測試 # for rate in learning_rate: for regular in regularization_strengths: Softmax2 = Softmax() #訓練 Softmax2.train(X_train,Y_train,learning_rate=rate,reg=regular,num_iters=1000) #預測 Y1 = Softmax2.predict(X_train) Y2 = Softmax2.predict(X_val) accuracy_train = np.mean(Y1==Y_train) accuracy_val = np.mean(Y2==Y_val) #判斷優略 if best_val < accuracy_val: best_val = accuracy_val best_svm = Softmax2#保存當前模型 #存儲數據 results[rate,regular] = (accuracy_train,accuracy_val) #打印數據 for lr,reg in sorted(results): accuracy_train,accuracy_val = results[(lr,reg)] print('lr:%e reg %e train accuracy: %f val val accuracy : %f'%(lr,reg,accuracy_train,accuracy_val))
結果以下,emmm有點低,等我之後調調,先學會寫輪子把