支持向量机(SVM)

简介:

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

首先我们假定有一个未知的欲分类的集合,可以进行分割,但是我们不知道分割的函数(超平面,也叫真实模型)。于是我们通过已知的样本集合进行训练,得到近视模型。然后我们用这个近视模型对未知的欲分类的点进行分割。

这里存在一个问题,即近似模型和真实模型之间存在误差。(SVM和普通分类有什么区别呢?)

这里要说两个误差,一个是经验误差,一个是置信误差。

经验误差,就是样本训练中样本本身的误差,一般解决办法是提高样本量,可以减少经验误差。

置信误差,就是训练后的近似模型与真实模型之间的误差。

普通的分类函数一般都是减少经验误差,但是对于置信误差,却没有处理也没有好的办法来处理,这就导致了分类函数对于样本几乎100%正确分类,对于样本外的,效果有时候差强人意。

而SVM则是结构误差最小,即结构误差=经验误差 + 置信误差。

SVM减少置信误差的方法是样本集合到达近似模型距离最小,此时的近似模型被认为最接近于真实模型。

所以,SVM得到的近似模型更加接近于真实模型,


下面来说说SVM的简单步骤,

1:准备好样本集合和欲分类的集合。

2:设置SVM参数,其中有一个是核函数,其作用是将不能线性分割的集合映射到更高维度的空间(可以进行线性分割的空间)。所以这个函数比较重要。

3:创建SVM对象,利用上述样本集合和设置好的参数开始训练。

4:利用训练好的SVM,对欲分类的集合进行分割。


大概步骤如上。说明一下,有时候我们需要不断的迭代运算才能不断的逼近真实模型,虽然每一次运算都能更加进一步逼近真实模型,但限于时间与运算量限制,所以我们一般加上最大迭代次数限制和最大误差限制。


下面给出opencv2.X的SVM简要示例代码:


#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>

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] = { {500, 10}, {200, 10}, {500, 200}, {10, 500} };
    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 < 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;
        }

        // 显示训练数据
        int thickness = -1;
        int lineType = 8;
        circle( image, Point(500,  10), 5, Scalar(  0,   0,   0), thickness, lineType);
        circle( image, Point(200,  10), 5, Scalar(255, 255, 255), thickness, lineType);
        circle( image, Point(500, 200), 5, Scalar(255, 255, 255), thickness, lineType);
        circle( image, Point( 10, 500), 5, Scalar(255, 255, 255), thickness, lineType);

        // 显示支持向量
        thickness = 2;
        lineType  = 8;
        int c     = SVM.get_support_vector_count();

        for (int i = 0; i < c; ++i)
        {
            const float* v = SVM.get_support_vector(i);
            circle( image,  Point( (int) v[0], (int) v[1]),   6,  Scalar(0, 0, 255), thickness, lineType);
        }

        imwrite("result.png", image);        // 保存图片

        imshow("SVM Simple Example", image); // 给用户显示图片
        waitKey(0);

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值