2 poin oleh GN⁺ 2024-07-02 | 1 komentar | Bagikan ke WhatsApp
  • Program ekstraksi informasi yang ambigu mudah berubah menjadi spaghetti code ketika aturan pengecualian terus menumpuk, dan logika berbasis keadaan seperti ini bisa dipikirkan ulang sebagai recurrent neural network (RNN)
  • Contoh pencarian referensi kode C dalam pesan code review diimplementasikan sebagai pengklasifikasi buatan tangan yang melacak pola token seperti identifieropen_parenclose_paren sebagai keadaan
  • Aturan ini menunjukkan presisi 100% pada contoh, tetapi melewatkan kasus seperti if (err) goto cleanup; sehingga recall tetap di 50%, dan semakin banyak aturan ditambahkan, State serta percabangan menjadi makin rumit
  • Mesin keadaan yang sama dapat dienkodekan dengan hidden state dan perhitungan lapisan pada RNN, dan untuk membuatnya dapat dilatih diperlukan ReLU·sigmoid serta bobot·bias yang bisa dipelajari, alih-alih fungsi indikator biner
  • Implementasi seperti Elman RNN, GRU, dan LSTM di PyTorch, serta masalah vanishing gradient pada sekuens token yang panjang, menjadi batasan dalam pelatihan nyata, dan proses menentukan dataset, label, serta fungsi loss itu sendiri juga membantu dalam merancang aturan manual

Bagaimana ekstraksi data ambigu berubah menjadi spaghetti code

  • Program riset untuk mengekstrak informasi dari data mentah cepat menjadi rumit ketika data tidak mengikuti spesifikasi yang jelas atau memiliki bentuk yang tidak biasa
  • Contoh tugasnya meliputi mengidentifikasi perusahaan dan eksekutif dalam artikel berita, memberi label kontrak pengadaan publik berdasarkan jenis layanan, dan menentukan apakah pesan insinyur berisi kode program
  • Jika menginginkan keluaran yang sempurna, kita bisa memeriksa setiap observasi dengan teliti dan menulis unit test untuk contoh-contoh yang representatif
    • Baik R maupun Python menyediakan pustaka pengujian untuk ini
  • Dalam situasi yang memerlukan aturan penilaian yang kompleks, seperti nama panggilan, sinonim, atau batas antara bahasa Inggris dan kode, aturan manual mudah goyah
  • Algoritme pelatihan jaringan saraf mengubah masalah ini menjadi pencarian kombinasi aturan dari data, alih-alih manusia terus-menerus menyetelnya secara manual

Mencari referensi kode dalam pesan code review

  • Tujuannya adalah mendeteksi apakah pesan yang dikirim selama code review secara eksplisit merujuk ke kode program
  • Diasumsikan codebase yang diamati ditulis dalam C
  • Pesan representatif mencakup referensi kode seperti berikut
    • render_ipa_alloc()
    • FTPSACK
    • debug_error()
    • NULL
    • IS_ERROR()
    • aarch64, amd64
    • if (err) goto cleanup;
  • Kandidat aturan sederhana masing-masing gagal dengan cara yang berbeda
    • Aturan yang menganggap kata yang diikuti tanda kurung sebagai kode dapat menangkap kasus seperti render_ipa_alloc(), tetapi melewatkan if (err) goto cleanup;
    • Aturan yang menganggap semua kata huruf besar sebagai kode dapat menangkap FTPSACK dan IS_ERROR(), tetapi menghasilkan false positive untuk singkatan seperti AFAICT
    • Aturan yang menganggap kata non-Inggris sebagai kode dapat salah menandai istilah rekayasa atau nama arsitektur sebagai kode
  • Untuk memperbaiki aturan 2 dan aturan 3, dibutuhkan daftar singkatan dan istilah teknis seperti AFAICT, LGTM, USD, COVID, aarch64, amd64

Pengklasifikasi yang dibuat dengan mesin keadaan manual

  • Algoritme sederhananya menentukan apakah sebuah pesan berisi kode dalam dua tahap
    • Prapemrosesan: mengubah pesan menjadi sekuens token yang mencerminkan elemen sintaks kode C
    • Inferensi: memeriksa apakah sekuens token memenuhi aturan
  • Rule 1 menganggap pola underscore_identifieropen_parenclose_paren sebagai referensi kode
  • Implementasi Python menyimpan keadaan token sebelumnya dengan data class State
    • previous_was_identifier
    • previous_was_open_paren
    • previous_previous_was_identifier
    • seen_code
  • contains_code menelusuri token sambil memanggil process, lalu pada akhir mengembalikan state.seen_code
  • process mengatur seen_code menjadi True jika token saat ini adalah close_paren, token sebelumnya open_paren, dan token sebelum itu adalah identifier
  • Pengklasifikasi ini pada contoh tidak memiliki false positive dan menunjukkan presisi 100%, tetapi karena banyak kasus terlewat, recall-nya bertahan di 50%
  • Jika Rule 2 ditambahkan, field State dan percabangan if/elif/else bertambah, dan semakin aturan disempurnakan, semakin sulit pemeliharaannya

Memindahkan mesin keadaan ke RNN

  • contains_code dan process adalah mesin keadaan, dan mesin keadaan dapat dienkodekan sebagai recurrent neural network (RNN)
  • RNN memproses sekuens token satu per satu sambil mengaproksimasi probabilitas bersyarat bahwa sebuah pesan mengandung kode
  • Nilai yang bersesuaian dengan State di Python direpresentasikan sebagai hidden state pada RNN
    • State_0 adalah keadaan awal
    • Setiap State_t dihitung dengan memasukkan token saat ini dan keadaan sebelumnya ke fungsi f
    • Keadaan akhir diteruskan ke lapisan keluaran g untuk menghasilkan hasil klasifikasi
  • Contoh RNN menggunakan tiga lapisan tersembunyi
    • Lapisan pertama menyimpan atau menyalin token saat ini dan keadaan sebelumnya
    • Lapisan kedua memeriksa pola yang sesuai dengan Rule 1
    • Lapisan ketiga mengingat apakah pernah melihat pola kode
  • Token direpresentasikan sebagai vektor biner berbentuk one-hot
  • Untuk meniru algoritme buatan tangan secara langsung, kita dapat menggunakan fungsi indikator biner 1{x > 0}
    • Lapisan tersembunyi dapat dipertahankan sebagai nilai biner
    • Namun, turunannya bernilai 0 hampir di mana-mana sehingga tidak cocok untuk pelatihan
  • Pola juga dapat diperiksa dengan perkalian identifier, open_paren, dan close_paren, tetapi pada lapisan tersembunyi biner pemeriksaan yang sama dapat dinyatakan dengan penjumlahan
  • Giles et al. (1992) terhubung dengan contoh penggunaan second-order RNN untuk menemukan mesin keadaan

Mengubahnya menjadi jaringan yang dapat dilatih

  • Untuk pelatihan, fungsi indikator biner diganti dengan ReLU
  • Konstanta numerik diganti dengan bobot dan bias, dan gradient descent mengestimasi parameter-parameter ini
  • Lapisan keluaran menggunakan fungsi aktivasi sigmoid untuk menghitung nilai probabilitas akhir
  • Bentuk ini dapat dimasukkan ke PyTorch untuk dilatih, tetapi jika dilatih begitu saja performanya tidak terlalu baik
  • Salah satu alasan kurangnya performa adalah arsitekturnya tidak umum, sehingga lebih banyak bagian dari prosedur pelatihan dijalankan di kode penghubung Python dan lebih sedikit memanfaatkan implementasi pustaka C++ milik PyTorch

Implementasi PyTorch dan batasan pesan panjang

  • torch.nn.RNN di PyTorch menyediakan implementasi berbasis Elman RNN
  • Arsitektur contoh dan Elman RNN berbeda dalam cara menghubungkan lapisan tersembunyi
    • Pada arsitektur contoh, lapisan pertama untuk token t menerima lapisan ketiga token t-1 sebagai masukan, dan setiap lapisan hanya menerima masukan dari lapisan tepat sebelumnya
    • Pada Elman RNN, setiap lapisan tersembunyi juga menerima keadaan waktu sebelumnya dari lapisan yang sama
    • Lapisan tersembunyi pertama pada Elman RNN tidak menerima lapisan akhir dari waktu sebelumnya sebagai masukan
  • Pesan code review nyata bisa panjang, dan pesan yang panjang menghasilkan sekuens token yang panjang
  • Pada sekuens panjang, meskipun gradient descent secara teori bekerja, masalah stabilitas numerik dapat muncul karena vanishing gradient
  • Elman RNN juga bisa rentan terhadap masalah ini, dan GRU atau LSTM mungkin memberi performa lebih baik pada tugas deteksi kode

Disiplin berbasis data

  • RNN mengubah kombinasi aturan yang sulit ditangani secara manual menjadi target pembelajaran, sekaligus memaksa definisi masalah menjadi lebih jelas
  • Untuk melatih jaringan, diperlukan hal-hal berikut
    • Memilih dataset pelatihan dan dataset validasi
    • Pelabelan awal
    • Fungsi loss yang menjelaskan apa yang harus dicapai pengklasifikasi dan apa yang harus dihindari
  • Proses ini menyingkap area abu-abu yang sebelumnya tidak terduga dan membuat kriteria penilaian menjadi lebih jelas
  • Disiplin berbasis data seperti ini juga berguna untuk masalah yang diselesaikan bukan dengan jaringan saraf, melainkan dengan algoritme buatan tangan

1 komentar

 
GN⁺ 2024-07-02
Komentar Hacker News
  • Tulisan ini tidak banyak membahas pengujian atau cara memperoleh data latih, padahal bagian itu tampaknya inti persoalannya
    Kode yang terasa kita pahami adalah kode yang, setidaknya secara informal, telah kita buktikan sendiri sifatnya akan tergeneralisasi ke semua input. Misalnya, algoritma pengurutan tidak hanya mengurutkan daftar yang diuji, tetapi daftar apa pun
    Bagian yang tidak pasti pada jaringan neural adalah kita tidak tahu bagaimana ia akan melakukan generalisasi. Jika input yang belum pernah dilihat berbeda sedikit saja, tidak ada sifat yang terjamin, dan sejak awal masalahnya mungkin memang sulit dispesifikasikan secara matematis sesuai sifat yang diinginkan
    Jika suatu sifat bisa didefinisikan cukup jelas untuk dijadikan pengujian berbasis properti seperti QuickCheck, kita bisa membuat sejumlah besar data uji atau data latih melalui randomisasi. Cukup tulis pengujian yang dimulai dari satu contoh yang diinginkan lalu menghasilkan variasi yang mungkin dari contoh positif/negatif
    Itu bukan bukti, tetapi bisa menjadi titik awal. Setidaknya jika bisa membuktikannya, kita tahu apa yang perlu dibuktikan
    Jika hal semacam ini ada, bergantung pada kode spaghetti dan bergantung pada jaringan neural terlihat cukup mirip. Jika ingin memenuhi sifat lain juga, tinggal tambahkan satu pengujian berbasis properti lagi. Jaringan neural mungkin bisa dilatih alih-alih dimodifikasi langsung, tetapi modifikasi kode pun punya bantuan AI
    Meski begitu, saya rasa saya akan lebih memercayai kode. Setidaknya debugging bisa dilakukan

  • Jika dibaca sebagai cara membuat jaringan neural yang melakukan tugas praktis, ini tulisan yang menarik. Namun kalau lain kali harus mem-parsing input lalu ingin mengikuti cara ini apa adanya, jujur saya tidak tahu harus berkata apa
    Penulis mengambil masalah sulit berupa parsing input arbitrer dengan pola yang didefinisikan longgar, dan dengan tepat mengatakan bahwa ini besar kemungkinan menghasilkan kode spaghetti yang sulit dibaca
    Namun sebagai alternatifnya ia mengusulkan kode yang begitu sulit dibaca sampai cara kerjanya masih diteliti, yaitu jaringan neural
    Saya bisa memahaminya, tetapi kita tidak boleh melebih-lebihkan sesuatu yang sama sekali tidak dapat ditafsirkan dibanding sesuatu yang “jelek”. Untuk sebagian tugas, model machine learning mungkin cocok, tetapi dalam banyak kasus, meski butuh usaha, pendekatan yang bisa dibaca dan diperiksa alasan kerjanya lebih baik daripada yang mustahil dipahami

    • Menurut saya, penulis mengangkat kode spaghetti lebih sebagai pengalih isu. Jika output algoritma tidak didefinisikan secara tepat sebagai fungsi dari input, tetapi ada contoh yang bisa ditunjukkan, di situlah machine learning berguna
      Pada akhirnya machine learning hanya menyediakan satu opsi tambahan. Cocok atau tidak bergantung pada hasil evaluasi, serta tingkat determinisme dan kemampuan dijelaskan yang dibutuhkan oleh algoritma yang dipilih
      Bagian yang menonjol adalah apakah RNN memang pilihan yang tepat. Ia perlu pelatihan dan mungkin membutuhkan jauh lebih banyak contoh daripada yang tersedia. Meski begitu, tampaknya data sintetis untuk kasus positif/negatif bisa dibuat berdasarkan aturan yang diketahui
    • Pendekatan kode spaghetti pada dasarnya adalah sistem pakar. Bisa dianggap sebagai AI algoritmik gaya lama. Di luar ranah yang terbatas, sistem seperti ini jarang benar-benar bekerja dengan baik, dan dunia nyata terlalu berantakan
      Sistem yang memungkinkan kita melihat mengapa ia bekerja seperti itu memang bagus, tetapi tidak ada artinya jika terus memberi jawaban yang salah. Dalam penggunaan nyata, sering kali mendapatkan jawaban yang benar lebih penting daripada mengetahui bagaimana jawaban itu dicapai
    • Kedengarannya seperti menyembunyikan kode spaghetti yang buruk rupa di balik matriks floating-point 1000x1000 yang rapi
  • Jaringan neural memiliki teorema aproksimasi fungsi universal. Isinya adalah bahwa ia dapat merepresentasikan atau mengodekan fungsi arbitrer hingga tingkat akurasi yang diinginkan[0]
    Namun tidak ada teorema yang mengatakan bahwa aproksimasi seperti itu bisa dipelajari, atau bagaimana cara mempelajarinya
    [0] https://en.m.wikipedia.org/wiki/Universal_approximation_theo...

    • Bukti itu sering dikutip, tetapi yang sebenarnya ditunjukkannya kurang lebih hanya bahwa jaringan neural setara dengan tabel lookup. Tabel lookup dengan memori yang cukup dapat mengaproksimasi fungsi apa pun
      Ini jauh dari menjelaskan bagaimana jaringan neural yang realistis dan berguna seperti jaringan neural konvolusional, transformer, atau LSTM benar-benar bekerja
    • Sebagai catatan, jauh sebelum jaringan neural, sudah ada banyak algoritma yang terbukti sebagai aproksimator fungsi universal. Jaringan neural bukan satu-satunya dan bukan yang pertama. Dalam banyak kasus, ada cukup banyak metode yang jauh lebih sesuai daripada jaringan neural
    • Bukan sembarang fungsi. Ada batasan pada jenis fungsi yang dicakup oleh teorema aproksimasi universal
      Menariknya, teorema ini membahas jaringan satu lapis. Dalam praktiknya, jaringan dengan banyak lapis bekerja jauh lebih baik
    • Ia hanya bisa memodelkan fungsi kontinu; lebih tepatnya, fungsi kontinu arbitrer pada subset kompak dari ℝⁿ dapat diaproksimasi dengan akurasi arbitrer jika neuronnya cukup banyak
    • Kalau begitu, saya jadi penasaran apa arti belajar
  • Ini tulisan yang sangat bagus, dan meski saya belum sepenuhnya memahami konsep matematika yang lebih dalam di sekitar RNN, tulisan ini memicu banyak pemikiran
    Rasanya mirip dengan hal yang belakangan ini saya eksplorasi: membuat aplikasi dengan merangkainya bersama algoritma forward chaining. Penulis memakai RNN, sedangkan saya sedang memasukkannya ke algoritma Rete
    Gagasan mencerna string input karakter demi karakter juga terasa kuat. Dengan begitu, logika inferensi diserahkan ke algoritma, dan kita hanya menulis logika input-output yang sangat tipis; sisanya ditangani algoritma

  • Alasan tulisan ini bagus adalah karena ia menjelaskan dari pengalaman belajar apa arti sebenarnya mengubah suatu fungsi menjadi RNN, lalu membandingkannya dengan RNN “batteries included” yang ada di PyTorch
    Pertanyaannya: untuk memodelkan state, disebutkan perlu menambahkan tiga hidden layer ke jaringan; mengapa tiga? Saya penasaran apakah itu akibat dari aturan spesifik yang ingin diimplementasikan, atau jumlah layer yang umumnya dipakai saat mengimplementasikan aturan berbentuk seperti ini dengan arsitektur tersebut. Saya juga penasaran apakah struktur Elman mungkin bisa melakukannya dengan lebih sedikit layer

    • Untuk pertanyaan pertama, memakai tiga hidden layer membuat apa yang dilakukan jaringan sedikit lebih jelas. Tiap layer melakukan satu langkah komputasi
      Layer pertama mengumpulkan apa yang bisa diketahui dari token saat ini dan apa yang sudah diketahui setelah perhitungan token sebelumnya. Layer kedua memeriksa apakah aturan keputusan terpenuhi untuk menilai apakah token saat ini terlihat seperti kode program. Layer ketiga membandingkan keputusan itu dengan keputusan atas token-token sebelumnya
      Sepertinya ini juga bisa dipadatkan menjadi satu hidden layer. Karena ReLU cukup untuk menangkap non-linearitas, tampaknya mungkin. Saya belum cukup menelaah korespondensinya dengan struktur Elman, jadi saya tidak tahu jawabannya
  • Apakah RNN sudah sepenuhnya terserap oleh transformer? Saya penasaran apakah kita bisa melupakan cara menangani RNN dan hanya fokus pada transformer

    • Kalau ingin membuat pertanyaan ini lebih rumit, makalah “Transformers are RNNs: Fast Autoregressive Transformers with Linear Attention” layak dibaca - https://arxiv.org/pdf/2006.16236
      Di sini ditunjukkan bahwa transformer dalam definisi sempit tertentu, yaitu transformer dengan masking kausal, setara dengan RNN dan sebaliknya juga bisa
      Demikian pula Mamba(https://arxiv.org/abs/2312.00752), arsitektur yang sedang hangat belakangan ini, juga memiliki unit yang setara dengan RNN bergate. Setahu saya, karena alasan performa, saat pelatihan digunakan CNN yang setara, sementara saat inferensi digunakan RNN
    • Transformer memiliki konteks terbatas, sedangkan RNN tidak. Dalam praktiknya, sinyal gradien RNN memang terbatas dan melemah karena backpropagation through time
      Ini sebenarnya keunggulan inti transformer. Relasi jarak dekat dan jarak jauh tidak menjadi lebih sulit atau lebih mudah. Namun secara teoretis, RNN bisa mengingat masa lalu yang jauhnya tak terbatas
    • Kalau ingin menjadi doktor machine learning atau peneliti, jawabannya tidak; selain itu, ya
      Selama 7 tahun terakhir saya menangani machine learning/LLM sebagai research engineer dan juga pernah bekerja di lab riset FAANG, tetapi saya hanya selalu berpikir harus belajar RNN, tidak pernah benar-benar mempelajarinya dan tidak pernah membutuhkannya
  • Jika tertarik, genetic programming layak dilihat. Saya menganggapnya pendekatan yang lebih sederhana untuk masalah yang sama, dan tidak membutuhkan matematika
    Program direkombinasi berdasarkan abstract syntax tree, lalu jika diberi heuristik tertentu, program dioptimalkan mengikuti kriteria itu. Keajaibannya ada pada fungsi heuristiknya; Anda bisa memilih apa yang ingin dioptimalkan, seperti kecepatan, panjang program, minimisasi struktur kompleks atau pemanggilan fungsi, efisiensi jaringan, atau kombinasi di antaranya
    https://youtu.be/tTMpKrKkYXo

    • Saya juga ingin menambahkan Humies Awards, yang menunjukkan hasil yang kompetitif pada tingkat manusia. Dengan sekadar menelusuri makalah-makalah yang diajukan, kita bisa banyak belajar tentang apa yang mungkin dan tidak mungkin di bidang ini
      https://www.human-competitive.org/
  • Baru-baru ini saya menulis posting blog yang mengeksplorasi ide berinteraksi dengan LLM lokal untuk tugas-tugas ambigu seperti ini
    Rasanya itu lebih masuk akal daripada mengodekan jaringan saraf secara langsung. Menggunakan sesuatu seperti llama.cpp untuk mengevaluasi apakah model kecil bisa langsung menyelesaikan masalahnya, lalu jika tidak bisa, melakukan fine-tuning dan kemudian menghubungkan llama.cpp secara programatik dengan wrapper yang diinginkan tampaknya lebih praktis

  • Recurrent neural network bisa digunakan untuk komputasi arbitrer, dan kesetaraannya dengan mesin Turing juga sudah dibuktikan. Namun untuk tugas itu, ini sama sekali tidak realistis
    Pendekatan dalam tulisan ini entah bagaimana terlihat seperti state machine yang telah dilatih. Akan lebih baik jika tulisannya memiliki ringkasan yang lebih panjang, dan “Python” sama sekali tidak tampak relevan. Mempelajari semantik Python yang sebenarnya kemungkinan cukup sulit karena sifat bahasanya. Ini bukan bahasa yang memiliki standar, melainkan bahasa yang mengikuti apa yang dilakukan CPython

    • Tulisan RNN Karpathy tahun 2015[1] menunjukkan bahwa RNN yang dilatih pada karya Shakespeare per karakter dapat menghasilkan teks bergaya Shakespeare, meskipun tidak memiliki koherensi naratif seperti LLM
      Kalau begitu, adakah alasan ia tidak bisa menangani bahasa alami yang formal seperti komentar code review?
      Dalam kasus itu, inferensi dijalankan dengan input acak untuk membuat “Shakespeare” acak, tetapi struktur dan gaya bahasanya tetap dipelajari oleh RNN. Mungkin juga bisa dipakai untuk klasifikasi
      1. https://karpathy.github.io/2015/05/21/rnn-effectiveness/
  • Pertama, kompilasikan Python menjadi jaringan saraf, lalu tumpangkan itu secara paksa ke jaringan saraf berbasis transformer
    Dengan begitu, Transformer Virtual Machine(TVM) bisa menjalankan program arbitrer
    Dengan transfer learning, yaitu cara menumpangkan bobot satu sama lain, LLM bisa “lahir” dengan algoritma yang terenkode secara mendalam