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

原理

基本原理

逻辑(Logistic)回归原理及Python实现(含数据集)_第1张图片
逻辑(Logistic)回归原理及Python实现(含数据集)_第2张图片
逻辑(Logistic)回归原理及Python实现(含数据集)_第3张图片

损失函数的求解方法

  • 二元逻辑回归的损失函数(极大似然函数)极小化的求解,有比较多的方法,最常见的有梯度下降法,坐标轴下降法,等牛顿法等,最常用的是梯度下降来不断逼近最优解。
  • 梯度下降法:随机梯度下降(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:[email protected]
# 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:[email protected]
# 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. 测试数据集

你可能感兴趣的:(机器学习,python,机器学习,逻辑回归)