在opencv3中實現機器學習之:利用邏輯斯諦回歸(logistic regression)分類


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%.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM