'SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)'

"

支持向量機算法(SVM)(二分問題)

1. 技術棧(OPENCV 3.0 +C++)

OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。

OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。

"

支持向量機算法(SVM)(二分問題)

1. 技術棧(OPENCV 3.0 +C++)

OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。

OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

圖1-2OpenCv

2. 支持向量機SVM算法介紹(OPENCV 3.0 +C++)

支持向量機 (SVM) 是一個類分類器,正式的定義是一個能夠將不同類樣本在樣本空間分隔的超平面。 換句話說,給定一些標記(label)好的訓練樣本 (監督式學習), SVM算法輸出一個最優化的分隔超平面。

如何來界定一個超平面是不是最優的呢? 考慮如下問題:

"

支持向量機算法(SVM)(二分問題)

1. 技術棧(OPENCV 3.0 +C++)

OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。

OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

圖1-2OpenCv

2. 支持向量機SVM算法介紹(OPENCV 3.0 +C++)

支持向量機 (SVM) 是一個類分類器,正式的定義是一個能夠將不同類樣本在樣本空間分隔的超平面。 換句話說,給定一些標記(label)好的訓練樣本 (監督式學習), SVM算法輸出一個最優化的分隔超平面。

如何來界定一個超平面是不是最優的呢? 考慮如下問題:

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

在這個示例中,我們考慮卡迪爾平面內的點與線,而不是高維的向量與超平面。 這一簡化是為了讓我們以更加直覺的方式建立起對SVM概念的理解, 但是其基本的原理同樣適用於更高維的樣本分類情形。

在上面的圖中, 你可以直覺的觀察到有多種可能的直線可以將樣本分開。 那是不是某條直線比其他的更加合適呢? 我們可以憑直覺來定義一條評價直線好壞的標準:距離樣本太近的直線不是最優的,因為這樣的直線對噪聲敏感度高,泛化性較差。 因此我們的目標是找到一條直線,離所有點的距離最遠。

由此, SVM算法的實質是找出一個能夠將某個值最大化的超平面,這個值就是超平面離所有訓練樣本的最小距離。這個最小距離用SVM術語來說叫做 間隔(margin) 。 概括一下,最優分割超平面 最大化 訓練數據的間隔。

"

支持向量機算法(SVM)(二分問題)

1. 技術棧(OPENCV 3.0 +C++)

OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。

OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

圖1-2OpenCv

2. 支持向量機SVM算法介紹(OPENCV 3.0 +C++)

支持向量機 (SVM) 是一個類分類器,正式的定義是一個能夠將不同類樣本在樣本空間分隔的超平面。 換句話說,給定一些標記(label)好的訓練樣本 (監督式學習), SVM算法輸出一個最優化的分隔超平面。

如何來界定一個超平面是不是最優的呢? 考慮如下問題:

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

在這個示例中,我們考慮卡迪爾平面內的點與線,而不是高維的向量與超平面。 這一簡化是為了讓我們以更加直覺的方式建立起對SVM概念的理解, 但是其基本的原理同樣適用於更高維的樣本分類情形。

在上面的圖中, 你可以直覺的觀察到有多種可能的直線可以將樣本分開。 那是不是某條直線比其他的更加合適呢? 我們可以憑直覺來定義一條評價直線好壞的標準:距離樣本太近的直線不是最優的,因為這樣的直線對噪聲敏感度高,泛化性較差。 因此我們的目標是找到一條直線,離所有點的距離最遠。

由此, SVM算法的實質是找出一個能夠將某個值最大化的超平面,這個值就是超平面離所有訓練樣本的最小距離。這個最小距離用SVM術語來說叫做 間隔(margin) 。 概括一下,最優分割超平面 最大化 訓練數據的間隔。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

如何計算最優超平面?(感興趣的同學可以自行百度,這裡不做科普。直接用Opencv 算法實現)

3支持向量機SVM算法OPENCV 實現(二分問題)

1建立訓練樣本

本例中的訓練樣本由分屬於兩個類別的2維點組成, 其中一類包含一個樣本點,另一類包含三個點。

\tfloat labels[4] = {1.0, -1.0, -1.0, -1.0};
\tfloat trainingData[4][2] = {{501, 10}, {255, 10}, {501, 255}, {10, 501}};

函數 CvSVM::train 要求訓練數據儲存於float類型的 結構中, 因此我們定義了以下矩陣:

\tMat trainingDataMat(3, 2, CV_32FC1, trainingData);
\tMat labelsMat (3, 1, CV_32FC1, labels);

2設置SVM參數

```此教程中,我們以可線性分割的分屬兩類的訓練樣本簡單講解了SVM的基本原理。 然而,SVM的實際應用情形可能複雜得多 (比如非線性分割數據問題,SVM核函數的選擇問題等等)。 總而言之,我們需要在訓練之前對SVM做一些參數設定。 這些參數保存在類 CvSVMParams 中。

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::train 來建立SVM模型。

\tCvSVM SVM;
\tSVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

4 SVM區域分割

函數 CvSVM::predict 通過重建訓練完畢的支持向量機來將輸入的樣本分類。 本例中我們通過該函數給向量空間著色, 及將圖像中的每個像素當作卡迪爾平面上的一點,每一點的著色取決於SVM對該點的分類類別:綠色表示標記為1的點,藍色表示標記為-1的點。

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) << 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;
}
5.支持向量
這裡用了幾個函數來獲取支持向量的信息。 函數 CvSVM::get_support_vector_count 輸出支持向量的數量,函數 CvSVM::get_support_vector 根據輸入支持向量的索引來獲取指定位置的支持向量。 通過這一方法我們找到訓練樣本的支持向量並突出顯示它們。
int c = SVM.get_support_vector_count();
for (int i = 0; i < c; ++i)
{
const float* v = SVM.get_support_vector(i); // get and then highlight with grayscale
circle( image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
}
結果
"

支持向量機算法(SVM)(二分問題)

1. 技術棧(OPENCV 3.0 +C++)

OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。

OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言接口。該庫也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。這些語言的API接口函數可以通過在線文檔獲得。如今也提供對於C#、Ch、Ruby,GO的支持。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

圖1-2OpenCv

2. 支持向量機SVM算法介紹(OPENCV 3.0 +C++)

支持向量機 (SVM) 是一個類分類器,正式的定義是一個能夠將不同類樣本在樣本空間分隔的超平面。 換句話說,給定一些標記(label)好的訓練樣本 (監督式學習), SVM算法輸出一個最優化的分隔超平面。

如何來界定一個超平面是不是最優的呢? 考慮如下問題:

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

在這個示例中,我們考慮卡迪爾平面內的點與線,而不是高維的向量與超平面。 這一簡化是為了讓我們以更加直覺的方式建立起對SVM概念的理解, 但是其基本的原理同樣適用於更高維的樣本分類情形。

在上面的圖中, 你可以直覺的觀察到有多種可能的直線可以將樣本分開。 那是不是某條直線比其他的更加合適呢? 我們可以憑直覺來定義一條評價直線好壞的標準:距離樣本太近的直線不是最優的,因為這樣的直線對噪聲敏感度高,泛化性較差。 因此我們的目標是找到一條直線,離所有點的距離最遠。

由此, SVM算法的實質是找出一個能夠將某個值最大化的超平面,這個值就是超平面離所有訓練樣本的最小距離。這個最小距離用SVM術語來說叫做 間隔(margin) 。 概括一下,最優分割超平面 最大化 訓練數據的間隔。

SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)

如何計算最優超平面?(感興趣的同學可以自行百度,這裡不做科普。直接用Opencv 算法實現)

3支持向量機SVM算法OPENCV 實現(二分問題)

1建立訓練樣本

本例中的訓練樣本由分屬於兩個類別的2維點組成, 其中一類包含一個樣本點,另一類包含三個點。

\tfloat labels[4] = {1.0, -1.0, -1.0, -1.0};
\tfloat trainingData[4][2] = {{501, 10}, {255, 10}, {501, 255}, {10, 501}};

函數 CvSVM::train 要求訓練數據儲存於float類型的 結構中, 因此我們定義了以下矩陣:

\tMat trainingDataMat(3, 2, CV_32FC1, trainingData);
\tMat labelsMat (3, 1, CV_32FC1, labels);

2設置SVM參數

```此教程中,我們以可線性分割的分屬兩類的訓練樣本簡單講解了SVM的基本原理。 然而,SVM的實際應用情形可能複雜得多 (比如非線性分割數據問題,SVM核函數的選擇問題等等)。 總而言之,我們需要在訓練之前對SVM做一些參數設定。 這些參數保存在類 CvSVMParams 中。

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::train 來建立SVM模型。

\tCvSVM SVM;
\tSVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

4 SVM區域分割

函數 CvSVM::predict 通過重建訓練完畢的支持向量機來將輸入的樣本分類。 本例中我們通過該函數給向量空間著色, 及將圖像中的每個像素當作卡迪爾平面上的一點,每一點的著色取決於SVM對該點的分類類別:綠色表示標記為1的點,藍色表示標記為-1的點。

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) << 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;
}
5.支持向量
這裡用了幾個函數來獲取支持向量的信息。 函數 CvSVM::get_support_vector_count 輸出支持向量的數量,函數 CvSVM::get_support_vector 根據輸入支持向量的索引來獲取指定位置的支持向量。 通過這一方法我們找到訓練樣本的支持向量並突出顯示它們。
int c = SVM.get_support_vector_count();
for (int i = 0; i < c; ++i)
{
const float* v = SVM.get_support_vector(i); // get and then highlight with grayscale
circle( image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
}
結果
SVM實現模式識別(一):支持向量機算法(SVM)(二分問題)


源碼:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
int main()
{
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
// Set up training data
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);
// Set up SVM's parameters
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
// Train the SVM
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

Vec3b green(0,255,0), blue (255,0,0);
// Show the decision regions given by the SVM
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;
}
// 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;
int c = SVM.get_support_vector_count();
for (int i = 0; i < c; ++i)
{
const float* v = SVM.get_support_vector(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);
}
注意:
32 位系統中,int 整數佔 4 個字節,指針同樣佔 4 個字節
64 位系統中,int 整數佔 4 個字節,指針同樣佔 8 個字節
"

相關推薦

推薦中...