2 poin oleh GN⁺ 2024-12-13 | 1 komentar | Bagikan ke WhatsApp
  • Membangun inferencer GPT-2 hanya dengan kode C sekitar 3000 byte, menangani semuanya dalam satu alur mulai dari pemuatan bobot, tokenisasi, eksekusi Transformer, hingga konversi keluaran
  • Meski ukuran kodenya kecil, ia menghasilkan jawaban GPT-2 Small dalam hitungan detik di mesin modern berkat KV caching, perkalian matriks cepat, dan paralelisasi OMP opsional
  • Kualitas keluarannya berada pada level “secara objektif cukup buruk”, dan masih ada batasan praktis seperti penanganan UTF-8 serta kebutuhan memori saat menjalankan model besar
  • Implementasinya dibagi menjadi operasi matriks, layer jaringan saraf, Transformer, Byte Pair Encoding, I/O, serta pemuatan bobot dan BPE, memperlihatkan struktur lengkap inferencer kecil
  • GPT-2 adalah model open source tahun 2019 yang jauh lebih lemah daripada GPT-4, tetapi komponen inti untuk menjalankan model bahasa modern tetap dapat diekspresikan bahkan dengan kode C kecil

Eksekutor GPT-2 yang Dibuat dengan C 3000 Byte

  • Program ini adalah implementasi GPT-2 tanpa dependensi, yang membaca matriks bobot dan file BPE dari file TensorFlow asli
  • Masukan ditokenisasi dengan encoder Byte Pair Encoding(BPE) sederhana, dan keluaran dikonversi kembali menjadi string dengan decoder BPE
  • Struktur internalnya berurutan dari paket aljabar linear dasar, operasi matriks, arsitektur Transformer, hingga kode inferensi
  • Kodenya tersedia di GitHub
  • GPT-2 Small menghasilkan satu jawaban dalam sekitar beberapa detik di mesin modern
    • Mengimplementasikan KV caching
    • Menggunakan perkalian matriks yang efisien
    • Paralelisasi OMP dapat diaktifkan secara opsional

Kondisi Eksekusi dan Batasan

  • Dengan implementasi ini, program percakapan seperti ChatGPT bisa dibuat, tetapi kualitas keluarannya tidak bagus
  • Ada beberapa keanehan dalam penanganan karakter UTF-8
  • Menjalankan model ukuran XL dengan panjang konteks besar dapat membutuhkan sekitar 100GB RAM
  • Kombinasi masukan ASCII dan GPT-2 Small dapat dijalankan hampir di mana saja

Cara Kerja GPT-2 dan Transformer

  • ChatGPT adalah aplikasi yang memungkinkan percakapan seperti dengan manusia menggunakan model bahasa, dan GPT-4 diperkenalkan sebagai model terbaru yang menggerakkan ChatGPT
  • Program C ini mengimplementasikan perilaku mirip ChatGPT dengan GPT-2, model tahun 2019
  • GPT-2 adalah model machine learning keluarga Transformer
  • Transformer menerima urutan kata berukuran tetap sebagai input dan memprediksi kata berikutnya
  • Dengan mengulang prosedur yang sama, urutan dengan panjang sembarang dapat dihasilkan

Operasi Matriks dan Kompresi Berbasis Makro

  • Karena jaringan saraf tersusun dari operasi matriks, implementasinya dimulai dari struct Matrix minimal
    • float* dat
    • int rows, cols
  • Operasi yang diperlukan secara garis besar ada dua jenis
    • Operasi matriks-konstanta
    • Operasi matriks-matriks
  • Makro C digunakan untuk mengurangi struktur loop yang berulang, lalu beberapa fungsi dibuat hanya dengan mengganti operator tertentu
  • #define di C hampir seperti substitusi sederhana, sehingga bukan hanya operator umum, tetapi juga ekspresi yang menyertakan titik koma dapat dimasukkan sebagai argumen makro untuk mengurangi ukuran kode

Perkalian Matriks Cepat

  • Perkalian matriks dasar berawal dari implementasi O(n³) sederhana dengan tiga loop bertingkat
  • Dengan mempertimbangkan karakteristik cache dan akses memori, loop diubah agar membaca dan menulis memori yang sama secara berulang
  • Implementasi cepat menaikkan j dan k masing-masing sebesar 4, dan menggunakan loop k2 serta j2 di dalamnya
  • Pada tahap inferensi, untuk menggunakan kembali sebagian hasil yang sudah dihitung, ditambahkan cara mengalikan hanya sebagian matriks A dengan B

Implementasi Layer Jaringan Saraf

  • Untuk membuat Transformer, beberapa layer jaringan saraf diimplementasikan langsung
  • Fungsi aktivasi GELU diimplementasikan dengan makro
  • Ada fungsi yang memproses bagian segitiga bawah matriks untuk causal attention
    • Matriks attention dibatasi agar hanya melihat masa lalu, bukan token masa depan
  • LayerNorm menormalisasi rata-rata dan varians tiap layer
  • Fungsi Linear menambahkan bias dengan cara tiling setelah perkalian matriks

Inti Transformer

  • Implementasi Transformer mengulangi alur berikut pada setiap layer
    • Melalui LayerNorm dan Linear, query, key, value dihitung sekaligus
    • qkv dibagi per head
    • Perkalian query dan key dihitung, lalu pemrosesan causal attention diterapkan
    • Hasil softmax dikalikan dengan matriks value
    • Hasilnya digabungkan dan residual connection diterapkan
    • Melalui GELU dan Linear, residual connection diterapkan lagi
  • Pada akhirnya, setelah LayerNorm final, keluaran di posisi token terakhir dikalikan dengan bobot embedding untuk menghitung kandidat token berikutnya

Metode KV Caching

  • Dalam inferensi Transformer, setelah menghasilkan satu token, tidak perlu menghitung ulang seluruh fungsi saat membuat token berikutnya
  • Jika sebagian besar hasil perhitungan hingga token ke-N digunakan kembali, pembuatan token ke-N+1 hanya memerlukan sedikit pekerjaan tambahan
  • Implementasi melakukan semua alokasi secara berurutan di dalam blok memori yang sama
  • Setiap perkalian matriks dibuat agar selalu menggunakan memori yang sama, sehingga pada iterasi berikutnya memori tidak diinisialisasi ke 0 dan hasil sebelumnya dipertahankan
  • Pada iterasi baru, hanya baris ke-N+1 yang dihitung

Implementasi Byte Pair Encoding

  • Karena model bahasa memerlukan input berukuran tetap, sulit memperlakukan kata yang jumlahnya tak terbatas apa adanya pada tingkat kata
  • Model berbasis karakter harus mempelajari makna semua kata dari awal, dan memiliki masalah mengurangi ukuran konteks efektif sebesar rata-rata panjang kata
  • Model seperti GPT-2 menggunakan BPE yang membuat token dari potongan kata
    • Kata yang umum dapat menjadi satu token
    • Kata yang langka dipecah menjadi potongan yang lebih kecil
    • Sebagai contoh, nicholas dapat dibagi menjadi nich, o, las
  • Algoritme BPE umum berulang kali menggabungkan pasangan token yang berdekatan
  • Implementasi C ini, demi mengurangi ukuran kode, menggunakan metode rekursif yang berpotensi memakan waktu eksponensial alih-alih algoritme waktu linear
    • Mencari entri vocabulary yang cocok dengan prefix kata saat ini
    • Mentokenisasi sisa string secara rekursif
    • Memilih tokenisasi terbaik berdasarkan panjang dan indeks vocabulary

Pemuatan Bobot

  • Bobot jaringan saraf harus dibaca dari disk, dan filenya berupa format serialisasi biner datar dari float 32-bit
  • Ukuran model GPT-2 menggunakan arsitektur yang sama, dan bobot juga disimpan dalam urutan yang sama, sehingga cukup membaca matriks dengan bentuk yang benar secara berurutan
  • Urutan penyimpanan layer berbeda dari dugaan
    • Setelah layer 0 dan 1, muncul 10
    • Ini karena nama diurutkan dalam lexicographic order
    • Dalam pengurutan string, 10 muncul sebelum 2
  • Implementasi menggunakan kode permutasi untuk mengubah urutan ini menjadi urutan layer sebenarnya

Pemuatan Vocabulary BPE

  • Untuk menjalankan BPE, file vocabulary harus terlebih dahulu dibaca dari disk
  • File asli adalah format untuk dibaca dari Python, bukan format yang mudah diparsing dengan kode C kecil
  • File tersebut bukan daftar kata, melainkan daftar merge BPE
    • Misalnya, alih-alih token Hello disimpan langsung, ia disimpan sebagai instruksi untuk menggabungkan H dan ello
  • File menggunakan encoding yang mirip UTF-8 tetapi tidak persis sama
    • Karakter ASCII yang dapat dicetak disimpan apa adanya
    • Karakter yang tidak dapat dicetak dalam rentang 0~31 dienkode sebagai 188 + nilai karakter
    • Misalnya, spasi dienkode sebagai token Ġ
  • Ġ di disk adalah 0xc4 0xa0 dalam UTF-8, sehingga diperlukan pemrosesan terpisah untuk mengubahnya kembali menjadi spasi

Hal yang Ditunjukkan oleh Kode Kecil Ini

  • Perkembangan machine learning selama puluhan tahun dapat dipadatkan menjadi kode beberapa ribu byte
  • Jika bobot model aktual dikecualikan, hampir tidak ada elemen yang hilang untuk menjalankan jaringan saraf modern
  • Implementasi ini terutama dibuat untuk bersenang-senang, tetapi menjadi contoh bahwa jaringan saraf sebenarnya dapat dijalankan dengan komponen-komponen sederhana

1 komentar

 
GN⁺ 2024-12-13
Komentar Hacker News
  • Saya belum benar-benar menjalankan kodenya, tetapi ukurannya yang kecil cukup mengesankan
    Mengingat program-program ELIZA awal bahkan lebih besar, terasa luar biasa bahwa dalam 4 tahun terakhir hal seperti ini bisa dipadatkan hingga level byte
    Saya ingin ada yang menjelaskan di mana letak sihirnya. Apakah di fungsi GELU, atau pada model yang diunduh lewat skrip Bash?

    • Sebagian besar sihirnya ada pada file model 475MB yang diunduh lewat skrip Bash
    • Saya mencobanya dan tidak terlalu terkesan
      Untuk Who are you? ia menjawab I am Alice., dan kalau ditanya tentang komputer atau fungsinya ia terus mengulang I am a computer model trained by OpenAI. How can I help you?
      Saat diminta menjelaskan penjumlahan, ia malah menjelaskan perkalian, dan untuk 2+2 atau Sum 2+2 ia cuma mengulanginya begitu saja
  • Saya masih ingat saat pertama kali GPT-2 keluar dan saya memainkannya
    Saya pernah mengekspor log chat dengan seorang teman, lalu melakukan fine-tuning GPT-2 agar meniru percakapan kami berdua, dan hasilnya sangat lucu sekaligus kadang-kadang menyeramkan karena akurat
    Saya penasaran apa yang menyebabkan lonjakan besar dari GPT-2 ke GPT-3. Apakah model yang lebih besar, data yang lebih banyak, atau keduanya
    Saya tahu RLHF membuat perbedaan besar, tetapi model dasar GPT-3 pun sudah cukup berguna hanya dengan text completion jika diberi cukup contoh

  • Saya tidak terlalu paham, tetapi ada dongeng favorit saya yang ditulis GPT-2
    https://deepdreams.stavros.io/episodes/the-princess-the-fair...

    • Sangat bagus, benar-benar menghibur, dan juga cocok didengarkan sampai tertidur
      Saya penasaran apakah yang di halaman ini juga dibuat dengan GPT-2
    • Mengesankan, aneh, dan sekitar 90% konsisten, jadi muncul suasana khas yang ganjil
  • Kalimat “Sebagian besar dibuat untuk bersenang-senang, tetapi ini contoh bagus untuk menunjukkan betapa sederhananya jaringan saraf sebenarnya” itu lucu
    Ssst, jangan bilang siapa-siapa. AI itu ilmu hitam untuk menghasilkan uang

  • Apakah GPT-2 ini di-instruction-tune sehingga benar-benar bisa dipakai untuk chat?
    Kalau tidak, menurut saya agak berlebihan menyebutnya klon ChatGPT

    • Artikel itu sendiri sudah mengatakan ini: kalau Anda tidak terlalu peduli pada kualitas output, Anda bisa membuat sesuatu yang mirip ChatGPT, dan secara objektif output-nya cukup mengerikan, tetapi memang berjalan
      Praktis tidak bisa dipakai, dan selain menumpang nama, nyaris tidak ada hubungannya. Meski begitu, ini tetap program yang bisa dikompilasi dan dijalankan
      Melihat reaksi yang menilai tinggi performa proyek yang pembuatnya sendiri akui tidak benar-benar bekerja, rasanya inti utamanya adalah menarik perhatian dengan kata kunci populer
  • Kalimat “Apakah kalian para bahasa dengan macro yang layak sedang memperhatikan. Lisp tidak selalu lebih baik daripada C!” kali ini bisa diterima. Soalnya ini lelucon yang menyerang ke atas
    Kalau Anda belum melihat tautan kodenya, itu tersembunyi di dalam artikel: https://github.com/carlini/c-chat-gpt-2

  • Saya pernah melihat chatbot AI klasik yang lebih baik
    https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/areas...
    Splotch bisa dikompilasi dengan baik di sistem Unix modern dengan sedikit perbaikan

  • Saya penasaran apakah ada yang menjalankannya secara lokal untuk melihat keluaran seperti apa yang dihasilkan GPT-2 ini

    • Rasanya ia hampir selalu mengulang keluaran yang sama
      Meski begitu, tetap cukup menarik dan saya ingin membongkar lalu menyesuaikannya sendiri. Sudah lama saya ingin mengutak-atik GPT-2 secara lokal
    • Dari yang saya baca, kalau memakai temperature dan seed yang sama, model GPT-2 yang dimuat biasa dan model yang dimuat lewat program ini seharusnya menghasilkan output yang persis sama
      Saya sendiri belum sempat memastikan temperature dan seed di kodenya, karena saya lebih sedang mencoba memahami kenapa kodenya diobfuscate
      Bahkan setelah deobfuscation pun, sepertinya kodenya tidak akan menjadi terlalu panjang, dan kalau sekitar 10 ribu karakter, menurut saya melihatnya di layar saja sudah cukup mengesankan
  • Sekarang kalau memakai gptscript, Anda bisa dengan cepat membuat ChatGPT versi sendiri
    https://github.com/gptscript-ai/gptscript

  • GELU memang terasa seperti sihir:
    UNARY(GELU, b / 2 * (1 + tanh(.7978845 * (b + .044715 * b * b * b))))

    • Itu hanya pendekatan praktis terhadap definisi matematis asli GELU
      Definisinya adalah GELU(x) := x * Φ(x), dengan Φ(x) sebagai fungsi distribusi kumulatif dari distribusi Gaussian
    • Bentuknya mengingatkan saya pada fast inverse square root