欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

【OpenCV2.4】SVM的参数和函数介绍

程序员文章站 2024-02-09 09:45:28
...

【原文:http://www.cnblogs.com/justany/archive/2012/11/23/2784125.html】 分类器 分类器是一种计算机程序。 他的设计目标是在通过学习后,可自动将数据分到已知类别。 平面线性分类器 一个简单的分类问题,如图有一些圆圈和一些正方形,如何找一条最优的

【原文:http://www.cnblogs.com/justany/archive/2012/11/23/2784125.html】

分类器

分类器是一种计算机程序。

他的设计目标是在通过学习后,可自动将数据分到已知类别。

平面线性分类器

一个简单的分类问题,如图有一些圆圈和一些正方形,如何找一条最优的直线将他们分开?

【OpenCV2.4】SVM的参数和函数介绍

我们可以找到很多种方法画出这条直线,但怎样的直线才是最优的呢?

距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度高,泛化性较差。 因此我们的目标是找到一条直线,离最近的点距离最远。

怎么寻找距离最远的直线?枚举所有直线,然后计算其样本最小距离?这样显然不是一个好办法,这将产生大量的计算开销。

我们利用另一种方法,对直线的正负偏移量1,这样就产生了一个区域(下图的Maximum margin覆盖的区域),区域边界上的点到直线的距离是固定的,现在的问题是最近的点是否刚好在边界上或者在边界外。

【OpenCV2.4】SVM的参数和函数介绍

还记得点到线的公式么?

对于直线Ax+By+C=0,点(x0, y0)到直线的距离:

  distance = |Ax0+By0+C| / (A2 + B2)1/2

那么区域边缘到直线的距离:

  distance = (|Ax+By+C| + 1)/ (A2 + B2)1/2 = 1/ (A2 + B2)1/2

并需要满足对于所有样本类别yi 满足:yi (Ax+By+C) > = 1,也就是所有样本都不在该区域以内。

于是我们可以找到适当的A、B、C,从而得到:

  Maximum margin = 2/ (A2 + B2)1/2

超平面推广

同理,我们将这一定理推广到任意维度。其超平面表达式为:

    【OpenCV2.4】SVM的参数和函数介绍

一维是线、二维是面、三维是体……四维呢?五维呢?好吧统称超平面吧……

其中 【OpenCV2.4】SVM的参数和函数介绍 叫做 权重向量 【OpenCV2.4】SVM的参数和函数介绍 叫做 偏置向量。

用这种表达式来表达线Ax+By+C = 0的话,可以这么表示:

    f(x) = (C, 0) + (A, B)T (x, y);

其中(C, 0) 是偏置向量 【OpenCV2.4】SVM的参数和函数介绍,(A, B)是权重向量 【OpenCV2.4】SVM的参数和函数介绍

由于最优超平面可以有很多种表达方式,我们定义:

    β0 + βTx = 0,

为最优超平面表达式。于是我们可以得到他的Maximum margin区域边界表达式应该为:

    【OpenCV2.4】SVM的参数和函数介绍

我们称在这边界上的点为:支持向量(Supper Vector)。

因为点到超平面距离公式为:

    【OpenCV2.4】SVM的参数和函数介绍

在边界上,即支持向量到超平面距离:

    【OpenCV2.4】SVM的参数和函数介绍

所以Maximum margin为两倍距离,即:

    【OpenCV2.4】SVM的参数和函数介绍

M求倒数1/M 则可将求最大转换成求最小。于是有:

    【OpenCV2.4】SVM的参数和函数介绍

其中 【OpenCV2.4】SVM的参数和函数介绍 表示样本的类别标记。

这是一个拉格朗日优化问题,可以通过拉格朗日乘数法得到最优超平面的权重向量 【OpenCV2.4】SVM的参数和函数介绍 和偏置 【OpenCV2.4】SVM的参数和函数介绍

什么是SVM

支持向量机 (SVM) 是一个类分类器,正式的定义是一个能够将不同类样本在样本空间分隔的超平面。 换句话说,给定一些标记好的训练样本 (监督式学习),SVM算法输出一个最优化的分隔超平面。

1995年Cortes和Vapnik于首先提出SVM,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。

使用SVM

【OpenCV2.4】SVM的参数和函数介绍

#include 
#include 
#include using namespace cv;

int main()
{
    // 用于保存可视化数据的矩阵
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // 创建一些训练样本
    float labels[4] = {1.0, -1.0, -1.0, -1.0};
    Mat labelsMat(3, 1, CV_32FC1, labels);

    float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
    Mat trainingDataMat(3, 2, CV_32FC1, trainingData);

    // 设置SVM参数
    CvSVMParams params;
    params.svm_type    = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

    // 对SVM进行训练
    CvSVM SVM;
    SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
    
    Vec3b green(0,255,0), blue (255,0,0);
    // 将SVM断定的分划区域绘制出来
    for (int i = 0; i i)