berita

Ribuan kata informasi teknis! Panduan kuantifikasi yang harus dibaca bagi para insinyur LLM, ilustrasi visual mengungkapkan cara mengompresi model besar

2024-07-31

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Laporan Kebijaksanaan Baru

Editor: Departemen Editorial

[Pengantar Kebijaksanaan Baru] Dihadapkan dengan skala parameter LLM yang berkembang secara bertahap, pengembang dan peneliti tanpa H100 telah menemukan banyak cara untuk mengatasinya, dan teknologi "kuantifikasi" adalah salah satunya. Panduan visual ini menggunakan berbagai ilustrasi untuk merangkum secara komprehensif konsep dasar dan metode cabang "kuantifikasi".

Model bahasa besar (LLM) seringkali terlalu besar untuk dijalankan pada perangkat keras tingkat konsumen. Model ini dapat memiliki lebih dari miliaran parameter dan seringkali memerlukan GPU dengan memori besar untuk mempercepat proses inferensi.

Oleh karena itu, semakin banyak penelitian yang mulai berfokus pada cara mengecilkan model, seperti meningkatkan metode pelatihan atau menggunakan adaptor. Salah satu teknik utama dalam bidang ini disebut kuantisasi.

Insinyur ML Maarten Grootendorst menulis postingan blog yang secara khusus memperkenalkan teknologi kuantifikasi dalam konteks pemodelan bahasa dan mengeksplorasi konsep terkait satu per satu melalui metode visual untuk membantu kami membangun pemahaman intuitif tentang teknologi tersebut.


Dalam postingan blog ini, Maarten mengeksplorasi berbagai metode, kasus penggunaan, dan prinsip di balik kuantifikasi.

Daftar isi dan isi artikel ditunjukkan pada gambar di bawah ini. Artikel ini terutama memperkenalkan dua metode kuantifikasi pasca pelatihan (PTQ) dan pelatihan sadar kuantisasi (QAT). langsung ke bagian kuantisasi simetris:


Bagian Satu: "Masalah" LLM

"Model bahasa besar" berukuran besar dalam hal jumlah parameter model, biasanya mencapai skala miliaran (terutama bobot).

Tidak hanya biaya penyimpanan parameter tersebut yang cukup tinggi, namun jumlah penghitungan pada tahap inferensi juga besar.

Pada saat inferensi, nilai aktivasi merupakan perkalian antara input dan bobot, sehingga semakin besar jumlah bobot maka semakin besar nilai aktivasi.


Oleh karena itu, kami ingin merepresentasikan miliaran nilai seefisien mungkin, sehingga meminimalkan ruang yang diperlukan untuk menyimpan parameter.

Mari kita mulai dari awal dan menjelajahi bagaimana nilai direpresentasikan sebelum melakukan pengoptimalan.

Cara merepresentasikan nilai numerik

Nilai numerik biasanya disimpan sebagai bilangan floating point (atau sekadar mengambang): bilangan positif atau negatif dengan koma desimal.

Nilai-nilai ini diwakili oleh digit biner pada setiap bit.

Standar IEEE-754 menjelaskan bagaimana digit pada setiap digit mewakili nilai tertentu. Secara khusus, ada tiga pemetaan: tanda, eksponen, atau desimal (mantissa).


Ketiga bagian ini dapat digabungkan untuk menghitung nilai yang diwakili berdasarkan sekumpulan nilai bit:


Semakin banyak digit yang digunakan, semakin presisi nilai numeriknya. Misalnya, formulir FP32 bisa akurat hingga lebih banyak digit setelah koma dibandingkan FP16:


batas memori

Semakin banyak digit yang tersedia, tidak hanya semakin tepat nilainya, namun juga semakin luas rentang nilai yang dapat direpresentasikan.


Dengan adanya nomor bit dan representasinya, rentang nilai yang dapat direpresentasikan disebut rentang dinamis, dan jarak antara dua nilai yang berdekatan disebut presisi.


Fitur menarik dari representasi ini adalah kita dapat menghitung berapa banyak memori yang dibutuhkan perangkat untuk menyimpan nilai tertentu.

Karena setiap byte dalam memori berisi 8 bit, kita dapat membuat rumus dasar untuk sebagian besar bentuk bilangan floating point -


Dalam aplikasi nyata, ada lebih banyak faktor yang mempengaruhi jumlah grafis/memori yang dibutuhkan selama inferensi, seperti ukuran konteks dan arsitektur model.

Sekarang bayangkan kita memiliki model dengan 70 miliar parameter. Sebagian besar model direpresentasikan menggunakan angka floating point 32-bit (sering disebut presisi penuh), yang memerlukan memori 280 GB untuk memuat model.


Namun jika semua parameter dapat dinyatakan sebagai angka floating point 16-bit, ukuran memori yang dibutuhkan dapat langsung dikurangi satu kali.

Oleh karena itu, sangat menarik untuk meminimalkan jumlah representasi parameter model (tidak hanya untuk inferensi tetapi juga untuk pelatihan).

Namun, pendekatan ini bukannya tanpa biaya. Akurasi model biasanya menurun seiring dengan berkurangnya jumlah bit representasi yang mengakibatkan penurunan akurasi.

Kami ingin mengurangi jumlah digit yang digunakan untuk mewakili suatu nilai dengan tetap menjaga akurasi...di sinilah teknik kuantisasi berguna.

Bagian 2: Pengantar Kuantifikasi

Kita sekarang tahu bahwa tujuan kuantisasi adalah untuk mengurangi keakuratan parameter model dari lebar bit yang lebih tinggi (seperti angka floating point 32-bit) ke lebar bit yang lebih rendah (seperti bilangan bulat 8-bit).


Saat mengurangi jumlah bit yang mewakili parameter asli, biasanya terjadi hilangnya beberapa presisi (granularitas).

Untuk membuat efek ini lebih intuitif, kita dapat menggunakan warna foto sebagai analogi. Misalnya, pilih gambar apa saja (kiri), tetapi gunakan hanya 8 warna (kanan):


Perhatikan bahwa cookie yang diperbesar terlihat lebih "berbutir" dibandingkan aslinya.

Demikian pula, tujuan utama kuantisasi adalah untuk mengurangi jumlah bit (warna) yang diperlukan untuk mewakili parameter asli sambil mempertahankan presisi sebanyak mungkin dari parameter asli.

Tipe data umum

Pertama, mari kita lihat tipe data umum dan dampak penggunaannya dibandingkan representasi 32-bit (disebut presisi penuh atau FP32).

FP16

Yang pertama adalah contoh peralihan dari floating point 32-bit ke 16-bit (disebut setengah presisi atau FP16):


Kisaran nilai yang mungkin untuk FP16 jauh lebih kecil dibandingkan dengan FP32.

BF16

Untuk mendapatkan rentang numerik yang serupa dengan FP32 asli, bfloat 16 diperkenalkan sebagai tipe "FP32 terpotong":


BF16 menggunakan jumlah bit yang sama dengan FP16, namun menambahkan bit eksponensial, sehingga dapat memperoleh rentang nilai yang lebih luas dan sering digunakan dalam bidang deep learning.

INT8

Saat Anda mengurangi jumlah bit lebih lanjut, representasi menjadi lebih dekat ke bilangan bulat daripada angka floating point. Misalnya beralih dari FP32 ke INT8 yang hanya memiliki 8 bit, hanya 1/4 dari jumlah bit aslinya:


Setiap kali jumlah bit dikurangi, pemetaan dilakukan untuk "mengompresi" representasi FP32 asli menjadi bit yang lebih sedikit.

Namun dalam pengoperasian sebenarnya, kita tidak perlu memetakan seluruh rentang FP32 [-3.4e38, 3.4e38] ke INT8. Kita hanya perlu menemukan cara untuk memetakan rentang data parameter model sebenarnya ke dalam INT8.

Metode kompresi/pemetaan yang umum mencakup kuantisasi simetris dan kuantisasi asimetris, keduanya merupakan pemetaan linier.

Yang akan kita bahas selanjutnya adalah metode kuantisasi dari FP32 hingga INT8.

Kuantisasi simetris

Dalam kuantisasi simetris, rentang nilai floating point asli dipetakan ke rentang simetris yang berpusat pada nol di ruang kuantisasi, dengan nol sebagai titik tengah rentang sebelum dan sesudah kuantisasi.

Ini berarti bahwa nol awal dalam ruang floating point adalah nol setelah dipetakan ke ruang terkuantisasi.


Contoh khas kuantisasi simetris adalah kuantisasi maksimum absolut (absmax).

Dengan adanya daftar nilai, kami mengambil nilai absolut tertinggi (α) sebagai rentang untuk melakukan pemetaan linier.


[-127, 127] mewakili rentang terbatas, dan rentang tidak terbatas adalah [-128, 127], bergantung pada metode kuantisasi

Karena ini adalah peta linier yang berpusat pada nol, rumusnya sederhana.

Pertama hitung faktor skalanya dengan menggunakan rumus berikut:

- b adalah jumlah byte yang ingin kita kuantisasi (8)

- α adalah nilai absolut tertinggi

Kami kemudian menggunakan s untuk mengukur input x:


Seperti terlihat pada gambar di atas, nilai absolut maksimum α adalah 10,8. Saat memetakan FP32 ke INT8, diperoleh rumus berikut:


Jika Anda ingin mengembalikan nilai FP32 asli, Anda juga dapat menggunakan faktor skala yang dihitung sebelumnya untuk kuantisasi terbalik.


Pertama-tama kuantisasi, lalu dekuantisasi untuk mengembalikan nilai aslinya.


Anda dapat melihat bahwa beberapa nilai, seperti 3,08 dan 3,02, keduanya bernilai 36 ketika dikuantisasi ke INT8. Jadi ketika didekuantisasi kembali ke FP32, presisinya akan hilang dan tidak lagi dapat dibedakan.

Perbedaan antara nilai asli dan nilai terkuantisasi terbalik disebut kesalahan kuantisasi. Umumnya, semakin sedikit bit hasil kuantisasi, semakin besar kesalahannya.


kuantisasi asimetris

Berbeda dengan kuantisasi simetris, kuantisasi asimetris bukanlah simetri yang berpusat pada nol. Sebaliknya, ini memetakan nilai minimum (β) dan maksimum (α) dari rentang floating point ke nilai minimum dan maksimum dari rentang terkuantisasi.

Metode yang kita bahas di sini disebut kuantisasi titik nol.


Perhatikan bagaimana posisi 0 berpindah. Itu sebabnya disebut kuantisasi asimetris. Pada rentang [-7.59, 10.8], nilai maksimum dan minimum berada pada jarak yang berbeda dari 0.

Karena adanya offset posisi titik nol, kita harus menghitung titik nol pada rentang INT8 untuk melakukan pemetaan linier. Seperti sebelumnya, kita juga harus menghitung faktor skala, tetapi menggunakan selisih pada rentang INT8 [-128, 127].


Ini agak rumit karena titik nol (z) perlu dihitung dalam rentang INT8 untuk memindahkan bobot.

Seperti sebelumnya, mari kita isi rumusnya:


Untuk mendekuantisasi nilai terkuantisasi dari INT8 kembali ke FP32, kita perlu menggunakan faktor skala (s) dan titik nol (z) yang telah dihitung sebelumnya.

Jika tidak, dekuantisasi sederhana saja:


Jika kita menempatkan kuantisasi simetris dan asimetris secara berdampingan, kita dapat dengan cepat melihat perbedaan antara kedua metode tersebut:


Pada gambar di atas terlihat ciri titik pusat nol pada kuantisasi simetris dan offset kuantisasi asimetris.

Pemetaan jangkauan dan kliping (Kliping)

Pada contoh sebelumnya, kita mempelajari cara memetakan rentang nilai dalam vektor tertentu ke representasi bit rendah. Meskipun dapat memetakan seluruh rentang nilai vektor, hal ini memiliki satu kelemahan utama, yaitu outlier.

Bayangkan Anda memiliki vektor yang berisi nilai-nilai berikut:


Nilai yang jauh lebih besar dibandingkan nilai lainnya dapat dianggap outlier. Jika kita memetakan seluruh rentang vektor, semua nilai kecil akan dipetakan ke representasi tingkat rendah yang sama dan kehilangan kekhasannya:


Ini adalah metode absmax yang digunakan sebelumnya.Hal yang sama terjadi dengan kuantisasi asimetris tanpa kliping

Sebagai gantinya, kita dapat memilih untuk memotong nilai-nilai tertentu. Kliping mengacu pada pengaturan rentang dinamis yang berbeda dari nilai asli sehingga semua outlier disetel ke nilai yang sama.

Pada contoh di bawah, kami menyetel rentang dinamis secara manual ke [-5, 5], dan semua nilai di luar rentang ini akan dipetakan ke -127 atau 127, terlepas dari nilai sebenarnya:


Keuntungan utama dari pendekatan ini adalah kesalahan kuantisasi untuk non-outlier berkurang secara signifikan. Namun, hal ini akan menyebabkan peningkatan kesalahan kuantisasi untuk outlier.

Kalibrasi

Dalam contoh di atas, kami secara acak menetapkan rentang dinamis ke [-5, 5], namun keputusan harus dibuat melalui proses "kalibrasi" untuk menemukan rentang yang sesuai yang mencakup nilai sebanyak mungkin sambil meminimalkan kesalahan kuantisasi.

Eksekusi spesifik langkah kalibrasi berbeda untuk jenis parameter yang berbeda.

Bobot (dan bias)

Kita dapat menganggap bobot & bias model bahasa besar (LLM) sebagai nilai statis karena diketahui sebelum model dijalankan. Misalnya, file Llama 3 berukuran ~20GB sebagian besar terdiri dari bobot dan biasnya.

Karena jumlah variabel bias (jutaan) secara signifikan lebih kecil daripada bobotnya (miliar), bias biasanya mempertahankan akurasi yang lebih tinggi (seperti INT16), sedangkan pekerjaan utama kuantisasi berfokus pada bobot.

Untuk anak timbangan statis yang diketahui, teknik kalibrasi untuk memilih rentang meliputi:

- Pilih persentil rentang input secara manual

- Optimalkan mean square error (MSE) antara bobot asli dan bobot terkuantisasi

- Minimalkan entropi antara nilai asli dan nilai terkuantisasi (divergensi KL)


Memilih persentil, misalnya, menghasilkan perilaku kliping yang serupa dengan yang kita lihat sebelumnya.

nilai aktivasi

Masukan yang terus diperbarui di seluruh model bahasa besar sering disebut aktivasi.


Disebut nilai aktivasi karena biasanya melalui beberapa fungsi aktivasi, seperti sigmoid atau relu

Tidak seperti bobot, aktivasi berubah seiring dengan masukan data selama inferensi dan oleh karena itu sulit untuk diukur secara akurat.

Karena nilai-nilai ini diperbarui setelah setiap lapisan tersembunyi, nilai spesifiknya tidak diketahui selama fase inferensi sampai data masukan melewati model.


Secara umum, ada dua metode untuk mengkalibrasi bobot dan aktivasi, yang diterapkan pada tahapan model yang berbeda:

- Kuantisasi Pasca Pelatihan (PTQ)

– Seperti namanya, ini adalah kuantifikasi setelah pelatihan

- Pelatihan Sadar Kuantisasi (QAT)

- Kuantisasi selama pelatihan/penyempurnaan

Bagian 3: Kuantifikasi pasca pelatihan (PTQ)

Kuantisasi pasca pelatihan (PTQ) adalah salah satu teknik kuantisasi yang paling populer. Ini mengkuantifikasi parameter model (termasuk bobot dan nilai aktivasi) setelah pelatihan model selesai.

Kuantisasi bobot dapat menggunakan kuantisasi simetris atau kuantisasi asimetris.

Namun, kuantifikasi nilai aktivasi memerlukan tahap inferensi untuk mendapatkan distribusi dasarnya, karena kita tidak mengetahui jangkauannya sebelumnya.

Ada dua bentuk kuantisasi nilai aktivasi:

- kuantisasi dinamis

- kuantisasi statis

kuantisasi dinamis

Setelah data melewati lapisan tersembunyi, nilai aktivasinya dikumpulkan dan nilai maksimum (α) dan nilai minimum (β) masing-masing lapisan dibandingkan:


Distribusi aktivasi ini kemudian digunakan untuk menghitung nilai titik nol (z) dan faktor skala (s) yang diperlukan untuk keluaran terkuantisasi:


Proses ini berulang setiap kali data melewati lapisan jaringan baru. Oleh karena itu, setiap lapisan memiliki nilai z dan s yang independen, sehingga menggunakan skema kuantisasi yang berbeda.

kuantisasi statis

Berbeda dengan kuantisasi dinamis, kuantisasi statis tidak menghitung titik nol (z) dan faktor skala (s) selama inferensi, tetapi menghitung nilai-nilai tersebut sebelum inferensi.

Untuk menemukan nilai-nilai ini, kami menggunakan kumpulan data kalibrasi dan memasukkannya ke dalam model untuk mengumpulkan distribusi nilai aktivasi yang mendasarinya.


Setelah distribusi ini dikumpulkan, nilai s dan z yang diperlukan untuk kuantifikasi selama inferensi dapat dihitung.

Pada waktu inferensi sebenarnya, nilai s dan z tidak dihitung ulang tetapi digunakan secara global di semua aktivasi untuk mengukurnya.

Secara keseluruhan, kuantisasi dinamis, yang menghitung nilai s dan z untuk setiap lapisan tersembunyi, cenderung lebih akurat. Namun, hal ini dapat menambah waktu komputasi karena nilai-nilai ini perlu dihitung pada setiap waktu inferensi.

Sebaliknya, kuantisasi statis meskipun tidak seakurat kuantisasi dinamis, namun lebih cepat karena sudah mengetahui terlebih dahulu nilai s dan z yang digunakan untuk kuantisasi.

Bidang kuantitatif 4-bit

Kuantisasi di bawah 8-bit selalu menjadi tantangan karena kesalahan kuantisasi meningkat seiring dengan hilangnya bit. Untungnya, ada beberapa cara cerdas untuk mengurangi jumlah bit menjadi 6, 4, atau bahkan 2-bit (meskipun mengurangi jumlah bit di bawah 4-bit umumnya tidak disarankan).

Kami akan menjelajahi dua metode umum di HuggingFace:

- GPTQ (model lengkap berjalan pada GPU)

- GGUF (mungkin memindahkan lapisan ke CPU)

GPTQ

GPTQ dapat dikatakan sebagai salah satu metode kuantisasi 4-bit yang paling terkenal dalam aplikasi praktis.

Ia menggunakan kuantisasi asimetris dan memprosesnya lapis demi lapis, memproses setiap lapisan secara independen sebelum melanjutkan ke lapisan berikutnya:


Dalam proses kuantisasi lapis demi lapis ini, pertama-tama bobot lapisan diubah menjadi matriks Hessian terbalik. Matriks Hessian terbalik merupakan turunan kedua dari fungsi kerugian model dan merepresentasikan sensitivitas keluaran model terhadap setiap perubahan bobot.

Sederhananya, ini pada dasarnya menunjukkan pentingnya (kepentingan terbalik) dari bobot di setiap lapisan.

Bobot nilai yang lebih kecil pada matriks Hessian lebih penting karena perubahan kecil pada bobot ini dapat menyebabkan perubahan signifikan pada performa model.


Dalam matriks invers Hessian, nilai yang lebih rendah mewakili bobot yang lebih "penting".

Selanjutnya, kita melakukan kuantisasi dan dekuantisasi baris pertama matriks bobot:


Proses ini memungkinkan kita menghitung kesalahan kuantisasi (q), yang dapat kita bobotkan menggunakan nilai Hessian terbalik yang dihitung sebelumnya (h_1).

Pada dasarnya, kami membuat kesalahan terkuantisasi tertimbang berdasarkan pentingnya bobot:


Selanjutnya, kami mendistribusikan ulang kesalahan kuantisasi tertimbang ini ke bobot baris lainnya. Ini membantu menjaga fungsionalitas dan output jaringan secara keseluruhan.

Misalnya, jika kita melakukan ini untuk bobot kedua (yaitu x_2=0,3), kita mengalikan kesalahan kuantisasi (q) dengan invers Hessian dari bobot kedua (h_2) dan menambahkannya:


Selanjutnya, lanjutkan operasi yang sama untuk bobot ketiga pada baris tertentu:


Proses mendistribusikan kembali kesalahan kuantisasi tertimbang q ini diulangi hingga semua nilai telah terkuantisasi.

Metode ini berhasil karena bobot biasanya berhubungan satu sama lain. Oleh karena itu, jika suatu bobot memiliki kesalahan kuantisasi, bobot terkait akan diperbarui melalui invers Hessian.

GGUF

Meskipun GPTQ adalah metode kuantisasi yang baik untuk menjalankan seluruh model bahasa besar (LLM) pada GPU, jika tidak ada kondisi perangkat keras yang sesuai, lapisan LLM mana pun juga dapat diturunkan ke CPU melalui GGUF.

Ini setara dengan menjalankan model pada CPU dan GPU secara bersamaan untuk menutupi kekurangan memori video (VRAM).

Metode kuantisasi GGUF sering diperbarui dan bergantung pada jumlah bit kuantisasi tertentu, namun prinsip dasarnya adalah sebagai berikut.

Pertama, bobot lapisan tertentu dibagi menjadi "blok super", yang masing-masing berisi sekumpulan "sub-blok". Dari "sub-blok" ini kami menghitung faktor skala dan nilai alfa:


Untuk mengkuantisasi "sub-blok" tertentu, Anda dapat menggunakan kuantisasi absmax yang disebutkan sebelumnya, mengalikan bobot tertentu dengan faktor skala (s_sub):


Faktor skala s_sub dihitung menggunakan informasi di "sub-blok", tetapi dikuantisasi menggunakan informasi s_super di "super-blok":


Singkatnya, kuantisasi blok demi blok ini menggunakan faktor skala "super blok" (s_super) untuk mengkuantisasi faktor skala "sub blok" (s_sub).

Tingkat kuantisasi setiap faktor skala mungkin berbeda, dan faktor skala "super-blok" umumnya memiliki presisi lebih tinggi dibandingkan faktor skala "sub-blok".

Untuk mengilustrasikannya, mari kita jelajahi beberapa level kuantisasi (2-bit, 4-bit, dan 6-bit):


Tergantung pada jenis kuantisasi, nilai minimum tambahan (m) juga diperlukan untuk menyesuaikan titik nol, nilai ini dikuantisasi serta faktor skalanya

Bagian 4: Pelatihan Kesadaran Kuantitatif (QAT)

Bagian ketiga menjelaskan cara mengkuantisasi model setelah pelatihan. Kelemahan metode ini adalah tidak memperhitungkan proses pelatihan yang sebenarnya.

Di sinilah Pelatihan Kesadaran Kuantitatif (QAT) berguna. Berbeda dengan kuantifikasi pasca pelatihan (PTQ), tujuan QAT adalah mempelajari proses kuantisasi selama pelatihan.


QAT cenderung lebih akurat dibandingkan PTQ karena kuantisasi sudah diperhitungkan selama proses pelatihan. Begini cara kerjanya:

Selama proses pelatihan, apa yang disebut kuantisasi "palsu" diperkenalkan. Misalnya, pertama-tama kuantisasi bobot ke dalam INT4, lalu dekuantisasi kembali ke FP32:


Proses ini memungkinkan model memperhitungkan kesalahan kuantisasi saat menghitung kerugian dan memperbarui bobot selama fase pelatihan.

Seperti yang ditunjukkan pada gambar di bawah, QAT berupaya mengeksplorasi nilai kerugian dalam kasus minimum "lebar" untuk mengurangi kesalahan kuantisasi, karena minimum "sempit" sering kali menyebabkan kesalahan kuantisasi yang lebih besar.


Dengan asumsi bahwa kuantisasi tidak dipertimbangkan selama propagasi mundur, proses penurunan gradien akan memilih bobot dengan nilai kerugian terkecil. Namun, jika nilai minimumnya "sempit", hal ini akan menimbulkan kesalahan kuantisasi yang lebih besar.

Sebaliknya, jika kita mempertimbangkan kuantisasi, bobot pembaruan yang berbeda akan dipilih dalam minimum "lebar", dengan kesalahan kuantisasi yang jauh lebih kecil.


Oleh karena itu, meskipun metode PTQ memiliki nilai kerugian yang rendah pada presisi tinggi (misalnya FP32), QAT juga memiliki nilai kerugian yang rendah pada presisi rendah (misalnya INT4), itulah yang sedang kami kejar.

Era 1-bit: BitNet

Kita telah melihat sebelumnya bahwa mengurangi akurasi kuantisasi menjadi 4-bit sudah cukup kecil, tapi bagaimana jika kita menguranginya lebih jauh?

Di sinilah BitNet berperan, ia mewakili bobot model sebagai bit tunggal, baik -1 atau 1, dan melakukan ini dengan memasukkan proses kuantisasi langsung ke arsitektur Transformer.

Arsitektur Transformer adalah dasar dari sebagian besar LLM dan terdiri dari perhitungan yang melibatkan lapisan linier:


Lapisan linier ini biasanya direpresentasikan dengan presisi lebih tinggi, seperti FP16, dan merupakan tempat sebagian besar bobot berada.

BitNet menggantikan lapisan linier ini dengan lapisan BitLinear:


Lapisan BitLinear bekerja sama seperti lapisan linier normal, mengalikan bobot dengan nilai aktivasi untuk menghitung keluaran.

Namun perbedaannya adalah lapisan BitLinear hanya menggunakan 1 bit untuk mewakili bobot model, dan menggunakan INT8 untuk mewakili nilai aktivasi:


Lapisan BitLinear, seperti pelatihan sadar kuantisasi (QAT), melakukan semacam kuantisasi "palsu" selama pelatihan untuk menganalisis efek kuantisasi bobot dan aktivasi:


Mari kita pahami BitLinear selangkah demi selangkah.

kuantifikasi berat badan

Selama pelatihan, bobot disimpan sebagai INT8 dan kemudian dikuantisasi menjadi 1 bit menggunakan strategi dasar yang disebut fungsi signum.

Intinya, ini memindahkan distribusi bobot agar terpusat pada 0, lalu menetapkan semua nilai yang kurang dari 0 menjadi -1 dan semua nilai yang lebih besar dari 0 menjadi 1:


Selain itu, ia melacak nilai β (nilai absolut rata-rata), yang akan kita gunakan nanti dalam proses kuantisasi terbalik.

Kuantisasi Aktivasi

Untuk mengukur aktivasi, BitLinear mengaktifkan metode nilai maksimum absolut (absmax) untuk mengubah aktivasi dari FP16 ke INT8 karena memerlukan perkalian matriks (×) dengan presisi lebih tinggi.


Selain itu, ia melacak nilai α (nilai absolut maksimum), yang nantinya akan kita gunakan dalam proses dekuantisasi.

kuantisasi terbalik

Kami melacak α (nilai absolut maksimum dari aktivasi) dan β (nilai absolut rata-rata dari bobot), yang akan membantu kami mendekuantisasi aktivasi kembali ke FP16.

Aktivasi keluaran diubah skalanya menggunakan {α, γ} untuk mendekuantisasinya ke akurasi asli:


Proses ini relatif sederhana dan memungkinkan model direpresentasikan hanya dengan dua nilai, -1 atau 1.

Dengan pendekatan ini, penulis mengamati bahwa seiring bertambahnya ukuran model, kesenjangan kinerja antara pelatihan 1-bit dan pelatihan FP16 menjadi semakin kecil.

Namun, ini hanya berlaku untuk model yang lebih besar (parameter >30B), kesenjangan antara model yang lebih kecil masih besar.

Semua LLM berukuran 1,58 bit

Untuk memperbaiki masalah skalabilitas yang disebutkan sebelumnya, BitNet 1.58b diperkenalkan.

Dalam pendekatan baru ini, setiap bobot model tidak hanya bisa bernilai -1 atau 1, namun juga bisa bernilai 0, sehingga menjadikan setiap variabel sebagai ternary.

Menariknya, menambahkan 0 saja sudah merupakan operasi sederhana yang sangat meningkatkan BitNet dan mempercepat proses penghitungan.

0 kekuatan

Mengapa menambahkan 0 merupakan peningkatan yang signifikan?

Ini ada hubungannya dengan perkalian matriks!

Pertama, mari kita telusuri cara kerja dasar perkalian matriks.

Saat menghitung keluaran, kita mengalikan matriks bobot dengan vektor masukan. Berikut visualisasi perkalian baris pertama matriks bobot lapisan pertama:


Perkalian ini melibatkan dua tindakan, mengalikan satu bobot dengan masukan dan kemudian menjumlahkan semuanya.

Sebaliknya, BitNet 1.58b berhasil menghindari tindakan perkalian, karena bobot tiga nilai pada dasarnya memberi tahu Anda hal berikut:

- 1: Saya ingin menambahkan nilai ini

- 0: Saya tidak menginginkan nilai ini

- -1: Saya ingin mengurangi nilai ini

Jadi jika bobot Anda dikuantisasi menjadi 1,58 bit, Anda hanya perlu melakukan penambahan:


Hal ini tidak hanya mempercepat penghitungan secara signifikan, tetapi juga memungkinkan pemfilteran fitur.

Menetapkan bobot tertentu ke 0 sama dengan mengabaikan masukan, daripada menambah atau mengurangi nilai masukan seperti 1-bit.

Mengukur

Untuk melakukan kuantisasi bobot, BitNet 1.58b menggunakan kuantisasi nilai absolut rata-rata (absmean), sebuah varian dari kuantisasi nilai absolut maksimum (absmax) yang telah kita lihat sebelumnya.

Ini hanya memampatkan distribusi bobot dan menggunakan mean absolut (α) untuk mengukur nilainya. Kemudian bulatkan menjadi -1, 0, atau 1:


Dibandingkan dengan BitNet, kuantisasi aktivasi sama kecuali untuk satu aspek: alih-alih menskalakan aktivasi ke rentang [0, 2ᵇ⁻¹], kami menggunakan metode nilai absolut maksimum untuk menskalakan ke [-2ᵇ⁻¹, 2ᵇ⁻¹] .

Singkatnya, kuantisasi 1,58-bit terutama melibatkan dua teknik:

- Tambahkan 0 untuk membuat representasi tiga nilai [-1, 0, 1]

- Kuantifikasi bobot rata-rata absolut

Makalah BitNet mempunyai kesimpulan sebagai berikut: "13B BitNet b1.58 lebih efisien daripada 3B FP16 LLM dalam hal latensi, penggunaan memori, dan konsumsi energi."


Alamat makalah: https://arxiv.org/abs/2402.17764

Dengan hanya 1,58 bit yang efisien secara komputasi, kami mendapatkan model yang ringan.

Referensi:

https://newsletter.maartengrootendorst.com/p/a-visual-guide-to-quantization