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有点低,等我之后调调,先学会写轮子把