【Transformers实战篇1】基于Transformers的NLP解决方案
文章目录
- 一、基础组件
- 二、基于Transformer的NLP解决方案
- 三、显存优化策略
- 3.1 显存占用简单分析
- 3.2 Transformers 显存优化
- 3.2.1 Baseline 不进行任何优化
- 3.2.2 Gradient Accumulation 梯度累加优化
- 3.2.3 Gradient Checkpoints 选择性存一些前向激活值
- 3.2.4 Adafactor Optiomizer 更换优化器
- 3.2.5 Freeze Model 冻结模型层
- 3.2.6 Data Length 降低最大长度
- 3.2.7 更多参数高效微调
本文为 https://space.bilibili.com/21060026/channel/collectiondetail?sid=1357748的视频学习笔记
项目地址为:https://github.com/zyds/transformers-code
一、基础组件
- Pipeline: 流水线,用于模型推理,封装了完整的推理逻辑,包括数据预处理、模型预测以及后处理
- Tokenizer: 分词器,用于数据预处理,将原始文本输入转化为模型的输入,包括input_ids、attention_mask等
- Model: 模型,用于加载、创建、保存模型,对pytorch中的模型进行了封装,同时更好的支持预训练模型
- Datasets: 数据集,用于数据集加载与预处理,支持加载在线与本地的数据集,提供了数据集层面的处理方法
- Evaluate: 评估函数,用于对模型的结果进行评估,支持多种任务的评估函数
- Trainer: 训练器,用于模型训练、评估,支持丰富的配置选项,快速启动模型训练流程
二、基于Transformer的NLP解决方案
- step1 导入相关包
- step2 加载数据集
Datasets
- step3 数据集划分
Datasets
- step4 数据集预处理
Tokenizer +Datasets
- step5 创建模型
Model
- step6 设置评估函数
Evaluate
- step7 配置训练参数
TrainingArguments
- step8 创建训练器
Trainer + Data Collator
- step9 模型训练、评估、预测(数据集)
Trainer
- step10 模型预测(单条)
Pipeline
三、显存优化策略
当机器显存不够时,可以选择牺牲模型准确率、牺牲训练时间等方式来换空间
3.1 显存占用简单分析
- 模型权重: 4 B y t e s × 模型参数量 4 Bytes × 模型参数量 4Bytes×模型参数量
- 优化器状态: 8 B y t e s × 模型参数量 8 Bytes × 模型参数量 8Bytes×模型参数量 (对常用的Adamw优化器)
- 梯度: 4 B y t e s × 模型参数量 4 Bytes × 模型参数量 4Bytes×模型参数量
- 前向激活值: 取决于序列长度、隐层维度、Batch大小等多个因素
3.2 Transformers 显存优化
先贴一张原博主的显存优化数据:
3.2.1 Baseline 不进行任何优化
BatchSize设置为32, MaxLength设置为128
3.2.2 Gradient Accumulation 梯度累加优化
- 优化对象 :前向激活值。当累计跑了32个step时,才会计算梯度
- 参数设置:在
TrainingArguments
里设置:per_device_train_batch_size=1
和gradient_accumulation_steps=32
3.2.3 Gradient Checkpoints 选择性存一些前向激活值
- 优化对象 :前向激活值。选择性的保存一些前向激活值,然后在反向传播时,再重新计算。
- 参数设置:在
TrainingArguments
里设置:gradient_checkpointing=True
3.2.4 Adafactor Optiomizer 更换优化器
- 优化对象 :优化器状态。理论比AdamW占用显存小
- 参数设置:在
TrainingArguments
里设置:optim="adafactor"
3.2.5 Freeze Model 冻结模型层
- 优化对象 :前向激活值和梯度。 通过冻结一些层
- 参数设置:如将Bert中的参数进行冻结。遍历模型的参数,设置
param.requires_grad = False
from transformers import DataCollatorWithPadding
# *** 参数冻结 ***
for name, param in model.bert.named_parameters():
param.requires_grad = False
trainer = Trainer(model=model,
args=train_args,
tokenizer=tokenizer,
train_dataset=tokenized_datasets["train"],
eval_dataset=tokenized_datasets["test"],
data_collator=DataCollatorWithPadding(tokenizer=tokenizer),
compute_metrics=eval_metric)
3.2.6 Data Length 降低最大长度
- 优化对象:前向激活值。会极大影响模型预测的准确率
- 参数设置:在
tokenizer
数据集预处理处进行操作,设置max_length=32
import torch
tokenizer = AutoTokenizer.from_pretrained("hfl/chinese-macbert-large")
def process_function(examples):
tokenized_examples = tokenizer(examples["review"], max_length=32, truncation=True, padding="max_length")
tokenized_examples["labels"] = examples["label"]
return tokenized_examples
tokenized_datasets = datasets.map(process_function, batched=True, remove_columns=datasets["train"].column_names)
3.2.7 更多参数高效微调
- Lora
- cpu offload
- flash attention等