Transformers 加速的一些常用技巧

简介: 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

目录
相关文章
|
Dubbo Java 应用服务中间件
nacos常见问题之Nacos dubbo耗时严重如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
|
7天前
|
人工智能 机器人 API
阿里云/本地部署 OpenClaw 多 Agent协同工作指南:单频道/多应用/群聊模式+大模型接入、子Agent配置与避坑大全
在AI辅助工作日益普及的今天,很多人误以为“超级个体”只需要一个主Agent就能完成所有任务。但真实场景中,营销、产品、开发、内容、研究等不同职能,需要专业化分工才能稳定输出高质量结果。OpenClaw提供了完整的多智能体协作能力,支持三种主流协作架构,可实现Agent之间调度、协作、产出最终方案,真正做到**一人管理一支AI团队**。
261 7
|
机器学习/深度学习 数据采集 自然语言处理
HuggingFace Transformers 库深度应用指南
本文首先介绍HuggingFace Tra环境配置与依赖安装,确保读者具备Python编程、机器学习和深度学习基础知识。接着深入探讨Transformers的核心组件,并通过实战案例展示其应用。随后讲解模型加载优化、批处理优化等实用技巧。在核心API部分,详细解析Tokenizers、Models、Configuration和Dataset的使用方法。文本生成章节则涵盖基础概念、GPT2生成示例及高级生成技术。最后,针对模型训练与优化,介绍预训练模型微调、超参数优化和推理加速等内容。通过这些内容,帮助读者掌握HuggingFace Transformers的深度使用,开发高效智能的NLP应用。
1918 22
|
3月前
|
物联网 测试技术
为什么 loss 几乎没用:微调里最容易让人“自嗨”的指标
本文揭示了大模型微调中一个常见误区:过度依赖loss曲线判断训练效果。loss仅反映模型对训练数据的拟合程度,并不衡量实际表现。它可能平稳下降,但模型输出无改善甚至变差。尤其在SFT/LoRA微调中,loss易被“虚假优化”,掩盖行为偏移、泛化缺失等问题。真正关键的是人工对照输出变化,结合loss作为辅助参考,而非决策核心。
|
机器学习/深度学习 数据处理
大语言模型中的归一化技术:LayerNorm与RMSNorm的深入研究
本文分析了大规模Transformer架构(如LLama)中归一化技术的关键作用,重点探讨了LayerNorm被RMSNorm替代的原因。归一化通过调整数据量纲保持分布形态不变,提升计算稳定性和收敛速度。LayerNorm通过均值和方差归一化确保数值稳定,适用于序列模型;而RMSNorm仅使用均方根归一化,省略均值计算,降低计算成本并缓解梯度消失问题。RMSNorm在深层网络中表现出更高的训练稳定性和效率,为复杂模型性能提升做出重要贡献。
3030 14
大语言模型中的归一化技术:LayerNorm与RMSNorm的深入研究
|
机器学习/深度学习 人工智能 自然语言处理
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
本文介绍了 NVIDIA FasterTransformer 库及其在加速大型 Transformer 模型推理中的应用。FasterTransformer 是一个高效、可扩展的库,支持分布式多 GPU 推理,特别适合处理具有数万亿参数的模型。文章还详细讲解了如何使用 FasterTransformer 和 NVIDIA Triton 推理服务器优化 GPT-J 和 T5 模型的推理性能,包括张量并行、流水线并行等技术。
663 0
NVIDIA Triton系列13-用 FasterTransformer 和 Triton 加速大型 Transformer 模型的推理
|
10月前
|
机器学习/深度学习 自然语言处理 测试技术
Qwen3技术报告首次全公开!“混合推理模型”是这样炼成的
近日,通义千问Qwen3系列模型已开源,其技术报告也正式发布。Qwen3系列包含密集模型和混合专家(MoE)模型,参数规模从0.6B到235B不等。该模型引入了“思考模式”与“非思考模式”的动态切换机制,并采用思考预算机制优化推理性能。Qwen3支持119种语言及方言,较前代显著提升多语言能力,在多个基准测试中表现领先。此外,通过强到弱蒸馏技术,轻量级模型性能优异,且计算资源需求更低。所有Qwen3模型均采用Apache 2.0协议开源,便于社区开发与应用。
6957 30
|
搜索推荐 物联网 PyTorch
Qwen2.5-7B-Instruct Lora 微调
本教程介绍如何基于Transformers和PEFT框架对Qwen2.5-7B-Instruct模型进行LoRA微调。
13816 34
Qwen2.5-7B-Instruct Lora 微调
|
文字识别
统一多模态Embedding, 通义实验室开源GME系列模型
随着多媒体应用的迅猛发展,用户产生的数据类型日益多样化,不再局限于文本,还包含大量图像、音频和视频等多模态信息。这为信息检索带来了前所未有的挑战与机遇。传统的信息检索模型多关注单一模态,如仅对文本或图像进行分析和搜索。
3032 6