SVM支持向量机简介3.0技术文档

官方源代码:

#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(int, char**)
{
    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    int labels[4] = {1, -1, -1, -1};
    Mat labelsMat(4, 1, CV_32SC1, labels);

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

    // Set up SVM's parameters
    SVM::Params params;
    params.svmType    = SVM::C_SVC;
    params.kernelType = SVM::LINEAR;
    params.termCrit   = TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6);

    // Train the SVM
    Ptr<SVM> svm = StatModel::train<SVM>(trainingDataMat, ROW_SAMPLE, labelsMat, params);

    Vec3b green(0,255,0), blue (255,0,0);
    // Show the decision regions given by the SVM
    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)  = green;
            else if (response == -1)
                image.at<Vec3b>(i,j)  = blue;
        }

    // Show the training data
    int thickness = -1;
    int lineType = 8;
    circle( image, Point(501,  10), 5, Scalar(  0,   0,   0), thickness, lineType );
    circle( image, Point(255,  10), 5, Scalar(255, 255, 255), thickness, lineType );
    circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType );
    circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness, lineType );

    // Show support vectors
    thickness = 2;
    lineType  = 8;
    Mat sv = svm->getSupportVectors();

    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);        // save the image

    imshow("SVM Simple Example", image); // show it to the user
    waitKey(0);

}

说明

1.设置训练数据

该练习的训练数据由属于两个不同类之一的一组标记的2D点形成; 其中一个课程包括一个点和另一个三点。

float labels[4] = {1.0, -1.0, -1.0, -1.0};
float trainingData[4][2] = {{501, 10}, {255, 10}, {501, 255}, {10, 501}};

之后使用的功能CvSVM :: train要求将训练数据作为浮点数的Mat对象存储。因此,我们从上面定义的数组创建这些对象:

Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
Mat labelsMat      (4, 1, CV_32FC1, labels);

2.设置SVM的参数

在本教程中,我们在最简单的情况下介绍了SVM的理论,当训练示例被分为两类是可分离的。然而,SVM可以用于各种各样的问题(例如,非线性可分离数据的问题,使用内核函数的SVM来提高示例的维度等)。因此,我们必须在训练SVM之前定义一些参数。这些参数存储在类CvSVMParams的对象中。

ml::SVM::Params params;
params.svmType    = ml::SVM::C_SVC;
params.kernelType = ml::SVM::LINEAR;
params.termCrit   = TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6);

    • SVM类型。我们在这里选择可用于n类分类的类型ml :: SVM :: C_SVC(n \ GEQ2)。该参数在属性ml :: SVM :: Params.svmType中定义

      注意

       

      SVM类型的重要特征CvSVM :: C_SVC处理类的不完全分离(即训练数据是非线性可分离的)。这个特性在这里并不重要,因为数据是线性可分的,我们选择这个SVM类型是最常用的。

    • SVM内核的类型。我们没有谈到内核函数,因为它们对于我们正在处理的训练数据并不感兴趣。不过,让我们简要介绍一下内核函数的主要思路。它是对训练数据进行的映射,以改进其与线性可分离数据集的相似性。该映射包括增加数据的维度,并使用内核函数高效地进行。我们在这里选择ml :: SVM :: LINEAR,这意味着没有做任何映射。该参数在属性ml :: SVMParams.kernel_type中定义。

    • 算法的终止标准。在SVM训练过程中所实施的解决受约束的二次优化问题迭代的方式。这里我们指定最大迭代次数和公差误差,因此即使最佳超平面尚未计算,我们允许算法在较少数量的步骤中完成。该参数在一个结构中定义cvTermCriteria


3.训练SVM

我们称之为CvSVM :: train方法构建SVM模型。

CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

4.由SVM分类的区域

方法CvSVM :: predict用于使用经过训练的SVM对输入样本进行分类。在这个例子中,我们使用这种方法来根据SVM所做的预测来对空间进行着色。换句话说,遍历图像将它的像素解释为笛卡尔平面的点。每个点根据SVM预测的类别着色; 如果是带有标签1的类,则为绿色,如果为带有标签-1的类,则为蓝色。

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) << i,j);
    float response = SVM.predict(sampleMat);

    if (response == 1)
       image.at<Vec3b>(j, i)  = green;
    else
    if (response == -1)
       image.at<Vec3b>(j, i)  = blue;
    }

5. 支持向量

我们在这里使用几种方法来获取有关支持向量的信息。方法CvSVM :: get_support_vector_count输出在问题中使用的支持向量的总数,并使用方法CvSVM :: get_support_vector,我们使用索引获取每个支持向量。我们在这里使用这种方法来找到支持向量的训练示例并突出显示。


int c     = SVM.get_support_vector_count();

for (int i = 0; i < c; ++i)
{
const float* v = SVM.get_support_vector(i); // get and then highlight with grayscale
circle(   image,  Point( (int) v[0], (int) v[1]),   6,  Scalar(128, 128, 128), thickness, lineType);
}

结果

  • 代码打开一个图像并显示两个类的训练示例。一个类的点用白色圆圈表示,黑色的点用于另一个类。
  • SVM被训练并用于对图像的所有像素进行分类。这导致在蓝色区域和绿色区域中的图像的划分。两个区域之间的边界是最优分离超平面。
  • 最后,训练样本周围使用灰色戒指显示支持向量。
                                                                                 分离的飞机


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值