之前学习的KNN算法属于直接将所有的训练图片数据化,根据图片的像素值进行判断,最简单的NN算法是用与待判断图片的差距最小(距离最近)的那张图片的类别当做此图片的类别,我们不难看到,1NN算法的正确性很差,相较于完全随机的10%的正确率,其正确率也不过只有20%左右,正确率低。我们用KNN算法则是用与其临近的K张图图片进行“投票”,得票最多的类别即为此图片的类别,可以看到,KNN算法有效的排除了某些噪声的干扰,但是主体的思路仍然是直接进行比较,此算法的缺点在于时间复杂度高,即每次判断一张新图片时,我们都需要遍历所有的训练数据,将训练数据的值与待判断题图片的像素值进行比较,而且十分不精确。

  SVM算法的特点是需要模型需要经过长时间的训练(例如在本次实践中,训练模型就花了2.5分钟,这还仅仅是在数据规模不是很大的情况下),而之前的KNN不需要任何的训练和迭代过程,所谓的训练,仅仅是将所有的像素值都存在了一个矩阵中进行比较而已。但是SVM的判断过程极其迅速,只需要做一个矩阵乘法,然后找到其中分数最高的类就可以实现,不需要遍历整个训练集,能够更为方便的判断数据,这是SVM相较于KNN在时间性能上比较优秀的地方,此外,在算法的正确性方面,SVM跟KNN比较也有了长足的进步,以下将说明SVM的整个代码流程:

  首先:与KNN一样,我们需要将输入的训练集(共有N个元素,M个类)抽象为矩阵存储,然后得到了训练矩阵(N*M),我们通过对训练矩阵进行某种操作,得到一个新的矩阵(W)。此矩阵就是我们计算机所产生的线性分类器模型,对于每一个输入的图片(一个行向量或者一个列向量),我们期望将输入的图片做一个变换(与线性分类器相乘),得到变换后的向量,此向量共有M个元素,每个元素体现了不同的类的得分情况。我们认为,图片在某一类分数越高,则属于这一类的可能性就越大。不妨看下面的图片

(摘自CS231N的课程笔记)

  其中b为偏置向量,我们可以考虑为y=kx+b中的b,b不同,则与y轴的截距不同。这样起到的作用是能够让我们的分类器在划出决策边界时可以上下移动,增强其泛化能力。在这个算法中,我们显然期望原本的类别的得分应该尽可能高,事实上,我们后续在线性分类做决策时也是根据这个得分做决策的。但是显然,并不是所有的时候正确的类别的分数都是最高的,像这个例子,本来是猫,但是猫的得分反而是最低的。对于单一照片的分类我们可以认为是偶然的误差,可是我们希望在所训练出的模型尽可能多的满足此项规律,即正确项得分最高,换言之,我们不希望在训练模型的过程中丢失训练样本原本的信息,希望尽可能的保有原来的信息。那么如何衡量我们的训练过后的model是否丢失了一些信息呢?我们就引入一个概念叫做损失函数:损失函数顾名思义,是衡量我们预测值与初始值相差的函数,我们想要知道在训练中到底损失了多少信息,即可以用损失函数来衡量,损失函数有SVM和softmax两种,本篇仅仅讨论SVM损失函数:

    

  我们考虑,对于一个具体的图片,其所属类别一定是确定的,在坐标系中,即在决策边界的外侧,那么我们该如何衡量我们的损失呢?显然,如果我们在经过变换后得到不同类别的分数,此分数可以作为决策依据,那么我们很自然的考虑到如果正确类别的分数要高于其他类别,而且分数高出一个安全的边界,那么这种情况下,我们显然就十分满意,因为我们有充足的理由相信,这个图片我们判断的是对的,那么如果这张图片是我们的训练集中的元素,则可以认定为:我们训练出的model并没有磨灭掉其信息,其属性仍然存在,那么此时,我们就认为没有损失。由上面的文字叙述,我们可以得到以下的数学表达式:

  其中,Li即为对于第i个样例的损失函数,值得注意的是,我们规定了j≠yi是因为我们需要判断正确的类与错误类的得分差,正确类在这里起到的是比较作用,j=yi的情况没有意义!

  

  我们希望尽可能多的数据,其错误类别都要尽可能的在绿色区域,而正确类别的分数都要尽可能在蓝色区域,那么此时正确和错误的差就有一个安全的delta,此时我们就不需要积累损失,显然,损失函数衡量了我们对于原本训练数据的正确性的满意程度,或者说损失了多少信息。显然,我们接下来要做的就是尽可能的减少损失函数,当然最优的可能性是损失函数恰好为0,即没有损失任何信息!但是显然我们遇到了一个问题,那就是可能不只有一个W符合我们的要求,如果有一个W能够完美符合我们所有的要求,即损失函数为0,那么对于W的任意倍数也都满足这个条件,显然是因为我们SVM损失函数所看中的,仅仅是数据之间的绝对差异。为了解决W不确定的问题,我们引入正则项的概念,正则项可以起到简化模型的作用。我们希望用一些偏好去唯一确定W,我们可以采取用正则惩罚项R(W)扩大损失值的方法:最常见的正则化惩罚是平方l2范数,它通过对所有元素二次惩罚来阻止大的权值:

  于是我们的损失函数可以定义为一下的样子:

  值得注意的是,前面的部分为所有损失函数的平均值,后面为正则项。我们期望上面的式子达到最小值,观察上式不难发现:有几个超参数,其中一个为W,还有一个安全边界delta(实际上delta=1即可,具体证明过程参见cs231n的课程介绍),另一个则是正则惩罚项的系数λ。我们可以采用K折交叉验证的方式去确定λ超参数。显然,不同的超参数的取值显著性的影响了我们分类器的性能,也即分类的准确性,那么接下来我们需要确定W到底该如何选取。

  我们可以采用动态的方式去确定W,具体的实现思路如下:我们可以先随机一个W矩阵,里面的元素完全随机,然后计算出此时的损失函数值以及当前的梯度。我们考虑梯度下降法(SGD),假定我们在一个山谷中,我们想要往山下走,我们显然最容易想到的办法就是,找到当前位置最陡的地方,然后迈开步子往下走,每次走之前,都调整方向为最陡的地方,那么显然我们可以走到山底。此算法的思想也同样。我们计算出当前的梯度,然后每次往梯度的相反方向移动一定的步长,移动一定次数。每次移动完得到一个新的损失函数,与当前存储最优的损失值比较,如果当前的更优,则更新。

SVM主体思路和代码实现的更多相关文章

  1. ASP.NET 大文件下载的实现思路及代码

    文件下载是一个网站最基本的功能,ASP.NET网站的文件下载功能实现也很简单,但是如果遇到大文件的下载而不做特殊处理的话,那将会出现不可预料的后果.本文就基于ASP.NET提供大文件下载的实现思路及代 ...

  2. 【转】Android自定义Adapter的ListView的思路及代码

    原文网址:http://www.jb51.net/article/37236.htm Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下   在开发中,我们经常使 ...

  3. HTML5绘制矩形和圆形并且还有获取在这个图层内的坐标的思路和代码 - feilong_12的专栏 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  4. SVM 之 MATLAB 实现代码

    MATLAB 中 SVM 实现 直接上代码 main.m %% Initialize data clear, clc, close all; load('data.mat'); y(y == 0) = ...

  5. 用Java实现断点续传的基本思路和代码

    用Java实现断点续传的基本思路和代码   URL url = new URL(http://www.oschina.net/no-exist.zip); HttpURLConnection http ...

  6. 1.Two Sum(c++)(附6ms O(n) accepted 思路和代码)

    问题描述: Given an array of integers, return indices of the two numbers such that they add up to a speci ...

  7. java 26 - 6 网络编程之 TCP协议 传输思路 以及 代码

    TCP传输 Socket和ServerSocket 建立客户端和服务器 建立连接后,通过Socket中的IO流进行数据的传输 关闭socket 同样,客户端与服务器是两个独立的应用程序 TCP协议发送 ...

  8. n皇后2种解题思路与代码-Java与C++实现

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了n皇后问题的解题思路,并分别用java和c++实现了过程,最后,对于算法改进 ...

  9. Objective-C运行时编程 - 实现自动化description方法的思路及代码示例

    发布自米高 | Michael - 博客园,源地址:http://www.cnblogs.com/michaellfx/p/4232205.html,转载请注明. 本文结构 基础实现 性能优化 参考 ...

  10. iOS高仿城觅应用客户端项目(开发思路和代码)

    这是一款非常完整的一个ios项目,基本实现了我们常用的一些功能了,而且界面设计个人感觉还是挺不错的,是一个不错的学习ios项目,喜欢的朋友可以参考一下吧. 项目展示,由于没有数据,所以所有的cell显 ...

随机推荐

  1. MGF multivariate generating function 多变量生成函数

    目录 MGF多变量生成函数multivariate generating function 定义 例子 Extremal parameters III.8.1 largest components 例 ...

  2. window的子对象

    在控制台输入 history history.length 历史记录个数history.back() 后退history.forward() 前进history.go(n) 跳到某一页,可正可负,当n ...

  3. vivo 手机云服务建设之路-平台产品系列04

    作者:vivo 互联网平台产品研发团队 - He Zhichuang.Han Lei 手机云服务目前作为每家手机厂商必备的一项基础服务,其服务能力和服务质量对用户来说可以说是非常重要.用户将自己大量的 ...

  4. [JavaScript]Promise:异步编程

    1 文由 某项目的需求:先要请求API1,再以API1的结果请求API2. var n, a; //var r = window.md5; var r = function (password, us ...

  5. 【译】ConfigureAwait FAQ

    .NET 在数年前就在语言和库中添加了 async/await.在那段时间里,它像野火一样蔓延开来,不仅在 .NET 生态系统中,而且在无数其他语言和框架中被复制.在 .NET 中也看到了大量的改进, ...

  6. 借助 APISIX Ingress,实现与注册中心的无缝集成

    作者张晋涛,API7.ai 云原生技术专家,Apache APISIX PMC 成员,Apache APISIX Ingress Controller 项目维护者. 原文链接 云原生场景下是否需要服务 ...

  7. 迁移学习(MEnsA)《MEnsA: Mix-up Ensemble Average for Unsupervised Multi Target Domain Adaptation on 3D Point Clouds》

    论文信息 论文标题:MEnsA: Mix-up Ensemble Average for Unsupervised Multi Target Domain Adaptation on 3D Point ...

  8. Cesium之Web Workers

    1. 引言 多线程是编程中常用的方法,例如,在桌面程序中,主线程一般是UI线程,负责UI绘制与用户交互,而运算处理往往是交给背后的工作线程,这样可以有效避免交互时的卡顿感 浏览器是多进程的,每打开一个 ...

  9. error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file o

    error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file o ...

  10. 基于QtAV的简易播放器(开源)

    这个开源代码,是我利用QtAV源码,提取其中一部分代码,进行整合到我自己项目中,做的一个小型播放器测试,至于怎么安装一些环境以及QtAV源码编译在我以前写的一篇博客中可以看到(Qt第三方库QtAV-- ...