作为算法工程师的你是否对如何应用大型语言模型构建智能问答系统充满好奇?是否希望深入探索LLaMA(类ChatGPT)模型的微调技术,进一步优化参数和使用不同微调方式?现在笔者会带您领略大模型训练与微调进阶之路,拓展您的技术边界!
通过阅读文章,读者将能够了解LLaMA(类ChatGPT)微调的相关内容,并理解训练过程中的 Batch_size、数据类型、Zero等参数设置以及 LoRA 方式、P-Tuning 方式等微调方式的应用。此外,读者将会了解优化器定义与参数的设定,同时了解和掌握监视器工具 Wandb 的使用。
除此之外,文章还会介绍包括数据准备、ChatGPT 数据生成流程等。对于微调方式,课程将分别以 LoRA 方式、P-Tuning 方式为例进行演示,并讲解合并 LoRA 参数与原始参数的方法、Fsdp 与 deepspeed 的全参数微调技巧等内容。最后,针对模型效果的测评,还将对相关指标进行说明和分析,帮助学员掌握有效评估模型性能的方法。
下面主要介绍几部分重点内容供大家参考和学习。
一、训练(微调)-多GPU训练
当单GPU单张卡无法支撑大模型的训练效率、无法放下一个大模型,当业务对训练速度有一定要求,需要成倍的提高训练效率的时候,就需要GPU集群的技术来处理。下面介绍几个多卡训练的知识点。
数据并行和模型并行(见下图)
二、知识准备-数据类型
多 GPU 训练中的数据类型设置与单 GPU 训练类似,需要根据模型的实际需求和硬件设备的支持性能进行选择。通常情况下,推荐使用 fp16/bf16/tf32 数据类型进行训练。
半精度:fp16
半精度:bf16
单精度:fp32
NVidia's TensorFloat(tf32)
从精度上看fp32>tf32>bf16,都显著优于google的bf16,Nvidia的tf32是使用fp16的计算性能向fp32的表达范围靠齐的一种尝试
Tensor Float 32是Tensor Core 支持新的数值类型,从 NVIDIA A100 中开始支持。A100 的普通 FP32 的峰值计算速度为 19.5 TOPs,而TF32的峰值计算速度为 156 TOPs,提升了非常多。
三、知识准备-显卡加速
我们在训练的时候无论是租机器、买机器,其实都是需要对训练目标和显卡有一定的了解。
注意看一下卡的性能指标、支持的数据类型、当然也要考虑价格因素。
计算卡主要看一下代数、计算能力、显存带宽等等。
下面提供了一个3090(家用)和A100针对resnet50累计100次训练迭代的耗时测试结果如下:
3090 | A100 |
---|---|
True True end1 43.1068 False False end2 46.1883 | True True end1 24.2842 False False end2 50.8318 |
从测试结果看有如下结论
•3090上TF32开不开,resnet训练耗时差别较微弱
•A100上TF32开启比不开启,快了1倍
•TF32模式下,A100比3090快很多(pytorch默认开启TF32)
•FP32模式下,A100比3090慢一点
•都不如nv官方TF32宣传页面里那么夸张的加速比
四、训练(微调)-知识准备-zero模式、offload模式
目前训练超大规模语言模型主要有两条技术路线:TPU XLA TensorFlow 和 GPU PyTorch Megatron-LM DeepSpeed。前者由Google主导,由于TPU和自家云平台GCP深度绑定,对于非Google开发者来说, 只可远观而不可把玩,后者背后则有NVIDIA、Meta、微软等大厂加持,社区氛围活跃,也更受到群众欢迎。
数据并行(Data Parallel, DP)
优点:可以不受单张GPU显存限制,训练更大的模型。
缺点:计算/通信效率低。
流水线并行(Pipeline Parallel, PP)
优点:层内计算/通信效率增加
缺点:存在空闲等待时间
流水线并行的核心思想是,模型按层分割成若干块,每块都交给一个设备。在前向传递过程中,每个设备将中间的激活传递给下一个阶段。在后向传递过程中,每个设备将输入张量的梯度传回给前一个流水线阶段。这允许设备同时进行计算,并增加了训练的吞吐量。流水线并行训练的一个缺点是,会有一些设备参与计算的冒泡时间,导致计算资源的浪费。
数据并行 流水线并行,如下图:
数据并行 流水线并行 模型并行,如下图:
五、训练(微调)-知识准备-deepspeed zero模式
ZeRO(Zero Redundancy Optimizer)
类似于张量并行进行切分,支持多种offload技术。
目标:优化存储效率的同时还能保持较高的计算和通信效率。
为了能够在比较普通的机器上也能微调大模型,我们首先需要分析一下模型训练过程中都有哪些部分需要消耗存储空间。在进行深度学习训练的时候,有4大部分的显存开销,分别是模型参数(Parameters),模型参数的梯度(Gradients),优化器状态(Optimizer States)以及中间激活值(Intermediate Activations)。
ZeRO-DP
基于上述问题,提出了ZeRO-DP技术,即ZeRO驱动的数据并行,兼顾数据并行的计算/通信效率和模型并行的空间效率。首先ZeRO-DP会对模型状态进行分区,避免了复制模型导致的冗余,然后在训练期间使用动态通信调度保留数据并行的计算粒度和通信量,也能维持一个类似的计算/通信效率。
ZeRO-Offload
ZeRO说到底是一种数据并行方案,可是很多人只有几张甚至一张卡,显存加起来都不够,那怎么办呢?在操作系统中,当内存不足时,可以选择一些页面进行换入换出,为新的数据腾出空间。类比一下,既然是因为显存不足导致一张卡训练不了大模型,那么ZeRO-Offload的想法就是:显存不足,内存来补。
单卡场景-上图
多卡场景-上图
现在的计算流程是,在GPU上面进行前向和后向计算,将梯度传给CPU,进行参数更新,再将更新后的参数传给GPU。为了提高效率,可以将计算和通信并行起来,GPU在反向传播阶段,可以待梯度值填满bucket后,一边计算新的梯度一边将bucket传输给CPU,当反向传播结束,CPU基本上已经有最新的梯度值了,同样的,CPU在参数更新时也同步将已经计算好的参数传给GPU。
六、训练(微调)-知识准备-优化器定义与参数
深度学习中几乎所有流行的优化器都是基于梯度下降。这意味着它们要反复估计给定损失函数 L 的斜率,并沿着相反的方向移动参数(因此向下移动至假定的全局最小值)。这种优化器最简单的示例是自 20 世纪 50 年代以来一直使用的随机梯度下降(SGD)算法。21 世纪前 10 年,自适应梯度法(如 AdaGrad 或 Adam)变得越来越流行。
七、训练(微调)-知识准备-wandb
Wandb(全称为Weights and Biases)是一个用于跟踪、可视化和协作机器学习项目的工具。它提供了许多功能,包括实时的指标跟踪、超参数调整、模型的可视化等。Wandb能够帮助机器学习工程师更好地管理和监控他们的实验,并从中获得更多的见解和知识。
使用Wandb非常简单,首先需要安装Wandb的Python包,可以通过pip或conda来安装。安装完成后,需要在Python脚本中导入wandb库,登录Wandb,创建一个项目并设置实验。在实验中,可以记录各种指标、超参数、模型权重等,并进行可视化分析。
八、数据准备
原始alpaca数据例子如下:
{
"instruction": "Describe the structure of an atom.",
"input": "",
"output": "An atom is made up of a nucleus, which contains protons and neutrons, surrounded by electrons that travel in orbits around the nucleus. The protons and neutrons have a positive charge, while the electrons have a negative charge, resulting in an overall neutral atom. The number of each particle determines the atomic number and the type of atom."
},
PROMPT_DICT = {
"prompt_input": (
"Below is an instruction that describes a task, paired with an input that provides further context. "
"Write a response that appropriately completes the request.nn"
"### Instruction:n{instruction}nn### Input:n{input}nn### Response:"
),
"prompt_no_input": (
"Below is an instruction that describes a task. "
"Write a response that appropriately completes the request.nn"
"### Instruction:n{instruction}nn### Response:"
),
}
翻译解释如下:
PROMPT_DICT = {
"prompt_input": (
"下面是描述一项任务的指令,与提供进一步背景的输入配对。"
"写一个适当的回应。nn"
"### Instruction:n{instruction}nn### Input:n{input}nn### Response:"
),
"prompt_no_input": (
"下面是描述一项任务的指令。"
"写一个适当的回应。nn"
"### Instruction:n{instruction}nn### Response:"
),
}
如何利用chatgpt 生成训练集。
八、训练(微调)-lora微调
LoRA的实现原理:冻结预训练模型权重,并将可训练的秩分解矩阵注入到Transformer层的每个权重中,大大减少了下游任务的可训练参数数量。直白的来说,实际上是增加了右侧的“旁支”,也就是先用一个Linear层A,将数据从 d维降到r,再用第二个Linear层B,将数据从r变回d维。最后再将左右两部分的结果相加融合,得到输出的hidden_state。
使用LoRA:
1、LoRA模型无法单独使用,需要搭配原版LLaMA模型,发布的是LoRA权重,可以理解为原LLaMA模型上的一个“补丁”,两者进行合并即可获得完整版权重。
2、LoRA 与 Transformer 的结合也很简单,仅在 QKV attention 中 QKV 的映射增加一个旁路(可看下文中具体的 LORA 网络结构),而不动MLP模块。基于大模型的内在低秩特性,增加旁路矩阵来模拟全模型参数微调,LoRA通过简单有效的方案来达成轻量微调的目的,可以将现在的各种大模型通过轻量微调变成各个不同领域的专业模型。