吴恩达机器学习笔记复盘(十二)逻辑回归的梯度下降和拟合问题

发布于:2025-03-30 ⋅ 阅读:(23) ⋅ 点赞:(0)

梯度下降算法推导过程

一、逻辑回归模型基础 

逻辑回归用于二分类问题,其假设函数为sigmoid函数

h_{\theta}(x) = \sigma(\theta^T x) = \frac{1}{1 + e^{-\theta^T x}}

其中,\theta是模型参数向量,x是特征向量。输出h_{\theta}(x)表示样本x属于正类的概率。

二、损失函数

 逻辑回归的损失函数采用 对数损失(交叉熵损失)

J(\theta) = -\frac{1}{m} \sum_{i=1}^m \left[ y^{(i)} \log h_{\theta}(x^{(i)}) + (1 - y^{(i)}) \log (1 - h_{\theta}(x^{(i)})) \right]

- m:样本数量

- y^{(i)} \in \{0,1\}:样本真实标签

- h_{\theta}(x^{(i)}):模型预测概率

三、梯度下降算法推导

梯度下降的目标是通过迭代更新参数\theta,使损失函数J(\theta)最小化。更新规则为:

\theta_j := \theta_j - \alpha \frac{\partial J(\theta)}{\partial \theta_j}  (对每个特征$j$)

其中,\alpha是学习率。

1. 计算梯度 

J(\theta)求偏导:

**推导过程**:

1. 对单个样本的损失项求导:

\frac{\partial J(\theta)}{\partial \theta_j} = \frac{1}{m} \sum_{i=1}^m \left( h_{\theta}(x^{(i)}) - y^{(i)} \right) x_j^{(i)}

\frac{\partial}{\partial \theta_j} \left[ -y \log h + (1 - y) \log (1 - h) \right] = \frac{y}{h} \cdot \frac{\partial h}{\partial \theta_j} - \frac{1 - y}{1 - h} \cdot \frac{\partial h}{\partial \theta_j}

2. 代入sigmoid函数导数

\frac{\partial h}{\partial \theta_j} = h(1 - h) x_j

化简后得到:

单个样本损失 \frac{\partial}{\partial \theta_j} = (h - y) x_j 

3. 对所有样本取平均,得到梯度。

2. 参数更新规则

 结合梯度和学习率,参数更新公式为:

\theta_j = \theta_j - \alpha \cdot \frac{1}{m} \sum_{i=1}^m \left( h_{\theta}(x^{(i)}) - y^{(i)} \right) x_j^{(i)}

四、梯度下降的变种简介

1. 批量梯度下降(BGD)

 - 使用全部样本计算梯度 - 优点:收敛稳定 - 缺点:计算量大,内存占用高

2. 随机梯度下降(SGD)

 - 每次随机选取一个样本更新参数

- 优点:计算速度快

- 缺点:梯度波动大,可能无法收敛到全局最优

3. 小批量梯度下降(Mini-Batch GD)

 - 每次使用一小批样本(如32-256个)

- 平衡计算效率和收敛稳定性

五、关键细节

 1. 学习率\alpha的选择

 - 过大:可能跳过最优解,导致发散

- 过小:收敛速度慢,易陷入局部最优

2. 特征缩放

 - 对特征进行标准化(如Z-score),避免梯度下降震荡,加快收敛。

3. 收敛判断

 - 当损失函数变化小于阈值(如10^{-5})时,停止迭代。

六、简单示例代码

import numpy as np


def sigmoid(z):
    """
    计算 sigmoid 函数的值
    :param z: 输入值
    :return: sigmoid 函数的输出
    """
    return 1 / (1 + np.exp(-z))


def cost_function(X, y, theta):
    """
    计算逻辑回归的代价函数
    :param X: 特征矩阵
    :param y: 标签向量
    :param theta: 参数向量
    :return: 代价函数的值
    """
    m = len(y)
    h = sigmoid(np.dot(X, theta))
    cost = (-1 / m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
    return cost


def gradient_descent(X, y, theta, alpha, num_iters):
    """
    执行梯度下降算法来更新参数
    :param X: 特征矩阵
    :param y: 标签向量
    :param theta: 参数向量
    :param alpha: 学习率
    :param num_iters: 迭代次数
    :return: 更新后的参数向量和每次迭代的代价
    """
    m = len(y)
    J_history = []

    for iter in range(num_iters):
        h = sigmoid(np.dot(X, theta))
        theta = theta - (alpha / m) * np.dot(X.T, (h - y))
        J_history.append(cost_function(X, y, theta))

    return theta, J_history


# 示例数据
np.random.seed(0)
X = np.random.randn(100, 2)
X = np.c_[np.ones((X.shape[0], 1)), X]
y = np.random.randint(0, 2, 100)

# 初始化参数
theta = np.zeros(X.shape[1])

# 设置超参数
alpha = 0.01
num_iters = 1000

# 执行梯度下降
theta, J_history = gradient_descent(X, y, theta, alpha, num_iters)

print("最终参数 theta:", theta)    

七、总结

 逻辑回归的梯度下降通过最小化对数损失函数,迭代调整参数,使模型预测概率与真实标签尽可能接近。其核心是梯度的计算和参数更新规则,变种算法则根据数据规模和计算资源选择。

欠拟合和过拟合问题的原理

过拟合(Overfitting)

  • 现象:模型把训练数据学 “过头” 了,记住了所有细节甚至噪声
  • 表现:在训练集上准确率很高,但遇到新数据时表现大幅下降
  • 类比:学生考试只背答案,遇到变形题就不会做
  • 常见原因
    • 模型过于复杂(如深层神经网络)
    • 训练数据量不足
    • 特征过多但无实际关联
  • 解决方法
    • 添加正则化(如 L1/L2 正则)
    • 增加训练数据
    • 使用交叉验证
    • 早停法(训练时监控验证集效果)

欠拟合(Underfitting)

  • 现象:模型没有充分捕捉数据中的规律
  • 表现:在训练集上表现就很差
  • 类比:学生完全没复习,考试连基础题都不会
  • 常见原因
    • 模型过于简单(如线性模型处理非线性问题)
    • 特征工程不足
    • 训练数据存在严重偏差
  • 解决方法
    • 增加模型复杂度(如使用多项式特征)
    • 进行更深入的特征工程
    • 调整超参数(如增加决策树深度)

对比表格

维度 过拟合 欠拟合
训练误差
测试误差
模型复杂度
偏差
方差

现实中的例子

  • 过拟合:用深度神经网络拟合 20 个数据点,模型会记住每个数据点的噪声
  • 欠拟合:用线性回归拟合正弦曲线数据,模型无法捕捉周期性变化

解决过拟合的三大方法

  1. 增加训练数据

    • 原理:更多数据能帮助模型学习普遍规律,减少对噪声的过度拟合。
    • 局限:实际场景中可能无法获取更多数据。
  2. 特征选择(减少特征数量)

    • 操作:选择最相关的特征子集(如仅用房屋大小、卧室数量预测房价)。
    • 缺点:可能丢失有用信息,且需人工判断特征相关性。
  3. 正则化(核心方法)

    • 原理:通过惩罚参数大小(如 L2 正则化),限制特征的影响,避免模型过于复杂。
    • 优势:保留所有特征但抑制其权重,平衡模型复杂度与泛化能力。
    • 注意点:通常仅正则化权重参数(W),偏差参数(B)可不处理。

实验与直观理解

  • 互动实验:允许用户调整多项式次数、添加数据点,观察过拟合现象及不同方法的效果。
  • 实验目的:通过可视化操作,帮助建立对过拟合和正则化的直觉理解。

笔者注:判断模型处于哪种状态,可以通过绘制学习曲线(训练集和验证集误差随训练轮数变化的曲线)来观察。理想状态是找到偏差 - 方差的平衡点,使模型既有足够的拟合能力,又具备良好的泛化性能。