【从零开始学习深度学习】38. Pytorch实战案例:梯度下降、随机梯度下降、小批量随机梯度下降3种优化算法对比【含数据集与源码】

简介: 【从零开始学习深度学习】38. Pytorch实战案例:梯度下降、随机梯度下降、小批量随机梯度下降3种优化算法对比【含数据集与源码】

1. 梯度下降、随机梯度下降、小批量随机梯度下降区别

梯度下降:在每一次迭代中,梯度下降使用整个训练数据集来计算梯度,一个epoch周期内参数只更新一次。

随机梯度下降:在每次迭代中,只随机采样一个样本来计算梯度,一个epoch周期内会进行样本数目次参数更新。

小批量随机梯度下降:在每次迭代中随机均匀采样多个样本来组成一个小批量来计算梯度,一个epoch周期内会进行(样本数目/批量大小)次的参数更新。

2. 读取训练数据

获取数据集方法,关注GZH:阿旭算法与机器学习,回复“梯度下降”即可。

该数据集为NASA的测试不同飞机机翼噪音的数据集,数据集一共包含1503个样本,每个样本包含5个特征与1个标签,下面我们将使用该数据集的前1,500个样本进行模型的训练,并比较各个优化算法的区别。

数据集展示:

%matplotlib inline
import numpy as np
import time
import torch
from torch import nn, optim
import sys
import d2lzh_pytorch as d2l
def get_data_ch7():  
    data = np.genfromtxt('./data/airfoil_self_noise.dat', delimiter='\t')
    # 标准化数据
    data = (data - data.mean(axis=0)) / data.std(axis=0)
    return torch.tensor(data[:1500, :-1], dtype=torch.float32), \
    torch.tensor(data[:1500, -1], dtype=torch.float32) # 前1500个样本(每个样本包含5个特征)
features, labels = get_data_ch7()
features.shape # torch.Size([1500, 5])

3. 从零实现3种梯度算法并进行训练

下面实现一个通用的训练函数,它初始化一个线性回归模型,然后可以使用梯度下降、随机梯度下降和小批量随机梯度下降算法来训练模型。

# 参数优化器
def sgd(params, states, hyperparams):
    for p in params:
        p.data -= hyperparams['lr'] * p.grad.data
# 训练函数        
def train_ch7(optimizer_fn, states, hyperparams, features, labels,
              batch_size=10, num_epochs=2):
    # 初始化模型,初始化一个线性回归模型
    net, loss = d2l.linreg, d2l.squared_loss
    
    w = torch.nn.Parameter(torch.tensor(np.random.normal(0, 0.01, size=(features.shape[1], 1)), dtype=torch.float32),
                           requires_grad=True)
    b = torch.nn.Parameter(torch.zeros(1, dtype=torch.float32), requires_grad=True)
    def eval_loss():
        return loss(net(features, w, b), labels).mean().item()
    ls = [eval_loss()]
    data_iter = torch.utils.data.DataLoader(
        torch.utils.data.TensorDataset(features, labels), batch_size, shuffle=True)
    
    for _ in range(num_epochs):
        start = time.time()
        for batch_i, (X, y) in enumerate(data_iter):
            l = loss(net(X, w, b), y).mean()  # 使用平均损失
            
            # 梯度清零
            if w.grad is not None:
                w.grad.data.zero_()
                b.grad.data.zero_()
                
            l.backward()
            optimizer_fn([w, b], states, hyperparams)  # 迭代模型参数
            if (batch_i + 1) * batch_size % 100 == 0:
                ls.append(eval_loss())  # 每100个样本记录下当前训练误差
    # 打印结果和作图
    print('loss: %f, %f sec per epoch' % (ls[-1], time.time() - start))
    d2l.set_figsize()
    d2l.plt.plot(np.linspace(0, num_epochs, len(ls)), ls)
    d2l.plt.xlabel('epoch')
    d2l.plt.ylabel('loss')

3.1 梯度下降训练结果

当批量大小为样本总数1,500时,使用的是梯度下降。梯度下降的1个迭代周期对模型参数只迭代1次。可以看到6次迭代后目标函数值(训练损失)的下降趋向了平稳。

def train_sgd(lr, batch_size, num_epochs=2):
    train_ch7(sgd, None, {'lr': lr}, features, labels, batch_size, num_epochs)
train_sgd(1, 1500, 6)

输出:

loss: 0.245426, 0.013536 sec per epoch

3.2 随机梯度下降将结果

当批量大小为1时,优化使用的是随机梯度下降。随机梯度下降中,每处理一个样本会更新一次自变量(模型参数),一个迭代周期里会对自变量进行1,500次更新。可以看到,目标函数值的下降在1个迭代周期后就变得较为平缓。

train_sgd(0.005, 1)

输出:

loss: 0.246051, 0.531435 sec per epoch

虽然随机梯度下降和梯度下降在一个迭代周期里都处理了1,500个样本,但实验中随机梯度下降的一个迭代周期耗时更多。这是因为随机梯度下降在一个迭代周期里做了更多次的自变量迭代,而且单样本的梯度计算难以有效利用矢量计算。

3.3 小批量随机梯度下降结果

当批量大小为10时,优化使用的是小批量随机梯度下降。它在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。

train_sgd(0.05, 10)

输出:

loss: 0.242805, 0.078792 sec per epoch

4 .使用Pytorch的optim.SGD实现梯度下降优化算法

在PyTorch里可以直接通过创建optimizer实例来调用优化算法。这能让实现更简洁。下面实现一个通用的训练函数,它通过优化算法的函数optimizer_fn和超参数optimizer_hyperparams来创建optimizer实例。

def train_pytorch_ch7(optimizer_fn, optimizer_hyperparams, features, labels,
                    batch_size=10, num_epochs=2):
    # 初始化模型
    net = nn.Sequential(
        nn.Linear(features.shape[-1], 1)
    )
    loss = nn.MSELoss()
    optimizer = optimizer_fn(net.parameters(), **optimizer_hyperparams)
    def eval_loss():
        return loss(net(features).view(-1), labels).item() / 2
    ls = [eval_loss()]
    data_iter = torch.utils.data.DataLoader(
        torch.utils.data.TensorDataset(features, labels), batch_size, shuffle=True)
    for _ in range(num_epochs):
        start = time.time()
        for batch_i, (X, y) in enumerate(data_iter):
            # 除以2是为了和train_ch7保持一致, 因为squared_loss中除了2
            l = loss(net(X).view(-1), y) / 2 
            
            optimizer.zero_grad()
            l.backward()
            optimizer.step()
            if (batch_i + 1) * batch_size % 100 == 0:
                ls.append(eval_loss())
    # 打印结果和作图
    print('loss: %f, %f sec per epoch' % (ls[-1], time.time() - start))
    d2l.set_figsize()
    d2l.plt.plot(np.linspace(0, num_epochs, len(ls)), ls)
    d2l.plt.xlabel('epoch')
    d2l.plt.ylabel('loss')

下面重复第3小节中的实验。

4.1 梯度下降训练结果

train_pytorch_ch7(optim.SGD, {"lr": 0.05}, features, labels, batch_size=1500, num_epochs=6)

输出:

loss: 0.701703, 0.013035 sec per epoch

4.2 随机梯度下降将结果

train_pytorch_ch7(optim.SGD, {"lr": 0.05}, features, labels, batch_size=1, num_epochs=2)

输出:

loss: 0.288860, 0.586868 sec per epoch

4.3 小批量随机梯度下降结果

train_pytorch_ch7(optim.SGD, {"lr": 0.05}, features, labels, batch_size=10, num_epochs=2)

输出:

loss: 0.242063, 0.075203 sec per epoch

5. 总结

  • 小批量随机梯度每次随机均匀采样一个小批量的训练样本来计算梯度。
  • 通常,小批量随机梯度在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。
相关文章
|
7月前
|
机器学习/深度学习 人工智能 PyTorch
PyTorch深度学习 ? 带你从入门到精通!!!
🌟 蒋星熠Jaxonic,深度学习探索者。三年深耕PyTorch,从基础到部署,分享模型构建、GPU加速、TorchScript优化及PyTorch 2.0新特性,助力AI开发者高效进阶。
PyTorch深度学习 ? 带你从入门到精通!!!
|
8月前
|
机器学习/深度学习 存储 PyTorch
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
Neural ODE将神经网络与微分方程结合,用连续思维建模数据演化,突破传统离散层的限制,实现自适应深度与高效连续学习。
791 3
Neural ODE原理与PyTorch实现:深度学习模型的自适应深度调节
|
10月前
|
机器学习/深度学习 存储 监控
基于深度学习YOLO框架的城市道路损伤检测与评估项目系统【附完整源码+数据集】
本项目基于深度学习的YOLO框架,成功实现了城市道路损伤的自动检测与评估。通过YOLOv8模型,我们能够高效地识别和分类路面裂缝、井盖移位、坑洼路面等常见的道路损伤类型。系统的核心优势在于其高效性和实时性,能够实时监控城市道路,自动标注损伤类型,并生成损伤评估报告。
596 0
基于深度学习YOLO框架的城市道路损伤检测与评估项目系统【附完整源码+数据集】
|
10月前
|
机器学习/深度学习 自动驾驶 算法
基于深度学习的YOLO框架的7种交通场景识别项目系统【附完整源码+数据集】
在智慧交通和智能驾驶日益普及的今天,准确识别复杂交通场景中的关键元素已成为自动驾驶系统的核心能力之一。传统的图像处理技术难以适应高动态、复杂天气、多目标密集的交通环境,而基于深度学习的目标检测算法,尤其是YOLO(You Only Look Once)系列,因其检测速度快、精度高、可部署性强等特点,在交通场景识别中占据了重要地位。
1161 0
基于深度学习的YOLO框架的7种交通场景识别项目系统【附完整源码+数据集】
|
11月前
|
机器学习/深度学习 存储 PyTorch
PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
本文通过使用 Kaggle 数据集训练情感分析模型的实例,详细演示了如何将 PyTorch 与 MLFlow 进行深度集成,实现完整的实验跟踪、模型记录和结果可复现性管理。文章将系统性地介绍训练代码的核心组件,展示指标和工件的记录方法,并提供 MLFlow UI 的详细界面截图。
511 2
PyTorch + MLFlow 实战:从零构建可追踪的深度学习模型训练系统
|
7月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
710 0
|
7月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
447 2
|
8月前
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
367 3
|
7月前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
344 8
|
7月前
|
机器学习/深度学习 算法 自动驾驶
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
395 8

热门文章

最新文章

推荐镜像

更多