1 poin oleh GN⁺ 2024-02-25 | 1 komentar | Bagikan ke WhatsApp
  • Mereplikasi alur inferensi GPT-2 dalam SQL hanya dengan PostgreSQL dan pgvector, mulai dari tokenisasi hingga blok Transformer dan pembuatan token berikutnya
  • LLM generatif dapat dipandang mirip fungsi deterministik yang menghasilkan probabilitas kandidat token yang sama untuk input yang sama; titik ketika respons menjadi berbeda adalah tahap pemilihan probabilistik kandidat token
  • Implementasi ini mengekspresikan tokenizer BPE GPT-2, 50.257 token, embedding 768 dimensi, konteks 1.024 token, 12 blok, 12 attention head, dan feedforward berbasis GELU sebagai query dan tabel SQL
  • Diperlukan solusi workaround realistis yang disesuaikan dengan lingkungan database, seperti tidak adanya dukungan properti Unicode pada regex PostgreSQL dan keterbatasan EXP dalam menangani nilai yang sangat kecil
  • Contohnya menghasilkan 10 token dari "Happy New Year! I wish you" dan mencetak "Happy New Year! I wish you all the best in your new year!"; di lingkungan penulis, proses ini memakan waktu 2 menit 44 detik

Membuat Pipeline Inferensi GPT-2 dengan SQL

  • ChatGPT menjawab bahwa SQL tidak cocok untuk mengimplementasikan model bahasa berskala besar, tetapi pipeline inferensi GPT-2 berhasil diimplementasikan dengan SQL PostgreSQL
  • Penjelasan implementasi yang dijadikan referensi adalah GPT in 60 Lines of NumPy oleh Jay Mody, dengan komponen yang sama dipindahkan ke tabel dan query database
  • LLM generatif dapat dilihat seperti fungsi berbentuk llm(prompt: str) -> list[tuple[str, float]]
    • Inputnya adalah prompt teks
    • Outputnya adalah kandidat string berikutnya beserta array probabilitas
    • Jika matematika internal dan parameternya sama, input yang sama akan mengembalikan hasil yang sama
  • Alasan produk seperti ChatGPT dapat memberi jawaban berbeda untuk pertanyaan yang sama lebih terletak pada pemilihan probabilistik di tahap pemilihan token berikutnya daripada pada model itu sendiri

Loop Pembuatan Teks

  • Proses pembuatan dimulai dengan mengubah prompt menjadi array token, lalu berulang kali memanggil model untuk memilih token berikutnya dan menambahkannya ke belakang prompt
  • Alur dasarnya terdiri dari langkah-langkah berikut
    • tokenize(prompt) mengubah string menjadi array ID token
    • gpt2(tokens) menghitung probabilitas untuk 50.257 token
    • select_next_token(candidates) memilih token berikutnya
    • Menambahkan token yang dipilih ke array
    • Berhenti pada kondisi seperti jumlah token yang ditentukan, timeout, atau stopword
    • detokenize(tokens) mengembalikan array token menjadi string
  • Urutan token yang terakumulasi seperti ini dapat menjadi teks bahasa alami yang memiliki karakteristik yang tampak seperti tata bahasa, sintaksis, makna, dan penalaran

Mengimplementasikan Tokenizer BPE dengan SQL

  • Sebelum masuk ke jaringan saraf, teks harus diubah menjadi daftar angka, tetapi memakai code point Unicode secara langsung membuat ruang token dan panjangnya tidak efisien
  • GPT-2 menggunakan variasi Byte pair encoding
    • Kamus token menggunakan 50.257 code point
    • Mencakup urutan byte UTF-8 dan token “end of text”
    • Awalnya dimulai dari 256 token byte, lalu pasangan token berdekatan yang sering muncul ditambahkan sebagai token baru
    • Penggabungan ini diulang 50.000 kali untuk membuat 50.256 token, lalu token end-of-text ditambahkan di akhir
  • Tokenizer GPT-2 memiliki lapisan tambahan yang memetakan byte ke karakter string, dan pemetaan ini didefinisikan dalam encoder.py milik OpenAI GPT-2
  • Dalam implementasi SQL, kamus token yang diunduh dari OpenAI dimasukkan ke tabel tokenizer, dan pemetaan byte-ke-karakter disimpan di tabel encoder
  • Contoh "Mississippilessly" menggunakan recursive CTE untuk memulai dari byte tunggal dan berulang kali menggabungkan pasangan berdekatan terbaik yang dapat digabungkan
    • Dalam contoh tersebut, jumlah token berkurang dari 17 menjadi 5
    • Menggunakan ruang sekitar 50k token GPT-2, bukan sekitar 150k ruang code point Unicode
  • Saat memproses beberapa kata, GPT-2 membagi teks dengan regex dan melakukan penggabungan di dalam tiap kata
    • PostgreSQL tidak mendukung properti karakter Unicode dalam regex, sehingga regex asli GPT-2 sebagian dimodifikasi
    • Modifikasi ini kemungkinan merusak dukungan Unicode yang semestinya
  • "PostgreSQL is great" diubah oleh tokenizer SQL menjadi [6307, 47701, 318, 1049]
    • Klaster tokennya adalah Post, greSQL, Ġis, Ġgreat
    • Ġ menunjukkan spasi

Embedding dan Context Window

  • ID token tidak langsung dipakai dalam perhitungan model, melainkan diubah menjadi vektor embedding
  • GPT-2 membuat embedding untuk token dan posisi secara terpisah
    • WTE adalah word token embedding, berupa matriks 50257×768
    • WPE adalah word position embedding, berupa matriks 1024×768
  • Untuk setiap posisi token, vektor WTE dan vektor WPE dijumlahkan untuk membuat vektor input bagi tahap berikutnya
  • Karena WPE hanya memiliki 1.024 posisi, jumlah token maksimum yang dapat digunakan dalam prompt GPT-2 adalah 1.024
    • Angka ini sesuai dengan context window LLM
    • Ini adalah hyperparameter yang ditentukan saat desain model dan tidak berubah melalui pelatihan
  • Implementasi SQL menggunakan pgvector
    • Operasi vektor dapat didefinisikan langsung pada array sehingga memungkinkan SQL murni, tetapi performanya menurun
    • Versi awal berjalan dengan fungsi SQL murni, tetapi lambat

Menguraikan Self-Attention sebagai Query SQL

  • Inti Transformer adalah mekanisme self-attention, yang didasarkan pada makalah 2017 Attention is all you need
  • Attention membuat vektor token saling memengaruhi, sehingga informasi dari bagian awal prompt dapat diteruskan ke vektor terakhir
  • Implementasi GPT-2 menggunakan 12 set matriks Q, K, V
    • Setiap set adalah satu attention head
    • Setiap head berdimensi 64
    • c_attn adalah transformasi linear 768×2304, dan hasilnya adalah vektor 2304 dimensi yang berisi Q, K, V yang ditumpuk secara horizontal
    • Bobot dan bias disimpan di tabel c_attn_w, c_attn_b
  • Sebelum perhitungan attention, layer normalization diterapkan
    • Parameter scale dan shift disimpan di tabel ln_1_g, ln_1_b
  • Dalam causal self-attention, causal mask diterapkan agar token di belakang tidak dapat memengaruhi token di depan
    • Kandidat token berikutnya dari model pada akhirnya ditentukan dari embedding terakhir
    • Aliran informasi harus mengarah ke vektor terakhir, dan nilai antara pada vektor terakhir tidak boleh memengaruhi vektor sebelumnya
  • Implementasi SQL menangani input yang lebih kecil dari -745.13 sebagai 0 untuk menghindari masalah PostgreSQL EXP yang gagal pada angka sangat kecil dalam perhitungan softmax
  • Berkat causal mask, meskipun token baru ditambahkan ke prompt, hasil perhitungan untuk token sebelumnya tidak berubah
    • Implementasi GPT-2 asli memanfaatkan sifat ini
    • Implementasi SQL tidak memakai reuse ini demi kesederhanaan

Multi-Head Attention dan Residual Connection

  • Hasil attention dari 12 head masing-masing berdimensi 64, lalu ditumpuk secara horizontal untuk kembali menjadi 768 dimensi
  • Selanjutnya, output attention diproyeksikan dengan transformasi linear terlatih yang disimpan di c_proj_w, c_proj_b
  • Input asli ditambahkan kembali ke hasil multi-headed attention
    • Residual connection ini adalah teknik yang disertakan dalam makalah Transformer asli
    • Teknik ini diperkenalkan sebagai desain untuk mengurangi masalah vanishing gradient dan exploding gradient selama pelatihan

Tahap Feedforward dan Blok Transformer

  • Setelah attention, jaringan saraf feedforward menyusul
  • Tahap feedforward GPT-2 terdiri dari multi-layer perceptron 3 lapis
    • Dimensinya 768 → 3072 → 768
    • Fungsi aktivasinya menggunakan GELU
  • Parameter transformasi linear disimpan di tabel berikut
    • mlp_c_fc_w, mlp_c_fc_b
    • mlp_c_proj_w, mlp_c_proj_b
  • Input feedforward juga lebih dulu dinormalisasi dengan parameter ln_2
    • ln_2_g, ln_2_b menyimpan scale dan shift
  • Residual connection yang menambahkan kembali input juga diterapkan pada output feedforward
  • Kombinasi attention + feedforward ini adalah satu blok, dan GPT-2 menghubungkan 12 blok seperti pipeline
    • Setiap blok memiliki set parameter terlatihnya sendiri
    • Dalam SQL, blok-blok tersebut dihubungkan dengan recursive CTE
  • Output blok terakhir dinormalisasi lagi dengan parameter ln_f

Mengubah Kembali Menjadi Token Berikutnya

  • Dari output akhir, vektor 768 dimensi pada posisi terakhir adalah embedding token berikutnya
  • Untuk mengubah vektor ini kembali menjadi token, matriks WTE yang digunakan pada embedding token awal digunakan kembali
  • Inversi yang tepat biasanya tidak mungkin
    • Embedding prediksi mungkin tidak persis sama dengan baris tertentu pada WTE
    • Karena itu, dot product dengan setiap embedding token dihitung untuk mencari token yang dekat
  • Hasil dot product antara WTE dan embedding prediksi menjadi 50.257 skor, yaitu logit
  • Skor ini diubah menjadi probabilitas melalui softmax
    • Jumlah kandidat teratas adalah top_n
    • Nilai yang mengatur distribusi probabilitas adalah temperature
    • Semakin tinggi temperature, semakin besar kemungkinan token yang bukan peringkat pertama dipilih, sehingga inferensi menjadi kurang dapat diprediksi
  • Dalam contoh "PostgreSQL is great", 5 kandidat token berikutnya teratas adalah sebagai berikut
    • Ġfor
    • ,
    • .
    • Ġat
    • Ġto
  • Ketika temperature berubah menjadi 0.5, 1, dan 2, distribusi probabilitas softmax untuk kandidat yang sama ikut berubah

Hasil Inferensi Nyata dan Kode

  • SQL final mengulangi proses memilih token berdasarkan probabilitas dan menambahkannya ke prompt
  • Model itu sendiri deterministik, dan satu-satunya unsur nondeterministik adalah angka acak yang termasuk dalam pemilihan token
  • Pengaturan contohnya adalah sebagai berikut
    • Prompt: "Happy New Year! I wish you"
    • Jumlah token yang dibuat: 10
    • temperature: 2
    • top_n: 1
    • Menggunakan SETSEED(0.20231231)
  • Di lingkungan penulis, query berjalan selama 2 menit 44 detik
  • Hasil outputnya adalah "Happy New Year! I wish you all the best in your new year!"
  • Query dan kode instalasi tersedia di repositori GitHub quassnoi/explain-extended-2024

1 komentar

 
GN⁺ 2024-02-25
Opini Hacker News
  • Indah. Aku juga pernah masuk ke lubang kelinci serupa dengan SQLite, tapi belum sampai tahap membawa jaringan saraf ke dalamnya
    Terinspirasi dari seri kuliah makemore[0], dan setelah sekitar 1 jam materinya beralih dari pendekatan counting ke jaringan saraf; kira-kira sampai situ juga aku mencapainya
    Memecah ini ke dalam model relasional benar-benar latihan yang bagus
    [0] https://www.youtube.com/watch?v=PaCmpygFfXo

    • Kalau terus ditonton, jaringan saraf menghasilkan tabel yang persis sama dengan pendekatan counting, dan saat melakukan generasi juga memberikan hasil yang persis sama
  • Demo yang bagus, tapi penjelasan tentang causal masking di artikelnya tampaknya mencampuradukkan pelatihan dan inferensi
    Causal masking bertujuan agar selama pelatihan model tidak bisa “mengintip” token masa depan, dan pada arsitektur bergaya GPT juga bertujuan memaksakan sifat autoregresif saat inferensi
    Saat inferensi, bagaimanapun hanya token terakhir yang digunakan, jadi token itu memperhatikan seluruh sekuens input; karena itu token berikutnya tidak ditentukan hanya dari embedding token terakhir

  • Aku penasaran apakah ini benar-benar merepresentasikan driver loop GPT: tampaknya strukturnya seperti men-tokenize prompt, mendapatkan probabilitas 50.257 token dengan gpt2(tokens), memilih token berikutnya, menambahkannya ke daftar token, memeriksa kondisi berhenti, lalu melakukan detokenisasi di akhir
    Tapi ini terlihat seperti state machine yang mengimplementasikan algoritma Shlemiel the painter, sehingga membuatku mempertanyakan biaya komputasi inheren dari pekerjaan generasi

    • Sejauh yang kupahami, context window yang dibicarakan orang dalam model bahasa besar berarti ada batas maksimum jumlah token yang dipertahankan, dan token paling lama akan dibuang
      Window itu adalah sliding window
    • Benar, itulah loop-nya, dan semua keajaibannya ada di dalam fungsi gpt2
    • Ini hanya bagian yang sangat kecil dari algoritmanya
      Lebih mirip menunjukkan cara mengumpulkan token yang dihasilkan menjadi kalimat
  • Materi terkait: A GPT in 60 Lines of NumPy - https://news.ycombinator.com/item?id=34726115 - Februari 2023, 146 komentar

    • Materi ini sudah muncul di bagian awal artikel
  • Dalam konteks serupa, aku mengimplementasikan seluruh GPT dengan fungsi spreadsheet, dan juga membuat tutorial video yang bisa ditonton bersamanya
    https://spreadsheets-are-all-you-need.ai/

    • Video pertamanya luar biasa
      Dari sudut pandang seseorang yang menganggap LLM cukup keren tetapi tidak perlu mempelajari cara kerjanya secara profesional, video 10 menit itu mengajariku lebih banyak daripada bertahun-tahun membaca komentar HN yang sulit dipahami dan artikel media arus utama yang dangkal
      Melihat begitu banyak angka floating-point menumpuk menunggu dihitung juga membuat jauh lebih intuitif mengapa teknologi ini memakan GPU sebanyak itu
    • Spreadsheet adalah cara yang alami untuk menjelaskan LLM
      Kalau menghitung turunan tiap parameter pada setiap contoh pelatihan dan menunjukkan secara eksplisit bagaimana itu dipetakan ke parameter terkait, tampaknya proses pelatihannya juga bisa dijelaskan dengan baik
  • Bagus. Sesuatu yang bahkan setahun lalu terlihat seperti semacam sihir kini dijelaskan dengan begitu baik, hampir sampai anak kecil pun bisa mengikutinya

    • Sihir ini bukan dimulai setahun lalu
      Model yang dijelaskan di artikel adalah GPT-2 yang dirilis pada awal 2019
    • Bukan “sampai anak kecil pun bisa mengikutinya”
      Untuk benar-benar memahami artikel ini, perlu latar belakang ilmu komputer yang kuat, dan judulnya sendiri pun kurang mudah diakses bagi 99% umat manusia
  • Aku selama ini sepenuhnya menghindari GPT dan LLM, tetapi cara ini tampaknya bisa menghasilkan tingkat kefasihan tertentu pada keluaran teks, namun belum terlihat mampu menafsirkan pertanyaan dan menjawabnya
    Aku penasaran apakah ada posting blog sederhana atau kursus yang menjelaskan cara kerjanya secara nyata, atau menunjukkan engine mainan seperti Python
    Materi edukasi yang kulihat sejauh ini cenderung berfokus pada cara memakai platform, dan tidak banyak membahas cara kerja internalnya

  • Menariknya, machine learning modern tidak menuntut Turing-completeness
    Namun kita tetap mempertimbangkan kemungkinan AGI, jadi kalau kesimpulannya ternyata Turing-completeness tidak diperlukan, itu akan cukup menarik

    • Turing-completeness tampaknya diperlukan
      Alasannya sederhana: aku bisa mengikuti eksekusi kode yang Turing-complete di dalam kepalaku
    • Inferensi token itu sendiri tidak Turing-complete, tetapi jika keluarannya bisa menimbulkan efek samping, misalnya bisa mengubah prompt untuk iterasi berikutnya, ceritanya jadi sama sekali berbeda
  • Artikelnya luar biasa, dan penjelasan tiap komponennya jelas serta cukup menyeluruh sehingga enak dibaca
    Namun setelah tidak sengaja menekan “+ expand source” dan melihat monster menakjubkan itu, aku jadi setuju ketika ChatGPT berkata “SQL tidak cocok untuk implementasi model bahasa besar”

    • Aku juga menekannya dan tidak menemukan cara untuk melipatnya kembali
  • Pernyataan bahwa “Unicode biasa tidak cocok dengan jaringan saraf” tidak benar. Lihat saja ByT5, misalnya
    Yang disebut “alfabet” di artikel biasanya disebut vocabulary, dan jika memakai byte UTF-8 sebagai vocabulary, jumlah tokennya menjadi 256, bukan 149.186
    ByT5 melakukan persis itu

    • Intinya bukan sama sekali tidak bisa, melainkan tidak bekerja sebaik pendekatan lain yang kita punya
      Fakta bahwa semua model dengan performa terbaik di pasar memakai tokenisasi adalah buktinya
      Bukan rahasia bahwa tokenisasi pada dasarnya mirip hack, dan idealnya suatu hari nanti ingin dihilangkan dengan satu atau lain cara (https://twitter.com/karpathy/status/1657949234535211009)
      Secara prinsip, kekurangan tokenisasi tingkat byte bisa dikompensasi dengan model yang lebih besar dan konteks yang lebih besar, tetapi dalam praktiknya melatih model dengan tingkat kecerdasan yang sama membutuhkan sumber daya jauh lebih banyak
      Tentu saja ada tugas tertentu, seperti menghitung jumlah huruf dalam kata, di mana tokenisasi justru merugikan kecerdasan