量化是一种通过降低模型参数的表示精度来减少模型的大小和计算存储需求的方法,如把单精度fp32转化为int8来减少存储和计算成本。
常见的是线性量化,公式 r = S(q-Z),将实数值r映射为量化的整数值q,其中缩放因子S和零点Z根据参数分布统计计算得来。
以下是几种llama.cpp采用的主要量化方法。
1 传统量化方法
Qx_y命名,x是量化位数,比如4、5、6等,y是0或1,0表示对称量化,1表示非对称量化。
对称量化是在正负范围内是对称的,零点是0。
w = q * block_scale
非对称量化允许零点偏移,适应于数据均值非0的情况,因此也比对称量化多一个参数。
w = q * block_scale + block_minimum
每个量化块包含32个权重,量化权重可以通过位移、按位与和乘法来快速解码,对非对称变体还需要加法。
llama.cpp传统量化示例:
Q8_0: 8-bit舍入到最近值量化,每个块32个权重,权重公式: w = q * block_scale
.
Q8_1: 8-bit 舍入到最近值量化,每个块32个权重, 权重公式: w = q * block_scale + block_minimum
.
Q4_0: 5-bit舍入到最近值量化,每个块32个权重,权重公式: w = q * block_scale
.
Q4_1: 5-bit 舍入到最近值量化,每个块32个权重, 权重公式: w = q * block_scale + block_minimum
.
Q4_0: 4-bit舍入到最近值量化,每个块32个权重,权重公式: w = q * block_scale
.
Q4_1: 4-bit 舍入到最近值量化,每个块32个权重, 权重公式: w = q * block_scale + block_minimum
.
2 K系列量化方法
不仅对权重进行量化,还对尺度因子block_scale和零点block_minimum再次进行量化,实现层次化的量化。
每256个权重组成一个超级块,层次化量化过程如下
1)首先以组大小16,对权重进行初始量化,如此1个超级块有256/16=16个尺度因子。
2)对初始尺度因子再次进行量化,得到一个二阶的尺度因子,减少了存储这些辅助信息的空间。
llama.cpp K系列量化示例:
Q8_K: 8位量化,每个超块有256个权重,仅用于量化中间结果,适用于2-6位点积运算,权重公式 w = q * block_scale
Q6_K: 8位量化,超块有16个块组成,每个块16个权重,权重公式 w = q * block_scale(8位),平均每个权重6.5625位。
Q5_K: 5位量化,超块有8个块组成,每个块32个权重,权重公式 w = q * block_scale(6位) + block_minimum(6位)
,平均每个权重5.5位。
Q4_K: 4位量化,超块有8个块组成,每个块32个权重,权重公式 w = q * block_scale(6位) + block_minimum(6位)
,平均每个权重4.5位。
Q3_K: 3位量化,超块有16个块组成,每个块16个权重,权重公式 w = q * block_scale(6位) ,平均每个权重3.4375位。
Q2_K: 4位量化,超块有8个块组成,每个块32个权重,权重公式 w = q * block_scale(4位) + block_minimum(4位)
,平均每个权重2.5625位。
3 IQ系列量化方法
使用了矢量量化和重要性矩阵
1)矢量量化,就是将多个权重视为一个矢量,在高维空间一起量化,捕捉了权重之间的相关性。这些矢量被影射到一个预训练码本(cookbook)中的某个条目,如此条目编号就可以表示一起量化的n个权重,所需空间约为原始权重空间的1/n。
2)重要性矩阵,利用重要性矩阵对权重进行分组,评估每个权重或组的重要性程度,对重要的权重使用更精细和码本或更高的量化精度,对不太重要的权重使用更粗略的码本或更低的量化精度。
这类量化方法还有一些特别后缀,比如M、S、XS、XXS,表示的是码本的精细程度,码本越小,模型的压缩率越大。
llama.cpp IQ系列量化示例:
IQ4_NL: 4位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得。
IQ4_XS: 4位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重4.25位。
IQ3_S: 3位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重3.44位。
IQ3_XXS: 3位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重3.06位。
IQ2_XXS: 2位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重2.06位。
IQ2_S: 2位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重2.5位。
IQ2_XS: 2位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重2.31位。
IQ1_S: 1位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重1.56位。
IQ1_M: 1位量化,每个超块有256个权重,权重通过super_block_sacle和重要性矩阵获得,平均每权重1.75位。
---
llama.cpp
https://github.com/ggml-org/llama.cpp
gguf
https://huggingface.co/docs/hub/gguf
GGUF量化原理详解
https://www.zhihu.com/question/633365088
在mac m1基于llama.cpp运行deepseek