量化是一種通過降低模型參數的表示精度來減少模型的大小和計算存儲需求的方法,如把單精度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
https://blog.csdn.net/liliang199/article/details/149246699