机器学习是由 模型 + 策略 + 算法 构成的,构建一种机器学习方法 (例如,支持向量机),就是具体去确定这三个要素。

1  支持向量机

支持向量机,简称 SVM (Support Vector Machine),是一种二分分类模型。

1) 模型 (model)

定义在特征空间上的,一种间隔 (margin) 最大的,线性分类器 (linear classifier)

2) 策略 (strategy)

使间隔最大化,可转化为求解凸二次规划的问题。

3) 算法 (algorithm)

求解凸二次规划的最优化算法。

供训练的样本数据可分为三类:第一类是线性可分的,第二类是近似线性可分的,第三类是线性不可分的。

三种样本数据对应的 SVM 分别为:线性可分 (硬间隔最大化),线性 (软间隔最大化),非线性 (核技巧 + 软间隔最大化)。

为了方便起见,下文提到的向量机 或 SVM,都是指线性可分支持向量机。

2  基本概念

2.1  超平面 (hyperplane)

n 维欧式空间中,余维度等于 1 (也即 n-1 维) 的线性子空间,称为超平面。

超平面在二维空间中是直线,在三维空间中是平面,可用来分隔数据。如下图所示,超平面 (直线) 能将两类不同的数据 (圆点和方点) 分隔开来。

如果将数据点记为 x (n 维向量),则超平面的方程为 $\ f(x) = \beta_{0} + \beta^{T} x = 0\; $,其中,$\beta $ 为权重向量 (有的书称为 “法向量”)

             

解释:右图中 $\beta^{*}$ 为超平面 (绿色直线) 的单位法向量 $\ \beta^{*} = \dfrac{\beta}{||\beta||}$,平面中任意点 x 到超平面的距离为 $\ r = \dfrac{|\beta_{0} + \beta^{T} x|} {||\beta||}$

又附: 平面坐标中,一个点 $\;(x_{0}, y_{0})\;$到直线$\;(Ax + By + C = 0)\;$ 的距离为 $\; d = \dfrac{Ax_{0} + By_{0} + C}{\sqrt{A^{2} + B^{2}}} $

2.2  支持向量 (support vector)

如果取输出 y 分别为 +1 和 -1,代表两种不同类别,则对于 x,其对应的 f(x) 有三种可能取值:

1) 当位于超平面上时 (也即图中的直线上),$ f(x) = \beta_{0} + \beta^{T} x = 0 $

2) 当位于超平面左边时, $f(x) = \beta_{0} + \beta^{T} x \leq -1$

3) 当位于超平面右边时, $f(x) = \beta_{0} + \beta^{T} x \geq +1$

假设存在一个超平面,能将 n 个样本数据正确的分类,则对于任意一个样本数据$\;(x_{i}, y_{i})$,满足如下约束条件:

$\quad y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 , i = 1, 2, ..., n $

如上图所示,距离超平面最近的三个样本点,使得 2) 和 3) 中的等号成立,它们称为 “支持向量”。

2.3  几何间隔 (geometric margin)

因为支持向量使得 2) 和 3) 的等号成立,所以它们到超平面的距离:

$\quad r = \dfrac{|\beta_{0} + \beta^{T} x|} {||\beta||} = \dfrac{1}{||\beta||}$

两个不同种类的支持向量 (分别取值为 +1 和 -1),到超平面的距离之和为:

$\quad r^{'} = \dfrac{2}{||\beta||}\;$,$r^{'}\;$称为 “几何间隔” (geometric margin)

一个点距离超平面的远近,可用来表示分类结果的正确性和确信度。

直观上看,超平面越是靠近两类样本数据的正中间 (也即两类数据点到超平面的距离越远),则分类结果的正确性和确信度就越高。

2.4  学习算法

SVM 的学习算法 (或称最大间隔法),就是基于所给的样本数据,去寻找到具有 “最大间隔” 的超平面,将不同种类的样本分隔开来。

也即,在满足 “约束条件” 的前提下,使得 $r^{'}$ 的值最大:

$\quad \max \limits_{\beta,\; \beta_{0}} \dfrac{2}{||\beta||} \quad subject\;to \quad y_{i}(\beta^{T} x_{i} + \beta_{0}) \geq 1 , i = 1, 2, ..., n $

再或者,最大化 $r^{'}$,等价于最小化 $||\beta||^{2}$,如下所示:

$\quad \min \limits_{\beta,\;\beta_{0}} \dfrac{1}{2} ||\beta||^{2} \quad subject \; to \quad y_{i} (\beta^{T} x_{i} + \beta_{0}) \geq 1 , i = 1, 2, ..., n $

3  OpenCV 函数

OpenCV 中 SVM 的实现是基于 libsvm 的,其基本的过程为:创建 SVM 模型 --> 设置相关参数 --> 样本数据训练 --> 预测

1) 创建模型

static Ptr<SVM> cv::ml::SVM::create ( );  // 创建一个空模型

 2) 设置参数

virtual void cv::ml::SVM::setType (int val);  // 设置 SVM 的类型,默认为 SVM::C_SVC 
virtual void cv::ml::SVM::setKernel (int kernelType); // 设置核函数类型,本文为线性核函数,设为 SVM::LINEAR virtual void cv::ml::SVM::setTermCriteria (const cv::TermCriteria & val); // 设置迭代终止准则 // type,准则类型; maxCount,最大迭代次数;epsilo,目标精度
cv::TermCriteria::TermCriteria(int type, int maxCount, double epsilon);

3) 训练 (train)

virtual bool cv::ml::StatModel::train (
  InputArray  samples,  // 训练样本
int     layout,   // 训练样本为 “行样本” ROW_SAMPLE 或 “列样本” COL_SAMPLE
InputArray responses // 对应样本数据的分类结果
)

4) 预测 (predict)

用来预测一个新样本的响应,各个参数如下:

// samples,输入的样本书数据;results,输出矩阵,默认不输出;flags,标识,默认为 0

virtual float cv::ml::StatModel::predict(InputArray samples, OutputArray results=noArray(),int flags=) const;  

4  代码示例

下面是 OpenCV 3.2 中的官方例程,更改了训练样本数据

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp> using namespace cv;
using namespace cv::ml; int main()
{
// 512 x 512 零矩阵
int width = , height = ;
Mat image = Mat::zeros(height, width, CV_8UC3); // 训练样本
float trainingData[][] = { { , },{ , },{ , },{ , },{, },{, } };
int labels[] = {-, , , ,-,}; // 每个样本数据对应的输出,因为是二分模型,所以输出为 +1 或者 -1
Mat trainingDataMat(, , CV_32FC1, trainingData);
Mat labelsMat(, , CV_32SC1, labels); // 训练 SVM
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, , 1e-));
svm->train(trainingDataMat, ROW_SAMPLE, labelsMat); // 显示二分分类的结果
Vec3b green(, , ), blue(, , );
for (int i = ; i < image.rows; ++i)
for (int j = ; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(, ) << j, i);
float response = svm->predict(sampleMat);
if (response == )
image.at<Vec3b>(i, j) = blue;
else if (response == -)
image.at<Vec3b>(i, j) = green;
}
// 画出训练样本数据
int thickness = -;
int lineType = ;
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);
circle(image, Point(, ), , Scalar(, , ), thickness, lineType);

    // 显示出支持向量
    thickness = 2;
    lineType = 8;
    Mat sv = svm->getUncompressedSupportVectors();
    for (int i = 0; i < sv.rows; ++i)
    {
        const float* v = sv.ptr<float>(i);
        circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
    }
imwrite("result.png", image); // 保存训练的结果
imshow("SVM Simple Example", image);
waitKey();
}

OpenCV 3.2 版本中使用了一个新的函数,来获取支持向量,即 getUncompressedSupportVectors()

而 OpenCV 3.0 中,获取支持向量的函数为 getSupportVectors(),但当内核设为 SVM::LINEAR 时,该函数并不能得到支持向量,这是 3.0 版本的缺陷。

运行结果如下图所示,超平面附近的三个灰色匡白色圆点,便是所谓的 “支持向量”。

参考资料:

<机器学习> 周志军  第6章

<统计学习方法> 李航  第7章

<The Elements of Statistical Learning_2nd>  ch 4.5 , ch 12

"支持向量机系列“  pluskid

OpenCV 3.2  Tutorials -- Machine Learning (ml module)  -- Introduction to Support Vector Machines

“LIBSVM -- A Library for Support Vector Machines”

OpenCV 之 支持向量机 (一)的更多相关文章

  1. OpenCV 之 神经网络 (一)

    人工神经网络(ANN) 简称神经网络(NN),能模拟生物神经系统对真实物体所作出的交互反应,是由具有适应性的简单单元(称为神经元)组成的广泛并行互连网络. 1  神经元 1.1  M-P 神经元 如下 ...

  2. OpenCV 学习笔记 07 支持向量机SVM(flag)

    1 SVM 基本概念 本章节主要从文字层面来概括性理解 SVM. 支持向量机(support vector machine,简SVM)是二类分类模型. 在机器学习中,它在分类与回归分析中分析数据的监督 ...

  3. OpenCV支持向量机(SVM)介绍

    支持向量机(SVM)介绍 目标 本文档尝试解答如下问题: 如何使用OpenCV函数 CvSVM::train 训练一个SVM分类器, 以及用 CvSVM::predict 测试训练结果. 什么是支持向 ...

  4. 支持向量机(理论+opencv实现)

    从基础开始讲起,没有这些东西看支持向量机真的很难!   1.拉格朗日乘子(Lagrangemultiplier)   假设需要求极值的目标函数(objectivefunction)为f(x,y),限制 ...

  5. OpenCV支持向量机SVM对线性不可分数据的处理

    支持向量机对线性不可分数据的处理 目标 本文档尝试解答如下问题: 在训练数据线性不可分时,如何定义此情形下支持向量机的最优化问题. 如何设置 CvSVMParams 中的参数来解决此类问题. 动机 为 ...

  6. opencv 支持向量机SVM分类器

    支持向量机SVM是从线性可分情况下的最优分类面提出的.所谓最优分类,就是要求分类线不但能够将两类无错误的分开,而且两类之间的分类间隔最大,前者是保证经验风险最小(为0),而通过后面的讨论我们看到,使分 ...

  7. OpenCV 机器学习之 支持向量机的使用方法实例

    用支持向量机进行文理科生的分类,根据的特征主要是 数学成绩与语文成绩,这两个特征都服从高斯分布 程序代码例如以下: 分类结果:

  8. OpenCV整体的模块架构

    之前啃了不少OpenCV的官方文档,发现如果了解了一些OpenCV整体的模块架构后,再重点学习自己感兴趣的部分的话,就会有一览众山小的感觉,于是,就决定写出这篇文章,作为启程OpenCV系列博文的第二 ...

  9. opencv 人脸识别

      背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从 ...

随机推荐

  1. mvc实现上传视频预览

    上个项目中用到了上传视频,本来打算用百度的webuploader做的,但是webuploader可能有个毛病就是不能上传太大的东西. 于是乎,只能换个方法做了啊,看了半天最终决定用传统的uploade ...

  2. 背水一战 Windows 10 (34) - 控件(进度类): RangeBase, Slider, ProgressBar, ProgressRing

    [源码下载] 背水一战 Windows 10 (34) - 控件(进度类): RangeBase, Slider, ProgressBar, ProgressRing 作者:webabcd 介绍背水一 ...

  3. ComponentOne 2016 V2发布了!

    火热的夏季迎了ComponentOne今年的第2个重大发布.这次发布包含了一些非常棒的新控件以及很多大的功能增强.   快来下载免费试用版体验吧! FlexChart(UWP.WPF.WinForms ...

  4. Unsupported major.minor version 52.0问题的解决

    下载Tomcat9.0,解压后安装运行,结果启动失败,进入logs文件夹看里面的日志文件,提示是Unsupported major.minor version 52.0错误,这是因为Tomcat版本过 ...

  5. virtualbox 虚拟机Ubuntu 传文件-共享

  6. 【JAVA并发编程实战】5、构建高效且可伸缩的结果缓存

    首先创建一个借口,用来表示耗费资源的计算 package cn.xf.cp.ch05; public interface Computable<A, V> { V compute(A ar ...

  7. 除去String字符串里面指定的字符串

    主要用到String的两个方法,分别是subString(int len)或subString(int start,int end)和str.indexOf(String str1) 思路:先判断指定 ...

  8. 【工匠大道】Git的使用总结

    初衷是想将一些常用的代码整理在博客园上,但是考虑到博客园上的代码量多,需要折叠,折叠后就不能直接修改,于是想到了 大家都常用的 gitHub来进行代码的管理. 其实之前我是用过 Osa的git的,但是 ...

  9. .NET平台BigO算法复杂度备忘

          之前一篇文章提到BIG O算法复杂度的备忘录, 今天这个是.NET 平台下集合类相关的Big O 算法复杂度   今天先到这儿,希望对您有参考作用, 您可能感兴趣的文章: 数据结构与算法 ...

  10. CSS:CSS样式表及选择器优先级总结

    我们在写网页的时候经常会遇到同一个HTML文件,使用了外部样式.内部样式以及内联样式,那么如果发生冲突时浏览器是怎么抉择的呢? 也会遇到这样的情况,在样式表中,对同一个HTML元素,我们有可能既用到了 ...