吴恩达机器学习笔记复盘(六)梯度下降算法

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

简介

梯度下降(Gradient Descent)是一种常用的优化算法,广泛应用于机器学习、深度学习等领域,在这里是用于求J(w,b)局部最小值。

我自己觉得这样说有点过于抽象。换个直观点的说法就是,一个人站在了一座小土包上,这个人要去找周围的最低点,求这个局部最低点的数学过程,就是这个梯度下降算法。

基本原理

梯度下降的核心思想是基于函数的梯度信息来寻找函数的最小值。对于一个多元函数J(\theta),其中 \theta = (\theta_1, \theta_2, \cdots, \theta_n)是函数的参数向量,梯度 \nabla J(\theta)是一个向量,它的每个元素是函数J 对相应参数 \theta_i的偏导数 \frac{\partial J}{\partial \theta_i}

梯度的方向是函数在当前点上升最快的方向,那么负梯度方向就是函数下降最快的方向。算法通过不断地沿着负梯度方向更新参数,来逐步减小目标函数的值,直到达到一个局部最小值或全局最小值。

算法步骤

初始化参数

随机选择一个初始参数向量\theta^{(0)},它可以是一个随机的数值向量,也可以根据具体问题的先验知识进行初始化。

计算梯度

对于给定的参数\theta^{(t)}(t表示当前的迭代次数),计算目标函数J(\theta)在该点的梯度 \nabla J(\theta^{(t)})。这需要对目标函数进行求导,根据函数的具体形式使用相应的求导规则来计算每个参数的偏导数。

更新参数

根据计算得到的梯度,按照以下公式更新参数:\theta^{(t + 1)}=\theta^{(t)}-\alpha\nabla J(\theta^{(t)}),其中 \alpha 是学习率,它控制着每次更新的步长大小。学习率是一个重要的超参数,需要根据具体问题进行调整。

检查收敛条件

判断是否满足收敛条件,常见的收敛条件有:达到预设的最大迭代次数、目标函数的变化量小于某个阈值、参数的变化量小于某个阈值等。如果满足收敛条件,则停止迭代,输出当前的参数 \theta^{(t + 1)} 作为最优解;否则,返回步骤2继续迭代。

学习率的选择

学习率 \alpha决定了梯度下降算法的收敛速度和最终结果。如果学习率过大,可能会导致算法跳过最优解,甚至无法收敛;如果学习率过小,算法可能会收敛得非常缓慢,需要大量的迭代才能达到满意的结果。

为了选择合适的学习率,可以采用一些策略,如固定学习率、动态调整学习率(如随着迭代次数增加逐渐减小学习率)、使用自适应学习率算法(如Adagrad、Adadelta、RMSProp、Adam等,这些算法可以根据参数的更新情况自动调整学习率)。

梯度下降的变体

批量梯度下降(Batch Gradient Descent,BGD)

在每次更新参数时,使用整个训练数据集来计算梯度。优点是能够找到全局最优解的可能性较大,缺点是当训练数据集很大时,计算梯度的成本很高,导致训练速度慢。

随机梯度下降(Stochastic Gradient Descent,SGD)

每次更新参数时,随机选择一个训练样本,使用该样本的梯度来更新参数。优点是训练速度快,能够处理大规模数据集,缺点是由于每次只使用一个样本,梯度估计可能存在较大的噪声,导致收敛过程可能会有波动,不一定能准确地收敛到全局最优解。

小批量梯度下降(Mini - Batch Gradient Descent,MBGD)

结合了批量梯度下降和随机梯度下降的优点,每次更新参数时,使用一小部分训练样本(称为一个小批量)来计算梯度。小批量的大小通常在几十到几百之间。这种方法既能够利用小批量数据的统计信息来稳定梯度估计,又能够在一定程度上提高训练速度,是实际应用中最常用的梯度下降变体之一。

应用场景

梯度下降在机器学习和深度学习中有广泛的应用,例如在线性回归、逻辑回归、神经网络等模型的训练中,用于最小化损失函数,以找到最优的模型参数。通过不断地调整模型的参数,使得模型的预测结果与真实标签之间的差异最小化,从而提高模型的性能和泛化能力。在这里就是应用在J(w,b)函数上。

简单的代码示例

import numpy as np
import matplotlib.pyplot as plt


def gradient_descent(x, y, learning_rate, num_iterations):
    # 初始化参数
    m = 0  # 斜率
    b = 0  # 截距
    n = len(x)

    for iteration in range(num_iterations):
        # 计算预测值
        y_pred = m * x + b

        # 计算梯度
        dm = (-2 / n) * np.sum(x * (y - y_pred))
        db = (-2 / n) * np.sum(y - y_pred)

        # 更新参数
        m = m - learning_rate * dm
        b = b - learning_rate * db

    return m, b


# 生成一些示例数据
np.random.seed(0)
x = np.array([1, 2, 3, 4, 5])
y = np.array([5, 7, 9, 11, 13])

# 设置超参数
learning_rate = 0.01
num_iterations = 1000

# 运行梯度下降算法
m, b = gradient_descent(x, y, learning_rate, num_iterations)

# 输出结果
print(f"斜率 m: {m}")
print(f"截距 b: {b}")

# 绘制原始数据和拟合直线
plt.scatter(x, y, label='原始数据')
plt.plot(x, m * x + b, color='red', label='拟合直线')
plt.xlabel('x')
plt.ylabel('y')
plt.title('梯度下降线性回归')
plt.legend()
plt.show()
    

代码解释

gradient_descent` 函数

该函数实现了梯度下降算法的核心逻辑。它接受输入特征 `x`、目标值 `y`、学习率 `learning_rate` 和迭代次数 `num_iterations` 作为参数。在函数内部,首先初始化斜率 `m` 和截距 `b` 为 0,然后进行指定次数的迭代。在每次迭代中,计算预测值 `y_pred`,接着计算斜率和截距的梯度 `dm` 和 `db`,最后根据梯度更新斜率和截距。 (m对应w,b对应b)

示例数据生成

使用 `numpy` 生成了一些简单的示例数据 `x` 和 `y`,模拟线性关系。

设置超参数

设置学习率 `learning_rate` 为 0.01,迭代次数 `num_iterations` 为 1000。

运行梯度下降算法

调用 `gradient_descent` 函数,得到最优的斜率和截距。

输出结果和绘图

打印出最优的斜率和截距,并使用 `matplotlib` 绘制原始数据点和拟合直线,直观展示梯度下降算法的效果。