C++实现简单逻辑回归 Logistic Regression

逻辑回归是非常经典的分类算法,通过sigmoid非线性函数实现的二分类器,关于函数原型、分类算法原理可参考:

https://blog.csdn.net/u014258807/article/details/80616647 

sigmoid函数定义为:

函数图形为:

C++实现简单逻辑回归 Logistic Regression_第1张图片

其推导过程略,实现可参考github:https://github.com/codestorm04/Arma_ML 项目下的src/logistic/logistic_classifier.cc。

对应logistic_classifier.h 定义如下:

/*
* The entry of the module datasets
* compile with flags:
* author: Yuzhen Liu
* Date: 2019.3.24 11:59
*/

#ifndef LOGISTIC_CLASSIFIER_H
#define LOGISTIC_CLASSIFIER_H

#include 
#include 
#include 

using namespace std;
using namespace arma;


// Implements a logistic binary classifier
class Logisitic_Classifier {

    public:
        Logisitic_Classifier();
        // ~Logisitic_Classifier();
        vec predict(mat x);
        void train(mat x, vec y);
        void initialize();

    private:
        rowvec w;    // a row vector of weights
        double b = 0; // bias
        double lr = 0.5; // Learing rate
        double delta_threshhold = 10;
        int iteration = 50;

        double _logistic(vec x);
        double _logistic_derivative(vec x);
};

#endif // LOGISTIC_CLASSIFIER_H

logistic_classifier.cc 实现如下:

/*
* Mathmetics reference: https://blog.csdn.net/u014258807/article/details/80616647
* compile with flags: g++ logistic_classifier.cc -std=c++14 -o test -larmadillo
* author: Yuzhen Liu
* Date: 2019.3.24 11:59
*/

#include 

// Implements here
Logisitic_Classifier::Logisitic_Classifier() {
    // TODO: w
}


void Logisitic_Classifier::train(mat x, vec y) {
    if (x.n_cols <= 0) 
        return;
    w = rowvec(x.n_rows, fill::zeros);

    for(int round =0; round < iteration; round++) {
        rowvec delta_sum_w = rowvec(size(w), fill::zeros);
        double delta_sum_b = 0;
        for (int i = 0; i < x.n_cols; i++) {
            delta_sum_b += y(i) - Logisitic_Classifier::_logistic(x.col(i));
            delta_sum_w += delta_sum_b * (x.col(i)).t();
        }
        b += lr * as_scalar(delta_sum_b) / x.n_cols;
        w += lr * delta_sum_w / x.n_cols;
        // if (sum(delta_sum_w) >= delta_threshhold) 
        //     break;
    }
}


vec Logisitic_Classifier::predict(mat x) {
    vec res = vec(x.n_cols);
    for (int i = 0; i < x.n_cols; i++) {
        res(i) = _logistic(x.col(i)) > 0.5 ? 1 : 0;
    }
    return res;
}

double Logisitic_Classifier::_logistic(vec x) {
    return 1/(1 + exp(0 - as_scalar(w * x) - b));
}

调用方法如下example.cc:

*
* compile with flags:   g++ test.cc softmax_classifier.cc   ../datasets/datasets.cc -std=c++14 -larmadillo -I ../../include/
* author: Yuzhen Liu
* Date: 2019.3.29 10:55
*/

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace arma;



int main() {
    Datasets dataset = Datasets("iris");

    Logistic classifier testing
    vec y = dataset.y.subvec(0, 99);
    mat x = dataset.x.submat(0, 0, 3, 99);
    Logisitic_Classifier lr_classifier = Logisitic_Classifier();
    lr_classifier.train(x, y);
    vec res = lr_classifier.predict(mat({{6.1, 2.9, 4.7, 1.4}, {5.1, 3.5, 1.4, 0.2}}).t());
    res.print();

    return 0;
}

 

你可能感兴趣的