Blog

Büyük bir model daha az bite nasıl sığar?

Nicemleme, bir modelin her sayısını daha az bitle saklar. Canlı şekiller bir ızgaraya yuvarlamanın nasıl çalıştığını, tek bir aykırı değerin onu neden bozduğunu, küçük bir ağa ne olduğunu ve bir modelin belleğinize sığıp sığmayacağını gösterir.

13 dk okumaYazan: RuneLab

Bir dil modeli, ağırlıkları denen çok uzun bir sayı listesidir. Her sayının kaç bayt tuttuğu, modelin makinenize sığıp sığmayacağını ve sayılarının bellekten ne kadar çabuk okunabileceğini belirler. Nicemleme (quantization), her sayıyı daha az bitle saklar: sayıyı, kısa bir izin verilen değerler listesinin en yakınına yuvarlar.

İlk hesap her model için aynıdır: ağırlıkların belleği, ağırlık sayısı çarpı her birinin tuttuğu bayttır; 16 bitlik bir sayı 2 bayt, 4 bitlik bir sayı yarım bayt tutar.

Yazının sonunda şunları bileceksiniz:

  • “4 bit” ifadesinin gerçekte ne demek olduğunu: izin verilen değerlerden bir ızgara ve onu geren bir ölçek;
  • tek bir büyük değerin yuvarlamayı neden herkes için bozduğunu ve ağırlık gruplarının bunu bir bedel karşılığında nasıl düzelttiğini;
  • bir modelin belleğinize sığıp sığmadığını nasıl anlayacağınızı ve bu kontrolün neyi dışarıda bıraktığını.

Izgaraya oturtma

#

Bir ağırlığı 4 bitte tutmak için onu tam olarak koruyamazsınız. Bir gruptaki en büyük ağırlığı, işaretine bakmadan alın, eksi o değerden artı o değere, eşit aralıklı çentikleri olan bir cetvel çizin ve her ağırlığı en yakın çentiğinin numarasıyla, yani küçük bir tam sayıyla saklayın. Grup tek bir ölçek saklar: çentikler arasındaki aralık.

ölçek s = en büyük mutlak değerli ağırlık ÷ (2bit−1 − 1) saklanan tam sayı q = yuvarla(w ÷ s) kullanılan değer w′ = q × s

4 bitte tam sayı −7 ile 7 arasında değişir: 15 çentik; 16 koddan biri, cetvel simetrik olsun diye kullanılmadan kalıyor. Ağırlığı sürükleyin, sonra bit kaydırıcısını 8 bitten 2 bite çekin ve izin verilen değerlerin nasıl seyrekleştiğini izleyin.

Bu şekil JavaScript gerektirir. −1 ile 1 arasında bir cetvel üzerinde 0,37 değerinde bir ağırlığı ve verilen bit sayısının izin verdiği çentikleri gösterir. 4 bitte 1/7 aralıklı 15 çentik vardır; 0,37 tam sayı 3 olarak saklanır ve 0,429 olarak geri okunur, yani hata 0,059’dur ve yarım adımı (0,071) aşamaz. 8 bitte 255 çentik vardır ve hata 0,001’in altındadır. 2 bitte yalnızca üç çentik vardır: −1, 0 ve 1; 0,37 sıfır olur ve ağırlık yok olur.

Hata, halka ile çentik arasındaki farktır ve bir aralığın yarısını aşmaz. Bir bit eksildikçe aralık yaklaşık iki katına çıkar, en kötü durum hatası da onunla birlikte (3 bitten 2 bite geçerken üç katına çıkar). 2 bitte 0’a oturur: yok olur.

Yani model gerçek sayıları değil, tam sayıları mı tutuyor? Her ağırlık için bir tam sayı, grup için de bir ölçek; hesabı bunların çarpımıyla yapıyor. Gerçek sayı gitti, geriye yalnızca en yakın çentik kaldı.

Tek bir aykırı değer cetveli bozar

#

Cetvelin uçları en büyük ağırlıktan gelir ve zayıf nokta da burasıdır. Geri kalanından çok büyük tek bir değer çentikler arasındaki aralığı belirler; sıfırın çevresindeki iki çentiğin arasına düşen sıradan değerler de sıfıra yuvarlanır. LLM.int8() makalesi (Dettmers ve arkadaşları, 2022) büyük dil modellerinde bunun bir benzerini buldu: değerleri diğerlerinden yaklaşık 20 kata kadar büyük birkaç gizli boyut; yazarlar bu boyutları 16 bitte tutuyor. Makalede bunlar ağırlıklarda değil, gizli durumlarda; aşağıdaki sıranın onlarla ortak yanı yalnızca aritmetik.

Sıra uydurma: 32 ağırlık, biri diğerlerinin en büyüğünden yaklaşık on dört kat büyük, hepsi 4 bite yuvarlanmış. Kaç ağırlığın bir ölçeği paylaşacağını seçin, sonra aykırı değeri kaldırın.

Bu şekil JavaScript gerektirir. 4 bite yuvarlanmış 32 uydurma ağırlığı gösterir; biri diğerlerinden yaklaşık on dört kat büyüktür. 32’nin hepsi için tek ölçekle büyük değer adımı 0,857 yapar ve ağırlıkların 31’i sıfıra yuvarlanır (ortalama kare hata 0,0275; 16 bitlik bir ölçekle ağırlık başına 4,5 bit). 16’lı gruplar ağırlık başına 5 bitle 0,0101, 8’li gruplar 6 bitle 0,0028, 4’lü gruplar 8 bitle 0,0024 verir. Büyük değer olmadan 32’nin hepsi için tek ölçek 0,00027 verir.

32 ağırlığın hepsi tek ölçeği paylaşınca aykırı değer aralığı 0,857 yapıyor ve 31 ağırlık sıfıra yuvarlanıyor. 8’erli gruplarda yalnızca onun grubundaki ağırlıklar zarar görüyor ve hata 0,0275’ten 0,0028’e, yani yaklaşık onda birine düşüyor. Aykırı değer olmadan seçim neredeyse hiçbir şeyi değiştirmiyor (0,00027).

Bedel son göstergede. Her grup bir ölçek saklıyor, burada 16 bit; bu, g ağırlıklık bir grubun her ağırlığına 16 ÷ g bit ekliyor: 32’de yarım bit, 4’te dört bit; her tek ağırlığa ayrı bir ölçek vermek 4 bitlik bir ağırlığı 20 bite, yani beş katına çıkarırdı. llama.cpp’nin Q4_0 bloğu bu düzende: 32 dört bitlik ağırlık ve bir 16 bitlik ölçek, ağırlık başına 4,5 bit.

Yani gruplar küçüldükçe hep daha mı iyi? Hayır: hata için daha iyi, fatura için daha kötü. Bu sırada 4 bitlik 8’erli gruplar (ağırlık başına 6 bit) 6 bitlik tek ölçeğe (6,5) ancak yetişiyor; 8 bitlik tek ölçek (8,5, hata 0,00015) ise 4 bitlik 4’erli gruplardan (8) 16 kat daha iyi.

Bir satırda bir ağırlık diğerlerinden yaklaşık on dört kat büyük; satır tek ölçekle 4 bite yuvarlanıyor. Sıradan ağırlıklara ne olur?

  1. Hiçbir şey: her ağırlık kendi başına yuvarlanır.
  2. Çoğu sıfıra yuvarlanır: büyük değer çentikler arası aralığı belirler.
  3. Ölçek tuhaf değeri fark ettiği için otomatik olarak 16 bitte tutulurlar.
Yanıtı göster

Çoğu sıfıra yuvarlanır: şekilde, 32 ağırlığın hepsi tek ölçeği paylaşınca 31’i silinip gidiyor.

A değil: çentikler ortak, bu yüzden en büyük değer hepsi için adımı belirler.

C değil: düz yuvarlama aykırı değer aramaz; LLM.int8() onlar için bilerek ayrı bir 16 bit yolu ekler.

Minik bir beyni nicemleyin

#

Bir dil modeli burada oynamak için çok büyük; bu yüzden bu şekil bir oyuncak kullanıyor: iki girdi, 16’şar birimlik iki gizli katman ve bir çıktı; iç içe geçmiş iki hilali birbirinden ayırmak için eğitilmiş. Yalnızca ağırlıkları yuvarlanıyor; sapma değerleri (bias) ve hesabı tam duyarlıkta kalıyor. Katman başına, bir katmanın tüm ağırlıkları için tek ölçek kullanır; nöron başına her nörona kendi ölçeğini verir: yine gruplama fikri.

Bitleri 32’den aşağı çekin. Kesikli çizgi özgün ağın iki hilal arasındaki sınırı, düz çizgi yuvarlanmış ağın sınırı.

Bu şekil JavaScript gerektirir. İç içe geçmiş iki hilali ayıran minik bir ağı, ağırlıkları daha az bite yuvarlanmış hâliyle gösterir. Tam duyarlıkta 200 test noktasının 197’sini doğru bilir. Katman başına tek ölçekle 8 bitte yine 197’yi, 4 bitte 190’ı (yüzde 95,0; ölçekler dahil ağırlık başına 4,16 bit), 3 bitte 126’yı (63,0) ve 2 bitte 100’ü bilir; 2 bitte her yerde tek bir yanıt verir. Nöron başına tek ölçekle 4 bitte 195’i (ağırlık başına 5,74 bit), 3 bitte 183’ü (4,74) bilir: daha çok ölçek, daha çok bit. Bu bir oyuncaktır, dil modeli değildir.

8 bitte çizgiler üst üste biniyor ve skor değişmiyor: 200 noktanın 197’si, yüzde 98,5. Katman başına 4 bitte sınır dalgalanıyor (95,0); 3 bitte bozuluyor (63,0); 2 bitte ağ her yerde tek bir sınıfı yanıtlıyor. Nöron başına ölçek 4 bitte 97,5’i, 3 bitte 91,5’i koruyor; ama 3 yerine 33 ölçek saklıyor ve gösterge bunları da sayıyor: nöron başına 3 bit ağırlık başına 4,74 bite, katman başına 4 bit 4,16 bite mal oluyor ve katman sürümü 95,0 alırken diğeri 91,5 alıyor. Gerçek maliyette ince ölçekler burada bir şey kazandırmadı. On altı böyle ağ eğittik ve yedincisini gösteriyoruz; 4 bitlik skoru (95,0) ortalamalarını (89,9) geçiyor, ortalamada ise nöron başına 3 bit (90,2) ile katman başına 4 bit (89,9) berabere. Bir oyuncak, değiş tokuşun biçimini gösterir; gerçek bir modelde düşüşün nerede olacağını göstermez: GPTQ yazarları daha büyük modelleri genel olarak nicemlemenin daha kolay olduğunu buldu.

Küçük ağda, nöron başına ölçekle 3 bit, katman başına ölçekle 3 bitten çok daha yüksek skor alıyor. Bunu ne açıklar?

  1. Nöron başına yuvarlama daha titiz bir kural kullanır, bu yüzden her ağırlık çentiğine daha yakın düşer.
  2. Toplamda daha az bit kullanır, çünkü nöron başına tek ölçek katman başına ölçekten küçüktür.
  3. Küçük ağırlıklı bir nöron daha ince çentikler alır; bedeli, saklanacak daha çok ölçektir.
Yanıtı göster

Bir nöronun ölçeği kendi en büyük ağırlığından gelir; bu yüzden küçük ağırlıklı nöronlar daha ince çentik alır. Bedeli: 3 yerine 33 ölçek, ağırlık başına yaklaşık 1,6 bit fazla.

A değil: kural aynı; yalnızca çentiklerin boyutu değişiyor.

B değil: nöron başına ayar 3 yerine 33 ölçek saklıyor, yani daha az değil, daha çok bit harcıyor.

Sığacak mı?

#

Şimdi bellek. Bir boyut ve bir kart seçin, sonra bitleri sürükleyin. Çubuk, ağırlıkların tuttuğu bellektir; her 32 ağırlık için 16 bitlik bir ölçek de sayılır, yani “4 bit” 4,5’e mal olur. Taramalı kısım geri kalan her şey için kalan yerdir: modelin şimdiye kadar okuduklarını tutan ve metinle birlikte büyüyen KV önbelleği (KV cache), aktivasyonlar (çalışma sayıları) ve yazılımın kendisi. Bunlar modele, programa ve metne bağlı olduğu için şekil tahmin yürütmüyor: yalnızca geriye kalanı gösteriyor. Boyutlar yuvarlak sayılar, belirli modeller değil.

Bu şekil JavaScript gerektirir. Bir modelin ağırlıklarının tuttuğu belleği, 2^30 baytlık birimlerle ve ölçekler için ağırlık başına yarım bit sayarak, bir kartın belleğiyle karşılaştırır. 13 milyar ağırlıklı bir model 16 bitte 24,2 GB tutar ve 16 GB belleği olan karta sığmaz (8,2 GB fazla); 8 bitte 12,9 GB tutar, sığar ve 3,1 GB kalır; 4 bitte 6,8 GB tutar. KV önbelleği, aktivasyonlar ve yazılım da bellek ister ve şekil bunun ne kadar olduğunu tahmin etmez.

16 bitte 13 milyar sayı 24,2 GB tutar; 16 GB belleği olan kart için 8,2 GB fazla. 8 bitte 12,9 GB tutar ve 3,1 GB bırakır; 4 bitte 6,8. 70 milyarlık bir model 24 GB belleği olan karta yalnızca 2 bitte sığar, geriye 3,6 GB kalır. “Sığıyor”, yalnızca ağırlıkların sığdığı anlamına gelir. 4 bitte sığan en büyük model çoğu zaman, her zaman değil, en iyi seçimdir: dört model ailesinde 35.000’den fazla deneyde (Dettmers ve Zettlemoyer, 2022) 4 bitlik ağırlıklar, doğruluk ile toplam bit arasındaki değiş tokuşta neredeyse her zaman en iyisiydi.

Bu, Hati Glint SQL’in model kartındaki hesap: 9 milyar bf16 ağırlık, 2’şer bayt, yaklaşık 16,8 GB GPU belleği gerektiriyor (burada 1 GB, 230 bayttır). Bu, 16 bitlik ağırlıklar hakkında bir gerçek; bu yazı o modelin daha küçük bir sürümü hakkında hiçbir iddiada bulunmuyor.

Kartın 24 GB belleği var ve bir modelin ağırlıkları 22 GB tutuyor. Çubuk size ne söylüyor?

  1. Ağırlıklar sığıyor; KV önbelleği ve gerisi için yalnızca yaklaşık 2 GB kalıyor.
  2. Sığıyor ve başka hiçbir şey bellek istemiyor.
  3. Sığmıyor: bir model kartın belleğinin yarısından fazlasını hiçbir zaman tutmamalıdır.
Yanıtı göster

Ağırlıklar sığıyor, geriye yaklaşık 2 GB kalıyor. Bunun geri kalanı karşılayıp karşılamadığı programa ve metne bağlı.

B değil: KV önbelleği, aktivasyonlar ve yazılım da bellek ister.

C değil: böyle bir kural yok; önemli olan geriye ne kaldığı.

Yuvarlamadan akıllısı

#

En yakın çentiğe yuvarlamak, ağırlıkların ne işe yaradığını görmezden gelir. Üç fikir daha iyisini yapar.

Daha iyi değerler seçmek. GPTQ (Frantar ve arkadaşları, 2022) bir seferde bir katmanı yuvarlar ve katmanın çıktısını küçük bir metin örneğinde özgününe yakın tutan değerleri seçer. Denemelerinde düz yuvarlama 3 bitte büyük modellerde çöktü, GPTQ ise dayandı.

Önemli olanı korumak. AWQ (Lin ve arkadaşları, 2023) en önemli ağırlıkları, büyüklüklerine değil modelin içinden akan sayılara bakarak bulur. 6,7 milyarlık bir modelde 3 bitte düz yuvarlama 23,5 şaşkınlık (perplexity) skoru aldı (modelin metni ne kadar kötü tahmin ettiğini gösterir; düşük iyidir; 16 bitte 10,9). Kanalların yüzde 1’ini 16 bitte tutmak, bu yolla seçilirse skoru 11,4’e düşürdü; ağırlık büyüklüğüne göre seçilirse 22,4’e.

Yuvarlamayı akılda tutarak eğitmek. Jacob ve arkadaşları (2017) yuvarlamayı eğitim sırasında benzetiyor. QLoRA (Dettmers ve arkadaşları, 2023) ise bitmiş bir modeli 4 bitte dondurup üzerinde küçük ek katmanlar eğitiyor; bu, 48 GB belleği olan tek bir kartta 65 milyarlık bir modeli ince ayarlamaya yetiyor.

Bunların hepsi ağırlıkları yuvarlar. Modelin içinden akan sayıları yuvarlamak daha zordur ve LLM.int8()’in aykırı değerleri oradadır.

Hesap hâlâ 16 bitse, tasarruf nereden geliyor? Bellek trafiğinden. Metin yazmanın hızını ağırlıkların ne kadar çabuk okunduğu sınırlıyor; spekülatif kod çözme yazısı tam olarak bu gerçeğe dayanıyor, yani daha az bayt okumak yardımcı oluyor. GPTQ yazarları hız kazanımlarının hesaplamanın azalmasından değil, bellek hareketinin azalmasından geldiğini söylüyor.

Kaybedeceğiniz kalite modele, yönteme ve işe bağlıdır; bu yazı hiçbir RuneLab modeli için böyle bir sayı vermiyor. Daha küçük bir modele giden başka bir yol, küçük bir modeli büyüğünü taklit edecek şekilde eğitmektir: model damıtma yazısına bakın.

Kaynaklar ve ileri okuma

#

Dışarıdan alınan her sayının ve iddianın kaynağı, 2026-10-15 itibarıyla (llama.cpp dosyası yaşayan bir sayfadır).

  1. Benoit Jacob ve arkadaşları, “Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference” (2017): ölçek ve tam sayı şeması, benzetilmiş nicemlemeyle eğitim.
  2. Tim Dettmers, Mike Lewis, Younes Belkada ve Luke Zettlemoyer, “LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale” (2022): aykırı özellikler, yaklaşık 20 kata kadar büyük.
  3. Elias Frantar, Saleh Ashkboos, Torsten Hoefler ve Dan Alistarh, “GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers” (2022): düz yuvarlamanın 3 bitte çöküşü, bellek hareketi, büyük modeller.
  4. Ji Lin ve arkadaşları, “AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration” (2023): yüzde 1 deneyi (bölüm 3.1, Tablo 1).
  5. Tim Dettmers, Artidoro Pagnoni, Ari Holtzman ve Luke Zettlemoyer, “QLoRA: Efficient Finetuning of Quantized LLMs” (2023): 48 GB üzerinde 65 milyarlık model.
  6. Tim Dettmers ve Luke Zettlemoyer, “The case for 4-bit precision: k-bit Inference Scaling Laws” (2022): 35.000’den fazla deney, 4 bit neredeyse her zaman en iyisi.
  7. llama.cpp projesi, ggml-common.h: Q4_0 (18 baytta 32 ağırlık ve 16 bitlik bir ölçek) ve Q8_0 (34 bayt) blok düzenleri.
  8. RuneLab, Hati Glint SQL model kartı: bf16 ağırlıklar yaklaşık 16,8 GB GPU belleği gerektirir.

Aklınızda kalsın

#
  • Nicemleme her ağırlığı birkaç izin verilen değerin en yakınına yuvarlar; çıkarılan her bit aralığı yaklaşık iki katına çıkarır.
  • Tek bir büyük değer ortak cetveli gerer; bu yüzden ölçekler grup başına tutulur ve “4 bit”, ölçekler sayıldığında ağırlık başına yaklaşık 4,5 bit demektir.
  • Bir oyuncak değiş tokuşun biçimini gösterir; kaliteyi kendi işinizde ölçün.
  • Ağırlıkların sığması ilk testtir, son test değil: KV önbelleği ve aktivasyonlar da bellek ister.