SVM Phân Lớp Nhị Phân Khi Dữ Liệu Phi Tuyến Tính Sử Dụng Softmargin?

Hello Mình sử dụng SVM trong OpenCV để kiểm nghiệm thuật toán SVM chạy ntn như sau Đây là chương trình phân lớp nhị phân 2 tập dữ liệu tách biệt tuyến tính. Chạy ổn

#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/ml/ml.hpp> using namespace std; using namespace cv; using namespace cv::ml; int main(int argc, char *argv[]) { Mat image = Mat::zeros(512, 512, CV_8UC3); int labels[6] = {1, -1, 1, -1, -1, 1}; float trainingData[6][2] = { {501, 10 }, {255, 10 }, {501, 255}, {10 , 501}, {310, 300}, {300, 350} }; Mat labelsMat(6, 1, CV_32SC1, labels); Mat trainingDataMat(6, 2, CV_32FC1, trainingData); 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); Vec3b blueRegion(254,195,189), greenRegion(189,254,198); for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { Mat sampleMat = (Mat_<float>(1,2) << j,i); // [j,i] in matrix == (x,y) in 2d float response = svm->predict(sampleMat); if (response == 1) image.at<Vec3b>(i,j) = blueRegion; else if (response == -1) image.at<Vec3b>(i,j) = greenRegion; } } int thickness = -1; int lineType = 4; Scalar bluePoint(255, 0, 0), greenPoint(0,100,0); float x1, x2; for (int i = 0; i < trainingDataMat.rows; i++) { x1 = trainingDataMat.at<float>(i, 0); x2 = trainingDataMat.at<float>(i, 1); if (labelsMat.at<int>(i, 0) == 1) circle(image, Point(x1,x2), 5, bluePoint, thickness, lineType); else if (labelsMat.at<int>(i, 0) == -1) circle(image, Point(x1,x2), 5, greenPoint, thickness, lineType); } thickness = 2; 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(0,0,255),thickness,lineType); } imshow("Linear SVM Binary Classifier", image); waitKey(0); system("pause"); return 0; }

model được cấu hình các tham số sau

Ptr<SVM> svm = SVM::create(); svm->setType(SVM::C_SVC); // phân loại n lớp (n>2), cho phép sử dụng softmargin với độ lỗi C svm->setKernel(SVM::LINEAR); // hàm sử dụng để chuyển dữ liệu từ không gian giả thiết sang không gian đặc trưng là hàm tuyến tính svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); // điều kiện dừng khi thuật toán lặp là 100 lần và độ chính xác của model đạt 1e-6 ~ 0.000001

Kết quả

[DEAD IMAGE]

1 số kết quả khác

[DEAD IMAGE]

Bây giờ vẫn chương trình trên nhưng mình sửa 1 chút dữ liệu cho 2 tập phi tuyến tính như sau

int labels[6] = {1, -1, 1, -1, -1, 1}; float trainingData[6][2] = { {501, 10 }, {255, 10 }, {501, 255}, {10 , 501}, {310, 300}, // phi tuyến {300, 350} // phi tuyến };

Vẫn để cấu hình tham số model như cũ và thử chạy thì có kêt quả

image.png515×540 3.48 KB

Có thể thấy siêu phẳng tối ưu tìm được đã bị sai. Giờ mình sẽ cấu hình thêm tham số độ lỗi C để chương trình sử dụng softmargin

svm->setC(0.1);

Thì kết quả vẫn như cũ

image.png515×540 3.48 KB

Ở đây có 1 chương trình phân lớp nhị phân khi dữ liệu phi tuyến nhưng có thể sử dụng được softmargin của trang chủ OpenCV.

https://docs.opencv.org/3.4.1/d0/dcc/tutorial_non_linear_svms.html

Họ cũng làm như chương trình trên, chỉ có là dữ liệu của họ nhiều hơn , tạo bằng cách random, và điều kiện dừng khi thuật toán lặp của họ khác. Mình cũng đã thử điện kiện dừng của họ vào chương trình trên nhưng vẫn không được.

Còn 1 vấn đề nữa. Chương trình của họ chạy sẽ ra ntn image.png515×540 5.92 KB

Ở đây các điểm được vòng màu đỏ là support vector. Mà theo định nghĩa, support vector là tập các điểm hỗ trợ xây đựng siêu phẳng tối ưu, chính là các điểm mà 2 siêu phẳng lề song song đi quá = các điểm gần siêu phẳng tối ưu nhất. Nhưng với softmargin, như ảnh trên có rât nhiều điểm được vòng màu đỏ. Vậy các điểm bị bỏ đi (nằm trong vùng k an toàn, vùng lề) có được coi là 1 support không?

Thank you.

Từ khóa » Svm Phi Tuyến