支持向量机(SVM)非线性数据切割

1.目标

本指导中你将学到:

l  当不可能线性切割训练数据时,如何定义SVM最优化问题。

l  在这样的问题上。如何配置CvSVMParams中的參数满足你的SVM;

2.动机

为什么我们有兴趣扩展SVM最优化问题来处理非线性切割训练数据?SVM在计算机视觉应用中须要一个比线性分类器更加强有力的工具。

原因在于,其实,在这样的问题上训练数据差点儿不能被一个超平面切割开。考虑一个这样的任务。比如,面部识别。

这样的情况下,训练数据由图像上的一组面部数据和非面部(不论什么除面部以外的其它东西)数据组成。这些训练数据很复杂,以至于能够对每个样本找到一种表述(特征向量),能把整个数据线性的从非面部中切割出来。

3.最优化问题扩展

记住,通过SVM我们得到一个切割超平面。

那么,由于如今训练数据是非线性可分的了。我们必须承认原来找到的超平面将不能正确分类当中的一些样本。

误分类是优化问题中须要考虑的一个新的变化。新的模型既要满足找超平面的老问题。给出最大边缘,而且还要做新工作,正确地生成新的训练数据,而使其不出现太多分类错误。我们先从寻找超平面这个优化问题的构想出发,由超平面给出最大边缘(边缘的概念在上篇中有解释):

有非常多种方法能够改动这个模型。所以它把误分类考虑在内了。

比方,你能够考虑最小化同一个量加上一个常数乘以训练数据误分类的错误数量,比如:

然而。这个并非最好的解决方式,在其它原因中(amongsome other reasons),我们对距离期望决策区域距离非常小的误分类样本和没有误分类的样本不作区分。因此,更好的解决方式将把误分类样本离他们的正确决策区域的距离考虑在内,比如:

对于每个训练数据样本,要定义一个新的參数ξi。每个此參数都包括了训练样本到他们的正确决策区域的距离。下图显示了两类非线性可分类的训练数据,一个分类超平面和误分类样本到正确决定区域的距离。

注意:图中值仅仅显示了误分类样本的距离。其它样本的距离为0。由于他们已经在正确的区域了。

图中红色和蓝色的线是每个决策区域的边界。每个ξi是从误分类点到期望区域的边界,明确这一点非常重要。最后。优化问题的新公式为:

怎么选择常数C呢?非常明显这个问题依赖于训练数据是怎么分布的。虽然没有统一的答案,考虑一下规则会非常有帮助:

l  C的值越大,误分类的数量会越少,但边缘也会越小。这样的情况。是把误分类错误看的非常重,对误分类要求严格。

然而,优化的目标是最小化自变量,少量误分类错误是同意的。

l  C值越小,边缘越大。误分类错误越大。这样的情况下最小化没有过多考虑求和项。因此其焦点在于寻找具有更大边缘的超平面。

4.代码

你可能也在OpenCV源码库中的此路径sample/cpp/tutorial_code/gpu/non_linear_svm/non_linear_svms目录中找到了源码,以及那些视频文件,也能够在此下载。

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>#define NTRAINING_SAMPLES   100         // Number of training samples per class
#define FRAC_LINEAR_SEP     0.9f        // Fraction of samples which compose the linear separable partusing namespace cv;
using namespace std;int main()
{// Data for visual representationconst int WIDTH = 512, HEIGHT = 512;Mat I = Mat::zeros(HEIGHT, WIDTH, CV_8UC3);//--------------------- 1. Set up training data randomly ---------------------------------------Mat trainData(2*NTRAINING_SAMPLES, 2, CV_32FC1);Mat labels   (2*NTRAINING_SAMPLES, 1, CV_32FC1);RNG rng(100); // Random value generation class// Set up the linearly separable part of the training dataint nLinearSamples = (int) (FRAC_LINEAR_SEP * NTRAINING_SAMPLES);// Generate random points for the class 1Mat trainClass = trainData.rowRange(0, nLinearSamples);// The x coordinate of the points is in [0, 0.4)Mat c = trainClass.colRange(0, 1);rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH));// The y coordinate of the points is in [0, 1)c = trainClass.colRange(1,2);rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));// Generate random points for the class 2trainClass = trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES);// The x coordinate of the points is in [0.6, 1]c = trainClass.colRange(0 , 1);rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH));// The y coordinate of the points is in [0, 1)c = trainClass.colRange(1,2);rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));//------------------ Set up the non-linearly separable part of the training data ---------------// Generate random points for the classes 1 and 2trainClass = trainData.rowRange(  nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples);// The x coordinate of the points is in [0.4, 0.6)c = trainClass.colRange(0,1);rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));// The y coordinate of the points is in [0, 1)c = trainClass.colRange(1,2);rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));//------------------------- Set up the labels for the classes ---------------------------------labels.rowRange(                0,   NTRAINING_SAMPLES).setTo(1);  // Class 1labels.rowRange(NTRAINING_SAMPLES, 2*NTRAINING_SAMPLES).setTo(2);  // Class 2//------------------------ 2. Set up the support vector machines parameters --------------------CvSVMParams params;params.svm_type    = SVM::C_SVC;params.C           = 0.1;params.kernel_type = SVM::LINEAR;params.term_crit   = TermCriteria(CV_TERMCRIT_ITER, (int)1e7, 1e-6);//------------------------ 3. Train the svm ----------------------------------------------------cout << "Starting training process" << endl;CvSVM svm;svm.train(trainData, labels, Mat(), Mat(), params);cout << "Finished training process" << endl;//------------------------ 4. Show the decision regions ----------------------------------------Vec3b green(0,100,0), blue (100,0,0);for (int i = 0; i < I.rows; ++i)for (int j = 0; j < I.cols; ++j){Mat sampleMat = (Mat_<float>(1,2) << i, j);float response = svm.predict(sampleMat);if      (response == 1)    I.at<Vec3b>(j, i)  = green;else if (response == 2)    I.at<Vec3b>(j, i)  = blue;}//----------------------- 5. Show the training data --------------------------------------------int thick = -1;int lineType = 8;float px, py;// Class 1for (int i = 0; i < NTRAINING_SAMPLES; ++i){px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(I, Point( (int) px,  (int) py ), 3, Scalar(0, 255, 0), thick, lineType);}// Class 2for (int i = NTRAINING_SAMPLES; i <2*NTRAINING_SAMPLES; ++i){px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick, lineType);}//------------------------- 6. Show support vectors --------------------------------------------thick = 2;lineType  = 8;int x     = svm.get_support_vector_count();for (int i = 0; i < x; ++i){const float* v = svm.get_support_vector(i);circle( I,  Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick, lineType);}imwrite("result.png", I);                      // save the Imageimshow("SVM for Non-Linear Training Data", I); // show it to the userwaitKey(0);
}

译者注:因为凝视直接加入在代码中会导致排版问题。偷懒把凝视堆在此下了:

//训练数据矩阵。行数200。列2
//标记矩阵。行200,列1
//生成线性可切割的训练数据
//生成第1类的随机点
//取子矩阵。0~nLinearSamples行
//取上面子矩阵的子矩阵,第0列
//随机填充该列,其值范围从1到0.4 * WIDTH
//取子矩阵的第1列
//随机填充该列。其值范围从1到HIGHT
//此例中矩阵的第0列和第1列分别当做点的x,y坐标
//生成第2类的随机点
//取子矩阵。留出一个切割带直到最后
//取第0列
//随机填充该列,其值范围从0.6 * WIDTH到WIDTH
//取第1列
//随机填充该列。其值范围从1到HIGHT
//随机生成非线性可切割的训练数据
//取子矩阵。中间切割带部分
//取第0列
//随机填充,其值范围就是中间带的x坐标
//取第1列
//随机填充,值就为整个HIGHT范围
//Class 1//设置标识,1为第一类
// Class 2//标识2为第二类
//通过上一篇能够了解到,此參数是跟维度有关的。高维又是须要映射,这里LINEAR指不映射
//遍历整副图片,预測每一个像素点所属的类别。并作对应着色

5.代码解析

(1)创建训练数据

此处训练数据由一组标记了的二维点组成,共两类。

为了让这个练习更加有吸引力,训练数据通过均匀分布概率密度方程(a uniform probability density functions (PDFs))随机生成。我们已经把训练数据的生成分成了两个主要部分。第一部分,我们生成线性可分的两类数据。

// Generate random points for the class 1
Mat trainClass = trainData.rowRange(0,nLinearSamples);
// The x coordinate of the points is in [0,0.4)
Mat c = trainClass.colRange(0, 1);
rng.fill(c, RNG::UNIFORM, Scalar(1),Scalar(0.4 * WIDTH));
// The y coordinate of the points is in [0,1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1),Scalar(HEIGHT));
// Generate random points for the class 2
trainClass =trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES);
// The x coordinate of the points is in[0.6, 1]
c = trainClass.colRange(0 , 1);
rng.fill(c, RNG::UNIFORM,Scalar(0.6*WIDTH), Scalar(WIDTH));
// The y coordinate of the points is in [0,1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1),Scalar(HEIGHT));

第二部分,我们为两类创建非线性可分的数据和重叠的数据。

// Generate random points for the classes 1and 2
trainClass = trainData.rowRange(  nLinearSamples,2*NTRAINING_SAMPLES-nLinearSamples);
// The x coordinate of the points is in[0.4, 0.6)
c = trainClass.colRange(0,1);
rng.fill(c, RNG::UNIFORM,Scalar(0.4*WIDTH), Scalar(0.6*WIDTH));
// The y coordinate of the points is in [0,1)
c = trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1),Scalar(HEIGHT));

译者注

void RNG::fill(InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false )
  这个函数是对矩阵mat填充随机数,随机数的产生方式有參数2来决定,假设为參数2的类型为RNG::UNIFORM。则表示产生均一分布的随机数,假设为RNG::NORMAL则表示产生高斯分布的随机数。相应的參数3和參数4为上面两种随机数产生模型的參数。比方说假设随机数产生模型为均匀分布。则參数a表示均匀分布的下限,參数b表示上限。

假设随机数产生模型为高斯模型,则參数a表示均值。參数b表示方程。

參数5仅仅有当随机数产生方式为均匀分布时才有效,表示的是是否产生的数据要布满整个范围(没用过,所以也没细致去研究)。

另外。须要注意的是用来保存随机数的矩阵mat能够是多维的,也能够是多通道的,眼下最多仅仅能支持4个通道。

(2)创建SVM參数

可參见上一篇中关于CvSVMParams的解说。

CvSVMParams params;
params.svm_type    = SVM::C_SVC;
params.C              = 0.1;
params.kernel_type = SVM::LINEAR;
params.term_crit   = TermCriteria(CV_TERMCRIT_ITER, (int)1e7,1e-6);

这里跟我们前一篇的配置仅有两处不同:

CvSVM::C_SVC:我们这里选择了一个非常小的数值。目的是,在优化中不正确误分类错位做过多惩处。这么做到原因是我们希望获得最接近直观预期的解决方式。然而,我们推荐通过调整获得一个更能反映问题的參数。

注意:这里在两类之间重叠的点非常少,给FRAC_LINEAR_SEP一个更小的值。点的密度将添加。并且參数CvSVM::C_SVC的影响更深。

Termination Criteria of thealgorithm,算法终止标准:为了通过非线性可分离的训练数据正确地解决这个问题,最大迭代次数必须添加非常多。特别的。我们对这一參数值添加了5个数量级。

(3)训练SVM

我们调用方法CvSVM::train来建立SVM模型。注意训练过程可能会花非常长时间。执行改程序是要有耐心。

CvSVM svm;
svm.train(trainData, labels, Mat(), Mat(),params);

(4)显示决策区域

方法CvSVM::predict通过已训练的SVM来分类输入样本。在此例中,我们用这种方法根据SVM的预測来着色相关区域。也就是说,遍历一个图像。把它的像素当成笛卡尔平面的点。每个点根据SVM预測的类来着色;深绿色的是标记为1的类,深蓝色是标记为2的类。

Vec3b green(0,100,0), blue (100,0,0);
for (int i = 0; i < I.rows; ++i)for (int j = 0; j < I.cols; ++j){Mat sampleMat = (Mat_<float>(1,2) << i, j);float response = svm.predict(sampleMat);if      (response == 1)    I.at<Vec3b>(j, i)  = green;else if (response == 2)   I.at<Vec3b>(j, i)  = blue;}

(5)显示训练数据

方法circle用来显示训练数据的样本点。标记为1的类的样本显示为亮绿色,标记为2的类的样本点显示为亮蓝色。

int thick = -1;
int lineType = 8;
float px, py;
// Class 1
for (int i = 0; i < NTRAINING_SAMPLES;++i)
{px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(I, Point( (int) px,  (int)py ), 3, Scalar(0, 255, 0), thick, lineType);
}
// Class 2
for (int i = NTRAINING_SAMPLES; i<2*NTRAINING_SAMPLES; ++i)
{px = trainData.at<float>(i,0);py = trainData.at<float>(i,1);circle(I, Point( (int) px, (int) py ), 3, Scalar(255, 0, 0), thick,lineType);
}

(6)支持向量机

这里我么用来非常多方法来获取支持向量的信息。

方法CvSVM::get_support_vector_count输出该问题中支持向量的总数,方法CvSVM::get_support_vector能够依据索引获取到每个支持向量。我们用这些方法找到是支持向量的训练样本,并显示为高亮。

thick = 2;
lineType = 8;
int x    = svm.get_support_vector_count();
for (int i = 0; i < x; ++i)
{const float* v = svm.get_support_vector(i);circle(     I,  Point( (int) v[0], (int) v[1]), 6,Scalar(128, 128, 128), thick, lineType);
}

6结果

l  代码打开了一个图像,显示两类的训练数据。当中一类显示为亮绿色,还有一类显示为亮蓝色。

l  训练SVM。并用它来分类图像上全部的像素点。图像被分成蓝绿两块区域。

两个区域的边界就是切割超平面。由于训练数据是非线性可切割的,可以看到,一些样本被误分类了。一些绿色的点在蓝色区域中,另一些蓝色的点在绿色区域中。

l  最后,被灰色的圈包围的训练样本的点是支持向量。

原文:http://docs.opencv.org/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms

转载于:https://www.cnblogs.com/hrhguanli/p/5060236.html

支持向量机(SVM)非线性数据切割相关推荐

  1. 一文读懂:支持向量机(SVM)非线性分类问题

    点击 机器学习算法与Python学习 ,选择加星标 精彩内容不迷路 福利时间 奖品:<机器学习算法的数学解析与Python实现>x 5 参与方式:文末留言,赞数最多的5位为本次中奖者 开奖 ...

  2. 【SVM预测】基于人工蜂群算法优化支持向量机SVM实现数据预测附Matlab代码

    1 简介 为确定合理的底板防水煤岩柱尺寸,减少底板突水安全事故的发生,利用支持向量机(SVM)与人工蜂群算法(ABCA)综合研究底板破坏深度问题.由于SVM训练参数惩罚因子C和核函数宽度g的选择对预测 ...

  3. 【SVM时序预测】基于matlab鲸鱼算法优化支持向量机SVM时序数据预测【含Matlab源码 2250期】

    ⛄一.鲸鱼算法优化支持向量机SVM 1 鲸鱼优化算法 WOA是由Mirjalili和Lewis在2016年提出的一种较为新颖的元启发式群体智能优化算法,该算法模仿座头鲸的"螺旋气泡网&quo ...

  4. 机器学习sklearn(9)支持向量机svm——非线性

    参数说明如下: C:惩罚项,float类型,可选参数,默认为1.0,C越大,即对分错样本的惩罚程度越大,因此在训练样本中准确率越高,但是泛化能力降低,也就是对测试数据的分类准确率降低.相反,减小C的话 ...

  5. 机器学习(三):支持向量机SVM(含代码和注释)

    目录 1. 线性可分 2. 支持向量机SVM 1. 线性可分 二维空间中,线性可分数据表示为可用一条直线分开两类数据:若不存在一条直线分开两类数据,则为非线性可分 可以把它拓展到更高维度空间.若在三维 ...

  6. [转载] python中svm的使用_Python中支持向量机SVM的使用方法详解

    参考链接: 使用Python中的支持向量机(SVM)对数据进行分类 {"moduleinfo":{"card_count":[{"count_phon ...

  7. OpenCV支持向量机SVM用于非线性可分离数据

    OpenCV支持向量机SVM用于非线性可分离数据 支持向量机SVM用于非线性可分离数据 目标 动机Motivation 优化问题的扩展 源代码 解释 设置训练数据 设置SVM的参数 训练SVM 显示决 ...

  8. OpenCV之ml 模块. 机器学习:支持向量机(SVM)介绍 支持向量机对线性不可分数据的处理

    支持向量机(SVM)介绍 目标 本文档尝试解答如下问题: 如何使用OpenCV函数 CvSVM::train 训练一个SVM分类器, 以及用 CvSVM::predict 测试训练结果. 什么是支持向 ...

  9. Tensorflow用SVM(高斯核函数)分类非线性数据

    如果想分割非线性数据集,该如何改变线性分类器映射到数据集?答案是,改变SVM损失函数中的核函数. # Illustration of Various Kernels #---------------- ...

  10. 数据分享|WEKA用决策树、随机森林、支持向量机SVM、朴素贝叶斯、逻辑回归信贷违约预测报告

    作者:Nuo Liu 数据变得越来越重要,其核心应用"预测"也成为互联网行业以及产业变革的重要力量.近年来网络 P2P借贷发展形势迅猛,一方面普通用户可以更加灵活.便快捷地获得中小 ...

最新文章

  1. 拓扑容差如何修改_如何做到全屋WIFI无死角,MESH组网对比有哪些优势?
  2. dom元素滚动条高度 js_js浏览器滚动条卷去的高度scrolltop(实例讲解)
  3. 读写分离oracle redis,redis集群主从之读写分离
  4. linux 统计TCP 连接各状态总数
  5. 【matlab】多维向量的转置
  6. Unity禁止多点触控
  7. dbf解析_DBF文件格式分析.doc
  8. Display debug(Blue Screen , fliker)
  9. Dual-edge triggered flip_flop(Dualedge)
  10. 系统时间与格林威治时间
  11. Python pandas 实现Excel分列效果
  12. GAN二次元头像生成Pytorch实现(附完整代码)
  13. windows.edb文件过大,导致c盘空间极小问题
  14. debian系统怎么连接服务器,zh_CN/SystemPrinting
  15. 使用国外DynDNS免费动态域名解析 随时访问家中电脑
  16. NXP i.MX 8M Plus工业开发板硬件说明书( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)
  17. 主成分分析PCA和矩阵的奇异值分解SVD
  18. 用android studio写一个简单的记单词?????App
  19. 微信小程序分享到朋友圈
  20. PS中按住Alt键或者Ctrl+Alt+G创建剪贴蒙版

热门文章

  1. python输出结果换行_如果Python中有很多换行,可以选择使用...表示多行内容...
  2. 数据结构(二):线性表的使用原则以及链表的应用-稀疏矩阵的三元组表示
  3. jq select 操作
  4. Android API 实验记录 (二)
  5. 一些碰到的陌生的技术名词搜集(持续更新……)
  6. MySQL存储引擎的区别(myisam和innodb)
  7. Redis12-事件
  8. 主题模型LDA理解与应用
  9. 分布式监控系统开发【day37】:填充表配置项目(三)
  10. 凸优化第四章凸优化问题 4.3 线性规划问题