【Svm機器學習篇】Opencv3.4.1與C++實現對分類問題的訓練與預測】
支援向量機(SVM)中最核心的是4個字——“支援向量”,一旦在兩類或多累樣本集中定位到某些特定的點作為支援向量,就可以依據這些支援向量計算出來分類超平面,再依據超平面對類別進行歸類劃分就是水到渠成的事了。有必要回顧一下什麼是支援向量機中的支援向量。 上圖中需要對紅色和藍色的兩類訓練樣本進行區分,實現綠線是決策面(超平面),最靠近決策面的2個實心紅色樣本和1個實心藍色樣本分別是兩類訓練樣本的支援向量,決策面所在的位置是使得兩類支援向量與決策面之間的間隔都達到最大時決策面所處的位置。
一般情況下,訓練樣本都會存在噪聲,這就導致其中一類樣本的一個或多個樣本跑到了決策面的另一邊,摻雜到另一類樣本中。針對這種情況,SVM加入了鬆弛變數(懲罰變數)來應對,確保這些噪聲樣本不會被作為支援向量,而不管它們離超平面的距離有多近。包括SVM中的另一個重要概念“核函式”,也是為訓練樣本支援向量的確定提供支援的。 在OpenCV中,SVM的訓練、歸類流程如下: 1. 獲取訓練樣本 SVM是一種有監督的學習分類方法,所以對於給出的訓練樣本,要明確每個樣本的歸類是0還是1,即每個樣本都需要標註一個確切的類別標籤,提供給SVM訓練使用。對於樣本的特徵,以及特徵的維度,SVM並沒有限定,可以使用如Haar、角點、Sift、Surf、直方圖等各種特徵作為訓練樣本的表述參與SVM的訓練。Opencv要求訓練資料儲存在float型別的Mat結構中。
1. SVM的核心思想
SVM的分類思想本質上和線性迴歸LR分類方法類似,就是求出一組權重係數,線上性表示之後可以分類。我們先使用一組trainging set來訓練SVM中的權重係數,然後可以對testingset進行分類。
說的更加更大上一些:SVM就是先訓練出一個分割超平面separation hyperplane, 然後該平面就是分類的決策邊界,分在平面兩邊的就是兩類。顯然,經典的SVM演算法只適用於兩類分類問題,當然,經過改進之後,SVM也可以適用於多類分類問題。
我們希望找到離分隔超平面最近的點,確保它們離分隔面的距離儘可能遠。這裡點到分隔面的距離被稱為間隔margin. 我們希望這個margin儘可能的大。支援向量support vector就是離分隔超平面最近的那些點,我們要最大化支援向量到分隔面的距離。
那麼為了達到上面的目的,我們就要解決這樣的一個問題:如何計算一個點到分隔面的距離?這裡我們可以借鑑幾何學中點到直線的距離,需要變動的是我們這裡是點到超平面的距離。具體轉換過程如下:
程式碼:
#include<sstream>
#include<opencv2\opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
#include<opencv2/ml/ml.hpp>
using namespace std;
using namespace cv;
using namespace ml;
cv::Mat trainData;
cv::Mat trainLabel;
void get_data1();
void get_data2();
int main() {
get_data1();
get_data2();
trainData.convertTo(trainData, CV_32FC1);
trainLabel.convertTo(trainLabel, CV_32SC1);
//vector<Mat> test_set;
//get_test(io, test_set);
Ptr<SVM> model = SVM::create();
model->setType(SVM::C_SVC); //SVM型別
model->setKernel(SVM::LINEAR); //核函式,這裡使用線性核
model->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
//model->train(trainData, ROW_SAMPLE, trainLabel);//只訓練不生成xml
Ptr<TrainData> tData = TrainData::create(trainData, ROW_SAMPLE, trainLabel);
//訓練生成xml
std::cout << "SVM: start train ..." << endl;
model->train(tData);
std::cout << "SVM: train success ..." << endl;
model->save("svm.xml");
waitKey();
getchar();
return 0;
}
void get_data1() {
ifstream fin("alist.txt", ios::in);
string s;
while (getline(fin, s)) {
if (s.length() != 0) {
string ss;
ss = "C:\\Users\\wangz\\Desktop\\\apple\\" + s;
Mat m2 = imread(ss, 0);
if (m2.empty()) {
cout << "fail" << endl;
}
Mat temp;
resize(m2, temp, Size(256, 256));
//imshow("12", m2);
trainData.push_back(temp.reshape(0, 1)); //連續放入Mat容器中
trainLabel.push_back(1);
//trainLabel.push_back(Mat(1, 1, CV_32SC1, 0)); //trainData.convertTo(trainData, CV_32FC1);
}
}
}
void get_data2() {
ifstream fin("mlist.txt", ios::in);
string s;
//Mat mm(29, 256 * 256, CV_8UC1);
while (getline(fin, s)) {
string ss;
if (s.length() != 0) {
ss = "C:\\Users\\wangz\\Desktop\\svm\\microsoft\\" + s;
Mat m2 = imread(ss, 0);
if (m2.empty()) {
cout << "fail" << endl;
}
Mat temp;
resize(m2, temp, Size(256, 256));
//imshow("12", m2);
trainData.push_back(temp.reshape(0, 1)); //連續放入Mat容器中
trainLabel.push_back(-1);
//trainLabel.push_back(Mat(1, 1, CV_32SC1, 1)); //trainData.convertTo(trainData, CV_32FC1);
}
}
}
/*
ifstream fin1(path1, ios::in);
string s1;
while (getline(fin1, s1)) {
if (s1.length() != 0) {
string slable;
slable = s1.substr(s1.find(" "));
int index = atoi(slable.c_str()); //slable - '0';
cout << index << endl;
trainLabels.push_back(Mat(1, 1, CV_32SC1, &index));
}
}
}
*/
//樣本資料必須是CV_32FC1型別。opencv3版本決定的
//樣本標籤必須是CV_32SC1,opencv3後從int陣列轉換為CV_32SC1型別,而opencv2是從float資料轉換。
程式碼二:
#include<sstream>
#include<opencv2\opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
#include<opencv2/ml/ml.hpp>
using namespace std;
using namespace cv;
using namespace ml;
void get_data1(Mat& trainimage,vector<int>& trainlab);
void get_data2(Mat& trainimage,vector<int>& trainlab);
int main() {
Mat classes;
Mat traindata, trainimg;
vector<int>trainlables;
get_data1(trainimg,trainlables);
get_data2(trainimg, trainlables);
Mat(trainimg).copyTo(traindata);
traindata.convertTo(traindata, CV_32FC1);
Mat(trainlables).copyTo(classes);
classes.convertTo(classes, CV_32SC1);
//vector<Mat> test_set;
//get_test(io, test_set);
Ptr<SVM> model = SVM::create();
model->setType(SVM::C_SVC); //SVM型別
model->setKernel(SVM::LINEAR); //核函式,這裡使用線性核
model->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));
//model->train(trainData, ROW_SAMPLE, trainLabel);//只訓練不生成xml
Ptr<TrainData> tData = TrainData::create(traindata, ROW_SAMPLE, classes);
//訓練生成xml
std::cout << "SVM: start train ..." << endl;
model->train(tData);
std::cout << "SVM: train success ..." << endl;
Mat tset=imread("123.jpg",0);
resize(tset, tset, Size(256, 256));
tset.reshape(0, 1);
double k= model->predict(tset);
cout << k;
//model->save("svm.xml");
//
waitKey();
getchar();
return 0;
}
void get_data1(Mat& trainimage, vector<int>& trainlab) {
ifstream fin("alist.txt", ios::in);
string s;
while (getline(fin, s)) {
if (s.length() != 0) {
string ss;
ss = "C:\\Users\\wangz\\Desktop\\\apple\\" + s;
Mat m2 = imread(ss, 0);
if (m2.empty()) {
cout << "fail" << endl;
}
Mat temp;
resize(m2, temp, Size(256, 256));
//imshow("12", m2);
trainimage.push_back(temp.reshape(0, 1)); //連續放入Mat容器中
trainlab.push_back(1);
//trainLabel.push_back(Mat(1, 1, CV_32SC1, 0)); //trainData.convertTo(trainData, CV_32FC1);
}
}
cout << trainimage.size() << endl;
cout << trainlab.size() << endl;
}
void get_data2(Mat& trainimage,vector<int>& trainlab) {
ifstream fin("mlist.txt", ios::in);
string s;
//Mat mm(29, 256 * 256, CV_8UC1);
while (getline(fin, s)) {
string ss;
if (s.length() != 0) {
ss = "C:\\Users\\wangz\\Desktop\\svm\\microsoft\\" + s;
Mat m2 = imread(ss, 0);
if (m2.empty()) {
cout << "fail" << endl;
}
Mat temp;
resize(m2, temp, Size(256, 256));
//imshow("12", m2);
trainimage.push_back(temp.reshape(0, 1)); //連續放入Mat容器中
trainlab.push_back(-1);
//trainLabel.push_back(Mat(1, 1, CV_32SC1, 1)); //trainData.convertTo(trainData, CV_32FC1);
}
}
cout << trainimage.size() << endl;
cout << trainlab.size() << endl;
}
/*
ifstream fin1(path1, ios::in);
string s1;
while (getline(fin1, s1)) {
if (s1.length() != 0) {
string slable;
slable = s1.substr(s1.find(" "));
int index = atoi(slable.c_str()); //slable - '0';
cout << index << endl;
trainLabels.push_back(Mat(1, 1, CV_32SC1, &index));
}
}
}
*/
//樣本資料必須是CV_32FC1型別。opencv3版本決定的
//樣本標籤必須是CV_32SC1,opencv3後從int陣列轉換為CV_32SC1型別,而opencv2是從float資料轉換。
第一次用opencv訓練svm出問題是很正常的如下:
百度解決方法如下:
http://www.it1352.com/481183.html
https://blog.csdn.net/galileoyuyu/article/details/82083673
參考部落格:https://www.cnblogs.com/br170525/p/9236479.html
https://blog.csdn.net/mao_hui_fei/article/details/80455538
https://blog.csdn.net/im6520/article/details/75240435
https://blog.csdn.net/a1111h/article/details/72568970
https://blog.csdn.net/sinat_34474705/article/details/80502789?utm_source=blogxgwz0
https://blog.csdn.net/xuan_zizizi/article/details/71102018
hog訓練的:https://blog.csdn.net/u013419097/article/details/80253977
相關文章
- 機器學習,詳解SVM軟間隔與對偶問題機器學習
- 機器學習基礎篇:支援向量機(SVM)理論與實踐機器學習
- 機器學習--有監督學習--分類演算法(預測分類)機器學習演算法
- 機器學習-訓練模型的儲存與恢復(sklearn)機器學習模型
- NLP與深度學習(五)BERT預訓練模型深度學習模型
- 瀏覽器中的機器學習:使用預訓練模型瀏覽器機器學習模型
- 機器學習的訓練集機器學習
- 機器學習之分類:預測偏差機器學習
- ResNet50的貓狗分類訓練及預測
- 機器學習策略篇:詳解訓練/開發/測試集劃分(Train/dev/test distributions)機器學習AIdev
- 如何用Python和機器學習訓練中文文字情感分類模型?Python機器學習模型
- 劃分訓練集與測試集
- 用Python實現一個SVM分類器策略Python
- 訓練一個影像分類器demo in PyTorch【學習筆記】PyTorch筆記
- 如何用機器學習對文字分類機器學習文字分類
- 機器學習實戰 | 性別預測模型的構建與優化機器學習模型優化
- OpML 2019提前看:模型表現預測與分散式機器學習模型分散式機器學習
- 機器學習在交通標誌檢測與精細分類中的應用機器學習
- 《機器學習Python實現_10_02_整合學習_boosting_adaboost分類器實現》機器學習Python
- 機器學習實戰-SVM模型實現人臉識別機器學習模型
- 機器學習之分類問題度量機器學習
- 【機器學習】--xgboost初始之程式碼實現分類機器學習
- 機器學習股票價格預測從爬蟲到預測-預測與調參機器學習爬蟲
- 【Python機器學習實戰】感知機和支援向量機學習筆記(三)之SVM的實現Python機器學習筆記
- 實踐篇:使用Spark和Scala來訓練您的第一個分類器!Spark
- python中的scikit-learn庫來實現SVM分類器。Python
- 《機器學習Python實現_10_06_整合學習_boosting_gbdt分類實現》機器學習Python
- 深入理解SVM,軟間隔與對偶問題
- 機器學習基礎專題:支援向量機SVM機器學習
- 抽象類練習_學生與工人抽象
- 《機器學習_07_01_svm_硬間隔支援向量機與SMO》機器學習
- Python機器學習基礎篇三《無監督學習與預處理》Python機器學習
- 機器學習——支援向量機(SVM)機器學習
- 機器學習:支援向量機(SVM)機器學習
- 使用sklearn實現svm--用於機械故障分類
- 如何對SAP Leonardo上的機器學習模型進行重新訓練機器學習模型
- 機器學習中的類別不均衡問題機器學習
- 機器學習演算法(一): 基於邏輯迴歸的分類預測機器學習演算法邏輯迴歸