专栏名称: 何时夕
14级计算机系学生,热爱科幻与编程。 QQ:1018998632,加时备注原因。
目录
相关文章推荐
51好读  ›  专栏  ›  何时夕

cs231n之SVM算法和SoftMax算法

何时夕  · 简书  ·  · 2018-04-19 21:12

正文

请到「今天看啥」查看全文


1.环境搭建以及前置条件

  • 1.前置环境:
    • 1.mac
    • 2.pycharm
    • 3.python3
    • 4.Anaconda
  • 2.环境搭建:
    • 1.官网下载并安装Anaconda
    • 2.官网下载并安装pycharm
    • 3.在pycharm中使用Anaconda
      • 1.preference-->project-->project interpreter
      • 2.将Anaconda的解释器当做一个project interpreter添加
    • 4.下载assignment1作业项目并导入pycharm中, 作业下载
    • 5.下载数据集并解压到assignment1作业项目的 assignment1/cs231n/datasets/中。 数据集下载
    • 6.执行数据集中的.sh文件使得数据集可用
  • 3.前置知识:numpy、python、SciPy基础学习, 教程

2.SVM知识了解

假设我们有一个训练图片集 10000*3072 ,也就是10000张像素为3072的图片,有一个测试图片集的图片 100*3072 ,测试和训练图片集总共的图片类型有10种(这里图片类型指的是图片内容的类型,如:图片内容为猫、狗等)。我们将某一张训练图片命名为 Tn ,将一张测试图片命名为 Cm ,将一个图片的类型命名为 La

1.SVM是什么

  • 1.我们定义一个函数为 f(Cm,W)=W*Cm ,在这里W为一个 3072*10 的矩阵。最终这个函数的结果是一个大小为10的数组,这里数组中的每个数字就是 Cm 这张图片在每个 La 下的得分,分数最高的 La 就表示我们预测这张测试图片是这种图片类型。
  • 2.从1中我们可以知道要让我们的预测准确率高,那么 W 就需要找准。我们有很多方法来寻找一个好的 W
    • 1.随机法:不断随机生成W,然后计算准确率,最终试出符合要求的 W ,但是很明显这种方式效率很低
    • 2.SVM:我们可以先随机初始化一个 W ,此时可以算出准确率为 z1 。此时我们可以尝试小幅度修改(整体加一个数或者减一个数) W 中的某一行数据,然后再计算准确率 z2 。如果 z1 小于 z2 ,那么表示我们修改对了,可以继续这样修改,否则我们需要往反方向修改。以上就是SVM的基本思想。 如果把寻找一个最佳的W比作在一座山中寻找最低点的话,那么SVM就是不断尝试沿着下降的路向前走,一直走到山谷最低点。

2.SVM具体实现

我们在1中说了SVM算法的基本思想,但是我们也可以从中发现一些问题。1.每次要通过计算最终的准确率才能知道当前的 W 是否变好了,这样效率太低了。2.修改 W 的时候我们只是在尝试,如果能知道当前具体的下降趋势是不是速度就更快了呢?接下来的一节我们就会解决上面的问题。

  • 1.损失函数:为了解决上面说到的第一个问题,我们就定义了一个损失函数来评价当前的 W 的好坏。
    • 1.公式:
      损失函数
    • 2.解释:
      • 1.我们都知道 f(Cm,W) 的结果会是一个大小为10的数组,这个数组的下标表示的是 La 数组中某个图片类型的下标,那么我们就可以将这个数组比作: 在W下Tm这张训练图片,在每个图片类型下面的得分 。我们这里讲这个得分数组设为 S[10]
      • 2.我们都知道每个 Tn 都会有一个正确的图片类型 La 我们设为 LaM ,那么此时对于 Tn 我们就有衡量这个 W 是否标准的方法了,用每个 S 减去 LaM (除了 LaM 本身)再加上一个 x (这里的 x 是一个自定义的数字,可以是1,2等等,这个 x 是一个阈值,表示 LaM 的分数到底超过其他 S 多少才算可以接受),最后将每个的结果求和这样就可以得出一个数字 Ls 这里的Ls就是Tn对于W的评价,Ls越大就表示,对于Tn来说这个W越不好,还有一个限制是0<=Ls,当Ls小于0的时候表示这个W对Tn来说已经够好了,所以小于0的Ls都算作0 ,到这里就是图片中公式 Li的解释
      • 3.我们在上面算出了一个 Tn 对于 W 的评价 Ls ,但是光有这一个样本太少了,我们需要让很多的 Tn W 进行评价得出大量的 Ls ,然后去平均值,此时就能得出当前图片训练集对于这个 W 的评价,到这就是图片中公式 L 的解释。
      • 4.我们能看见公式中最后还有一个直接定义的项,这个一项被称为 正则项 。大家可以想想,我们前面获取的评价 LsM 是基于训练图片集的,但是我们正在需要进行预测的是测试图片集。那么此时就会有个问题 我们的W只对训练图片集的预测正确率高,对测试图片集的预测正确率很低,这个现象就被称为————过拟合 ,那么我们如何解决这个问题呢?这就要 正则项 出马了
        正则化公式

        ,这几个公式就是常用的 正则项 ,我们直接拿来使用就好了。
  • 2.优化函数:为了解决上面提出的第二个问题,我们可以定义一个优化函数,来不断的根据趋势优化我们的 W
    • 1.我们首先需要获取到当前 W 朝着好的方向前进的趋势,这里就要用上前面定义的 损失函数了 ,因为损失函数是关于 Wj和Wi的函数 ,也就是说这两个参数影响着 损失函数 的走向,而 损失函数 的结果就表示当前 W 的好坏程度。如果你知道 偏导数 的话就可以知道算出 损失函数对于Wj和Wi的偏导数dW 就是的 W 当前的趋势。所以便有了这个公式:
      dw
    • 2.我们得到了 dW 之后,优化的公式就出来了,我们需要不断更改 W 使得 损失函数 的结果向0靠近,所以优化函数是这样的:
      优化函数
      ,注意这里还有一个参数 learning_rate 被称为 学习率 ,这个 学习率就表示我们在通往山谷的路上迈的步子有多的大,如果太大的话就越过山谷到另一边山坡去了,如果太小我们下降的又太慢,所以这是一个超参数,需要我们多试试找到最优结果
  • 3.随机梯度下降法:我们现在已经有了 优化函数 损失函数 ,但是我们会发现每一次进行 W 优化的时候,都要遍历一整个图片训练集,这样效率就会很低,所以我们可以每次训练取一小部分,图片训练集,然后进行训练,这样的话效率就会比较高。 一般来说,取的数字都是2的幂

2.SVM代码实现

1.我的项目

  • 1.先上一个github吧,会持续更新直到把cs231n课程学习完: cs231n
  • 2.我的项目目录:
    项目目录

2.代码分析

全局代码1

全局代码2
  • 1. 建议结合github代码食用 ,前面6行就不说了,我在上一篇博客中分析过,就是导入模块,然后从文件中读取数据: cs231n之KNN算法 ,只要看里面的第二节代码解析的前两个小结就行了。
  • 2.定义了:
    • 1. num_training :全体训练集数量( num_dev 会从其中抽取一定数量的图片用于训练,减少训练时间)
    • 2. num_validation :验证集数量(在不同的 学习率和正则参数 下使用该验证集获取最高的正确率,最终找到最好的 学习率和正则参数 )
    • 3. num_test :测试集数量(在获取到最好的 学习率和正则参数 之后,测试最终的正确率)
    • 4. num_dev :随机训练集数量(用于实现 随机化梯度下降的 )。
  • 3.接下来三行是从训练数据 x_train和y_train 中获取 验证集数据
  • 4.接下来三行是从训练数据 x_train和y_train 中获取 全体训练集数据
  • 5.接下来三行是从 num_training 中随机选取 随机训练集数据
  • 6.接下来四行表示:将 x_train,x_val,x_test,x_dev 这些 n*32*32*3 的图片集,转化成 n*3072 的矩阵。简单来说就是将每张图片拉伸成一维的矩阵,方便后面进行数据处理。
  • 7.接下来五行表示:将 x_train,x_val,x_test,x_dev 这些图片集进行 去均值处理 ,简单来说就是计算出 x_train 全体图片的均值,然后让其他图片集的每张图片邱减去这个均值。 这样的好处是统一量纲,和归一化操作类似,只是没有再除以方差而已
  • 8.接下来两行定义了一系列 学习率和正则参数 ,在后面会使用两层循环找到最高正确率下的 学习率和正则参数
  • 9.接下来三行定义了:每个 学习率和正则参数 下的正确率键值对 results ,最高的正确率 best_val ,最高正确率下的 SVM对象 后面可以之间对测试集进行预测。
  • 10.进入了两层循环,被循环测参数分别是 学习率和正则参数
    • 1.在某个 学习率和正则参数 下,我们创建了一个 SVM对象 ,然后将 学习率和正则参数 、训练集 x_train和y_train 、W需要迭代的次数 num_iters ,传入训练方法中。
      训练代码
      • 1.我们进入了训练 W 的代码中,先是获取了训练集图片数量 num_train ,图片种类数量 num_classes 。然后随机初始化了 W
      • 2.定义一个 loss_history 用于储存每次迭代的损失值
      • 3.进入一个循环,被循环的参数是 num_iters ,也就是前面说的 W 需要迭代的次数
        • 1.从训练集 x_train和y_train 中再取出 batch_size 数量的数据集,再次减少训练时间。
        • 2.将再次减少的训练集 X_batch和y_batch 还有 正则参数reg 传入 loss() 方法中以获取损失值 loss W 的趋势 grad,也就是dW
          计算loss
          • 1.有两种方式来计算损失值 loss W 的趋势 dW ,我这里选择简单的方式。
          • 2.先定义了一个与 W 同矩阵大小的 dW ,获取了训练集图片数量和图片种类数量 num_train和num_classes
          • 3.初始化 loss为0
          • 4.进入循环,循环参数是训练集图片数量 num_train
            • 1.计算当前 W 和当前训练图片 X[i] 在各个图片种类下的分数 scores
            • 2.获得当前训练图片 X[i] 真实图片种类的分数 correct_class_score
            • 3.进入循环,循环参数是图片种类数量 num_classes
              • 1.如果当前的图片种类 j ,就是当前训练图片 X[i] 真实的图片种类 y[i] ,那么由前面损失函数的定义可知,我们不需要继续执行
              • 2.如果1不成立,我们就能计算出对于当前训练图片 X[i] ,在图片种类 j 下的损失分量 margin
              • 3.由前面损失函数的定义可知 loss 只需要大于0的 margin ,所以如果 margin 小于0,那么就当0处理,接下来就没必要继续了。
              • 4.如果 margin 大于0,那么为 loss 加上 margin ,并且给 dW[,j]和dw[,y[i]] 都加上公式:
                求偏导
                Wj和Wyi 求过偏导数之后的 X[i]和-X[i]
          • 5.退出两层循环,此时计算出了全部训练图片的 dW和loss 之和,所以 dW和loss 需要除以 num_train ,再为 loss和dW 加上正则项。
          • 6.返回 dW和loss
        • 3.获得了 loss W 的趋势 grad,也就是dW 之后,将本次 loss 储存在了 loss_history
        • 4.根据公式:
          优化函数
          ,对 W 进行优化
        • 5.这样一直循环直至迭代次数 num_iters 完成
      • 4. W 的循环迭代结束之后,返回上一层
    • 2.在当前 学习率和正则参数 下,将 W 训练完毕之后,分别使用 x_train和x_val 来进行预测并算出准确率 train_accuracy和val_accuracy
    • 3.一直循环上面的操作,直至找到最大的正确率下的 best_svm和best_val ,并将历次的 train_accuracy,val_accuracy 储存在 results 中。
    • 4.结束两层循环
  • 11.输出10中历次循环的 train_accuracy,val_accuracy 学习率和正则参数
  • 12.使用上面找到的最佳的 best_svm 来预测 测试集x_test 得到了 测试集 的准确率 test_accuracy 并输出
  • 13.获取最佳的 best_svm 中的 W ,将其重新转化为 n*32*32*3 ,然后以图片形式输出。

3.结果

  • 1.训练过程中在不同 学习率和正则参数 下训练好模型后, 验证集和训练集 进行预测的准确率:
    结果1
  • 2.最终 测试集 的准确率:
    结果2
  • 3. W 最终学习成的图片:可以看出车子的图片还是有一点大概的模型存在的。
    结果3

4.不同损失函数的SoftMax算法

我们前面做的了 Svm 算法就是不断根据损失函数对于 Wi Wj 这两个分量的偏导数来优化 W 的算法。这里的损失函数定义了 W 的好坏,如果我们换一个损失函数的定义方式,会不会有不一样的结果呢?我们接下来要讲的就是另一种损失函数的算法 SoftMax

  • 1.损失函数:
    softmax损失函数
    • 1.解释:这里的 Li 公式我们只要看 Log 里面的东西就好了,这里的 j 表示某一个图片种类, yi 表示该训练图片的真实种类,所以里面的东西就很好理解了, 即该训练图片真实种类的分数在总的分数中的占比 。最后Log内部算出的会是一个百分比,所以使用 Log 将其转化一下。
    • 2.当然最终的 损失函数L ,还需要算所有 Li 的均值
  • 2.损失函数的梯度,这里就是对 Wj Wyi 算偏导:
    softmax偏导
  • 3.以上就是 SoftMax和Svm 的全部不同,所以只需要更换一下公式的代码就可以了。

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻: https://cloud.tencent.com/developer/support-plan?invite_code=pe24xbp4axut







请到「今天看啥」查看全文