W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在本教程中,您將學(xué)習(xí)如何:
Support Vector Machines(SVM)是由分離超平面正式定義的鑒別分類器。換句話說,給定的訓(xùn)練數(shù)據(jù)(監(jiān)督學(xué)習(xí)),算法輸出了一個最優(yōu)的超平面,對新的例子進行了分類。
在哪個意義上是超平面獲得最優(yōu)?讓我們考慮以下簡單問題:
對于屬于兩類之一的線性可分離的2D點組,找到分離直線。
在上圖中,您可以看到有多條線路可以解決問題。他們中的任何一個比別人好嗎?我們可以直觀地定義一個標準來估計線條的價值:如果線路通過太靠近點,則它是壞的,因為它將會對噪聲敏感,并且不會正確地推廣。所以我們的目標應(yīng)該是盡可能地找出所有的路線。
然后,SVM算法的操作基于找到給出訓(xùn)練樣本最大最小距離的超平面。兩次,這個距離在SVM的理論中得到了邊緣的重要名稱。因此,最優(yōu)分離超平面使訓(xùn)練數(shù)據(jù)的余量達到最大。
我們來介紹用于定義超平面的符號:
其中β被稱為權(quán)重向量,而β0稱為偏差。
通過縮放β和可以以無限數(shù)量的不同方式表示最優(yōu)超平面β0。作為慣例,在超平面的所有可能的表示中,選擇的是
其中X表示最接近超平面的訓(xùn)練樣本。通常,最接近超平面的訓(xùn)練樣本稱為支持向量。這種表示被稱為規(guī)范超平面。
現(xiàn)在,我們使用幾何的結(jié)果給出點X和超平面之間的距離(β,β0):
特別地,對于規(guī)范超平面,分子等于1,并且到支持向量的距離為
回想一下,上一節(jié)中介紹的the margin(這里表示為M)是距離最接近的例子的兩倍:
最后,m最大化問題等價于一個函數(shù)L(β)在某些約束條件下的極小化問題。約束模型對超平面的要求正確分類所有訓(xùn)練樣本。從形式上看,
其中yi 表示訓(xùn)練樣本的每個標簽。
這是拉格朗日優(yōu)化的問題,可以使用拉格朗日乘數(shù)來求解最優(yōu)超平面的權(quán)重向量β和偏置β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};
float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
Mat labelsMat(4, 1, CV_32SC1, labels);
// Train the SVM
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);
// Show the decision regions given by the SVM
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) << 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->getUncompressedSupportVectors();
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);
}
int labels [4] = {1,-1,-1,-1};
float trainingData [4] [2] = {{501,10},{255,10},{501,255},{10,501}};
將要使用的函數(shù)cv :: ml :: SVM :: train需要將訓(xùn)練數(shù)據(jù)存儲為cv :: Mat對象的浮點數(shù)。因此,我們從上面定義的數(shù)組創(chuàng)建這些對象:
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
Mat labelsMat(4, 1, CV_32SC1, labels);
在本教程中,我們在最簡單的情況下介紹了SVM的理論,當訓(xùn)練示例分為兩類可以線性分離時。然而,SVM可以用于各種各樣的問題(例如,非線性可分離數(shù)據(jù)的問題,使用內(nèi)核函數(shù)的SVM來提高示例的維度等)。因此,我們必須在訓(xùn)練SVM之前定義一些參數(shù)。這些參數(shù)存儲在類cv :: ml :: SVM的對象中。
ptr <SVM> svm = SVM :: create();
svm->的setType(SVM :: C_SVC);
svm-> setKernel(SVM :: LINEAR);
svm-> setTermCriteria(TermCriteria(TermCriteria :: MAX_ITER,100,1e-6));
這里:
svm-> train(trainingDataMat,ROW_SAMPLE,labelsMat);
方法cv :: ml :: SVM :: predict用于使用經(jīng)過訓(xùn)練的SVM對輸入樣本進行分類。在這個例子中,我們使用這種方法來根據(jù)SVM所做的預(yù)測來對空間進行著色。換句話說,遍歷圖像將其像素解釋為笛卡爾平面的點。每個點根據(jù)SVM預(yù)測的類別著色; 如果是帶有標簽1的類,則為綠色,如果為帶有標簽-1的類,則為藍色
支持向量
我們在這里使用幾種方法來獲取有關(guān)支持向量的信息。方法cv :: ml :: SVM :: getSupportVectors獲取所有的支持向量。我們在這里使用這種方法來找到支持向量的訓(xùn)練示例并突出顯示。
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) << 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;
}
我們在這里使用幾種方法來獲取有關(guān)支持向量的信息。方法cv :: ml :: SVM :: getSupportVectors獲取所有的支持向量。我們在這里使用這種方法來找到支持向量的訓(xùn)練示例并突出顯示。
thickness = 2;
lineType = 8;
Mat sv = svm->getUncompressedSupportVectors();
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);
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: