欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 逻辑(Logistic)回归原理及Python实现(含数据集)

程序员文章站 2024-01-22 14:33:40
二元逻辑回归的损失函数(极大似然函数)极小化的求解,有比较多的方法,最常见的有梯度下降法,坐标轴下降法,等牛顿法等,最常用的是梯度下降来不断逼近最优解。梯度下降法:随机梯度下降(SGD)、批量梯度下降(BGD)、小批量梯度下降(MBGD)。优缺点优点:(1)训练速度较快,分类的时候,计算量仅仅只和特征的数目相关;(2)简单易理解,模型的可解释性非常好,从特征的权重可以看到不同的特征对最后结果的影响;(3)适合二分类问题,不需要缩放输入特征;(4)内...

原理

基本原理

荐
                                                        逻辑(Logistic)回归原理及Python实现(含数据集)
荐
                                                        逻辑(Logistic)回归原理及Python实现(含数据集)
荐
                                                        逻辑(Logistic)回归原理及Python实现(含数据集)

损失函数的求解方法

  • 二元逻辑回归的损失函数(极大似然函数)极小化的求解,有比较多的方法,最常见的有梯度下降法,坐标轴下降法,等牛顿法等,最常用的是梯度下降来不断逼近最优解。
  • 梯度下降法:随机梯度下降(SGD)、批量梯度下降(BGD)、小批量梯度下降(MBGD)。

优缺点

优点:
(1)训练速度较快,分类的时候,计算量仅仅只和特征的数目相关;
(2)简单易理解,模型的可解释性非常好,从特征的权重可以看到不同的特征对最后结果的影响;
(3)适合二分类问题,不需要缩放输入特征;
(4)内存资源占用小,因为只需要存储各个维度的特征值;

缺点:
(1)不能用Logistic回归去解决非线性问题,因为Logistic的决策面试线性的;
(2)对多重共线性数据较为敏感;
(3)很难处理数据不平衡的问题;
(4)准确率并不是很高,因为形式非常的简单(非常类似线性模型),很难去拟合数据的真实分布;
(5)逻辑回归本身无法筛选特征,有时会用gbdt来筛选特征,然后再上逻辑回归。

Python实现

LR_Train训练模型

# coding:UTF-8
# Author:xwj
# Date:2020-7-2
# Email:xwj770427414@126.com
# Environment:Python3.7
import numpy as np


def sig(x):
    """
    对数几率函数  Sigmoid函数
    :param x: feature * x + b
    :return:P(y=1|x,w,b)
    """
    return 1.0/(1+np.exp(-x))


def lr_train_bfd(feature, label, maxCycle, alpha):
    """
    利用梯度下降法训练LR模型
    :param feature:mat,特征 
    :param label: mar,标签
    :param maxCycle: int,最大迭代次数
    :param alpha: float,学习率
    :return: w,权重
    """
    n = np.shape(feature)[1]  # 特征的个数
    w = np.mat(np.ones((n, 1)))  # 初始化权重
    i = 0
    while i <= maxCycle:  # 在最大迭代次数内循环
        i += 1
        h = sig(feature * w)  # 计算Sigmoid的值
        err = label - h  # 误差
        if i % 100 == 0:  # 没迭代一百次进行一次
            print('\t--------迭代次数 = ' + str(i) + ',训练错误率 = ' + str(error_rate(h, label)) )
            w = w + alpha * feature.T * err  # 权重修正
    return w


def error_rate(h, label):
    """
    计算损失函数值
    :param h: mat,预测值
    :param label: mat,实际值
    :return: float,err/m错误率
    """
    m = np.shape(h)[0]   # 预测值的个数
    sum_err = 0.0  # 初始化错误率
    for i in range(m):   # m个预测值迭代
        if h[i, 0] > 0 and (1 - h[i, 0]) > 0:  # 预测值切片
            sum_err -= (label[i, 0] * np.log(h[i, 0]) + (1 - label[i, 0]) * np.log(1 - h[i, 0]))  # 损失函数公式计算
        else:
            sum_err -= 0
    return sum_err / m


def load_data(file_name):
    """
    清洗数据,导入数据
    :param file_name: 数据集名称
    :return: 矩阵形式的特征值和标签
    """
    f = open(file_name)
    feature_data = []  # 特征数据
    label_data = []  # 标签数据
    for line in f.readlines():  # 数据集逐行读取
        feature_tmp = []  # 暂存特征
        label_tmp = []  # 暂存标签
        lines = line.strip().split('\t')  # 去除数据收尾特殊符号(\n等),以\t为间隔,将数据分割成列表。
        feature_tmp.append(1)  # 初始偏置项b为1 合并至特征中
        for i in range(len(lines) - 1):  # 特征数据逐个读取,除去末尾的标签
            feature_tmp.append(float(lines[i]))  # 将特征逐个浮点数化并加入暂存特征,构成列表
        label_tmp.append(float(lines[-1]))  # 将标签加入暂存标签,构成列表
        feature_data.append(feature_tmp)  # 将暂存列表加入总列表
        label_data.append(label_tmp)  # 将暂存列表加入总列表
    f.close()
    return np.mat(feature_data), np.mat(label_data)  # 将特征序列、标签序列 矩阵化


def save_model(file_name, w):
    """
    保存最终模型的权重
    :param file_name:数据集名称
    :param w: 权重
    :return: 保存模型的文件
    """
    m = np.shape(w)[0]
    f_w = open(file_name, 'w')
    w_array = []
    for i in range(m):
        w_array.append(str(w[i, 0]))
    f_w.write('\t'.join(w_array))
    f_w.close()


if __name__ == "__main__":
    print('------1.导入数据------')
    feature, label = load_data("data.txt")
    print('------2.训练模型------')
    w = lr_train_bfd(feature, label, 1000, 0.01)
    print('------3.保存模型------')
    save_model("weights.txt", w)

测试模型

# coding:UTF-8
# Author:xwj
# Date:2020-7-2
# Email:xwj770427414@126.com
# Environment:Python3.7
import numpy as np


def sig(x):
    """
    对数几率函数  Sigmoid函数
    :param x: feature * x + b
    :return:P(y=1|x,w,b)
    """
    return 1.0/(1+np.exp(-x))


def load_weight(w):
    """
    导入LR训练模型
    :param w: w权重存储位置
    :return: np.mat(w),权重的矩阵
    """
    f = open(w)
    w = []
    for line in f.readlines():
        lines = line.strip().split('\t')
        w_tmp = []
        for x in lines:
            w_tmp.append(float(x))
        w.append(w_tmp)
    f.close()
    return np.mat(w)


def load_data(file_name, n):
    """
    导入测试数据
    :param file_name:测试数据位置
    :param n: 特征的个数
    :return: np.mat(feature)测试集的特征
    """
    f = open(file_name)
    feature_data = []
    for line in f.readlines():
        feature_tmp = []
        lines = line.strip().split('\t')
        if len(lines) != n - 1:
            continue
        feature_tmp.append(1)  # 初始偏置项b为1 合并至特征中
        for x in lines:
            feature_tmp.append(float(x))
        feature_data.append(feature_tmp)
    f.close()
    return np.mat(feature_data)


def predict(data, w):
    """
    对测试数据进行预测
    :param data: mat,模型的特征
    :param w: 模型的参数
    :return: h,mat,最终预测结果
    """
    h = sig(data * w.T)
    m = np.shape(h)[0]
    for i in range(m):
        if h[i, 0] < 0/5:
            h[1, 0] = 0.0
        else:
            h[i, 0] = 1.0
    return h


def save_result(file_name, result):
    """
    保存最终预测结果
    :param file_name: 预测结果保存文件名
    :param result: mat,预测的结果
    """
    m = np.shape(result)[0]
    tmp = []
    for i in range(m):
        tmp.append(str(h[i, 0]))
    f_result = open(file_name, "w")
    f_result.write("\t".join(tmp))
    f_result.close()


if __name__ == "__main__":
    print('------1.导入模型------')
    w = load_weight("weights.txt")
    n = np.shape(w)[1]
    print('------2.导入数据------')
    testData = load_data("test_data", n)
    print('------3.预测数据------')
    h = predict(testData, w)
    print('------4.保存结果------')
    save_result("result.txt", h)

数据集

  1. 训练数据集
  2. 测试数据集

本文地址:https://blog.csdn.net/weixin_46283583/article/details/107316386