大模型的量化和浮点数调整
大模型的量化是一种通过降低模型参数精度来优化模型的技术,其核心是将模型的浮点数参数(如32位浮点数FP32)转换为低精度的整数或定点数(如8位整数INT8或4位整数INT4),从而实现模型的压缩和优化,要想理解什么是大模型的量化,我们先要了解什么是浮点数。
1.什么是浮点数
浮点数(Floating Point Number) 是一种用于表示实数(包括小数)的数值格式,广泛应用于计算机科学和工程计算中。浮点数通过将数字表示为“尾数”和“指数”的形式,能够在有限的位数内表示非常大或非常小的数值。在大模型中的各种参数 都是以浮点数的形式保存的。
1.1 浮点数的保存方式
在计算机中内存中,浮点数被表示为二进制数,只用零和一表示。在了解浮点数之前还要补充几个概念:
注意:以32位浮点数为例
- 符号位(S):1位,表示数字的正负(0表示正,1表示负)。
- 指数位(Exponent):8位,表示2的幂次。
- 尾数位(Mantissa,也称小数部分):23位,表示小数部分。
浮点数的实际值通过以下公式计算:
V a l u e = ( − 1 ) S × 2 E − b i a s × ( 1 + M ) Value = (-1)^S \times 2^{E-bias} \times (1 + M) Value=(−1)S×2E−bias×(1+M)
- S 是符号位。
- E 是指数位的值。
- Bias 是偏移量,对于FP32,偏移量为127。
- M 是尾数位的值,表示为二进制小数。
为什么要偏移量
在浮点数表示中,偏移量(Bias) 是一个固定的数值,用于调整指数部分的表示范围,使得浮点数能够表示正指数和负指数。偏移量是 IEEE 754 标准中浮点数表示的一个重要组成部分。
有人说那指数部分也使用符号位来表示不就好了嘛,也就是有符号数来表示。
有符号整数(Signed Integer):
有符号整数使用一个单独的符号位来表示正负,通常采用**补码(Two’s Complement)**表示法。例如,对于一个8位有符号整数:
- 最高位(第8位)是符号位:0表示正数,1表示负数。
- 其余7位表示数值。
例如:
- 00000001 表示 +1
- 11111111 表示 -1(补码表示)
补码表示法的优点是简化了加法和减法运算,但它的缺点是表示范围不完全对称。例如,一个8位有符号整数的范围是 -128 到 +127。
无符号整数(Unsigned Integer):
无符号整数不包含符号位,所有位都用于表示数值。因此,无符号整数只能表示非负数。例如,一个8位无符号整数的范围是 0 到 255。
(1)浮点数指数的表示需求
浮点数的指数部分需要表示正指数和负指数。例如,一个非常小的数可能需要表示为 2 − 100 2^{-100} 2−100,而一个非常大的数可能需要表示为 2 100 2^{100} 2100。然而,直接使用有符号整数来表示指数会带来一些问题:
- 表示范围不完全对称:有符号整数的范围是不对称的(如 -128 到 +127),这在浮点数表示中是不理想的。
- 硬件实现复杂:有符号整数的运算需要考虑符号位,这会增加硬件设计的复杂性。
(2)偏移量的作用
为了解决这些问题,IEEE 754 标准引入了偏移量(Bias),将指数部分转换为无符号整数。具体来说:
- 偏移量将指数的表示范围从负数偏移到正数。
- 这样,指数部分可以用无符号整数表示,简化了硬件设计和运算。
例如,对于单精度浮点数(FP32):
- 指数部分有8位,偏移量为127。
- 实际指数范围为 -126 到 +127(不考虑特殊值)。
- 加上偏移量后,存储的指数范围为 1 到 254,完全在无符号整数的范围内。
例子:将浮点数10.5保存到内存中
步骤1:将10.5转换为二进制
首先,将10.5转换为二进制:
- 整数部分:10的二进制是 1010 。
- 小数部分:0.5的二进制是 0.1 (因为0.5 = 1/2)。
- 因此,10.5的二进制表示为 1010.1 。
步骤2:规范化表示
将二进制数规范化为科学计数法的形式:
1010.1
=
1.0101
×
2
3
1010.1 = 1.0101 \times 2^3
1010.1=1.0101×23
这里,尾数部分为 1.0101 ,指数为3。
步骤3:计算指数位
E = 3 + 127 = 130 E=3+127=130 E=3+127=130
这里,尾数部分为1.0101,指数为3
步骤4:提取尾数位
尾数部分1.0101中,小数点后的部分0101是尾数位。在FP32中,尾数位需要扩展到23位:
M=01010000000000000000000
步骤5:组合符号位、指数位和尾数位
- 符号位 S:因为10.5是正数,所以符号位为0。
- 指数位 E:10000010
- 尾数位 M:01010000000000000000000
将它们组合在一起:
- 符号位(1位):0
- 指数位(8位):10000010
- 尾数位(23位):01010000000000000000000
因此,10.5的二进制表示为:
0 10000010 01010000000000000000000
1.2 浮点数的精度
1.2.1 单精度浮点数(FP32)
- 位数:32位
格式:
- 第1位(最高位):符号位(S),0表示正数,1表示负数。
- 第2到第9位(共8位):指数位(Exponent),用于表示2的幂次。
- 第10到第32位(共23位):尾数位(Mantissa),表示小数部分
精度:大约7位十进制有效数字
范围:
最小正正规数:
1.175494
×
1
0
−
38
1.175494 \times 10^−38
1.175494×10−38
最大正正规数:
3.402823
×
1
0
38
3.402823 \times 10^{38}
3.402823×1038
1.2.2 双精度浮点数(FP64)
- 位数:64位(8字节)
格式:
- 第1位(最高位):符号位(S),0表示正数,1表示负数。
- 第2到第12位(共11位):指数位Exponent),用于表示2的幂次。
- 第13到第64位(共52位):尾数位(Mantissa),表示小数部分。
精度:大约15-17位十进制有效数字
范围:
最小正正规数: 2.225074 × 1 0 − 308 2.225074 \times 10^−308 2.225074×10−308
最大正正规数: 1.797693 × 1 0 308 1.797693 \times 10^{308} 1.797693×10308
1.2.3 半精度浮点数(FP16)
- 位数:16位(2字节)
格式:
- 第1位(最高位):符号位(S),0表示正数,1表示负数。
- 第2到第6位(共5位):指数位(Exponent),用于表示2的幂次。
- 第7到第16位(共10位):尾数位(Mantissa),表示小数部分。
精度:大约15-17位十进制有效数字
范围:
最小正正规数: 6.103516 × 1 0 − 5 6.103516 \times 10^−5 6.103516×10−5
最大正正规数: 6.550400 × 1 0 4 6.550400 \times 10^{4} 6.550400×104
2. 量化
大模型的量化是一种通过降低模型参数精度来优化模型的技术,其核心是将模型的浮点数参数(如32位浮点数FP32)转换为低精度的整数或定点数(如8位整数INT8或4位整数INT4),从而实现模型的压缩和优化
假如我以一个30亿参数(3B)的模型为例,不同浮点数格式下的内存占用情况如下:
FP32(32位浮点数):
- 内存占用:每个参数占用4字节。
- 总内存需求:3B × 4字节 ≈ 12GB。
- 特点:精度最高,但内存占用大,适合对精度要求极高的研究场景
FP16(16位浮点数):
- 内存占用:每个参数占用2字节。
- 总内存需求:3B × 2字节 ≈ 6GB。
- 特点:精度略有损失,但内存占用减少一半,适合GPU推理。
我们可以看到为什么大家都在搞大模型量化了,节省的内存和显存不是一点半点。甚至也能够加快推理速度。
大模型量化并不一定是对模型中的所有参数进行量化,具体是否量化以及量化哪些参数,取决于量化的目标、模型的特性以及应用场景。以下是一些常见的量化策略和情况:
2.2 量化的类型
1. 部分量化(Selective Quantization)
在实际应用中,通常会选择对模型中计算量大或存储需求高的部分进行量化,而不是对所有参数进行量化。例如:
- 权重(Weights):模型的权重参数通常会进行量化,因为它们占用了大量的存储空间,并且在推理过程中需要频繁计算。
- 激活值(Activations):激活值也可以进行量化,但有时会根据具体需求选择性量化,因为它们的动态范围可能较大,需要更谨慎地处理。
- 偏置(Biases):偏置参数通常较小,对存储和计算的影响有限,有时会被保留为浮点数,不进行量化。
2. 分层量化(Layer-wise Quantization)
在一些情况下,模型的不同层可能会根据其重要性和计算需求选择不同的量化策略:
- 关键层(如Transformer中的注意力机制):可能需要更高的精度,因此可能不量化或仅进行轻量化。
- 非关键层(如某些全连接层):可以进行更激进的量化以节省资源。
- 某些层可能完全不量化:例如,某些层可能对精度非常敏感,量化后会导致性能大幅下降。
3. 混合精度量化(Mixed Precision Quantization)
混合精度量化是一种常见的策略,即在模型中同时使用不同精度的参数。例如:
- 权重可以量化为INT8,而激活值保留为FP16:这种策略可以在节省存储和计算资源的同时,尽量减少精度损失。
- 关键层使用FP16,非关键层使用INT8:通过灵活调整精度,平衡模型性能和资源占用。
4. 动态量化与静态量化
- 动态量化:只在推理时对激活值进行量化,权重保持浮点数形式。这种方式适用于需要快速部署的场景,但对精度的影响较小。
- 静态量化:对权重和激活值都进行量化,通常需要在训练后或训练过程中进行校准,以确保量化后的模型性能。
5. 特殊层的处理
在某些情况下,一些特殊层(如归一化层、嵌入层)可能不适合量化,或者需要特殊的量化策略。例如:
- LayerNorm(层归一化):由于其计算依赖于精确的均值和方差,可能不适合量化,或者需要采用特殊的量化方法。
- Embedding层:由于其稀疏性,可能需要特殊的量化策略,如稀疏量化。
总结
大模型量化并不是简单地对所有参数进行量化,而是根据模型的结构、性能需求和应用场景,灵活选择量化策略和量化范围。通过部分量化、混合精度量化和分层量化等方法,可以在节省资源的同时,尽量减少对模型性能的影响。
作者码字不易,觉得有用的话不妨点个赞吧,关注我,持续为您更新AI的优质内容。