• CS231N assignment3 SoftMax


    CS231N Assignment3 SoftMax

     

    Begin


    本文主要介绍CS231N系列课程的第三项作业,写一个SoftMax损失的线形训练模型。

    课程主页:网易云课堂CS231N系列课程

    语言:Python3.6

    系统:Windows10

    1 SoftMax分类器


            简单介绍SoftMax,它和SVM都是比较常用的线形分类器,SoftMax最终得到的损失是

    反应每个分类的概率大小。如下所示:

            最左边蓝色框为每个分类的分数,我们取exp可以得到红色框,再归一化得到最右边绿色

    的框,标准化的值就反应它的概率情况,我们再取它的-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有点低,等我以后调调,先学会写轮子把

  • 相关阅读:
    poj 3096 Surprising Strings (set)
    hdu 4038 stone
    STL set 使用总结
    poj 3185 The Water Bowls (bfs 加未压缩)
    QPixmap显示图片
    addStretch的作用 .
    Qt SizeHint()
    StyleSheet
    linux编程守护进程编写
    Qt样式表的使用
  • 原文地址:https://www.cnblogs.com/flyingjun/p/10403660.html
Copyright © 2020-2023  润新知