Transformers 加速的一些常用技巧

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
简介: Transformers架构因自注意力机制面临训练过程中的内存不足和GPU限制问题,主要源于大量参数、自注意力计算的高复杂度以及激活状态存储。为解决这些问题,常用策略包括:固定长度填充(使用注意力掩码处理填充部分)、动态填充(每批内序列长度相同)和等长匹配(按序列长度分组批量处理),以及自动混合精度(AMP)训练,通过float16降低内存使用和加速计算。尽管如此,大型模型仍可能需要高性能GPU支持。

Transformers 是一个强大的架构,但模型因其采用的自注意力机制,虽然能够有效地处理序列数据并捕获长距离依赖关系,但同时也容易导致在训练过程中出现OOM(Out of Memory,内存不足)或者达到GPU的运行时限制。

主要是因为

  1. 参数数量庞大:Transformer模型通常包含大量的参数,尤其是在模型层面进行扩展时(例如,增加层数或头数)。这些参数需要大量的内存来存储权重和梯度。
  2. 自注意力计算:自注意力机制需要对输入序列的每个元素与其他所有元素计算其相互关系,导致计算复杂度和内存需求随着输入长度的增加而显著增加。对于非常长的序列,这一点尤其突出。
  3. 激活和中间状态存储:在训练过程中,需要存储前向传播中的中间激活状态,以便于反向传播时使用。这增加了额外的内存负担。

为了解决这些问题,我们今天来总结以下一些常用的加速策略

固定长度填充

在处理文本数据时,由于文本序列的长度可能各不相同,但许多机器学习模型(尤其是基于Transformer的模型)需要输入数据具有固定的尺寸,因此需要对文本序列进行固定长度填充(padding)。

在使用Transformer模型时,填充部分不应影响到模型的学习。因此通常需要使用注意力掩码(attention mask)来指示模型在自注意力计算时忽略这些填充位置。通过这种固定长度填充和相应的处理方法,可以使得基于Transformer的模型能够有效地处理不同长度的序列数据。在实际应用中,这种方法是处理文本输入的常见策略。

 def fixed_pad_sequences(sequences, max_length, padding_value=0):
     padded_sequences = []
     for sequence in sequences:
         if len(sequence) >= max_length:
             padded_sequence = sequence[:max_length]  # Trim the sequence if it exceeds max_length
         else:
             padding = [padding_value] * (max_length - len(sequence))  # Calculate padding
             padded_sequence = sequence + padding  # Pad the sequence
         padded_sequences.append(padded_sequence)
     return padded_sequences

这种方式会将所有的序列填充成一个长度,这样虽然长度相同了,但是因为序列的实际大小本来就不同,同一批次很可能出现有很多填充的情况,所以就出现了动态填充策略。

动态填充是在每个批处理中动态填充输入序列到最大长度。与固定长度填充不同,在固定长度填充中,所有序列都被填充以匹配整个数据集中最长序列的长度,动态填充根据该批中最长序列的长度单独填充每个批中的序列。

这样虽然每个批次的长度是不同的,但是批次内部的长度是相同的,可以加快处理速度。

 def pad_sequences_dynamic(sequences, padding_value=0):
     max_length = max(len(seq) for seq in sequences)  # Find the maximum length in the sequences
     padded_sequences = []
     for sequence in sequences:
         padding = [padding_value] * (max_length - len(sequence))  # Calculate padding
         padded_sequence = sequence + padding  # Pad the sequence
         padded_sequences.append(padded_sequence)
     return padded_sequences

等长匹配

等长匹配是在训练或推理过程中将长度相近的序列分组成批处理的过程。等长匹配通过基于序列长度将数据集划分为桶,然后从这些桶中采样批次来实现的。

从上图可以看到,通过等长匹配的策略,减少了填充量,这样也可以加速计算

 def uniform_length_batching(sequences, batch_size, padding_value=0):
     # Sort sequences based on their lengths
     sequences.sort(key=len)

     # Divide sequences into buckets based on length
     buckets = [sequences[i:i+batch_size] for i in range(0, len(sequences), batch_size)]

     # Pad sequences within each bucket to the length of the longest sequence in the bucket
     padded_batches = []
     for bucket in buckets:
         max_length = len(bucket[-1])  # Get the length of the longest sequence in the bucket
         padded_bucket = []
         for sequence in bucket:
             padding = [padding_value] * (max_length - len(sequence))  # Calculate padding
             padded_sequence = sequence + padding  # Pad the sequence
             padded_bucket.append(padded_sequence)
         padded_batches.append(padded_bucket)

     return padded_batches

自动混合精度

自动混合精度(AMP)是一种通过使用单精度(float32)和半精度(float16)算法的组合来加速深度学习模型训练的技术。它利用了现代gpu的功能,与float32相比,使用float16数据类型可以更快地执行计算,同时使用更少的内存。

 import torch
 from torch.cuda.amp import autocast, GradScaler

 # Define your model
 model = YourModel()

 # Define optimizer and loss function
 optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
 criterion = torch.nn.CrossEntropyLoss()

 # Create a GradScaler object for gradient scaling
 scaler = GradScaler()

 # Inside the training loop
 for inputs, targets in dataloader:
     # Clear previous gradients
     optimizer.zero_grad()

     # Cast inputs and targets to the appropriate device
     inputs, targets = inputs.to(device), targets.to(device)

     # Enable autocasting for forward pass
     with autocast():
         # Forward pass
         outputs = model(inputs)
         loss = criterion(outputs, targets)

     # Backward pass
     # Scale the loss value
     scaler.scale(loss).backward()

     # Update model parameters
     scaler.step(optimizer)

     # Update the scale for next iteration
     scaler.update()

AMP在训练过程中动态调整计算精度,允许模型在大多数计算中使用float16,同时自动将某些计算提升为float32,以防止下流或溢出等数值不稳定问题。

Fp16 vs Fp32

双精度(FP64)消耗64位。符号值为1位,指数值为11位,有效精度为52位。

单精度(FP32)消耗32位。符号值为1位,指数值为8位,有效精度为23位。

半精度(FP16)消耗16位。符号值为1位,指数值为5位,有效精度为10位。

所以Fp16可以提高内存节省,并可以大大提高模型训练的速度。考虑到Fp16的优势和它在模型使用方面的主导区域,它非常适合推理任务。但是fp16会产生数值精度的损失,导致计算或存储的值不准确,考虑到这些值的精度至关重要。

另外就是这种优化师针对于分类任务的,对于回归这种需要精确数值的任务Fp16的表现并不好。

总结

以上这些方法,可以在一定程度上缓解内存不足和计算资源的限制,但是对于大型的模型我们还是需要一个强大的GPU。

https://avoid.overfit.cn/post/7240bee210cd408a90ca04279830040e

目录
相关文章
|
6月前
|
人工智能 并行计算 PyTorch
【Hello AI】手动安装AIACC-Inference(AIACC推理加速)Torch版
AIACC-Inference(AIACC推理加速)支持优化基于Torch框架搭建的模型,能够显著提升推理性能。本文介绍如何手动安装AIACC-Inference(AIACC推理加速)Torch版并提供示例体验推理加速效果。
|
6月前
|
机器学习/深度学习 并行计算 PyTorch
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
TensorRT部署系列 | 如何将模型从 PyTorch 转换为 TensorRT 并加速推理?
935 0
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
本文介绍了 NVIDIA FasterTransformer 库及其在加速大型 Transformer 模型推理中的应用。FasterTransformer 是一个高效、可扩展的库,支持分布式多 GPU 推理,特别适合处理具有数万亿参数的模型。文章还详细讲解了如何使用 FasterTransformer 和 NVIDIA Triton 推理服务器优化 GPT-J 和 T5 模型的推理性能,包括张量并行、流水线并行等技术。
59 0
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
|
3月前
|
机器学习/深度学习 并行计算 PyTorch
ONNX 优化技巧:加速模型推理
【8月更文第27天】ONNX (Open Neural Network Exchange) 是一个开放格式,用于表示机器学习模型,使模型能够在多种框架之间进行转换。ONNX Runtime (ORT) 是一个高效的推理引擎,旨在加速模型的部署。本文将介绍如何使用 ONNX Runtime 和相关工具来优化模型的推理速度和资源消耗。
1348 4
|
3月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习模型训练的最佳实践
【8月更文第27天】随着深度学习应用的广泛普及,高效利用GPU硬件成为提升模型训练速度的关键。PyTorch 是一个强大的深度学习框架,它支持动态计算图,易于使用且高度灵活。CUDA (Compute Unified Device Architecture) 则是 NVIDIA 开发的一种并行计算平台和编程模型,允许开发者直接访问 GPU 的并行计算能力。本文将详细介绍如何利用 PyTorch 与 CUDA 的集成来加速深度学习模型的训练过程,并提供具体的代码示例。
155 1
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
【AI大模型】Transformers大模型库(一):Tokenizer
【AI大模型】Transformers大模型库(一):Tokenizer
81 1
|
6月前
|
机器学习/深度学习 并行计算 TensorFlow
TensorFlow与GPU加速:提升深度学习性能
【4月更文挑战第17天】本文介绍了TensorFlow如何利用GPU加速深度学习, GPU的并行处理能力适合处理深度学习中的矩阵运算,显著提升性能。TensorFlow通过CUDA和cuDNN库支持GPU,启用GPU只需简单代码。GPU加速能减少训练时间,使训练更大、更复杂的模型成为可能,但也需注意成本、内存限制和编程复杂性。随着技术发展,GPU将继续在深度学习中发挥关键作用,而更高效的硬件解决方案也将备受期待。
|
6月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习训练
【4月更文挑战第18天】本文介绍了如何使用PyTorch与CUDA加速深度学习训练。CUDA是NVIDIA的并行计算平台,常用于加速深度学习中的矩阵运算。PyTorch与CUDA集成,允许开发者将模型和数据迁移到GPU,利用`.to(device)`方法加速计算。通过批处理、并行化策略及优化技巧,如混合精度训练,可进一步提升训练效率。监控GPU内存和使用调试工具确保训练稳定性。PyTorch与CUDA的结合对深度学习训练的加速作用显著。
|
6月前
|
存储 人工智能 并行计算
【Hello AI】自动安装AIACC-Inference(AIACC推理加速)
AIACC-Inference(AIACC推理加速)支持优化基于TensorFlow和可导出ONNX格式的框架搭建的模型,能显著提升推理性能。本文介绍如何自动安装AIACC-Inference(AIACC推理加速)并测试demo。
|
6月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【Hello AI】如何安装AIACC-Training(AIACC训练加速)
AIACC-Training支持基于主流人工智能(包括PyTorch、TensorFlow、MXNet、Caffe等)搭建的模型进行分布式训练。在接口层面上,目前AIACC-Training兼容了PyTorch DDP以及Horovod的API,对于原生使用上述分布式训练方法的训练代码,可以做到无感的性能加速。本文将为您介绍安装AIACC-Training 1.5.0的多种方式。