首页 > 编程语言 > 详细

【机器学习】逻辑回归的C++实现

时间:2021-03-16 22:30:31      阅读:73      评论:0      收藏:0      [点我收藏+]

代码框架与感知机一致,区别仅在于train和test函数上。

train

逻辑回归和感知机一样,也是来解决二分类问题。但输出的为当前标签为1的概率,所以和感知机只训练错误样例不同,我们需要对每个样本进行训练。

我们需要的输出范围为[0, 1],但是线性方程f(x) = wx + b的范围为负无穷到正无穷,所以我们要对输出进行变化(感知机的变换函数为符号函数)。于是我们使用sigmoid函数,sigmoid除了能够将输入调整到0到1的功能外,还具备很好的导数性质。sigmoid函数表示f(z)=1 / (1 + e^-z),则逻辑回归的整体数学形式为y = 1 / (1 + e^-wx),输出的值为样本为1的概率,为了方便后续计算,我们将其设为p。对w求导,可以得到p‘=p(1-p)x,其导数形式也非常简单,有利于后续的参数更新。

在当前w参数下,对于任意输入样本,逻辑回归的预测结果概率可以表示为...。综合起来可以写为...。我们要求得一组w参数,使当前抽样样本发生的概率最大,也就是取极大似然估计,再加上负号就可以定义为逻辑回归的损失函数。所以我们对所有概率连乘,两边取log变成连加,再取负号,得到逻辑回归的损失函数F(x)=-(求和ylogp + (1-y)log(1-p))。

得到目标函数后,我们w求偏导,得(求和(y-p)x)。我们使用随机梯度下降的方法,每次输入样本后都能更新w = w - h * (w_delta)。

void train(int itera) {
    int m = train_set.size();
    int n = train_set[0].size();
    w.assign(n + 1, 0); // w与b合并,维度+1
    double h = 0.0001;
    for (int i = 0; i < itera; i++) { // 开始迭代
        for (int j = 0; j < m; j++) {
            Vec xi = train_set[j]; // 当前训练数据,一维向量
            double yi = train_label[j]; // 当前label
            double exp_wx = exp(mul_vv(w, xi)); // 先计算好,避免重复运算
            Vec w_delta = mul_vd(xi, h * (yi - exp_wx / (1 + exp_wx))); // 计算w更新值
            w = add_vv(w, w_delta); // 更新w
        }
    }
}

test

测试时,只需要计算预测为1的概率p即可。p>=0.5则预测为1,否则预测为0。

double test() {
    int m = test_set.size();
    int n = test_set[0].size();
    double err_cnt = 0;
    for (int i = 0; i < m; i++) {
        Vec xi = test_set[i];
        double yi = test_label[i];
        double exp_wx = exp(mul_vv(w, xi));
        double predict = exp_wx / (1 + exp_wx);
        double res = predict >= 0.5 ? 1 : 0;
        if (res != yi) err_cnt++;
    }
    double acc_rate = 1 - (err_cnt / m);
    return acc_rate;
}

【机器学习】逻辑回归的C++实现

原文:https://www.cnblogs.com/tmpUser/p/14545329.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!