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”

 

相关文章

Leave a Comment.