logistic regression,注意這個單詞logistic ,並不是邏輯(logic)的意思,音譯過來應該是邏輯斯諦回歸,或者直接叫logistic回歸,並不是什么邏輯回歸。大部分人都叫成邏輯回歸,無奈啊。。。雖然這個算法中有回歸二字,但它做的事情卻並不是回歸,而是分類。這個算法只能解決簡單的線性二分類,在眾多的機器學習分類算法中並不出眾,但它能被改進為多分類,並換了另外一個名字softmax, 這可是深度學習中響當當的分類算法。因此,logistic回歸瞬間也變得高大上起來。
本文用它來進行手寫數字分類。在opencv3.0中提供了一個xml文件,里面存放了40個樣本,分別是20個數字0的手寫體和20個數字1的手寫體。本來每個數字的手寫體是一張28*28的小圖片,但opencv把它reshape了一下,變成了1*784 的向量,然后放在xml文件中。這個文件的位置:
\opencv\sources\samples\data\data01.xml
代碼:
// face_detect.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include "opencv2\opencv.hpp" #include <iostream> using namespace std; using namespace cv; using namespace cv::ml; //將向量轉化成圖片矩陣並顯示 void showImage(const Mat &data, int columns, const String &name) { Mat bigImage; for (int i = 0; i < data.rows; ++i) { bigImage.push_back(data.row(i).reshape(0, columns)); } imshow(name, bigImage.t()); } //計算分類精度 float calculateAccuracyPercent(const Mat &original, const Mat &predicted) { return 100 * (float)countNonZero(original == predicted) / predicted.rows; } int main() { const String filename = "E:\\opencv\\opencv\\sources\\samples\\data\\data01.xml"; Mat data, labels; //訓練數據及對應標注 cout << "加載數據..." << endl; FileStorage f; if (f.open(filename, FileStorage::READ)) { f["datamat"] >> data; f["labelsmat"] >> labels; f.release(); } else { cerr << "文件無法打開: " << filename << endl; return 1; } data.convertTo(data, CV_32F); //轉換成float型 labels.convertTo(labels, CV_32F); cout << "讀取了 " << data.rows << "行數據" << endl; Mat data_train, data_test; Mat labels_train, labels_test; //將加載進來的數據均分成兩部分,一部分用於訓練,一部分用於測試 for (int i = 0; i < data.rows; i++) { if (i % 2 == 0) { data_train.push_back(data.row(i)); labels_train.push_back(labels.row(i)); } else { data_test.push_back(data.row(i)); labels_test.push_back(labels.row(i)); } } cout << "訓練數據: " << data_train.rows << "行" << endl; cout<<"測試數據:"<< data_test.rows <<"行"<< endl; // 顯示樣本圖片 showImage(data_train, 28, "train data"); showImage(data_test, 28, "test data"); //創建分類器並設置參數 Ptr<LogisticRegression> lr1 = LogisticRegression::create(); lr1->setLearningRate(0.001); lr1->setIterations(10); lr1->setRegularization(LogisticRegression::REG_L2); lr1->setTrainMethod(LogisticRegression::BATCH); lr1->setMiniBatchSize(1); //訓練分類器 lr1->train(data_train, ROW_SAMPLE, labels_train); Mat responses; //預測 lr1->predict(data_test, responses); // 展示預測結果 cout << "原始數據 vs 預測數據:" << endl; labels_test.convertTo(labels_test, CV_32S); //轉換為整型 cout << labels_test.t() << endl; cout << responses.t() << endl; cout << "accuracy: " << calculateAccuracyPercent(labels_test, responses) << "%" << endl; waitKey(0); return 0; }
從結果顯示可以看出,待測數據(test data)是20個,算法分對了19個,精度為95%.