「模型量化技術(shù)」可視化指南:A Visual Guide to Quantization 原創(chuàng) 精華
編者按:隨著大語(yǔ)言模型(LLMs)規(guī)模的不斷擴(kuò)大,如何在有限的計(jì)算資源下高效部署這些模型成為了一個(gè)迫切需要解決的問題。模型量化作為一種有效的模型壓縮技術(shù),在保持模型性能的同時(shí)大大降低了計(jì)算和存儲(chǔ)開銷,因此廣受關(guān)注。但對(duì)于許多人來(lái)說,模型量化的具體原理和實(shí)現(xiàn)方法仍然是一個(gè)“黑盒”。
我們今天為大家?guī)?lái)的這篇文章,通過可視化圖示詳細(xì)解析各種模型量化技術(shù)的原理和實(shí)現(xiàn)方法,為各位讀者提供一個(gè)全面且直觀的模型量化技術(shù)指南。
本文旨在幫助各位讀者涉獵以下技能領(lǐng)域:
- 理解模型量化技術(shù)的基本原理和作用
- 掌握多種模型量化方法及其優(yōu)缺點(diǎn)
- 學(xué)會(huì)如何選擇合適的量化方法,并根據(jù)實(shí)際場(chǎng)景進(jìn)行調(diào)整
我們分享這篇全面且深入的技術(shù)解析,期望各位讀者不僅能夠理解模型量化的基本原理,還能洞察該領(lǐng)域的最新發(fā)展趨勢(shì)。隨著模型量化技術(shù)的不斷進(jìn)步,我們有理由相信,未來(lái)將會(huì)出現(xiàn)更加高效、更輕量級(jí)的大語(yǔ)言模型,為 AI 技術(shù)的更廣泛應(yīng)用鋪平道路。
作者 ?? | Maarten Grootendorst
編譯 ?? | 岳揚(yáng)
目錄??
01 第 1 部分:LLMs 存在的“問題”
1.1 參數(shù)數(shù)值(value)的表示方法
1.2 內(nèi)存限制問題
02 第 2 部分:模型量化技術(shù)簡(jiǎn)介
2.1 常用的數(shù)據(jù)類型
2.1.1 FP16
2.1.2 BF16
2.1.3 INT8
2.2 對(duì)稱量化 Symmetric Quantization
2.3 非對(duì)稱量化 asymmetric quantization
2.4 取值范圍的映射與裁剪
2.5 校準(zhǔn)過程 Calibration
2.5.1 權(quán)重(和偏置項(xiàng)) Weights (and Biases)
2.5.2 激活值
03 第 3 部分:Post-Training Quantization
3.1 動(dòng)態(tài)量化(Dynamic Quantization)
3.2 靜態(tài)量化(Static Quantization)
3.3 探索 4-bit 量化的極限
3.3.1 GPTQ
3.3.2 GGUF
04 第 4 部分:Quantization Aware Training
4.1 1-bit LLM 的時(shí)代:BitNet
4.2 權(quán)重的量化 Weight Quantization
4.3 激活值的量化 Activation Quantization
4.4 反量化過程 Dequantization
4.5 所有 LLMs 實(shí)際上均為 1.58-bit
4.5.1 The Power of 0
4.5.2 Quantization 量化過程
05 Conclusion
Resources
文中鏈接??
顧名思義,大語(yǔ)言模型(Large Language Models,LLMs)的特點(diǎn)就是龐大,以至于普通的消費(fèi)級(jí)硬件都難以承載。這些模型的參數(shù)量級(jí)可達(dá)數(shù)十億,而且在進(jìn)行推理時(shí),往往需要依賴擁有大量顯存(VRAM)的 GPU 來(lái)加快推理速度。
鑒于此,越來(lái)越多的研究者將目光投向如何通過優(yōu)化訓(xùn)練方法、使用適配器(adapters)等技術(shù)來(lái)縮小模型體積。在這一領(lǐng)域,模型量化(quantization)技術(shù)成為了一個(gè)重要的研究方向。
本篇文章將帶領(lǐng)大家深入了解語(yǔ)言模型領(lǐng)域的量化技術(shù),并逐一探討相關(guān)概念,幫助大家建立起對(duì)這一領(lǐng)域的直觀認(rèn)識(shí)。我們將一起探索不同的量化方法、實(shí)際應(yīng)用場(chǎng)景,以及模型量化技術(shù)的基本原理。
本文將提供許多圖表(visualizations)來(lái)幫助各位讀者更好地理解和掌握模型量化技術(shù)這一概念,希望大家能夠直觀、深入地理解模型量化技術(shù)。
01 第 1 部分:LLMs 存在的“問題”
大語(yǔ)言模型之所以被稱為“大”,是因?yàn)槠鋮?shù)數(shù)量十分之龐大。目前,這類模型的參數(shù)數(shù)量通常能夠達(dá)到數(shù)十億之巨(主要是指權(quán)重參數(shù)(weights)),這樣的數(shù)據(jù)量其存儲(chǔ)成本無(wú)疑是一筆巨大的開銷。
在模型的推理過程中,激活值(譯者注:activations,神經(jīng)網(wǎng)絡(luò)中某個(gè)層對(duì)輸入數(shù)據(jù)應(yīng)用激活函數(shù)后產(chǎn)生的輸出值。)是通過輸入數(shù)據(jù)(input)與模型權(quán)重(weights)相乘等一系列步驟來(lái)生成的,這些激活值的數(shù)據(jù)量也可能非常龐大。
因此,我們的目標(biāo)是找到一種盡可能高效的方式來(lái)表達(dá)數(shù)十億個(gè)參數(shù),以減少存儲(chǔ)每個(gè)參數(shù)所需的空間。
在開始對(duì)這些參數(shù)進(jìn)行優(yōu)化之前,我們從最基本的部分入手,先探討一下參數(shù)數(shù)值(value)在計(jì)算機(jī)中最初是如何表示的。
1.1 參數(shù)數(shù)值(value)的表示方法
在計(jì)算機(jī)科學(xué)中,特定的數(shù)值(value)通常都以浮點(diǎn)數(shù)的形式來(lái)表示,即帶有正負(fù)號(hào)和小數(shù)點(diǎn)的數(shù)字。
這些數(shù)值是由 “bits” 組成的,也就是由二進(jìn)制數(shù)字表示。根據(jù) IEEE-754 標(biāo)準(zhǔn)[1],這些 “bits” 可以用來(lái)表示三個(gè)不同的部分,從而構(gòu)成一個(gè)完整的數(shù)值(value):符號(hào)位、指數(shù)部分以及小數(shù)部分(也稱為尾數(shù))。
這三個(gè)部分結(jié)合起來(lái),就能根據(jù)一組特定的 “bit” 值來(lái)計(jì)算出一個(gè)具體的數(shù)值(value):
一般來(lái)說,用來(lái)表示數(shù)值(value)的 “bit” 越多,得到的數(shù)值(value)精確度就越高:
1.2 內(nèi)存限制問題
可用的 “bits” 數(shù)量越多,所能表示的數(shù)值范圍就越大。
一個(gè)特定的數(shù)值表示法能夠表示的所有數(shù)值的區(qū)間被稱為動(dòng)態(tài)范圍(dynamic range) ,而相鄰兩個(gè)數(shù)值之間的間隔則被稱為精度(precision) 。
使用這些 “bits” 的一個(gè)有趣功能是,我們可以計(jì)算出存儲(chǔ)一個(gè)特定數(shù)值(value)所需的設(shè)備內(nèi)存量。由于一個(gè)字節(jié)(byte)占 8 位(bits),我們可以為大多數(shù)浮點(diǎn)表示形式(floating point representation)制定一個(gè)基本的計(jì)算公式。
Note:在實(shí)際應(yīng)用中,模型推理階段所需的顯存(VRAM)量還受到諸多因素的影響,比如模型處理上下文的大小和模型架構(gòu)設(shè)計(jì)。
假設(shè)我們有一個(gè)擁有 700 億參數(shù)的模型。通常情況下,這些模型默認(rèn)使用 32 位浮點(diǎn)數(shù)(常稱為全精度)進(jìn)行表示,僅加載模型就需要 280GB 內(nèi)存。
因此,盡可能地減少用于表示模型參數(shù)的 “bits” 數(shù)量(包括模型訓(xùn)練過程中也是如此)是非常有必要的。但是,有一點(diǎn)必須注意,精度的降低往往會(huì)導(dǎo)致模型準(zhǔn)確性下降。
我們的目標(biāo)是減少用于表示模型參數(shù)的 “bits” 數(shù)量,同時(shí)又不損害模型的準(zhǔn)確性…… 這就是模型量化技術(shù)的作用所在!
02 第 2 部分:模型量化技術(shù)簡(jiǎn)介
模型量化的核心在于將模型參數(shù)的精度從較高的位寬(bit-widths)(例如 32 位浮點(diǎn)數(shù))降低到較低的位寬(bit-widths)(例如 8 位整數(shù))。
在減少參數(shù)的 “bits” 數(shù)量時(shí),通常會(huì)出現(xiàn)一定的精度損失(即丟失一些數(shù)值細(xì)節(jié))。
為了更直觀地說明這種影響,我們可以嘗試將任意一張圖片僅用 8 種顏色來(lái)表示:
該圖像基于 Slava Sidorov 的原作[2]進(jìn)行了修改
觀察放大區(qū)域,我們可以發(fā)現(xiàn)它比原始圖片看起來(lái)更加“粗糙”,因?yàn)槭褂玫念伾N類減少了。
模型量化的主要目的就是減少表示原始參數(shù)所需的 “bits” 數(shù)量(在上述案例中即為顏色種類),同時(shí)盡可能保留原始參數(shù)的精度。
2.1 常用的數(shù)據(jù)類型
首先,我們來(lái)看看一些常見的數(shù)據(jù)類型,以及它們與 32-bit(全精度(full-precision)或 FP32 )表示法相比的影響。
2.1.1 FP16
以從 32-bit 轉(zhuǎn)換到 16-bit(半精度或 FP16 )的浮點(diǎn)數(shù)為例:
可以看到,F(xiàn)P16 的數(shù)值范圍比 FP32 要窄得多。
2.1.2 BF16
為了保持與原始 FP32 相似的數(shù)值范圍,引入了 bfloat 16 這一數(shù)據(jù)類型,它類似于“截?cái)喟娴腇P32”:
BF16 雖然使用的 “bits” 數(shù)量與 FP16 相同,但能表示的數(shù)值范圍更廣,因此在深度學(xué)習(xí)領(lǐng)域內(nèi)得到了廣泛應(yīng)用。
2.1.3 INT8
當(dāng)我們需要再進(jìn)一步減少 “bits” 的數(shù)量時(shí),就到了整數(shù)表示法施展身手的領(lǐng)域,而不再是浮點(diǎn)數(shù)表示法。例如,從 FP32 轉(zhuǎn)換為僅有 8 bits 的 INT8,其占用的 bits 數(shù)量?jī)H僅是原來(lái)的四分之一:
有些硬件優(yōu)化了整數(shù)運(yùn)算,因此在這些硬件上整數(shù)運(yùn)算可能會(huì)更高效。然而,并不是所有硬件都進(jìn)行了這樣的優(yōu)化。不過,一般來(lái)說,使用較少的 “bits” 數(shù)量,計(jì)算速度通常會(huì)更快一些。
每減少一個(gè) bits ,就需要進(jìn)行一次映射(mapping)操作,將原本的 FP32 表示形式“壓縮”到更少的 “bits” 數(shù)量。
在實(shí)際應(yīng)用中,我們并不需要將 FP32 所表示的全部數(shù)值范圍 [-3.4e38, 3.4e38] 都映射到 INT8。我們只需找到一種方法,將數(shù)據(jù)(即模型參數(shù))范圍映射到 INT8 即可。
常用的壓縮(squeezing)和映射(mapping)方法包括對(duì)稱量化(symmetric quantization)和非對(duì)稱量化(asymmetric quantization),它們都是線性映射(linear mapping)的不同形式。
接下來(lái),我們將探討一下這些將 FP32 量化為 INT8 的方法。
2.2 對(duì)稱量化 Symmetric Quantization
在對(duì)稱量化過程中,原本浮點(diǎn)數(shù)的值域會(huì)被映射到量化空間(quantized space)中一個(gè)以零為中心的對(duì)稱區(qū)間。從前面的例子可以看出,量化前后的值域都是圍繞零點(diǎn)對(duì)稱的。
這就意味著,在浮點(diǎn)數(shù)中表示零的值,在量化空間中仍然是正好為零。
對(duì)稱量化(symmetric quantization)有一種經(jīng)典方法是絕對(duì)最大值(absmax,absolute maximum)量化。
具體操作時(shí),我們會(huì)從一組數(shù)值中找出最大的絕對(duì)值(α),以此作為線性映射的范圍(譯者注:從 -α 到 +α)。
Note:值域 [-127, 127] 代表的是受限制??的范圍,而 8-bit 整數(shù)可以表示的完整范圍是[-128, 127],選擇哪種范圍取決于所采用的量化方法。
由于這是一種以零為中心的線性映射(linear mapping),所以計(jì)算公式相對(duì)簡(jiǎn)單。
我們首先根據(jù)以下公式計(jì)算比例因子(s):
- b 是我們想要量化到的字節(jié)數(shù)(譯者注:原文為“Byte”,此處保留原義,譯為字節(jié)數(shù),譯者認(rèn)為可能為 bits 數(shù)量)(這里是 8 ),
- α 是最大絕對(duì)值,
接著,我們用這個(gè)比例因子 s 來(lái)量化輸入值 x:
將這些數(shù)值代入公式后,我們將得到以下結(jié)果:
為了恢復(fù)原始的 FP32 值,我們可以使用之前計(jì)算出的比例因子(s)來(lái)對(duì)量化后的數(shù)值進(jìn)行反量化(dequantize)。
先量化后再反量化以恢復(fù)原始值的過程如下所示:
我們可以觀察到,某些值(如 3.08 和 3.02 )在量化到 INT8 后,都被分配了相同的值 36。當(dāng)這些值反量化(dequantize)回 FP32 時(shí),會(huì)丟失一些精度,變得無(wú)法再區(qū)分。
這種現(xiàn)象通常被稱為量化誤差(quantization error) ,我們可以通過比較原始值(original values)和反量化值(dequantized values)之間的差值來(lái)計(jì)算這個(gè)誤差。
一般來(lái)說,“bits” 的數(shù)量越少,量化誤差往往越大。
2.3 非對(duì)稱量化 asymmetric quantization
與對(duì)稱量化(symmetric around)不同,非對(duì)稱量化并不是以零為中心對(duì)稱的。 它將浮點(diǎn)數(shù)范圍中的最小值(β)和最大值(α)映射到量化范圍(quantized range)的最小值和最大值。
我們?cè)诖艘接懙姆椒ǚQ為零點(diǎn)量化。
各位注意到 0 的位置是如何移動(dòng)的嗎?這正是它被稱為“非對(duì)稱量化”的原因。在區(qū)間 [-7.59, 10.8] 中,最小值和最大值與零點(diǎn)之間的距離是不相等的。
由于零點(diǎn)位置的偏移,我們需要計(jì)算 INT8 范圍的零點(diǎn)來(lái)進(jìn)行線性映射(linear mapping)。與之前一樣,我們還需要計(jì)算一個(gè)比例因子(s),但這次要使用 INT8 范圍( [-128, 127] )的兩個(gè)端點(diǎn)之間的差值。
請(qǐng)注意,由于需要計(jì)算 INT8 取值范圍中的零點(diǎn)(z)來(lái)調(diào)整權(quán)重,這個(gè)過程稍微復(fù)雜一些。
和之前一樣填入公式:
要將從 INT8 量化后的數(shù)值反量化回 FP32 ,需要使用之前計(jì)算的比例因子(s)和零點(diǎn)(z)。
除此之外,反量化過程則相對(duì)比較直接:
當(dāng)我們將對(duì)稱量化和非對(duì)稱量化放在一起對(duì)比時(shí),我們可以迅速看出這兩種方法之間的差異:
Note:請(qǐng)注意對(duì)稱量化(symmetric quantization)以零點(diǎn)為中心的特性,以及非對(duì)稱量化(asymmetric quantization)存在的零點(diǎn)偏移。
2.4 取值范圍的映射與剪裁
在前文所舉的例子中,我們研究了如何將向量中的數(shù)值映射到更低的位表示形式(lower-bit representation)中。雖然這樣使得向量的全范圍都能被映射,但有一個(gè)明顯的缺點(diǎn),那就是有離群值(outlier)時(shí)不太好處理。
假設(shè)有一個(gè)向量,其值如下:
請(qǐng)注意,如果其中一個(gè)數(shù)值(value)遠(yuǎn)大于其他所有數(shù)值,該數(shù)值就可以被視作離群值(outlier)。 如果我們要映射這個(gè)向量的全部數(shù)值,那么所有較小的數(shù)值都將映射到相同的較低位表示,并因此失去它們的獨(dú)特特性:
這就是我們之前使用的 absmax 方法。請(qǐng)注意,如果我們不進(jìn)行剪裁(clipping),非對(duì)稱量化也會(huì)出現(xiàn)這樣的問題。
另一種選擇是裁剪(clip)掉某些數(shù)值。裁剪(Clipping)操作會(huì)為原始值設(shè)定一個(gè)不同的動(dòng)態(tài)范圍,這樣所有離群值都會(huì)被映射到相同的值。
在下文給出的案例中,如果我們手動(dòng)將動(dòng)態(tài)范圍設(shè)置為 [-5, 5] ,所有超出這個(gè)范圍的數(shù)值無(wú)論其原始值是多少,都將被映射為 -127 或 127 :
這種方法的主要優(yōu)點(diǎn)是,顯著減少了非離群值的量化誤差。然而,離群值的量化誤差卻增加了。
2.5 校準(zhǔn)過程 Calibration
在前文的示例中,我展示了一種簡(jiǎn)單方法 —— 即任意選擇一個(gè)取值范圍 [-5, 5]。這個(gè)過程被稱為校準(zhǔn)(calibration),其目的是找到一個(gè)能夠包含盡可能多數(shù)值(values)的范圍,同時(shí)盡量減少量化誤差(quantization error)。
對(duì)于不同類型的參數(shù),執(zhí)行校準(zhǔn)步驟的方法并不相同。
2.5.1 權(quán)重(和偏置項(xiàng)) Weights (and Biases)
在 LLMs 中,我們可以將權(quán)重(weights)和偏置項(xiàng)(Biases)視為預(yù)先確定的靜態(tài)值,因?yàn)檫@些值在運(yùn)行模型之前就已經(jīng)確定了。例如,Llama 3 的約 20 GB 文件[3]中大部分都是其權(quán)重和偏置項(xiàng)。
由于偏置項(xiàng)的數(shù)量(以百萬(wàn)計(jì))遠(yuǎn)少于權(quán)重(以數(shù)十億計(jì)),偏置項(xiàng)通常被保留在更高的精度(如 INT16 ),而量化的主要工作則集中在權(quán)重的處理上。
因?yàn)闄?quán)重是靜態(tài)且已知的,所以對(duì)其的量化技術(shù)可以有:
- 手動(dòng)選擇輸入范圍的百分位數(shù)
- 優(yōu)化原始權(quán)重和量化權(quán)重之間的均方誤差(MSE)
- 最小化原始值和量化值之間的熵(KL 散度)
例如,第一種方法(手動(dòng)選擇輸入范圍的百分位數(shù))會(huì)導(dǎo)致出現(xiàn)與前文我們看到的相似的裁剪(clipping)行為。
2.5.2 激活值
在 LLMs 中, 那些在整個(gè)推理過程中持續(xù)更新的輸入(input)通常被稱為“激活值”(activations)。
請(qǐng)注意,這些值之所以被稱為激活值,是因?yàn)樗鼈兘?jīng)常需要經(jīng)過某些激活函數(shù)處理,比如 sigmoid 或 relu。
與權(quán)重不同,激活值會(huì)隨著每次輸入數(shù)據(jù)的改變而變化,因此很難對(duì)其進(jìn)行精確量化。
由于這些值在每個(gè)隱藏層之后都會(huì)更新,因此我們只能在輸入數(shù)據(jù)通過模型時(shí)才能預(yù)測(cè)它們?cè)谕评磉^程中的具體數(shù)值。
一般來(lái)說,校準(zhǔn)權(quán)重和激活值的量化方法主要有兩種:
- Post-Training Quantization(PTQ)— 訓(xùn)練完成后進(jìn)行量化
- Quantization Aware Training(QAT)— 訓(xùn)練/微調(diào)過程中同時(shí)進(jìn)行量化
03 第 3 部分:Post-Training Quantization
在眾多量化技術(shù)中,post-training quantization(PTQ)是最為流行的一種。這種方法是在訓(xùn)練完模型之后對(duì)模型的參數(shù)(包括權(quán)重和激活值)進(jìn)行量化。
對(duì)于權(quán)重值的量化可以采用對(duì)稱量化(symmetric quantization) 或非對(duì)稱量化(asymmetric quantization) 兩種方式。
至于激活值,由于我們不知道其范圍,因此需要通過模型的推理來(lái)獲取它們的 potential distribution(譯者注:指的是在不同的輸入數(shù)據(jù)和模型參數(shù)下,激活值可能出現(xiàn)的一系列數(shù)值。了解這個(gè)分布有助于我們選擇一個(gè)能夠包含大部分激活值范圍的量化級(jí)別,從而減少量化誤差。),然后再進(jìn)行量化。
激活值的量化主要有兩種形式:
- 動(dòng)態(tài)量化(Dynamic Quantization)
- 靜態(tài)量化(Static Quantization)
3.1 動(dòng)態(tài)量化(Dynamic Quantization)
當(dāng)數(shù)據(jù)通過隱藏層時(shí),其激活值會(huì)被收集起來(lái):
隨后,利用這些激活值的分布(distribution of activations)來(lái)計(jì)算量化輸出值所需的零點(diǎn)(z)和比例因子(s)值:
每次數(shù)據(jù)通過一個(gè)新模型層時(shí),都要重復(fù)上述過程。因此,每個(gè)模型層都有其獨(dú)特的 z 值和 s 值,因此也有不同的量化方案。
3.2 靜態(tài)量化(Static Quantization)
與動(dòng)態(tài)量化不同,靜態(tài)量化在模型推理過程中不實(shí)時(shí)計(jì)算零點(diǎn)(z)和比例因子(s),而是在模型訓(xùn)練或校準(zhǔn)過程中提前計(jì)算。
為了找到這些值,會(huì)使用一個(gè)校準(zhǔn)數(shù)據(jù)集,并讓模型處理這些數(shù)據(jù),以便收集可能的激活值分布(potential distributions)。
收集到這些數(shù)值后,我們就可以計(jì)算出必要的 s 值和 z 值,以便在推理過程中進(jìn)行量化。
在實(shí)際推理過程中,s 值和 z 值不需要重新計(jì)算,而是被應(yīng)用于所有激活值,實(shí)現(xiàn)全局量化。
通常情況下,動(dòng)態(tài)量化技術(shù)可能會(huì)稍微更精確一些,因?yàn)樗鼮槊總€(gè)隱藏層計(jì)算一次 s 值和 z 值。不過,由于需要計(jì)算這些值,因此可能會(huì)增加計(jì)算時(shí)間。
相比之下,靜態(tài)量化雖然準(zhǔn)確度稍低,但由于事先已知用于量化的 s 值和 z 值,因此在推理時(shí)更為高效。
3.3 探索 4-bit 量化的極限
將量化位數(shù)降至 8-bit 以下是一項(xiàng)艱巨的任務(wù),因?yàn)槊繙p少一個(gè) bit,量化誤差(quantization error)就會(huì)增加。 幸運(yùn)的是,有幾種巧妙的方法可以將量化位數(shù)進(jìn)一步降低到 6-bit、4-bit,甚至 2-bit (不過不建議低于 4-bit )。
接下來(lái)將探討兩種在 HuggingFace** 上常用的方法:
- GPTQ — 全模型在 GPU 上運(yùn)行。
- GGUF — 將一部分模型層從 GPU 轉(zhuǎn)移到 CPU 上執(zhí)行。
3.3.1 GPTQ
GPTQ 無(wú)疑是實(shí)際應(yīng)用中最著名的 4-bits 量化方法之一。1
它采用非對(duì)稱量化(asymmetric quantization),并逐層處理,每一層都經(jīng)過獨(dú)立處理,然后再繼續(xù)處理下一層:
在這個(gè)逐層量化的過程中,首先將模型層的權(quán)重轉(zhuǎn)換為 Hessian 矩陣(譯者注:Hessian 矩陣是二階偏導(dǎo)數(shù)矩陣,用于描述函數(shù)在其輸入變量上的局部曲率。對(duì)于多變量函數(shù),Hessian 矩陣可以幫助我們了解函數(shù)在某一點(diǎn)上的凹凸性,以及函數(shù)值對(duì)輸入變量的變化有多敏感。)的逆矩陣。它是模型損失函數(shù)的二階導(dǎo)數(shù),它告訴我們模型輸出對(duì)每個(gè)權(quán)重變化的敏感程度。
簡(jiǎn)單來(lái)說,該過程展示了模型層中每個(gè)權(quán)重的重要性(或者說是權(quán)重的影響程度)。
與 Hessian 矩陣中較小值相關(guān)的權(quán)重更為重要,因?yàn)檫@些權(quán)重的微小變化可能會(huì)對(duì)模型的性能產(chǎn)生重大影響。
在 Hessian 矩陣的逆矩陣中,數(shù)值越低,權(quán)重越 “重要”。
接下來(lái),我們對(duì)權(quán)重矩陣的第一行權(quán)重進(jìn)行量化,再進(jìn)行反量化:
通過這一過程,我們可以計(jì)算出量化誤差 (q),我們可以用之前計(jì)算的 Hessian 矩陣的逆矩陣(h_1)來(lái)調(diào)整這個(gè)誤差。
換句話說,我們是在根據(jù)權(quán)重的重要性來(lái)構(gòu)建加權(quán)量化誤差(weighted-quantization error):
接著,我們將這個(gè)加權(quán)的量化誤差重新分配到該行的其他權(quán)重上。這樣做可以保持神經(jīng)網(wǎng)絡(luò)的整體功能(overall function)和輸出(output)不變。
例如,如果要對(duì)第二個(gè)權(quán)重(如果它是 0.3(x_2))進(jìn)行此操作,我們就會(huì)將量化誤差(q)乘以第二個(gè)權(quán)重的 Hessian 矩陣的逆矩陣(h_2)加上去。
我們可以對(duì)第一行中的第三個(gè)權(quán)重進(jìn)行同樣的處理:
重復(fù)這個(gè)重新分配加權(quán)量化誤差的過程,直到所有值都被量化。
這種方法之所以行之有效,是因?yàn)闄?quán)重之間通常是相互關(guān)聯(lián)的。因此,當(dāng)一個(gè)權(quán)重出現(xiàn)量化誤差(quantization error)時(shí),與之相關(guān)的權(quán)重也會(huì)相應(yīng)地更新(通過 Hessian 矩陣的逆矩陣)。
NOTE:本文作者[4]采用了幾種技巧來(lái)加快計(jì)算速度并提高性能,例如在 Hessian 矩陣中添加阻尼因子(dampening factor)、“懶惰批處理(lazy batching)”,以及使用 Cholesky 方法預(yù)先計(jì)算信息(precomputing information)。我強(qiáng)烈建議各位讀者觀看這個(gè)視頻[5]。
TIP:如果你想要一種可以優(yōu)化性能和提高推理速度的量化方法,可以查看 EXL2[6] 這個(gè)項(xiàng)目。
3.3.2 GGUF
雖然 GPTQ 是一種在 GPU 上運(yùn)行完整 LLMs 的最佳模型量化方法,但我們可能很多時(shí)候沒有這種條件。于是我們可以使用 GGUF 將 LLM 的某些模型層放到到 CPU 上進(jìn)行處理。2
這樣,當(dāng) VRAM 不足時(shí),就可以同時(shí)使用 CPU 和 GPU。
量化方法 GGUF 仍不斷在更新,并且其性能可能會(huì)根據(jù)量化位數(shù)的不同而有所變化。其基本原理如下:
首先,給定模型層的權(quán)重被分割成包含一組“子”塊的“超級(jí)”塊(“super” blocks)。
我們從這些 blocks 中提取比例因子(s)和 α(α):
為了量化給定的“子”塊(“sub” block),我們可以使用之前介紹的 absmax 量化方法。這種方法會(huì)將給定權(quán)重乘以比例因子(s):
比例因子是通過“子”塊的信息計(jì)算出來(lái)的,但量化時(shí)使用的是“超級(jí)”塊的信息,后者有自己的比例因子:
這種基于塊(blocks)的量化方法使用“超級(jí)”塊的比例因子(s_super)來(lái)量化“子”塊的比例因子(s_sub)。
每個(gè)比例因子的量化級(jí)別可能會(huì)有所不同,“超級(jí)”塊的比例因子通常比“子”塊的比例因子有更高的精度。
為了更直觀地理解,觀看下圖進(jìn)一步了解這幾個(gè)量化級(jí)別相關(guān)信息( 2-bit、4-bit 和 6-bit ):
NOTE:在某些量化方法中,為了保持量化后的模型性能,可能需要一個(gè)額外的最小值來(lái)調(diào)整零點(diǎn),以確保模型能夠正確處理極端值。這個(gè)最小值和比例因子一樣,都是量化過程中的關(guān)鍵參數(shù),它們需要被正確地量化,以確保量化后的模型能夠保持原有的性能。
各位讀者可以查看這個(gè) PR[7] ,了解所有量化級(jí)別的詳細(xì)信息。此外,還可以查看這個(gè) PR[8],獲取更多關(guān)于使用重要性矩陣(importance matrices)進(jìn)行量化的信息。
04 第 4 部分:Quantization Aware Training
在第 3 部分中,我們了解到如何在訓(xùn)練完成后對(duì)模型進(jìn)行量化。這種方法的不足之處在于,量化過程并未考慮到實(shí)際的訓(xùn)練過程。
于是 Quantization Aware Training(QAT)就有了用武之地。與訓(xùn)練后使用 post-training quantization(PTQ)技術(shù)對(duì)模型進(jìn)行量化不同,QAT 的目標(biāo)是在訓(xùn)練過程中學(xué)習(xí)量化過程。
QAT 通常比 PTQ 更準(zhǔn)確,因?yàn)樵谟?xùn)練過程中已經(jīng)考慮了量化。其工作原理如下:
在訓(xùn)練過程中,引入所謂的“偽”量化。比如先將權(quán)重量化到例如 INT4 等形式,然后將它們反量化回 FP32 :
這一過程使得模型在訓(xùn)練階段進(jìn)行損失值計(jì)算和權(quán)重更新時(shí)能夠考慮到量化誤差。
QAT 嘗試探索損失函數(shù)中的“寬”最小值區(qū)域,以盡可能減少量化誤差,因?yàn)椤罢弊钚≈祬^(qū)域往往會(huì)導(dǎo)致更大的量化誤差。
例如,假設(shè)我們?cè)诜聪騻鞑ミ^程(backward pass)中沒有考慮量化誤差。我們將根據(jù)梯度下降法(gradient descent)選擇損失值(loss)最小的權(quán)重。但是,如果它位于“窄”最小值區(qū)域,可能會(huì)引入更大的量化誤差。
相反,如果我們考慮到量化誤差,我們將選擇在“寬”最小值區(qū)域中的不同權(quán)重進(jìn)行更新,量化誤差會(huì)小得多。
因此,雖然 PTQ 在高精度(例如,F(xiàn)P32)下具有較小的損失值,但 QAT 在低精度(例如, INT4 )下的損失值較小,這正是我們追求的目標(biāo)。
4.1 1-bit LLM 的時(shí)代:BitNet
正如前文所述,將量化位數(shù)降低到 4-bit 已經(jīng)非常小了,但如果我們還要進(jìn)一步降低呢?
這就是 BitNet[9] 的用武之地了,它使用 1-bit 表示模型的權(quán)重,每個(gè)權(quán)重都使用 -1 或 1 表示。3
它通過直接將量化過程整合到 Transformer 架構(gòu)中來(lái)實(shí)現(xiàn)這一點(diǎn)。
Transformer 架構(gòu)是大多數(shù) LLMs 的基礎(chǔ),它依賴于線性層來(lái)處理序列數(shù)據(jù),并在模型中執(zhí)行關(guān)鍵的計(jì)算操作:
這些線性層(linear layers)通常使用更高的精度,如 FP16,它們也是大部分權(quán)重所在的地方。
BitNet 將這些線性層替換為他們稱之為 BitLinear 的模型層:
BitLinear 層的工作原理與普通線性層相同,根據(jù)權(quán)重(weights)和激活值(activation)的乘積計(jì)算輸出值(output)。
BitLinear 層使用 1-bit 來(lái)表示模型的權(quán)重,并使用 INT8 來(lái)表示激活值:
類似于 Quantization-Aware Training(QAT)技術(shù),BitLinear 層在訓(xùn)練過程中執(zhí)行一種 “偽” 量化,以便用來(lái)分析權(quán)重和激活值的量化效果:
NOTE:在論文中使用的是 γ 而不是 α ,但由于在本文中所舉的例子一直使用 α ,所以我使用 α 。此外,請(qǐng)注意此處的 β 與前文在零點(diǎn)量化(zero-point quantization)中使用的 β 不同,它是基于平均絕對(duì)值(average absolute value)計(jì)算得出的。
讓我們一步一步來(lái)學(xué)習(xí) BitLinear 。
4.2 權(quán)重的量化 Weight Quantization
在訓(xùn)練過程中,權(quán)重以 INT8 的形式存儲(chǔ),然后使用一種稱為 signum 函數(shù)的基本策略,將其量化到 1-bit。
這種方法的核心在于,它將權(quán)重分布(distribution of weights)重新調(diào)整到以 0 為中心,然后將所有小于 0 的值(左側(cè))設(shè)置為 -1 ,將所有大于 0 的值(右側(cè))設(shè)置為 1 :
此外,它還會(huì)跟蹤記錄一個(gè)值 β(平均絕對(duì)值(average absolute value)),我們稍后會(huì)用到它來(lái)進(jìn)行反量化(dequantization)。
4.3 激活值的量化 Activation Quantization
為了量化激活值,BitLinear 利用 absmax 量化方法將 FP16 格式的激活值轉(zhuǎn)換為 INT8 格式,因?yàn)榫仃嚦朔?(×) 需要更高精度的激活值。
同時(shí),它還會(huì)跟蹤記錄 α(最高絕對(duì)值),我們將在后續(xù)的反量化過程中使用該值。
4.4 反量化過程 Dequantization
我們跟蹤記錄了 α(激活值的最高絕對(duì)值)和 β(權(quán)重的平均絕對(duì)值),因?yàn)檫@些值將在后續(xù)的反量化過程中幫助我們把激活值從 INT8 格式恢復(fù)到 FP16 格式。
輸出激活值(output activations)通過 {α, γ} 進(jìn)行縮放,然后進(jìn)行反量化將其恢復(fù)到原始精度:
就是這樣!這個(gè)過程相對(duì)簡(jiǎn)單,只需用兩個(gè)值(-1 或 1)來(lái)表示模型。
根據(jù)這一流程,作者發(fā)現(xiàn)隨著模型規(guī)模的擴(kuò)大,1-bit 形式和 FP16 形式訓(xùn)練的模型之間的性能差異逐漸縮小。
不過,這只適用于較大型的模型(參數(shù)超過 300 億(30 B)),而對(duì)于較小型的模型,這個(gè)性能差距仍然很大。
4.5 所有 LLMs 實(shí)際上均為 1.58-bit
BitNet 1.58b[10] 就是為了解決之前提到的擴(kuò)展性問題而提出的。4
在這種新方法中,模型的每一個(gè)權(quán)重不僅可以是 -1 或 1 ,還可以取 0 ,從而成為了一個(gè)三元模型。有趣的是,僅僅添加了 0 這一可取值就極大地提升了 BitNet 的性能,并使得計(jì)算速度大大提升。
4.5.1 The Power of 0
那么,為什么就添加了一個(gè)可取值 0 就能帶來(lái)如此大的提升呢?
這與矩陣乘法的原理緊密相關(guān)!
首先,讓我們了解一下矩陣乘法的一般工作原理。在計(jì)算輸出值時(shí),我們將權(quán)重矩陣(weight matrix)與輸入向量(input vector)相乘。下圖展示了權(quán)重矩陣第一層與輸入向量相乘的過程:
請(qǐng)注意,這一過程包含兩個(gè)步驟:首先將每個(gè)權(quán)重與輸入值相乘,然后將所有乘積相加。
與此不同,BitNet 1.58b 則省略了乘法這一步驟,因?yàn)槿獧?quán)重(ternary weights)實(shí)際上傳達(dá)了這樣的信息:
- 1: 我想要加上這個(gè)值
- 0: 我不需要加上這個(gè)值
- -1: 我想要減去這個(gè)值
因此,當(dāng)權(quán)重量化到 1.58 bit 時(shí),只需要執(zhí)行加法運(yùn)算:
這樣不僅可以大大加快了計(jì)算速度,還可以進(jìn)行特征過濾(feature filtering)。
將某個(gè)權(quán)重設(shè)置為 0 后,我們就可以選擇忽略它,而不是像 1-bit 表示法那樣要么加上要么減去權(quán)重。
4.5.2 Quantization 量化過程
在 BitNet 1.58b 中,進(jìn)行權(quán)重量化(weight quantization)時(shí)采用了 absmean 量化方法,這是之前看到的 absmax 量化方法的一種改進(jìn)形式。
這種方法通過壓縮權(quán)重的分布,并利用權(quán)重的絕對(duì)平均值(α)來(lái)進(jìn)行數(shù)值(value)的量化。之后,這些數(shù)值會(huì)被歸整到 -1、0 或 1 :
相較于 BitNet,激活值的量化過程基本相同,但還是有一點(diǎn)不同。激活值不再被縮放到 [0, 2??1] 區(qū)間,而是通過 absmax 量化方法被調(diào)整到了 [-2??1, 2??1] 區(qū)間。
就是這樣!1.58-bit 量化主要需要兩種技巧:
- 通過添加可取值 0 構(gòu)建三元數(shù)值表示法 [-1, 0, 1]
- 對(duì)權(quán)重實(shí)施 absmean 量化方法。
“13B BitNet b1.58 在響應(yīng)延遲、內(nèi)存占用和能耗方面,相較于 3B FP16 LLM 更高效?!?/p>
由于僅需 1.58 個(gè) bits ,計(jì)算效率高,我們得以構(gòu)建出更為輕量的模型!
05 Conclusion
我們的量化之旅到此告一段落!但愿本文能幫助你更深入地認(rèn)識(shí)到量化技術(shù)、GPTQ、GGUF 以及 BitNet 的巨大潛力。未來(lái)模型的體積又將能夠縮小到何種程度?真是令人期待?。?/p>
如果要查看更多與 LLMs 相關(guān)的可視化內(nèi)容,并希望支持我們,不妨留意一下我和 Jay Alammar 正在編寫的新書。該書即將發(fā)行!
你可以在 O’Reilly 網(wǎng)站[11]上免費(fèi)試讀此書,或者直接在亞馬遜[12]上預(yù)訂。我們還會(huì)將所有相關(guān)代碼同步更新到 Github[13] 上。
Resources
Hopefully, this was an accessible introduction to quantization! If you want to go deeper, I would suggest the following resources:
- A HuggingFace blog about the LLM.int8()[14] quantization method: you can find the paper here[15]. (譯者注:LLM.int8() 量化方法)
- Another great HuggingFace blog about quantization for embeddings[16].(譯者注:嵌入向量的量化問題)
- A blog about Transformer Math 101[17], describing the basic math related to computation and memory usage for transformers.(譯者注:介紹了與 Transformer 的計(jì)算和內(nèi)存使用相關(guān)的基本概念)
- This[18] and this are two nice resources to calculate the (V)RAM you need for a given model.(譯者注:計(jì)算特定模型所需(V)RAM 的數(shù)量)
- If you want to know more about QLoRA5, a quantization technique for fine-tuning, it is covered extensively in my upcoming book: Hands-On Large Language Models[19].(譯者注:QLoRA 技術(shù)的學(xué)習(xí)資料)
- A truly amazing YouTube video[20] about GPTQ explained incredibly intuitively.(譯者注:GPTQ 技術(shù)的學(xué)習(xí)資料)
腳注:
- Frantar, Elias, et al. "Gptq: Accurate post-training quantization for generative pre-trained transformers." arXiv preprint arXiv:2210.17323 (2022).
- You can find more about GGUF on their GGML repository here[21].
- Wang, Hongyu, et al. "Bitnet: Scaling 1-bit transformers for large language models." arXiv preprint arXiv:2310.11453 (2023).
- Ma, Shuming, et al. "The era of 1-bit llms: All large language models are in 1.58 bits." arXiv preprint arXiv:2402.17764 (2024).
- Dettmers, Tim, et al. "Qlora: Efficient finetuning of quantized llms." Advances in Neural Information Processing Systems 36 (2024).
Thanks for reading!
Hope you have enjoyed and learned new things from this blog!
Maarten Grootendorst
Data Scientist | Psychologist | Writer | Open Source Developer (BERTopic, PolyFuzz, KeyBERT) | At the intersection of Artificial Intelligence and Psychology
END
??文中鏈接??
[1]??https://en.wikipedia.org/wiki/IEEE_754??
[3]??https://huggingface.co/meta-llama/Meta-Llama-3-8B/tree/main??
[4]??https://arxiv.org/pdf/2210.17323??
[5]??https://www.youtube.com/watch?v=mii-xFaPCrA??
[6]??https://github.com/turboderp/exllamav2??
[7]??https://github.com/ggerganov/llama.cpp/pull/1684??
[8]??https://github.com/ggerganov/llama.cpp/pull/4861??
[9]??https://arxiv.org/pdf/2310.11453??
[10]??https://arxiv.org/pdf/2402.17764??
[11]??https://www.oreilly.com/library/view/hands-on-large-language/9781098150952/??
[12]??https://www.amazon.com/Hands-Large-Language-Models-Understanding/dp/1098150961??
[13]??https://github.com/HandsOnLLM/Hands-On-Large-Language-Models??
[14]??https://huggingface.co/blog/hf-bitsandbytes-integration??
[15]??https://arxiv.org/pdf/2208.07339??
[16]??https://huggingface.co/blog/embedding-quantization??
[17]??https://blog.eleuther.ai/transformer-math/??
[18]??https://huggingface.co/spaces/NyxKrage/LLM-Model-VRAM-Calculator??
[19]??https://www.amazon.com/Hands-Large-Language-Models-Understanding/dp/1098150961??
[20]??https://www.youtube.com/watch?v=mii-xFaPCrA??
[21]??https://github.com/ggerganov/ggml/blob/master/docs/gguf.md??
本文經(jīng)原作者授權(quán),由 Baihai IDP 編譯。如需轉(zhuǎn)載譯文,請(qǐng)聯(lián)系獲取授權(quán)。
原文鏈接:
??https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-quantization??
