进阶Task1.2:《深度学习详解》(Datawhale X 李宏毅苹果书 AI夏令营)

前言 

文章概述《深度学习详解》- 3.2

书中探讨了深度学习中批量梯度下降法、随机梯度下降法以及动量法三种常用的优化算法。首先介绍了批量梯度下降法的基本原理,即通过大量数据的平均梯度来更新模型参数,从而实现参数的有效更新和模型性能的提升。然而,文中指出该方法在实际应用中面临的主要问题是计算成本较高,尤其是当数据集较大时。随机梯度下降法则通过每次仅使用单个样本来计算梯度并更新参数,显著降低了计算成本,但也引入了更多的噪声,可能导致模型在训练过程中震荡不定。针对这一问题,文章进一步讨论了动量法,通过引入历史梯度信息来调整当前的更新方向,有效地利用了梯度的正则化作用,有助于模型跳出局部最优解,加速训练进程。此外,文中还提到了自适应学习率的重要性,强调在训练的不同阶段,应根据模型表现动态调整学习率,以提高训练效率和模型性能。通过对这些优化算法的详细分析,文章旨在为读者提供一套有效的策略,用于解决深度学习模型训练中的常见问题,特别是在大数据背景下如何提高训练效率和模型泛化能力。


个人学习笔记以及概念梳理,望对大家有所帮助。


思维导图3.2

动量法(补充)

优点

缺点

加速收敛:通过利用梯度的历史信息,动量法可以帮助梯度下降更快地达到最小值。

选择合适的动量系数:如果动量系数设置得过高,可能会导致过冲现象,即梯度更新幅度过大,使得模型难以收敛。

避免震荡:在损失曲面中沿某些方向存在较大变化时,标准梯度下降可能会在这些方向上产生剧烈震荡。动量法通过平滑这些更新来减少这种震荡。

适应性问题:对于非凸问题,动量法可能不是最优的选择,因为它可能错过重要的局部极小值。

涉及的一些术语

术语

解释

批量(batch)

在训练过程中,将所有训练数据分成一系列的小组或批次。每个批次包含一定数量的数据样本。

批量大小(batch size, B)

每个批量中包含的数据样本的数量。

回合(epoch)

在训练过程中,模型遍历整个训练数据集一次的过程。

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

使用全部训练数据来计算梯度并更新参数的方法。

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

每次只使用一个数据样本来计算梯度并更新参数的方法。

小批量梯度下降法(Mini-batch Gradient Descent)

使用介于批量梯度下降法和随机梯度下降法之间的一个小批量数据来计算梯度并更新参数的方法。

损失(loss, L)

衡量模型预测输出与实际输出之间差异的函数。

海森矩阵(Hessian matrix)

二阶导数的矩阵形式,用于描述损失函数的曲率。

泛化能力(generalization)

模型在未见过的数据上的表现能力。

学习过程遇到的一些问题的理解:

1批量梯度下降与随机梯度下降的应用场合

首先,这两种方法的主要区别在于每次迭代时使用的样本数量不同。

批量梯度下降 (BGD)    整个训练集来计算梯度并更新参数
应用场合:

当数据集比较小且可以轻松放入内存时。

对于需要更精确解的情况,尤其是在数据集非常一致的情况下。

在对收敛速度要求不高但对最终模型精度要求较高的场景下。

随机梯度下降 (SGD)    一个样本(或一个小批量的样本)来估计梯度并更新参数

应用场合:

当数据集非常大时,批量梯度下降可能因为需要处理所有数据而导致计算成本过高。

对于实时更新模型参数的需求,例如在线学习场景。

在需要较快收敛速度的场景下,即使牺牲一定的最终精度。

当训练数据包含大量冗余信息时,不需要每个样本都能提供新的信息给模型。

2对于使用动量法,评估其逃离鞍点能力的几种指标

代码运行

为了验证动量法逃离鞍点的能力,我们可以构建一个具有明确鞍点特征的人工数据集。

这里,我们将创建一个简单的二维非凸函数,其中包含明显的鞍点,以便于观察和分析。

对应的临界点类型
鞍点 (1,0) (−1,0) (0,1) (0,−1)   局部最小点(1,1) (1,−1) (−1,1) (−1,−1)    局部最大点(0,0)

计算过程可见进阶Task1:《深度学习详解》(Datawhale X 李宏毅苹果书 AI夏令营)-CSDN博客

逃逸速度/成功率 动量参数

开始逃离鞍点的处理,以鞍点 (1,0)周边点为例,取100个均匀分布在其周边,距离为0.01*2^{1/2}

动量参数(取0,0.2,0.5,0.8) 来验证逃逸速度 逃逸成功率 分布的影响
 

import torch
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 定义目标函数
def func(x, y):
    return x ** 4 + y ** 4 - 2 * x ** 2 - 2 * y ** 2

# 使用PyTorch自动计算梯度
def grad_func(x, y):
    x = torch.tensor(x, requires_grad=True)
    y = torch.tensor(y, requires_grad=True)
    z = func(x, y)
    z.backward()
    return x.grad.item(), y.grad.item()

# 动量下降优化器
def momentum_optimizer(x, y, lr=0.1, momentum=0.9, epochs=100):
    velocity_x = 0
    velocity_y = 0

    for _ in range(epochs):
        # 计算梯度
        grad_x, grad_y = grad_func(x, y)

        # 更新速度
        velocity_x = momentum * velocity_x - lr * grad_x
        velocity_y = momentum * velocity_y - lr * grad_y

        # 更新位置
        x += velocity_x
        y += velocity_y

    return x.item(), y.item()

# 计算逃逸成功率和逃逸速度
def evaluate_escape_success(start_points, lr=0.1, momentum=0.9, epochs=100):
    successful_escapes = 0
    total_time = 0
    n_points = len(start_points)

    for point in start_points:
        x, y = point
        x, y = momentum_optimizer(torch.tensor(x), torch.tensor(y), lr, momentum, epochs)

        # 检查是否到达了局部最小点
        if abs(x) > 0.5 and abs(y) > 0.5:
            successful_escapes += 1
            total_time += epochs  # 这里假设所有点都用了完整的迭代次数来达到局部最小点

    success_rate = successful_escapes / n_points
    average_time = total_time / successful_escapes if successful_escapes > 0 else None

    return success_rate, average_time

# 创建 PyTorch 张量作为起始点
n_points = 100
distance = 0.01 * np.sqrt(2)  # 距离中心点 (1, 0) 的距离

# 生成随机角度
angles = np.random.uniform(low=0, high=2 * np.pi, size=n_points)

# 生成半径,这里我们使用正态分布,但确保半径在允许的范围内
radii = np.random.normal(loc=distance, scale=0.001, size=n_points)
radii = np.clip(radii, 0, distance * 1.5)  # 确保半径不会超出允许的范围

# 从极坐标转换到直角坐标系
x = 1 + radii * np.cos(angles)
y = radii * np.sin(angles)

start_points = np.column_stack((x, y))

# 定义要测试的不同动量参数
momentum_values = [0, 0.2, 0.5, 0.8]

# 对于每个动量参数,运行评估并打印结果
results = {}
for momentum in momentum_values:
    success_rate, average_time = evaluate_escape_success(start_points, momentum=momentum)
    results[momentum] = (success_rate, average_time)
    print(f"Momentum: {momentum:.1f}")
    print(f"Escape Success Rate: {success_rate:.2%}")
    print(f"Average Time to Escape: {average_time} epochs")
    print()

运行结果:

可见在这种情况下,几乎都是成功逃离,且平均时间为100.0 epochs

路径分析

对此,那我们就看看不同动量参数对应收敛路径分析效果,以其中1点(1.01,0.01)为例

代码如下

# 跟踪优化路径
def track_path(x, y, lr=0.1, momentum=0.9, epochs=100):
    path = [(x.item(), y.item())]

    velocity_x = 0
    velocity_y = 0

    for epoch in range(epochs):
        # 计算梯度
        grad_x, grad_y = grad_func(x, y)

        # 更新速度
        velocity_x = momentum * velocity_x - lr * grad_x
        velocity_y = momentum * velocity_y - lr * grad_y

        # 更新位置
        x += velocity_x
        y += velocity_y

        # 添加当前位置到路径列表
        path.append((x.item(), y.item()))

    return path

# 起始点
start_point = (1.01, 0.01)

# 对于每个动量参数,跟踪路径
paths = {}
for momentum in momentum_values:
    path = track_path(torch.tensor(start_point[0]), torch.tensor(start_point[1]), momentum=momentum)
    paths[momentum] = path

# 绘制路径
fig, axs = plt.subplots(2, 2, figsize=(12, 10))

# 绘制目标函数等高线
x = np.linspace(0, 2, 400)
y = np.linspace(0, 2, 400)
X, Y = np.meshgrid(x, y)
Z = func(X, Y)

# 绘制路径
for i, (momentum, ax) in enumerate(zip(momentum_values, axs.flatten())):
    # 绘制等高线
    contour = ax.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5)
    ax.clabel(contour, inline=True, fontsize=8)

    # 绘制路径
    Xp, Yp = zip(*paths[momentum])
    ax.plot(Xp, Yp, label=f'Momentum: {momentum:.1f}', color='red')

    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_xlim(0, 2)
    ax.set_ylim(0, 2)
    ax.legend()
    ax.set_title(f'Momentum = {momentum:.1f}')

plt.tight_layout()
plt.show()

结果如下


可见还是有细微的路径差别的,对于Momentum=0.6 或 0.8 时,都有一点返回路径的行为,可能是由于动量参数过大导致的。这也就说明,当使用动量法时,我们要适当注意动量参数的选择,以达到预期的效果。


小结

批量梯度下降法 (BGD)
  • 定义: 使用整个训练集来计算梯度并更新模型参数。
  • 优点:
    • 参数更新较为稳定。
    • 在每一步更新中可以获得全局梯度的方向。
  • 缺点:
    • 需要大量的计算资源。
    • 当数据集很大时,计算一次梯度非常耗时。
随机梯度下降法 (SGD)
  • 定义: 每次更新只使用一个样本(或一个小批量样本)来计算梯度。
  • 优点:
    • 计算速度快。
    • 可以帮助模型跳出局部最小值。
  • 缺点:
    • 更新不稳定,容易在损失曲面上震荡。
    • 收敛速度慢,需要更多迭代才能达到较优解。
动量法 (Momentum)
  • 定义: 引入历史梯度信息来调整当前梯度方向,减少震荡,加速收敛。
  • 优点:
    • 减少在陡峭山谷中的震荡。
    • 加速收敛过程。
  • 缺点:
    • 动量参数选择不当可能导致过冲。
    • 对于复杂的损失曲面,可能错过重要的局部极小值。
实验结果
  • 动量参数: 通过实验发现不同的动量参数对逃离鞍点的能力有所影响。
  • 得出: 动量参数选择非常重要,过大可能导致过冲现象,而适当的动量可以有效地帮助模型逃离鞍点并加速收敛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值