SVM簡介

2018-10-19 10:24 更新

目標

在本教程中,您將學(xué)習(xí)如何:

什么是SVM?

Support Vector Machines(SVM)是由分離超平面正式定義的鑒別分類器。換句話說,給定的訓(xùn)練數(shù)據(jù)(監(jiān)督學(xué)習(xí)),算法輸出了一個最優(yōu)的超平面,對新的例子進行了分類。

在哪個意義上是超平面獲得最優(yōu)?讓我們考慮以下簡單問題:

對于屬于兩類之一的線性可分離的2D點組,找到分離直線。

separating-lines

注意
在這個例子中,我們處理笛卡爾平面中的線和點,而不是在高維空間中的超平面和向量。這是一個簡化的問題。重要的是要明白,這只是因為我們的直覺更好地從容易想象的例子構(gòu)建。然而,相同的概念適用于要分類的示例位于維度高于2的空間中的任務(wù)。

在上圖中,您可以看到有多條線路可以解決問題。他們中的任何一個比別人好嗎?我們可以直觀地定義一個標準來估計線條的價值:如果線路通過太靠近點,則它是壞的,因為它將會對噪聲敏感,并且不會正確地推廣。所以我們的目標應(yīng)該是盡可能地找出所有的路線。

然后,SVM算法的操作基于找到給出訓(xùn)練樣本最大最小距離的超平面。兩次,這個距離在SVM的理論中得到了邊緣的重要名稱。因此,最優(yōu)分離超平面使訓(xùn)練數(shù)據(jù)的余量達到最大。

SVM簡介

如何計算最佳超平面?

我們來介紹用于定義超平面的符號:

SVM簡介

其中β被稱為權(quán)重向量,而β0稱為偏差

也可以看看
這和超平面更深入的描述,你可以在4.5節(jié)(發(fā)現(xiàn)分隔條件超平面書的):統(tǒng)計學(xué)習(xí)的要素通過 T. Hastie, R. Tibshirani和JH Friedman([172])。

通過縮放β和可以以無限數(shù)量的不同方式表示最優(yōu)超平面β0。作為慣例,在超平面的所有可能的表示中,選擇的是

SVM

其中X表示最接近超平面的訓(xùn)練樣本。通常,最接近超平面的訓(xùn)練樣本稱為支持向量。這種表示被稱為規(guī)范超平面。

現(xiàn)在,我們使用幾何的結(jié)果給出點X和超平面之間的距離(β,β0):

SVM

特別地,對于規(guī)范超平面,分子等于1,并且到支持向量的距離為

SVM

回想一下,上一節(jié)中介紹的the margin(這里表示為M)是距離最接近的例子的兩倍:

SVM簡介

最后,m最大化問題等價于一個函數(shù)L(β)在某些約束條件下的極小化問題。約束模型對超平面的要求正確分類所有訓(xùn)練樣本。從形式上看,

SVM簡介

其中yi 表示訓(xùn)練樣本的每個標簽。

這是拉格朗日優(yōu)化的問題,可以使用拉格朗日乘數(shù)來求解最優(yōu)超平面的權(quán)重向量β和偏置β0。

源代碼

注意
以下代碼已經(jīng)通過OpenCV 3.0類和函數(shù)實現(xiàn)??梢栽?a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" target="_blank">此頁面中找到使用OpenCV 2.4的代碼的等效版本
#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);
}

說明

  • 設(shè)置訓(xùn)練數(shù)據(jù)該練習(xí)的訓(xùn)練數(shù)據(jù)由屬于兩個不同類之一的一組標記的2D點形成; 其中一個課程包括一個點和另一個三點。
    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);
  • 設(shè)置SVM的參數(shù)

在本教程中,我們在最簡單的情況下介紹了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));

這里:

  1. SVM類型。我們在這里選擇可用于n類分類的類型C_SVC(n 2)。這種類型的重要特征是處理類的不完全分離(即訓(xùn)練數(shù)據(jù)是非線性分離的)。這個功能在這里并不重要,因為數(shù)據(jù)是線性可分的,我們選擇這個SVM類型是最常用的?!?/li>
  2. SVM內(nèi)核的類型。我們沒有談到內(nèi)核函數(shù),因為它們對我們正在處理的培訓(xùn)數(shù)據(jù)不是有趣的。不過,現(xiàn)在讓我們簡單介紹一下內(nèi)核函數(shù)的主要思路。它是對訓(xùn)練數(shù)據(jù)進行的映射,以改進其與線性可分離數(shù)據(jù)集的相似度。該映射包括增加數(shù)據(jù)的維度,并使用內(nèi)核函數(shù)高效地完成。我們在這里選擇類型LINEAR,這意味著沒有映射完成。此參數(shù)使用cv :: ml :: SVM :: setKernel定義
  3. 算法的終止標準。SVM訓(xùn)練程序以迭代方式解決約束二次優(yōu)化問題。這里我們指定最大迭代次數(shù)和公差誤差,因此即使最佳超平面尚未計算,我們允許算法以較少的步數(shù)完成。此參數(shù)在結(jié)構(gòu)cv :: TermCriteria中定義。

    svm-> train(trainingDataMat,ROW_SAMPLE,labelsMat);

  • 由SVM分類的區(qū)域

方法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);
    }

結(jié)果

  1. 該代碼打開一個圖像并顯示兩個類的訓(xùn)練示例。一個等級的點用白色圓圈表示,黑色的點用于另一個類。
  2. SVM被訓(xùn)練并用于對圖像的所有像素進行分類。這導(dǎo)致在藍色區(qū)域和綠色區(qū)域中的圖像的劃分。兩個區(qū)域之間的邊界是最優(yōu)分離超平面。
  3. 最后,訓(xùn)練示例周圍使用灰色戒指顯示支持向量。

SVM簡介

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號