1. 建立训练样本
本例中的训练样本由分属于两个类别的2维点组成。为了让程序更加吸引人,我们用均匀概率密度函数(PDF)随机生成样本. 我们将样本的生成代码分成两部分。 在第一部分我们生成两类线性可分样本
// class 1 随机样本生成
Mat trainClass=trainData.rowRange(0, nLinearSamples); // x 坐标范围 [0, 0.4)
Mat c =trainClass.colRange(0, 1);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4* WIDTH)); // y 坐标范围 [0, 1)
c =trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT));
// class 2 随机样本生成
trainClass=trainData.rowRange(2*NTRAINING_SAMPLES-nLinearSamples, 2*NTRAINING_SAMPLES); // x 坐标范围 [0.6, 1]
c =trainClass.colRange(0 , 1);
rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH)); // y 坐标范围 [0, 1)
c =trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); 在第二部分我们同时生成重叠分布线性不可分的两类样本.
// classes 1 , 2 随机样本生成
trainClass=trainData.rowRange( nLinearSamples, 2*NTRAINING_SAMPLES-nLinearSamples); // x 坐标范围 [0.4, 0.6) c =trainClass.colRange(0,1);
rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH)); // y 坐标范围 [0, 1)
c =trainClass.colRange(1,2);
rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); 2. 设置SVM参数 See also
前一节 支持向量机(SVM)介绍 提到了类 CvSVMParams 中的一些参数需要在训练SVM之前设置。
CvSVMParamsparams;
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. 此处取值较小,目的是优化时不过分惩罚分类错误。这样做的目的是为了得到一个与直觉预期比较接近的分隔线。您可以通过调整该参数来加深你对问题的理解。
Note
这里在两类之间重叠区域的点比较少,缩小 FRAC_LINEAR_SEP 会增加不可分区域的点数,此时 CvSVM::C_SVC 参数的调整对结果的影响深远。
?
算法终止条件. 最大迭代次数需要显著增加来容许非线性可分的训练数据,这里的最大迭代设置是前一节的10的5次方倍。
3. 训练支持向量机
调用函数 CvSVM::train 来建立SVM模型。注意训练过程可能耗时比较长,您需要多一点耐心来等待。
CvSVMsvm; svm.train(trainData, labels, Mat(), Mat(), params); 4. SVM区域分割
函数 CvSVM::predict 通过重建训练完毕的支持向量机来将输入的样本分类。本例中我们通过该函数给向量空间着色,即将图像中的每个像素当作卡迪尔平面上的一点,每一点的着色取决于SVM对该点的分类类别:深绿色表示分类为1的点,深蓝色表示分类为2的点。
Vec3b green(0,100,0), blue (100,0,0); for (int i =0; i Mat sampleMat= (Mat_ if (response ==1) I.at 5. 显示训练样本 函数 circle 被用来显示训练样本。标记为1的样本用浅绿表示,标记为2的样本用浅蓝表示。 int thick =-1; intlineType=8; floatpx, py; // Class 1 for (int i =0; i < NTRAINING_SAMPLES; ++i) { px= trainData.at 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 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) { constfloat* v =svm.get_support_vector(i); circle( I, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thick, lineType); } 结果 程序创建了一张图像,在其中显示了训练样本,其中一个类显示为浅绿色圆圈,另一个类显示为浅蓝色圆圈。 ? 训练得到SVM,并将图像的每一个像素分类。分类的结果将图像分为蓝绿两部分,中间线就是最优分割超平面。由于样本非线性可分,自然就有一些被错分类的样本。一些绿色点被划分到蓝色区域,一些蓝色点被划分到绿色区域。 ? 最后支持向量通过灰色边框加重显示。 ? 你可以在 YouTube 观看本程序的实时运行. 百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库支持向量机的介绍(4)在线全文阅读。
相关推荐: