机器学习之逻辑回归(Logistic Regression)

一、逻辑回归基本介绍

        逻辑回归是一种用于解决分类问题的统计学习方法,尽管其名称包含 “回归”,但实际用于处理因变量为二分类或多分类的场景(最常见的是二分类问题,如 “是 / 否”“0/1”)。它通过构建模型来预测样本属于某个类别的概率,进而实现分类

 1.1 核心原理

        1.1.1. 线性回归的延伸

        逻辑回归基于线性回归模型:z = \theta _{0}x_{0} + \theta _1{}x_{1} + \theta _2{}x_{2} + ... + \theta _n{}x_{n},也可写成  z = \theta ^{T}x,通过逻辑函数(Sigmoid函数)将线性输出映射到概率值[0,1]之间。

        Sigmoid函数:y = \sigma (z) = \frac{1}{1 + e^{-z}}

        函数图像呈“S”型,当z趋近于正无穷时,σ(z)趋近于1;当z趋近于负无穷时,σ(z)趋近于0。

        1.1.2.概率与分类决策

        对于二分类问题(如正类“1”和负类“0”),模型输出样本属于正类的概率P(y=1|x) = σ(z),属于负类的概率为P(y=0|x) = 1 - g(z)。

        分类阈值:通常设定阈值为0.5,若P(y=1|x) ≥ 0.5,则预测为正类,否则为负类。

1.2 数学模型与参数估计

        1.2.1 二分类逻辑回归模型

        设样本特征为 x = (x1,x2,...,xn),参数为 θ = (θ1,θ2,...,θn),则有:

 P(y = 1 | x;\theta ) = \frac{1}{1 + e^{\theta ^{T}x}} ,P(y = 0 | x;\theta ) = 1 - \frac{1}{1 + e^{\theta ^{T}x}}
合并表示为:P(y | x;\theta ) = (\frac{1}{1 + e^{-\theta ^{T}x}})^{y} (1-\frac{1}{1 + e^{-\theta ^{T}x}})^{1-y}

        1.2.2. 参数估计:极大似然估计(MLE) 

        通过最大化样本的似然函数来求解参数θ。对数似然函数为:

        通常使用梯度上升法或其优化变体(如牛顿法、拟牛顿法)求解最优参数。

1.3 适用场景

        二分类问题:医学诊断(如是否患病)、金融风控(如是否违约)、垃圾邮件分类等。

        多分类问题:可通过“一对多”(One-vs-Rest)或“多分类逻辑回归”(Softmax回归)扩展到多类别场景(如手写数字识别)。

1.4 与线性回归的区别

                                逻辑回归                                 线性回归
用于分类问题用于回归问题
因变量为离散型(如 0/1)因变量为连续型(如房价、温度)
通过 Sigmoid 函数映射到概率直接输出连续值
损失函数为交叉熵损失,也称为对数损失(Log Loss)损失函数为均方误差(MSE)
可以用梯度上升法直接最大化对数似然函数,但通常选择用梯度下降法最小化交叉熵损失用梯度下降法最小化损失函数

二、逻辑回归的优化目标

2.1 损失函数

        损失函数(Loss Function)是机器学习中用于衡量模型预测结果与真实标签之间差异的函数,本质上是对 “预测错误程度” 的量化。它是模型优化的核心目标,直接决定了模型训练的方向(如最小化损失或最大化收益)。

核心作用:

1. 量化误差:将预测值与真实值的差异转化为具体数值,便于数学优化。

例如:真实标签 y = 1,模型预测 y = 0.8,损失函数计算两者的差异(如交叉熵为-log(0.8) ≈ 0.223)。

2. 指导模型学习:通过损失函数的梯度(导数)反向传播,调整模型参数,使损失逐渐降低。

3. 评估模型性能:不同损失函数反映不同的优化目标(如回归注重数值误差,分类注重概率准确性)。

2.2 均方误差

        线性回归最常用的损失函数为均方误差(MSE),定义为:

        

其中: 

 h_{\theta }(x) = \theta ^{T}x = \theta _{0}x_{0} + \theta _1{}x_{1} + \theta _2{}x_{2} + ... + \theta _n{}x_{n} 是模型预测值;

 y^{(i)} 是第 i 个样本的真实值;

 m 是样本数量;

 θ 是模型参数(权重和偏置)。

        线性回归之所以选择均方误差,是因为: 

        1.MSE是关于参数 θ 的凸函数,保证了全局最优解的存在性;

        2.若误差项服从高斯分布,MSE等价于极大似然估计(MLE);

        3.计算梯度时导数形式简洁,便于优化。

        MSE关于参数 \theta _{j} 的梯度为:

2.3 交叉熵

        在逻辑回归中,模型通过最大化训练数据的似然函数来估计参数。由于直接最大化似然函数在数学上不方便处理,通常会最小化负的对数似然函数,也称为交叉熵损失。

        对于二分类问题(标签 y ∈ {0,1} ),逻辑回归通过Sigmoid函数将线性输出转换为概率:

        单个样本的交叉熵损失为:

  • 当真实标签 y = 1 时,损失为 -log\widehat{y},若模型预测概率 \widehat{y}接近 1,损失趋近于 0;若 \widehat{y}接近 0,损失趋向无穷大;
  • 当真实标签 y = 0 时,损失为 -log(1 - \widehat{y} ),若模型预测概率 \widehat{y}接近 0,损失趋近于 0;若 \widehat{y} 接近 1,损失趋向无穷大。

        整体的交叉熵损失函数为(m个样本的平均):

        极大似然估计的目标是最大化 L(θ),而交叉熵损失函数 J(θ) = -L(θ)/m 正是对数似然的负值取平均,因此最小化交叉熵等价于最大化对数似然

        逻辑回归之所以选择交叉熵,是因为:

        1. 交叉熵损失是关于参数 θ 的凸函数,保证了全局最优解的存在性;而 MSE 对于Sigmoid 函数是非凸的,存在多个局部最优解,梯度下降可能陷入局部极小值;

        2. 梯度形式简洁,便于高效计算:

        3. 交叉熵对错误预测的惩罚是指数级的,从而迫使模型对 “确信的错误” 进行更大幅度的参数调整。

三、优化算法

3.1 梯度下降法

        梯度下降(Gradient Descent)是一种优化算法,用于寻找函数的局部最小值。在机器学习中,它是训练模型(如线性回归、逻辑回归、神经网络)最常用的优化方法之一,通过迭代更新模型参数来最小化损失函数。

        3.1.1 核心思想与数学原理

        梯度下降的基本思想可以用 “下山” 来比喻:

        假设你站在一座山上,想要最快到达山脚(最小值点),每一步,你选择当前位置下降最快的方向(即梯度的反方向)前进一小步,重复这个过程,直到无法继续下降(接近最小值点)。

        数学原理:
        对于函数 J(θ),其在点 θ 处的梯度 ▽J(θ) 指向函数值增长最快的方向。因此,梯度的反方向就是函数值下降最快的方向。

        3.1.2 数学公式与迭代过程

        梯度下降的参数更新公式为:θ = θ - α * ▽J(θ)

其中:

θ 是模型参数(如线性回归中的权重和偏置);

α 是学习率(Learning Rate),控制每次更新的步长;

▽J(θ) 是损失函数 J(θ) 关于参数 θ 的梯度。

        迭代过程: 

        1. 初始化参数 θ (通常为随机值或全零);

        2.计算当前参数下的梯度 ▽J(θ) ;

        3.沿梯度反方向更新参数:θ ← θ - α * ▽J(θ) ;

        4.重复步骤2-3直到满足收敛条件(如梯度接近零、损失变化小于阈值、达到最大迭代次数)。

        3.1.3 学习率的影响

        学习率 α 是梯度下降的关键超参数,其选择直接影响算法的收敛性:

        学习率过大:参数更新步长过大,可能导致跳过最小值点,甚至发散(损失函数值不断增大);

        学习率过小:参数更新步长过小,收敛速度极慢,需要更多迭代才能达到最小值。

        3.1.4 应用场景与局限性

        适用场景:

        损失函数可导:梯度下降依赖于计算梯度,因此要求损失函数可微;

        大规模优化问题:尤其适用于参数众多的模型(如神经网络);

        局限性:

        对于非凸函数,可能陷入局部最小值而非全局最优;

        在高维空间中,梯度为零的鞍点可能导致算法停滞;

        在深度神经网络中,梯度可能变得极小或极大,导致训练困难。

3.2 梯度上升法

        梯度上升法(Gradient Ascent)是一种优化算法,用于寻找函数的局部最大值。也是训练模型(如极大似然估计、强化学习(策略梯度))的常用优化方法,通过迭代更新模型参数来最大化目标函数。

        3.2.1 核心思想与数学原理

        梯度上升的核心思想可以用 “爬山” 来比喻:

        假设你站在一座山上,想要最快到达山顶(最大值点),每一步,你选择当前位置上升最快的方向(即梯度方向)前进一小步,重复这个过程,直到无法继续上升(接近山顶)。

        数学原理:
        对于目标函数 f(θ),其在点 θ 处的梯度 ▽f(θ) 指向函数值增长最快的方向。因此,梯度方向就是函数值上升最快的方向。

        3.2.2 数学公式与迭代过程

        梯度上升的参数更新公式为:θ = θ + α * ▽f(θ)

        迭代过程:

        1. 初始化参数 θ (通常为随机值或全零);

        2.计算当前参数下的梯度 ▽f(θ) ;

        3.沿梯度反方向更新参数:θ ← θ + α * ▽f(θ) ;

        4.重复步骤2-3直到满足收敛条件(如梯度接近零、损失变化小于阈值、达到最大迭代次数)。

        3.2.3 学习率的影响

        学习率过大:参数更新步长过大,会导致参数震荡或发散;

        学习率过小:参数更新步长过小,会导致收敛缓慢。

        3.2.4 应用场景与局限性

        适用场景:

        极大似然估计(MLE):最大化对数似然函数估计模型参数,如逻辑回归、高斯混合模型;

        强化学习(策略梯度):最大化累积奖励函数,优化策略网络参数;

        对抗生成网络(GANs):判别器网络通过梯度上升最大化判别准确率;

        局限性:

        对于非凸函数,可能陷入局部最大值而非全局最优;

        对于复杂函数,梯度可能在某些区域变得非常大或非常小,需进行梯度缩放或归一化。

四、示例:利用给定数据集完成逻辑回归

        4.1 数据加载与预处理

        给定数据集:

        从文件加载数据集,提取特征矩阵 X 和标签向量 y。文件为制表符分隔的文本,共包含100个样例,文本前两列为特征值,最后一列是标签(0/1),即所属类别。

        4.2 自定义逻辑回归实现

        1. 初始化参数

        学习率:控制梯度下降时参数更新的步长,自定义设置(我将其设置为0.1);

        最大迭代次数:自定义设置(我设置为10000),防止算法无限循环。

        收敛阈值:自定义设置(我设置为1e-4),当梯度的范数小于设置值时,认为算法已收敛。

        参数向量:存储模型的权重和偏置,初始化为 None。

        2. 调用sigmoid函数,将线性输出转换为概率值(0-1之间)

        3.模型训练

        添加偏置项:将输入特征矩阵X扩展为X_b,在第一列插入全 1 向量,对应偏置参数\theta _{0}

        线性组合与概率转换:z = \theta _{0}x_{0} + \theta _1{}x_{1} + \theta _2{}x_{2} + ... + \theta _n{}x_{n},h = σ(z)得到预测概率;

        梯度计算:利用numpy库里的dot函数计算梯度(向量化实现),再用梯度下降法更新参数。

        4.预测概率

        添加偏置项,计算线性组合 z = \theta ^{T}X_{b},通过 Sigmoid 函数转换为概率。

        5.类别预测

        根据预测概率和阈值将样本分类为 0 或 1,例如:若 prob = 0.65,则prob ≥ 0.5,为True,转换为整数1

        4.3 可视化数据集与决策边界

        使用 meshgrid生成网格点,覆盖特征空间,通过 predict_prob计算每个网格点的预测概率,使用 contour绘制概率为 0.5 的等高线(即决策边界),使用 contourf填充不同概率区域,增强可视化效果。

        4.4 模型训练对比

        调用前面的自定义逻辑回归,用给定数据集训练模型,并存储模型的参数(包括偏置项和特征权重),再使用 scikit-learn 库中的 LogisticRegression类训练模型,存储模型的参数,作为对比基准,将参数对比输出,验证自定义逻辑回归的正确性。

        4.5 代码实现

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

#加载数据集
def load_data(file_path):
    data = np.loadtxt(file_path, delimiter='\t')
    X = data[:, :-1]             #特征
    y = data[:, -1].astype(int)  #标签转为整数
    return X, y
X, y = load_data('testSet(logistic).txt')
print("数据集大小:", X.shape[0], "样本")

#自定义逻辑回归类
class LogisticRegressionCustom:
    def __init__(self, learning_rate=0.1, max_iter=10000, tol=1e-4):
        self.learning_rate = learning_rate
        self.max_iter = max_iter
        self.tol = tol
        self.theta = None
    def sigmoid(self, z):
        return 1 / (1 + np.exp(-z))
    def fit(self, X, y):
        m, n = X.shape
        X_b = np.c_[np.ones((m, 1)), X]
        self.theta = np.zeros(n + 1)
        for iter in range(self.max_iter):
            z = np.dot(X_b, self.theta)
            h = self.sigmoid(z)
            gradient = np.dot(X_b.T, (h - y)) / m
            self.theta -= self.learning_rate * gradient
            if np.linalg.norm(gradient) < self.tol:
                print(f"迭代 {iter + 1} 收敛")
                break
        print(f"训练完成,迭代次数: {iter + 1}")
    def predict_prob(self, X):
        X_b = np.c_[np.ones((X.shape[0], 1)), X]
        return self.sigmoid(np.dot(X_b, self.theta))
    def predict(self, X, threshold=0.5):
        prob = self.predict_prob(X)
        return (prob >= threshold).astype(int)
    
#数据可视化及决策边界绘制
def plot_data_with_boundary(X, y, model):
    plt.figure(figsize=(10, 6))
    #绘制类别分布
    scatter_0 = plt.scatter(X[y == 0, 0], X[y == 0, 1], color='red', marker='o', label='类别0')
    scatter_1 = plt.scatter(X[y == 1, 0], X[y == 1, 1], color='green', marker='s', label='类别1')
    #生成网格点并绘制决策边界
    x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np.linspace(y_min, y_max, 100))
    #预测网格点概率并绘制阈值边界
    Z = model.predict_prob(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    #绘制概率等高线(阈值0.5)
    plt.contour(xx, yy, Z, levels=[0.5], colors='black', linewidths=2, linestyles='--')
    #填充概率区域
    plt.contourf(xx, yy, Z, levels=[0, 0.5, 1], colors=['lightcoral', 'lightblue'], alpha=0.3)
    plt.xlabel('特征1')
    plt.ylabel('特征2')
    #手动构建handles来添加图例
    handles = [scatter_0, scatter_1, plt.Line2D([], [], color='black', linestyle='--', label='Decision Boundary')]
    plt.legend(handles=handles)
    plt.title('类别分布与决策边界(阈值=0.5)')
    plt.grid(True)
    plt.show()

#训练模型
model = LogisticRegressionCustom(learning_rate=0.1, max_iter=10000)
model.fit(X, y)

#绘制合并图形
plot_data_with_boundary(X, y, model)

#对比scikit-learn模型
model_sk = LogisticRegression(max_iter=10000)
model_sk.fit(X, y)
print("\n自定义模型参数:", model.theta)
print("scikit-learn模型参数:", np.r_[model_sk.intercept_, model_sk.coef_[0]])

运行测试结果截图:

ps:更改学习率和迭代次数,模型参数值都会发生变化。

五、实验小结

        优点:①计算高效:逻辑回归的训练和预测速度都非常快,因为只需要进行线性计算和 Sigmoid 转换,复杂度为 O(n);②可解释性强:逻辑回归的权重直接对应每个特征的重要性,正负号表示特征与类别之间的正相关或负相关关系;③不容易过拟合:通过正则化,可以有效防止过拟合,提高模型的泛化能力。

        缺点:①对异常值敏感:由于使用对数损失函数,异常值可能对模型参数产生较大影响,需要进行数据预处理;②容易欠拟合,分类精度可能不高;

        逻辑回归通过可视化权重,可以直观地看出哪些特征对预测最为重要,这在某些实际应用中非常重要(例如医学诊断);如果数据集中存在复杂的非线性关系,逻辑回归的表现会明显下降,此时应考虑使用非线性模型;可以尝试不同的学习率和迭代次数,以找到最优的训练参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值