赞
踩
在计算机领域,“精度”指的是浮点数的表示方式,如半精度(FP16)、单精度(FP32)、双精度(FP64)等。浮点数存储方式,由符号位(sign)、指数位(exponent)和小数位(fraction)三部分组成。符号位都是1位,指数位影响浮点数范围,小数位影响精度。
Floating Point,是最原始的,IEEE定义的标准浮点数类型。FP64,是64位浮点数,由1位符号位,11位指数位和52位小数位组成。FP32、FP16、FP8、FP4都是类似组成,只是指数位和小数位不一样。
不同精度的浮点数在计算机中的存储空间不同,因此在同等的任务规模下,采用半精度计算的速度比单精度要快。但是,又由于不同精度的数值表示范围不同,所以更高精度的计算,结果更为精确。
当前的深度学习框架大都采用的都是fp32来进行权重参数的存储,比如Python float的类型为双精度浮点数fp64,PyTorch Tensor的默认类型为单精度浮点数fp32。
Brain Float 16,由Google Brain提出,也是为了机器学习而设计。由1个符号位,8位指数位(和FP32一致)和7位小数位(低于FP16)组成。所以精度低于FP16,但是表示范围和FP32一致,和FP32之间很容易转换。
为了想让深度学习训练可以使用FP16的好处,又要避免精度溢出和舍入误差。于是可以通过FP16和FP32的混合精度训练(Mixed-Precision),混合精度训练过程中可以引入权重备份(Weight Backup)、损失放大(Loss Scaling)、精度累加(Precision Accumulated)三种相关的技术。
保留一份FP32的主权重(Master-Weights),同时在训练中使用FP16存储权重、激活、梯度等数据。在参数更新的过程汇总,用FP16更新FP32的主权重。
如果仅仅使用FP32训练,模型收敛得比较好,但是如果用了混合精度训练,会存在网络模型无法收敛的情况。原因是梯度的值太小,会造成FP16精度下数据下溢的问题,即一些梯度会变为0,导致模型不收敛。
为了解决梯度过小数据下溢的问题,对前向计算出来的Loss值进行放大操作,也就是把FP32的参数乘以某一个因子系数后,把可能溢出的小数位数据往前移,平移到FP16能表示的数据范围内。根据链式求导法则,放大Loss后会作用在反向传播的每一层梯度,这样比在每一层梯度上进行放大更加高效。
而在反向传播完成后,在权重更新前,立刻对权重梯度进行缩小(FP16->FP32),这样可以保证任何超参数不会被影响。
动态损失缩放(Dynamic Loss Scaling):上面提到的损失缩放都是使用一个默认值对损失值进行缩放,为了充分利用FP16的动态范围,可以更好地缓解舍入误差,尽量使用比较大的放大倍数。总结动态损失缩放算法,就是每当梯度溢出时候减少损失缩放规模,并且间歇性地尝试增加损失规模,从而实现在不引起溢出的情况下使用最高损失缩放因子,更好地恢复精度。
在混合精度的模型训练过程中,使用FP16进行矩阵乘法运算,利用FP32来进行矩阵乘法中间的累加(accumulated),然后再将FP32的值转化为FP16进行存储。简单而言,就是利用FP16进行矩阵相乘,利用FP32来进行加法计算弥补丢失的精度。这样可以有效减少计算过程中的舍入误差,尽量减缓精度损失的问题。
例如在Nvidia Volta 结构中带有Tensor Core,可以利用FP16混合精度来进行加速,还能保持精度。Tensor Core主要用于实现FP16的矩阵相乘,在利用FP16或者FP32进行累加和存储。在累加阶段能够使用FP32大幅减少混合精度训练的精度损失。
采用混合精度训练,模型能够:
(1)减少内存占用:FP16的位宽是FP32的一半,权重等参数所占内存也是原有精度下模型的一半,节省的内存可以用于更大规模模型和更多数据的训练;
(2)加快通讯效率:降低数据位宽可以提升通讯性能,减少机器等待的时间;
(3)提升计算效率:在一些加速芯片上,FP16的执行性能比FP32更快。
但采用FP16和FP32的混合精度训练,会带来以下两个问题:
(1)数据溢出:由于FP16的有效数据表示范围远远小于FP32,替换后模型的参数精度收到较大的影响,出现上溢(Overflow)和下溢(Underflow)的问题;
(2)舍入误差:当网络模型的反向梯度很小时,一些FP32能够表示的数值可能不能满足FP16精度下的表示范围,导致被强行舍入,带来误差。
量化是指用于执行计算并以低于浮点精度的位宽存储张量的技术。 量化模型对张量使用整数而不是浮点值执行部分或全部运算。 这允许更紧凑的模型表示,并在许多硬件平台上使用高性能矢量化操作。 与典型的 FP32 型号相比,PyTorch 支持 INT8 量化,从而可将模型大小减少 4 倍,并将内存带宽要求减少 4 倍。 与 FP32 计算相比,对 INT8 计算的硬件支持通常快 2 到 4 倍。 量化主要是一种加速推理的技术,并且量化算子仅支持前向传递。
PyTorch 支持多种方法来量化深度学习模型。 在大多数情况下,该模型在 FP32 中训练,然后将模型转换为 INT8。 此外,PyTorch 还支持量化意识训练,该训练使用伪量化模块对前向和后向传递中的量化误差进行建模。 注意,整个计算是在浮点数中进行的。 在量化意识训练结束时,PyTorch 提供转换功能,将训练后的模型转换为较低的精度。
在较低级别,PyTorch 提供了一种表示量化张量并对其执行操作的方法。 它们可用于直接构建以较低的精度执行全部或部分计算的模型。 提供了更高级别的 API,这些 API 合并了将 FP32 模型转换为较低精度并降低精度损失的典型工作流程。
量化用更少的比特表示数据,这使它成为一种减少内存使用和加速推理的技术,尤其是在涉及大型语言模型(LLM)时。有几种方法可以量化模型,包括:
模型被量化后,通常不会针对下游任务进行进一步训练,因为权重和激活的精度较低,训练可能不稳定。但由于PEFT方法只添加了额外的可训练参数,这允许您在顶部使用PEFT适配器来训练量化模型!将量化与PEFT相结合是在单个GPU上训练最大模型的好策略。例如,QLoRA是一种将模型量化为4位,然后使用LoRA进行训练的方法。
QLoRA可以显著减少内存使用,使得可以在单个48GB的GPU上微调一个有650亿参数的模型,同时保持16比特微调的性能。QLoRA通过冻结的、4比特量化的预训练语言模型来做 LoRA,进行反向传播梯度。作者提出的最佳模型命名为Guanaco,在Vicuna基准测试中超越了所有以前公开发布的模型,达到了ChatGPT性能水平的99.3%,而只需要在单个GPU上微调24小时。
QLORA引入了几项创新来节省内存而不牺牲性能,包括
作者使用 QLoRA 技术微调了 1000 多个模型来实验,在一些小型高质量数据集上可以做到 SOTA,甚至用更小的模型也能做到 SOTA。
值得注意的是,LoRA作为一种参数高效微调方法,其主要的内存占用来自于优化器状态(activation gradients),而不是LoRA参数。因此,QLoRA计算使用BF16的LoRA参数的权重梯度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。