AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


从零开始学大模型 | 给大模型瘦身的艺术 - 向量化
发布日期:2024-04-16 15:12:15 浏览次数: 1717


引言

huggingface, github上开源大模型一般都会提供多种量化等级的模型,常见的比如,FP32,FP16,INT8,INT4,模型的介绍里面,不同等级的量化,对应不同的GPU资源需求。量化等级高的,比如FP32,可能得在专业显卡A100,H100上才能跑起来,低等级的INT8,普通显卡2080 6G显存就足够了。
那么,量化到底是什么意思,为什么不同等级,会对应不同的计算资源要求呢?

计算机里如何表示浮点数

开始之前,先介绍下计算机中是如何表示浮点数的。引言中FP,表示的是Float Point Representation。
计算机中使用二进制来表示所有数据,包括浮点数。常见的浮点数表示方式有IEEE 754标准定义的单精度(32位)和双精度(64位)格式。以双精度格式为例,64位中由3个部分组成:
  1. 符号位(sign)  1位  0表示正数,1表示负数
  2. 阶码(exponent) 11位  表示数值的阶数
  3. 尾数(fraction)  52位 表示有效数字部分(去掉最高位的1)
双精度能够表达的数据范围,要比单精度高。不管是CPU,还是GPU,在做计算的时候,需要把数据加载到内存或者显存里,之后,CPU,GPU才能读取到数据开始计算。精度不同,对内存的需求也就不同了。
对于大模型的场景,量化等级越高,我们模型参数能够表示的精度也就越高,对模型越能精确/准确地记住训练过程中的参数,相应的,内存的需求也就越大,反之则反。

什么是量化?

我们要介绍的量化,跟股票投资市场上讲的量化可不一样。不过也是有相通的地方,目的是一致的,就是把钱变多,一个是频繁交易,一个是降低资源需求,手段不同而已。
"Quantization"(量化)通常指的是一种压缩模型大小的技术,旨在加速推理过程,减少模型对存储和计算资源的需求。
它将模型中的参数(如权重和偏置),从使用较高精度(如32位浮点数)表示,转换为使用较低精度(如8位整数)表示的过程。通过这种方式,量化可以显著降低模型的存储需求,并且在许多硬件上能够加速模型的执行速度,因为较低精度的运算通常比较高精度的运算要快。
图中的FP32,占用 1 + 8 + 23 = 32个字节,也就是说,如果用FP32格式来存储浮点数,那么每个浮点数需要占用23个字节。我们常说的大模型,都是几十亿,甚至是千亿参数,那么,光参数就需要消耗非常大的内存,比如10亿参数就需要占用29.8G内存。
所以,对于这些真正意义上的大模型,你的消费级别的显卡,甚至是4090,要想跑起来也是不可能的。这种规模,其实对大企业也是非常贵的,降低成本的方式有好几种,我们先看下量化是如何做到降低计算规模的。

量化是如何做到降低计算规模的?

量化的过程包括几个关键步骤:
  1. 选择量化策略:这可能包括对权重、激活函数输出等进行静态量化(在模型训练完成后进行),或者动态量化(在模型推理时进行)。

  2. 确定量化参数:这包括为每个量化的元素选择最适合表示其分布的量化范围和精度。

  3. 应用量化:将模型参数和激活从浮点数转换为选定精度的整数。

  4. 量化意识训练(可选):有时,为了补偿由于量化引入的误差,模型会经过进一步的训练过程,以调整其权重以最小化量化的影响。

我们看个实际的例子,用已经训练好的模型来应用量化,所以,我们只需要关注上面提到的第三步就可以了。
拿huggingface上的“gpt2”来举例,量化之前,先看下内存大小:
model_name = "./models/gpt2"tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForCausalLM.from_pretrained(model_name)
# fix dtype post quantization to "pretend" to be fp32def get_float32_dtype(self):return torch.float32GPT2Model.dtype = property(get_float32_dtype)
# This will return the memory footprint of the current model in bytesmodel.get_memory_footprint() # 510342192 => 0.47GB
我们采用zero-point量化方案,对此模型做量化,降低参数的量化等级。其实就是把高精度浮点映射到低精度空间内:
计算过程如下:
1. 计算数据范围
首先,需要计算待量化数据的最小值和最大值。对于浮点型数据,可以使用以下公式计算:
r_min = min(x_1, x_2, ..., x_n)r_max = max(x_1, x_2, ..., x_n)
其中,x_1, x_2, ..., x_n 是待量化数据。
2. 计算缩放因子
然后,需要计算缩放因子。缩放因子用于将浮点型数据映射到整数型数据。缩放因子可以根据以下公式计算:
s = (r_max - r_min) / (q_max - q_min)
其中,q_max 和 q_min 是整数型数据的最大值和最小值。通常情况下,q_max 和 q_min 分别设置为 127 和 -128。
3. 计算零点
零点用于将浮点型数据中的 0 映射到整数型数据中的特定值。零点可以根据以下公式计算:
z = q_min - r_min / s
4. 进行量化
最后,可以使用以下公式进行量化:
q = round(x / s + z)
其中,x 是待量化数据,q 是量化后的数据。
具体到代码实现,可以通过下面的方法来做:
def quantize(t):# obtain range of values in the tensor to map between 0 and 255min_val, max_val = t.min(), t.max()
# determine the "zero-point", or value in the tensor to map to 0scale = (max_val - min_val) / 255zero_point = min_val
# quantize and clamp to ensure we're in [0, 255]t_quant = (t - zero_point) / scalet_quant = torch.clamp(t_quant, min=0, max=255)
# keep track of scale and zero_point for reversing quantizationstate = (scale, zero_point)
# cast to uint8 and returnt_quant = t_quant.type(torch.uint8)return t_quant, state    quant_model, states = quantize_model(model)quant_model.get_memory_footprint() # 137022768 => 0.12G
可以看到,量化后,内存大小降低到0.12G,降低了~74%。当然,降低量化等级,参数的精度就降低了,也就意味着模型可能会有损。
量化可以大幅度提高模型的部署效率,特别是在资源受限的环境中,如移动设备和嵌入式系统。然而,量化也可能会导致模型精度的损失,因此在应用量化时需要权衡精度损失与性能提升之间的关系。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询