Transformers documentation

Konsep kuantisasi

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Konsep kuantisasi

Sebuah angka terkuantisasi hanya dapat mengambil salah satu dari sejumlah kecil nilai, yaitu 256 untuk int8 dan 16 untuk int4, sehingga setiap metode kuantisasi memperkenalkan error pembulatan. Metode-metode tersebut berbeda dalam cara mereka mencegah error tersebut merusak output model. Halaman ini menjelaskan pilihan di balik perbedaan-perbedaan tersebut: bagaimana angka dipetakan ke himpunan kecil tersebut, tensor mana yang dikuantisasi, tipe data apa yang digunakan, dan kapan kuantisasi dilakukan.

Jika Anda baru dalam kuantisasi di Transformers, mulailah dengan Ikhtisar.

Petakan nilai ke bit yang lebih sedikit

Quantization memetakan rentang nilai presisi tinggi ke himpunan kecil bilangan bulat yang dapat direpresentasikan oleh tipe bit rendah. int8 dapat merepresentasikan 256 bilangan bulat, [-128, 127], dan int4 dapat merepresentasikan 16.

Affine quantization adalah pemetaan yang paling umum. Metode ini mengambil nilai minimum dan maksimum dari sebuah tensor, lalu meregangkan rentang bilangan bulat di atasnya. Pada contoh di bawah, tensor dengan nilai yang berkisar dari -1,8 hingga 2,4 dipetakan ke int8, dan 0,0 jatuh pada -19.

bf16  -1.8             0.0                    2.4
       ├────────────────┼──────────────────────┤
       ▼                ▼                      ▼
int8  -128             -19                    127

Dua parameter mendefinisikan pemetaan.

  • Nilai scale S adalah ukuran satu langkah bilangan bulat dalam satuan asli. S=valmax−valminqmax−qmin S = \frac{val_{max} - val_{min}}{q_{max} - q_{min}}

  • Titik nol Z adalah bilangan bulat yang merepresentasikan 0.0. Z=qmin−round(valminS) Z = q_{min} - round\left(\frac{val_{min}}{S}\right)

Sebuah nilai x dikuantisasi menjadi bilangan bulat q dengan membagi dengan skala dan menggeser dengan titik nol. q=round(xS+Z) q = round\left(\frac{x}{S} + Z\right)

Dequantizing membalikkan pemetaan dan memberikan kembali aproksimasi dari x. Selisih antara x dan aproksimasinya adalah error pembulatan. x≈S⋅(q−Z) x \approx S \cdot (q - Z)

Pada contoh di atas, S sekitar 0.0165 dan Z adalah -19. Nilai 0.5 dikuantisasi menjadi 11, dan 11 didekuantisasi menjadi sekitar 0.494, dengan error pembulatan sekitar 0.006.

┌─────┐  quantize   ┌────┐ dequantize   ┌───────┐
│ 0.5 │ ──────────▶ │ 11 │ ───────────▶ │ 0.494 │
└─────┘             └────┘              └───────┘

Kuantisasi afine hadir dalam dua bentuk.

  • Kuantisasi Asymmetric menggunakan rumus di atas. Ia memetakan rentang yang tepat, sehingga tidak ada nilai yang dapat direpresentasikan yang terbuang ketika bobot tidak terpusat pada nol.
  • Kuantisasi Symmetric mengasumsikan rentang adalah [-a, a] dan menetapkan Z ke 0, sehingga hanya skala yang disimpan. Perhitungannya lebih ringan, tetapi beberapa nilai yang dapat direpresentasikan tidak terpakai ketika bobot condong ke satu sisi nol.

Pilih granularitas

Satu skala untuk seluruh tensor memang hemat untuk disimpan, tetapi satu nilai ekstrem yang besar akan memperlebar rentang dan menyebarkan nilai-nilai yang dapat direpresentasikan semakin jauh untuk setiap bobot lainnya. Kelompok yang lebih kecil memberikan setiap skala rentang yang lebih sempit untuk dicakup.

  • Per-tensor menggunakan satu skala dan satu titik nol untuk seluruh tensor.
  • Per-channel menggunakan satu skala untuk setiap kanal output, yaitu setiap baris dari matriks bobot.
  • Per-group, atau per-block, menggunakan satu skala untuk setiap grup nilai berurutan, seperti 128 bobot. Setiap grup memerlukan penyimpanan tambahan untuk skalanya.

Diagram di bawah ini menunjukkan tiga opsi pada matriks bobot dengan tiga baris. Setiap s adalah satu skala.

per-tensor        per-channel           per-group
┌────────────┐    ┌────────────┐        ┌──────┬──────┐
│            │    │            │ s0     │  s0  │  s1  │
│            │    ├────────────┤        ├──────┼──────┤
│     s      │    │            │ s1     │  s2  │  s3  │
│            │    ├────────────┤        ├──────┼──────┤
│            │    │            │ s2     │  s4  │  s5  │
└────────────┘    └────────────┘        └──────┴──────┘

Sebagian besar metode low-bit melakukan kuantisasi per grup. GPTQ secara default menggunakan grup berisi 128 bobot, dan Fine-grained FP8 secara default menggunakan blok 128x128. Format FP4 dalam Data types membangun ukuran blok ke dalam format itu sendiri.

Kuantisasi bobot atau aktivasi

Metode berbeda-beda dalam hal tensor mana yang dikuantisasi, dan hal ini menentukan di mana perkalian matriks dijalankan.

  • Metode Weight-only menyimpan bobot dalam presisi rendah dan membiarkan aktivasi tetap dalam bf16 atau fp16. Sebelum setiap matmul, kernel melakukan dekuantisasi bobot ke dtype komputasi dengan presisi yang lebih tinggi. bitsandbytes 4-bit, AWQ, GPTQ, dan HQQ bekerja dengan cara ini. Di bitsandbytes, bnb_4bit_compute_dtype mengatur dtype komputasi tersebut.
  • Metode Weight-and-activation juga mengkuantisasi aktivasi, dan matmul dijalankan langsung dalam presisi rendah. Hal ini memerlukan perangkat keras yang mendukung matmul presisi rendah, seperti FP8 pada GPU terbaru. Skema ini sering ditulis sebagai W8A8 untuk bobot dan aktivasi 8-bit.

Metode weight-only menghemat memori tetapi tidak selalu berjalan lebih cepat, karena dequantizing menambah beban kerja pada setiap matmul. Metode ini mempercepat generasi ketika model bersifat memory-bound. Saat menghasilkan satu token pada satu waktu, GPU menghabiskan sebagian besar setiap langkah untuk membaca bobot dari memori, bukan untuk menghitung. Membaca bobot 4-bit memindahkan seperempat dari data yang dibaca oleh bobot bf16, dan penghematan tersebut dapat melampaui biaya dequantizing.

Metode bobot-aktivasi membantu ketika model bersifat compute-bound, seperti pada prefill atau batch besar, karena matmul presisi rendah itu sendiri lebih cepat. Beberapa metode beralih di antara keduanya. NVFP4 menjalankan matmul bobot 4-bit, aktivasi 4-bit untuk prefill dan matmul bobot 4-bit, aktivasi 16-bit untuk decoding.

Tipe data

Tipe data menentukan nilai-nilai yang dapat direpresentasikan oleh angka terkuantisasi.

int8 dan int4

int8 dan int4 mewakili bilangan bulat yang berjarak sama dan menggunakan pemetaan afine di atas. int4 hanya dapat merepresentasikan 16 nilai, sehingga kehilangan lebih banyak akurasi dibandingkan int8. Metode yang menggunakan int4 biasanya melakukan kuantisasi per grup atau menggunakan kalibrasi untuk menjaga akurasi tetap tinggi.

Sebagian besar perangkat keras tidak memiliki tipe penyimpanan 4-bit, sehingga dua nilai int4 dikemas ke dalam satu byte. Misalnya, nilai pertama dapat menempati 4 bit bawah dan nilai kedua menempati 4 bit atas. Kernel mengurai nilai-nilai tersebut sebelum melakukan komputasi.

┌──────┐  ┌──────┐        ┌──────┬──────┐
│ val1 │  │ val2 │        │ val2 │ val1 │
│ 0101 │  │ 0011 │   →    │ 0011 │ 0101 │  1 byte
└──────┘  └──────┘        └──────┴──────┘
  int4      int4            high   low

Beberapa tipe 4-bit mengatur nilai yang dapat diwakilinya secara tidak merata agar sesuai dengan distribusi bobot. bitsandbytes NF4 menempatkan lebih banyak nilainya di dekat nol, di mana sebagian besar bobot berada.

FP8

FP8 mempertahankan tata letak bilangan titik apung yang terdiri dari tanda, eksponen, dan mantisa dalam 8 bit. Nilai-nilai yang dapat direpresentasikannya lebih berdekatan di sekitar nol dan semakin berjauhan pada magnitudo besar, yang sesuai dengan sebaran nilai pada bobot dan aktivasi.

FP8 hadir dalam dua varian.

  • E4M3 memiliki 4 bit eksponen dan 3 bit mantisa. Format ini lebih presisi tetapi mencakup rentang yang lebih kecil. Ini adalah pilihan umum untuk bobot dan aktivasi selama inferensi.
  • E5M2 memiliki 5 bit eksponen dan 2 bit mantisa. Format ini mencakup rentang yang lebih luas dengan presisi yang lebih rendah.
E4M3   ┌─┬───────┬─────┐
       │S│E E E E│M M M│
       └─┴───────┴─────┘
E5M2   ┌─┬─────────┬───┐
       │S│E E E E E│M M│
       └─┴─────────┴───┘
  S sign   E exponent   M mantissa

Matmul FP8 memerlukan dukungan perangkat keras, seperti GPU NVIDIA dengan compute capability 8.9 atau lebih tinggi (Ada, Hopper, Blackwell), AMD Instinct MI300, dan Intel XPU. Transformers mendukung FP8 melalui Fine-grained FP8, FBGEMM FP8, dan compressed-tensors.

FP4 dengan skala blok

FP4 memiliki 1 bit tanda, 2 bit eksponen, dan 1 bit mantisa (E2M1). Format ini hanya merepresentasikan nilai 0, 0,5, 1, 1,5, 2, 3, 4, dan 6, baik positif maupun negatif. Dengan begitu sedikit nilai yang tersedia, format FP4 tidak dapat bekerja dengan satu skala per tensor. Skala ditempelkan pada setiap blok kecil nilai, dan skala-skala tersebut disimpan sebagai bagian dari format.

FormatUkuran blokSkala per blokSkala tambahan
MXFP432 nilai8-bit pangkat dua (E8M0)None
NVFP416 nilaiFP8Satu skala FP32 per tensor

MXFP4 adalah format microscaling. Skala pangkat dua hanya menggeser eksponen, sehingga penerapannya murah, tetapi hanya dapat mendarat pada pangkat dua. NVFP4 menggunakan blok yang lebih kecil dan skala FP8 yang dapat mengambil nilai di antara pangkat dua. Hal ini mempertahankan lebih banyak akurasi, dengan biaya berupa skala per-tensor yang menjaga skala blok FP8 tetap dalam rentang. Four Over Six dan FP-Quant juga menghasilkan bobot NVFP4 atau MXFP4.

Ide blok yang sama juga muncul pada 8 bit. MXFP8 menyimpan nilai FP8 dengan skala blok pangkat dua, dan Fine-grained FP8 memuatnya.

Codebooks

Di bawah 4 bit, beberapa metode berhenti membulatkan setiap bobot ke nilai terdekat yang dapat direpresentasikan. Mereka melakukan kuantisasi pada kelompok bobot secara bersama-sama sebagai vektor. Codebook menyimpan seperangkat vektor yang telah dipelajari, dan setiap kelompok bobot disimpan sebagai indeks dari vektor terdekatnya. AQLM secara default menggunakan kelompok 8 bobot dan indeks 16-bit, yang setara dengan 2 bit per bobot. VPTQ juga menggunakan codebook. Menemukan codebook yang baik memerlukan optimasi yang panjang pada data kalibrasi, sehingga model-model ini dikuantisasi terlebih dahulu dan dimuat sebagai checkpoint.

Ketika kuantisasi terjadi

Sebuah model dikuantisasi baik setelah pelatihan maupun selama proses pelatihan. Sebagian besar metode di Transformers melakukan kuantisasi setelah pelatihan.

Kuantisasi pasca-pelatihan

Post-training quantization (PTQ) mengkuantisasi model yang sudah dilatih, tanpa mengubah apa yang telah dipelajarinya. Metode PTQ berbeda dalam hal apakah memerlukan data atau tidak, dan hal ini menentukan ke dalam kelompok mana suatu metode diklasifikasikan dalam daftar isi dokumentasi.

  • Tanpa data kalibrasi, skala berasal hanya dari bobot, dan kuantisasi cukup cepat untuk dijalankan saat model dimuat. bitsandbytes, HQQ, dan torchao bekerja dengan cara ini. Metode-metode ini tercantum di bawah Kuantisasi saat memuat.
  • Dengan data kalibrasi, metode ini menjalankan dataset kecil melalui model dan menggunakan aktivasi untuk menentukan cara mengkuantisasi setiap layer. Kalibrasi biasanya memberikan akurasi yang lebih baik pada 4 bit dan di bawahnya, tetapi membutuhkan waktu dari beberapa menit hingga beberapa jam.

Metode kalibrasi menggunakan aktivasi dengan cara yang berbeda. GPTQ mengkuantisasi sebuah layer satu kolom pada satu waktu dan menyesuaikan kolom-kolom yang tersisa untuk mengompensasi error pembulatan dari setiap kolom. AWQ menemukan kanal-kanal bobot dengan aktivasi terbesar dan memperbesarnya sebelum pembulatan untuk melindunginya.

Di mana jumlah eksekusi kalibrasi menentukan cara Anda menggunakan metode tersebut di Transformers.

  • GPTQ melakukan kalibrasi di dalam from_pretrained ketika Anda meneruskan dataset ke GPTQConfig, sehingga dicantumkan di bawah Kuantisasi saat memuat.
  • Metode kalibrasi lain, seperti AWQ, AutoRound, AQLM, dan VPTQ, melakukan kalibrasi di pustaka mereka sendiri. Transformers memuat hasilnya, sehingga metode-metode tersebut tercantum di bawah Memuat checkpoint terkuantisasi.

Pelatihan yang mempertimbangkan kuantisasi

Quantization-aware training (QAT) mensimulasikan kuantisasi selama pelatihan. Pada forward pass, nilai dibulatkan seperti yang dilakukan kuantisasi, sementara gradien memperbarui bobot berpresisi penuh, sehingga model belajar mentoleransi kesalahan pembulatan. QAT biasanya memberikan akurasi terbaik pada lebar bit yang sangat rendah, tetapi memerlukan pelatihan model.

Model BitNet dilatih dengan cara ini, dengan bobot 1,58-bit mereka dalam loop, dan Transformers memuat checkpoint yang telah dilatih.

Sumber daya

Update on GitHub