【PyTorch】优化分析

文章目录

  • [1. 模型训练过程划分](#1. 模型训练过程划分)
    • [1.1. 定义过程](#1.1. 定义过程)
      • [1.1.1. 全局参数设置](#1.1.1. 全局参数设置)
      • [1.1.2. 模型定义](#1.1.2. 模型定义)
    • [1.2. 数据集加载过程](#1.2. 数据集加载过程)
      • [1.2.1. Dataset类:创建数据集](#1.2.1. Dataset类:创建数据集)
      • [1.2.2. Dataloader类:加载数据集](#1.2.2. Dataloader类:加载数据集)
    • [1.3. 训练循环](#1.3. 训练循环)
  • [2. 模型训练过程追踪](#2. 模型训练过程追踪)
  • [3. 优化分析](#3. 优化分析)
    • [3.1. 定义过程](#3.1. 定义过程)
    • [3.2. 数据集加载过程](#3.2. 数据集加载过程)
    • [3.3. 训练循环](#3.3. 训练循环)
      • [3.3.1. 训练模型](#3.3.1. 训练模型)
      • [3.3.2. 评估模型](#3.3.2. 评估模型)

1. 模型训练过程划分

  • 主过程在__main__下。
python 复制代码
if __name__ == '__main__':
	...
  • 主过程分为定义过程数据集加载过程训练循环

1.1. 定义过程

1.1.1. 全局参数设置

参数名 作用
learning_rate 控制模型参数的更新步长
device 指定模型训练使用的设备(CPU或GPU)
num_epochs 指定在训练集上训练的轮数
batch_size 指定每批数据的样本数
num_workers 指定加载数据集的进程数
prefetch_factor 指定每个进程预加载的批数

1.1.2. 模型定义

组件 作用
writer 定义tensorboard的事件记录器
net 定义神经网络结构
net.apply(init_weights) 模型参数初始化
criterion 定义损失函数
optimizer 定义优化器

1.2. 数据集加载过程

1.2.1. Dataset类:创建数据集

  • 作用:定义数据集的结构和访问数据集中样本的方式。定义过程中通常需要读取数据文件,但这并不意味着将整个数据集加载到内存中
  • 如何创建数据集
    • 继承Dataset抽象类自定义数据集
    • TensorDataset类:通过包装张量创建数据集

1.2.2. Dataloader类:加载数据集

  • 作用:定义数据集的加载方式,但这并不意味着正在加载数据集

    • 数据批量加载:将数据集分成多个批次(batches),并逐批次地加载数据。
    • 数据打乱(可选):在每个训练周期(epoch)开始时,DataLoader会对数据集进行随机打乱,以确保在训练过程中每个样本被均匀地使用。
  • 主要参数

    参数 作用
    dataset 指定数据集
    batch_size 指定每批数据的样本数
    shuffle=False 指定是否在每个训练周期(epoch)开始时进行数据打乱
    sampler=None 指定如何从数据集中选择样本,如果指定这个参数,那么shuffle必须设置为False
    batch_sampler=None 指定生成每个批次中应包含的样本数据的索引。与batch_size、shuffle 、sampler and drop_last参数不兼容
    num_workers=0 指定进行数据加载的进程数
    collate_fn=None 指定将一列表的样本合成mini-batch的方法,用于映射型数据集
    pin_memory=False 是否将数据缓存在物理RAM中以提高GPU传输效率
    drop_last=False 是否在批次结束时丢弃剩余的样本(当样本数量不是批次大小的整数倍时)
    timeout=0 定义在每个批次上等待可用数据的最大秒数。如果超过这个时间还没有数据可用,则抛出一个异常。默认值为0,表示永不超时。
    worker_init_fn=None 指定在每个工作进程启动时进行的初始化操作。可以用于设置共享的随机种子或其他全局状态。
    multiprocessing_context=None 指定多进程数据加载的上下文环境,即多进程库
    generator=None 指定一个生成器对象来生成数据批次
    prefetch_factor=2 控制数据加载器预取数据的数量,默认预取比实际所需的批次数量多2倍的数据
    persistent_workers=False 控制数据加载器的工作进程是否在数据加载完成后继续存在

1.3. 训练循环

  • 外层循环控制在训练集上训练的轮数
python 复制代码
for epoch in trange(num_epochs):
	...
  • 循环内部主要有以下模块:

    • 训练模型
    python 复制代码
    for X, y in dataloader_train:
        X, y = X.to(device), y.to(device)
        loss = criterion(net(X), y)
        optimizer.zero_grad()
        loss.mean().backward()
        optimizer.step()
    • 评估模型
      • 每轮训练后在数据集上损失
        • 每轮训练损失
        • 每轮测试损失
    python 复制代码
    def evaluate_loss(dataloader):
    	"""评估给定数据集上模型的损失"""
    	metric = d2l.Accumulator(2)  # 损失的总和, 样本数量
        with torch.no_grad():
            for X, y in dataloader:
                X, y = X.to(device), y.to(device)
                loss = criterion(net(X), y)
                metric.add(loss.sum(), loss.numel())
            return metric[0] / metric[1]

2. 模型训练过程追踪

注意: 以下只区分变量、对象是在GPU还是在CPU内存中处理。实际处理过程使用的硬件是CPU、内存和GPU,其中CPU有缓存cache,GPU有显存。忽略具体的数据传输路径和数据处理设备。谈GPU包括GPU和显存,谈CPU内存包括CPU、缓存cache和内存

主过程 子过程 追踪情况
定义过程 全局参数设置 变量的定义都是由CPU完成的
定义过程 模型定义 * 对象的定义都是由CPU完成的 * 模型参数和梯度信息可以转移到GPU
数据集加载过程 ------ 对象的定义都是由CPU完成的
训练循环 训练模型 * 每批数据的加载是由CPU完成的,先加载到CPU内存,然后可以转移到GPU * 数据的前向传播可以由GPU完成 * 误差反向传播(包括梯度计算)可以由GPU完成的 * 模型参数更新可以由GPU完成的
训练循环 评估模型 * 每批数据的加载是由CPU完成的,先加载到CPU内存,然后可以转移到GPU * 数据的前向传播可以由GPU完成,此时可以禁用自动求导机制

由此提升硬件资源的利用率和训练效率,总体上有以下角度:

  • 提升CPU的运算效率
  • 提升数据从CPU转移到GPU的效率
    • 数据传输未准备好也传输(即非阻塞模式):non_blocking=True
    • 将张量固定在CPU内存 :pin_memory=True
  • 提升GPU的运算效率

3. 优化分析

3.1. 定义过程

  • 特点:每次程序运行只需要进行一次。
  • 优化思路:将模型转移到GPU ,同时non_blocking=True

3.2. 数据集加载过程

  • 特点:只是定义数据加载的方式,并没有加载数据。
  • 优化思路:合理设置数据加载参数 ,如
    • batch_size:一般取能被训练集大小整除的值。过小,则每次参数更新时所用的样本数较少,模型无法充分地学习数据的特征和分布,同时参数更新频繁,模型收敛速度提高,CPU到GPU的数据传输次数增加,CPU内存的消耗总量增加;过大,则每次参数更新时所用的样本数较多,模型性能更稳定,对GPU、CPU内存的单次消耗增加,对硬件配置要求更高,同时参数更新缓慢,模型收敛速度下降。
    • num_workers:一般取CPU内核数。过小,则数据加载进程少,数据加载缓慢;过大,则数据加载进程多,对CPU要求高。
    • pin_memory:当设置为True时,它告诉DataLoader将加载的数据张量固定在CPU内存中,使数据传输到GPU的过程更快。
    • prefetch_factor:决定每次从磁盘加载多少个batch的数据到内存中,预先加载batch越多,在处理数据时,不会因为数据加载的延迟而影响整体的训练速度,同时可以让GPU在处理数据时保持忙碌,从而提高GPU利用率;过大,则会导致CPU内存消耗增加。

3.3. 训练循环

  • 优化思路:
    • 训练和评估过程分离或者减少评估的次数:模型从训练到评估需要进行状态切换,模型评估过程开销很大。
    • 尽量使用非局部变量:减少变量、对象的创建和销毁过程

3.3.1. 训练模型

  • 特点:训练结构固定

  • 优化思路:

    • 将数据转移到GPU ,同时non_blocking=True
    • 优化训练结构:比如使用自动混合精度(AMP,要求pytorch>=1.6.0),通过将模型和数据转换为低精度的形式(如FP16),可以显著减少内存使用,即
    python 复制代码
    from torch.cuda.amp import autocast, GradScaler
    
    grad_scaler = GradScaler()
    for epoch in range(num_epochs):
        start_time = time.perf_counter()
        for X, y in dataloader_train:
            X, y = X.to(device, non_blocking=True), y.to(device, non_blocking=True)
            with autocast():
                loss = criterion(net(X), y)
                optimizer.zero_grad()
                grad_scaler.scale(loss.mean()).backward()
                grad_scaler.step(optimizer)
                grad_scaler.update()

3.3.2. 评估模型

  • 特点:评估结构固定

  • 优化思路:

    • 将数据转移到GPU ,同时non_blocking=True
    • 减少不必要的运算:比如梯度计算,即:
    python 复制代码
    with torch.no_grad():
    	...
相关推荐
deephub2 小时前
加速LLM大模型推理,KV缓存技术详解与PyTorch实现
人工智能·pytorch·深度学习·缓存·大语言模型
从零开始学习人工智能5 小时前
深度解析 MindTorch:无缝迁移 PyTorch 到 MindSpore 的高效工具
人工智能·pytorch·python
热爱生活的猴子9 小时前
一个完整的神经网络训练流程详解(附 PyTorch 示例)
人工智能·pytorch·深度学习·神经网络
猫头虎-人工智能9 小时前
最新DeepSeek-Prover-V2-671B模型 简介、下载、体验、微调、数据集:专为数学定理自动证明设计的超大垂直领域语言模型(在线体验地址)
人工智能·pytorch·python·语言模型·自然语言处理·chatgpt·agi
Francek Chen9 小时前
【现代深度学习技术】现代循环神经网络02:长短期记忆网络(LSTM)
人工智能·pytorch·rnn·深度学习·神经网络·lstm
九章云极AladdinEdu10 小时前
存算一体架构下的新型AI加速范式:从Samsung HBM-PIM看近内存计算趋势
人工智能·pytorch·算法·架构·gpu算力·智能电视
奋斗者1号10 小时前
PyTorch 与 TensorFlow:深度学习框架的深度剖析与实战对比
pytorch·深度学习·tensorflow
意.远12 小时前
PyTorch线性代数操作详解:点积、矩阵乘法、范数与轴求和
人工智能·pytorch·python·深度学习·线性代数·矩阵
JOYCE_Leo1612 小时前
深度学习框架:PyTorch使用教程 !!
图像处理·人工智能·pytorch·深度学习·计算机视觉
什么芮.18 小时前
大数据应用开发和项目实战(2)
大数据·pytorch·sql·spark·scala