SVM支持向量分类器原理及OpenCV实现
2016-11-20 22:58
295 查看
SVM原理:
通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。假设给定一些分属于两类的2维点,这些点可以通过直线分割, 我们要找到一条最优的分割线,如下图所示:
在上面的图中, 你可以直觉的观察到有多种可能的直线可以将样本分开。 那是不是某条直线比其他的更加合适呢? 我们可以凭直觉来定义一条评价直线好坏的标准。很明显,距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度高,泛化性较差。 因此我们的目标是找到一条直线,离所有点的距离最远。
由此, SVM算法的实质是找出一个能够将某个值最大化的超平面,这个值就是超平面离所有训练样本的最小距离。这个最小距离用SVM术语来说叫做 间隔(margin) 。 概括一下,最优分割超平面 最大化 训练数据的间隔。如下图中间的斜线就是最大间隔向量:
至于如何去求解这个最大间隔向量,请参考http://blog.csdn.net/sealyao/article/details/6442403,说的很详细。
代码及注释:
注意:SVM算法只能分割两部分,如果需要多个分割,请先把分割出一块,把其他部分当作一个整体,然后递归分割。
通俗来讲,它是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。假设给定一些分属于两类的2维点,这些点可以通过直线分割, 我们要找到一条最优的分割线,如下图所示:
在上面的图中, 你可以直觉的观察到有多种可能的直线可以将样本分开。 那是不是某条直线比其他的更加合适呢? 我们可以凭直觉来定义一条评价直线好坏的标准。很明显,距离样本太近的直线不是最优的,因为这样的直线对噪声敏感度高,泛化性较差。 因此我们的目标是找到一条直线,离所有点的距离最远。
由此, SVM算法的实质是找出一个能够将某个值最大化的超平面,这个值就是超平面离所有训练样本的最小距离。这个最小距离用SVM术语来说叫做 间隔(margin) 。 概括一下,最优分割超平面 最大化 训练数据的间隔。如下图中间的斜线就是最大间隔向量:
至于如何去求解这个最大间隔向量,请参考http://blog.csdn.net/sealyao/article/details/6442403,说的很详细。
代码及注释:
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/ml/ml.hpp> #include<iostream> using namespace cv; using namespace std; int main() { int width = 512, height = 512; Mat image = Mat::zeros(height, width, CV_8UC3); // 1,设置样本训练数据 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); // 2,设置SVM的初始参数 CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::LINEAR;//直接线性化处理 params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);//求最大间隔向量的算法,最大迭代次数和容许误差 // 3,训练 CvSVM SVM; SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); Vec3b green(0, 255, 0), blue(255, 0, 0); //4,进行预测 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(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; int c = SVM.get_support_vector_count(); for (int i = 0; i < c; ++i) { const float* v = SVM.get_support_vector(i); cout << "最大间隔向量方向" << v[0] << " " << v[1] << endl; circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(0, 0, 255), thickness, lineType); } imwrite("resultSVM.png", image); imshow("SVM", image); waitKey(0); }
注意:SVM算法只能分割两部分,如果需要多个分割,请先把分割出一块,把其他部分当作一个整体,然后递归分割。
相关文章推荐
- 支持向量机SVM和支持向量回归SVR简介——原理方法
- 找到SVM分类器的支持向量(scikit-learn)
- OpenCV机器学习:SVM分类器实现MNIST手写数字识别
- 支持向量SVM分类器的学习记录
- OpenCV实现SVM分类器
- SVM多分类器的实现(Opencv3,C++)
- 基于OpenCV的 SVM算法实现数字识别(二)---SVM原理
- 支持向量分类器的scikit-learn 实现(Support Vector Classifier)
- 機器學習中的算法(2)-支持向量機(SVM)基礎
- I18n(国际化)原理(国际化资源文件2种实现支持中文的方法,propedit5.3.3插件在MyEclipse和Eclipse中安装)
- 线性支持向量分类机及其实现
- 支持向量机(SVM)、支持向量回归(SVR)
- Opencv 向量的一阶差分函数封装实现 功能等价于Matlab的diff函数 附:显示CvMat的函数封装
- 支持向量机(SVM)、支持向量回归(SVR)
- [转载]用opencv实现svm
- Camshift原理 及其OpenCV实现
- CYQ.Data V5 文本数据库支持SQL语句操作(实现原理解说)
- 相机标定的原理与意义及OpenCV、Matlab实现差异小结
- 機器學習中的算法(2)-支持向量機(SVM)基礎
- 支持向量机(SVM)、支持向量回归(SVR)