OpenCV 之 支持向量机 (一)OpenCV 之 支持向量机 (一)

  机器上是出于 模型 + 策略 + 算法
构成的,构建平种机器上道
(例如,支持于量机),就是具体去确定就三独因素。

  机器上是由 模型 + 策略 + 算法
构成的,构建平种植机器上道
(例如,支持为量机),就是具体去确定这三单因素。

1  支持于量机

  支持为量机,简称 SVM (Support Vector Machine),是同等种植次细分分类型。

1  支持为量机

  支持为量机,简称 SVM (Support Vector Machine),是千篇一律种次划分分类型。

1) 模型 (model)

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

1) 模型 (model)

    定义在特点空间及之,一种植间隔 (margin) 最酷的,线性分类器 (linear
classifier)

2) 策略 (strategy)

    使间隔最大化,可转化为求解凸二不良设计的题目。

2) 策略 (strategy)

    使间隔最大化,可转化为求解凸二糟糕设计之题目。

3) 算法 (algorithm)

    求解凸二涂鸦规划的不过优化算法。

 
供训练之样书数而分为三类:第一看似是线性可分割的,第二近似是近似线性可划分的,第三近乎是线性不可分的。

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

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

 

3) 算法 (algorithm)

    求解凸二蹩脚规划的无限优化算法。

 
供训练之样书数而分为三类:第一近似是线性可分割的,第二近乎是近似线性可划分的,第三接近是线性不可分的。

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

  为了有利于起见,下文提到的向量机 或 SVM,都是负线性可划分支持为量机

 

2  基本概念

2  基本概念

2.1  超平面 (hyperplane)

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

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

  如果以数据点记为 x (n 维向量),则超越平面的方程为 $\ f(x) = \beta_{0}

  • \beta^{T} x = 0\; $,其中,$\beta $ 为权重为量 (有的书称为
    “法向量”)

      图片 1             
图片 2

  解释:右图中 $\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.1  超平面 (hyperplane)

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

 
超平面在二维空间受到凡是直线,在三维空间被凡面,可用来隔数据。一般来说图所示,超平面
(直线) 能将两类不同的数据 (圆点和方点) 分隔开来。

  如果以数据点记为 x (n 维向量),则超过平面的方程为 $\ f(x) = \beta_{0}

  • \beta^{T} x = 0\; $,其中,$\beta $ 为权重为量 (有的书称为
    “法向量”)

      图片 3             
图片 4

  解释:右图中 $\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 $

       图片 5  

  如达到图所示,距超平面最近之老三独样本点,使得 2) 和 3)
中之相当于号成立,它们称为 “支持向量”

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 $

       图片 6  

  如齐图所示,离开超平面最近底老三个样本点,使得 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)

  一个沾离开超平面的远近,可用来表示分类结果的对和确实信度。

  直观上看,超平面越是接近两看似样本数的当心间
(也便有限近似数据点到超过平面的距离越远),则分类结果的没错和真正信度就更强。

    图片 7

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)

  一个触及距离超平面的远近,可用来代表分类结果的不易和实在信度。

  直观上看,超平面越是临近两好像样本数量的中间间
(也尽管有限像样数据点到过平面的相距越远),则分类结果的科学和真正信度就越来越强。

    图片 8

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 $

 

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 模型
–> 设置相关参数 –> 样本数训练 –> 预测

3  OpenCV 函数

  OpenCV 中 SVM 的兑现是基于 libsvm 的,其核心的历程为:创建 SVM 模型
–> 设置相关参数 –> 样本数训练 –> 预测

1) 创建模型

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

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);       

 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 // 对应样本数据的分类结果
)     

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=0) const;  

 

4) 预测 (predict)

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

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

virtual float cv::ml::StatModel::predict(InputArray samples, OutputArray results=noArray(),int flags=0) 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 = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // 训练样本
    float trainingData[6][2] = { { 500, 60 },{ 245, 40 },{ 480, 250 },{ 160, 380 },{400, 25},{55, 400} };
    int labels[6] = {-1, 1, 1, 1,-1,1};  // 每个样本数据对应的输出,因为是二分模型,所以输出为 +1 或者 -1
    Mat trainingDataMat(6, 2, CV_32FC1, trainingData);
    Mat labelsMat(6, 1, CV_32SC1, labels);

    // 训练 SVM
    Ptr<SVM> svm = SVM::create();
    svm->setType(SVM::C_SVC);
    svm->setKernel(SVM::LINEAR);
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
    svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);

    // 显示二分分类的结果
    Vec3b green(0, 255, 0), blue(255, 0, 0);
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        {
            Mat sampleMat = (Mat_<float>(1, 2) << j, i);
            float response = svm->predict(sampleMat);
            if (response == 1)
                image.at<Vec3b>(i, j) = blue;
            else if (response == -1)
                image.at<Vec3b>(i, j) = green;
        }

    // 画出训练样本数据
    int thickness = -1;
    int lineType = 8;
    circle(image, Point(500, 60), 5, Scalar(0, 0, 0), thickness, lineType);
    circle(image, Point(245, 40), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(480, 250), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(160, 380), 5, Scalar(0, 0, 255), thickness, lineType);
    circle(image, Point(400, 25), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(55, 400), 5, Scalar(0, 0, 255), 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(0);
}

  OpenCV 3.2 版本被运用了一个初的函数,来博取支持向量,即 getUncompressedSupportVectors()

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

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

      图片 9

   

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 = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // 训练样本
    float trainingData[6][2] = { { 500, 60 },{ 245, 40 },{ 480, 250 },{ 160, 380 },{400, 25},{55, 400} };
    int labels[6] = {-1, 1, 1, 1,-1,1};  // 每个样本数据对应的输出,因为是二分模型,所以输出为 +1 或者 -1
    Mat trainingDataMat(6, 2, CV_32FC1, trainingData);
    Mat labelsMat(6, 1, CV_32SC1, labels);

    // 训练 SVM
    Ptr<SVM> svm = SVM::create();
    svm->setType(SVM::C_SVC);
    svm->setKernel(SVM::LINEAR);
    svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
    svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);

    // 显示二分分类的结果
    Vec3b green(0, 255, 0), blue(255, 0, 0);
    for (int i = 0; i < image.rows; ++i)
        for (int j = 0; j < image.cols; ++j)
        {
            Mat sampleMat = (Mat_<float>(1, 2) << j, i);
            float response = svm->predict(sampleMat);
            if (response == 1)
                image.at<Vec3b>(i, j) = blue;
            else if (response == -1)
                image.at<Vec3b>(i, j) = green;
        }

    // 画出训练样本数据
    int thickness = -1;
    int lineType = 8;
    circle(image, Point(500, 60), 5, Scalar(0, 0, 0), thickness, lineType);
    circle(image, Point(245, 40), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(480, 250), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(160, 380), 5, Scalar(0, 0, 255), thickness, lineType);
    circle(image, Point(400, 25), 5, Scalar(255, 255, 255), thickness, lineType);
    circle(image, Point(55, 400), 5, Scalar(0, 0, 255), 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(0);
}

  OpenCV 3.2 版本被利用了一个新的函数,来赢得支持向量,即 getUncompressedSupportVectors()

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

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

      图片 10

   

参考资料:

  <机器上> 周志军  第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”

 

参考资料:

  <机器上> 周志军  第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”

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注