Lewati ke konten
6/30Bab 6 dari 30

Membuatnya Belajar, Lalu Membuatnya Menggeneralisasi

Jaringan enam lapis yang loss-nya macet di ln 2, diperbaiki satu pengukuran demi satu. Lalu double descent: 5.000 parameter pada 40 titik.

Di halaman ini

Jaringan dari Bab 5 berfungsi. Ia punya sembilan parameter, belajar XOR, dan gradiennya cocok dengan PyTorch hingga enam belas angka desimal.

Buat ia sedalam enam lapis dan ia berhenti belajar sama sekali. Bukan perlahan — sama sekali. Ini jaringan enam lapis pada masalah klasifikasi dua spiral, dilatih selama 5000 langkah:

TEXT
step    1: loss 0.693147
step 5000: loss 0.693147
accuracy: 50.0 %

Angka itu tidak sembarang. ln2=0.693147\ln 2 = 0.693147 adalah binary cross-entropy dari model yang mengeluarkan probabilitas 0.50.5 untuk semuanya, dan 50 % adalah lemparan koin pada dataset seimbang. Setelah lima ribu langkah, jaringan belum bergerak satu digit pun. Tidak ada yang crash, tidak ada peringatan, dan gradiennya masih benar persis.

Bab ini membahas jarak antara jaringan yang berjalan dan jaringan yang bekerja. Ada dua bagian yang tampak seperti topik berbeda, padahal pekerjaannya sama: membuat loss bergerak turun, dan membuatnya turun pada data yang belum pernah dilihat model.

Mulailah dengan melihat, bukan menebak. Dorong satu batch input melewati jaringan dan cetak deviasi standar aktivasi di tiap layer, lalu deviasi standar gradien bobot:

profile.pyPYTHON
def profile(model, x):
    h = x
    for layer in model:
        h = layer(h)
        if isinstance(layer, (nn.Tanh, nn.ReLU)):
            print(f"activation std: {h.std().item():.4f}")
    model(x).sum().backward()
    for p in model.parameters():
        if p.dim() == 2:
            print(f"gradient std: {p.grad.std().item():.2e}")

Tiga inisialisasi, arsitektur yang sama, enam lapis tanh\tanh:

inisialisasistd aktivasi, lapis 1→6
normal, std 0.010.010.0145 · 0.0016 · 0.0002 · 0.0000 · 0.0000 · 0.0000
normal, std 110.6573 · 0.9296 · 0.9585 · 0.9634 · 0.9637 · 0.9625
Xavier0.1579 · 0.1493 · 0.1353 · 0.1333 · 0.1325 · 0.1403
inisialisasistd gradien, lapis pertama → terakhir
normal, std 0.010.013.20e-06 · 4.97e-07 · … · 6.40e-06
normal, std 111.94e+03 · 2.28e+02 · 1.22e+02 · 4.43e+01 · 1.85e+01 · 7.30e+00
Xavier2.31e+00 · 4.50e-01 · 4.26e-01 · 3.89e-01 · 4.39e-01 · 4.73e-01

Baris pertama adalah jaringan di atas, dan ia bukan belajar lambat — ia sudah tidak punya sinyal tersisa. Pada lapis keempat, deviasi standar aktivasi sudah underflow menjadi nol hingga empat angka desimal. Setiap input menghasilkan output yang sama, outputnya konstan, dan gradien dari konstanta adalah kosong. Bobot diinisialisasi kecil "agar aman", dan kecil ternyata fatal.

Baris kedua adalah kegagalan yang berlawanan, dan layak dipahami karena terasa kontraintuitif. Aktivasinya tampak sehat — sekitar 0.96 — tetapi itu adalah tanh\tanh yang saturasi, tertahan dekat batasnya, persis rezim yang diukur Bab 5 sebagai kehilangan faktor hampir sepuluh ribu pada gradien. Namun gradiennya sangat besar: 1940 di lapis pertama. Keduanya benar sekaligus. Setiap langkah backward mengalikan dengan WW^\top, dan dengan 128 input pada varians satuan, faktor itu punya gain sekitar 12811\sqrt{128} \approx 11, yang mengalahkan penyusutan dari tanh\tanh yang tersaturasi. Gradien tumbuh secara geometris saat bergerak mundur. Ini adalah exploding gradient, dan menghasilkan nilai loss nan dalam beberapa langkah pada training run sungguhan apa pun.

Baris ketiga adalah yang kamu inginkan: aktivasi kira-kira konstan skalanya sepanjang kedalaman, gradien kira-kira konstan skalanya sepanjang kedalaman. Tidak ada yang mati, tidak ada yang meledak.

Inisialisasi yang baik memperbaiki skala pada langkah nol. Ia tidak menjaganya tetap tetap: bobot bergerak, dan pada langkah lima ribu argumen varians yang rapi tadi tidak lagi berlaku.

Layer normalisasi menegakkan skala secara terus-menerus. Diberi sebuah vektor aktivasi, kurangi dengan mean, bagi dengan deviasi standar, lalu terapkan skala yang dipelajari γ\gamma dan shift β\beta agar layer bisa membatalkan normalisasi jika ternyata itu yang diinginkannya:

h^=hμσ2+ϵ,y=γh^+β\hat{h} = \frac{h - \mu}{\sqrt{\sigma^2 + \epsilon}}, \qquad y = \gamma\hat{h} + \beta

Satu-satunya pertanyaan nyata adalah apa yang kamu rata-ratakan. Batch normalisation3 mengambil μ\mu dan σ\sigma melintasi dimensi batch, satu statistik per fitur. Layer normalisation4 mengambilnya melintasi fitur, satu statistik per contoh.

Pilihan itu terlihat kecil dan menentukan hampir semua hal setelahnya:

BatchNorm membuat output setiap contoh bergantung pada contoh lain yang kebetulan ada di batch-nya. Saat training, ini adalah regularizer ringan. Saat inference, tidak ada batch, sehingga ia harus menyimpan running average dari statistik yang dikumpulkan selama training — yang berarti layer berperilaku berbeda dalam mode training dan evaluasi, dan lupa mengganti mode adalah salah satu bug paling umum di lapangan. Ia juga memburuk dengan batch kecil, dan canggung untuk sequence dengan panjang variabel, karena "mean atas batch pada posisi 40" dihitung dari berapa pun sequence yang kebetulan sepanjang itu.

LayerNorm menormalisasi setiap contoh sendiri-sendiri. Tidak ada ketergantungan batch, tidak ada running statistics, perilaku identik saat training dan inference, tidak peduli ukuran batch, tidak peduli panjang sequence. Setiap properti itu menjadi kebutuhan, bukan sekadar kenyamanan, begitu kamu menghasilkan satu token pada satu waktu untuk satu pengguna, yaitu tempat Bab 13 berakhir.

Inilah mengapa LayerNorm adalah yang akan kamu temui lagi di Bab 9 tanpa berubah: blok transformer menggunakannya, dan menggunakannya karena alasan di kolom kanan, bukan karena ia lebih baik secara abstrak.

Memperbaiki satu hal pada satu waktu, yang sebenarnya adalah skill

Tautan ke bagian: Memperbaiki satu hal pada satu waktu, yang sebenarnya adalah skill

Empat kandidat perbaikan untuk jaringan mati: inisialisasi Xavier, LayerNorm, residual connections, dan Adam alih-alih SGD. Godaannya adalah menerapkan keempatnya lalu lanjut. Lakukan itu dan kamu tidak akan pernah tahu mana yang penting, dan saat ini terjadi lagi kamu tidak punya metode — hanya ritual.

Jadi terapkan satu per satu. Seed sama, data sama, arsitektur sama, 800 langkah:

yang ditambahkanloss akhirakurasi
tidak ada0.693150.0 %
inisialisasi Xavier0.569260.4 %
LayerNorm0.623061.5 %
residual connections0.665156.6 %
Adam0.678758.7 %
keempatnya0.0000100.0 %

Baca tabel itu seperti kamu membacanya pukul 2 pagi dan kesimpulannya adalah: tidak ada yang bekerja sendiri, semuanya bekerja bersama, jadi deep learning adalah alkimia. Kesimpulan itu salah, dan mencari tahu alasannya adalah hal paling berguna dalam bab ini.

Beri setiap run anggaran enam kali lipat — 5000 langkah, bukan 800 — dan gambarnya berubah total:

yang ditambahkanloss akhir @ 5000akurasi
tidak ada0.693150.0 %
inisialisasi Xavier0.0007100.0 %
LayerNorm0.0002100.0 %
residual connections0.665356.7 %
Adam0.690853.4 %
Xavier + Adam0.0000100.0 %
Xavier + LayerNorm0.0001100.0 %

Sekarang gambarnya tajam, dan ini diagnosis, bukan ritual.

Inisialisasi saja memperbaikinya. Normalisasi saja memperbaikinya. Masing-masing menangani penyakit sebenarnya — sinyal forward yang runtuh ke nol — dan salah satunya sudah cukup. Pada 800 langkah, keduanya hanya tampak seperti nilai parsial, karena keduanya sudah memecahkan masalah dan masih sedang merangkak naik keluar.

Residual connections dan Adam tidak memperbaikinya, pada anggaran berapa pun. Bukan karena keduanya buruk, tetapi karena keduanya mengobati penyakit yang berbeda. Residual connection memberi gradien jalur di sekitar layer yang memblokir; itu sangat berharga saat gradien adalah masalahnya, dan tidak bernilai saat sinyal forward sudah nol, karena shortcut di sekitar layer mati tetap membawa nilai mati. Adam menskalakan ulang langkah tiap parameter dengan riwayat gradiennya sendiri; itu membantu saat gradien punya magnitudo yang sangat berbeda-beda, dan tidak bisa membangkitkan jaringan yang outputnya tidak bergantung pada inputnya.

Dan "tidak ada" masih persis 0.6931 setelah lima ribu langkah. Bukan 0.6929. Ia tidak lambat; ia mati, dan perbedaan itu terlihat dengan cara yang sebelumnya tidak terlihat, karena kamu punya baris pembanding yang menunjukkan perbaikan bekerja.

Mulai dari sini kursus ini memakai PyTorch. Itu seharusnya diperoleh, bukan sekadar diumumkan, jadi inilah persisnya apa yang ia lakukan yang kamu sudah tahu cara melakukannya.

Optimiser adalah aturan untuk mengubah gradien menjadi update parameter. gradient descent polos menggunakan gradien. Momentum menggunakan running average dari gradien, yang menghaluskan noise dan membangun kecepatan di sepanjang arah yang tetap konsisten:

optim_by_hand.pyPYTHON
v = beta * v + p.grad          
p -= lr * v                    

Adam5 menyimpan dua running average — dari gradien dan dari gradien kuadrat — lalu membagi yang satu dengan akar kuadrat yang lain, sehingga setiap parameter mendapat langkah yang diskalakan menurut magnitudo gradien terbarunya sendiri:

optim_by_hand.pyPYTHON
m = b1 * m + (1 - b1) * g          # mean of the gradient          
v = b2 * v + (1 - b2) * g * g      # mean of the squared gradient  
m_hat = m / (1 - b1 ** t)          # bias correction: both averages start at zero
v_hat = v / (1 - b2 ** t)
p -= lr * m_hat / (v_hat.sqrt() + eps)   

Sepuluh baris. Jalankan keduanya terhadap torch.optim pada masalah yang sama selama 50 langkah:

TEXT
SGD+momentum   by hand [2.7781870365142822, -1.0304985046386719]
               torch   [2.7781870365142822, -1.0304983854293823]   max |diff| = 1.19e-07
Adam           by hand [0.4893140196800232, -0.46317872405052185]
               torch   [0.48931416869163513, -0.46317875385284424]   max |diff| = 1.49e-07

Identik hingga presisi float32. torch.optim.Adam adalah lima baris itu, ditambah puluhan tahun perhatian pada edge case dan kernel C++. Itulah pertukaran yang kamu lakukan mulai sekarang: bukan sihir sebagai ganti pemahaman, tetapi kecepatan sebagai ganti baris yang sudah kamu tulis.

Penjelasan Adam yang biasa adalah "learning rate adaptif per parameter", yang merupakan deskripsi, bukan alasan. Alasannya adalah geometri, dan itu bisa diukur.

Ambil sebuah loss yang kelengkungannya berbeda antar arah: curam di satu arah, landai di arah lain. SGD punya satu learning rate global, sehingga harus memilih nilai yang cukup kecil agar stabil di arah paling curam — dan nilai itu kemudian terlalu kecil untuk arah yang landai, tempat progres merayap. Inilah yang menyebabkan gambar klasik gradient descent zig-zag menuruni lembah sempit.

Dua rasio kelengkungan, tiga optimiser, 300 langkah, dan setiap optimiser diberi learning rate terbaik dari sweep agar tidak ada yang dirugikan:

rasio kelengkunganSGDSGD + momentumAdam
10 : 1error 0.000002error 0.000000error 0.000000
1000 : 1error 1.925485error 0.001432error 0.000000
divergen pada (1000:1)4 dari 8 rate4 dari 8 rate0 dari 6 rate

Pada rasio sepuluh, semuanya bekerja dan tidak ada yang perlu dibahas. Pada seribu, SGD polos tidak bisa mencapai jawaban pada learning rate mana pun yang dicoba — hasil terbaiknya masih error 1.93 — dan benar-benar divergen pada setengah rate. Adam mendarat tepat di target dan tidak divergen pada satu pun.

Kolom terakhir itulah alasan praktis Adam menjadi default. Bukan karena Adam menemukan solusi yang lebih baik; pada masalah yang well-conditioned, SGD yang dituning sering menyamai atau mengalahkannya. Alasannya Adam jauh kurang sensitif terhadap learning rate yang kamu pilih, dan jaringan nyata punya rasio kelengkungan yang jauh lebih buruk daripada seribu di antara jutaan parameternya.

Dua bagian lagi perlu ada di sini dan keduanya satu baris. Gradient clipping menskalakan ulang vektor gradien setiap kali norm-nya melewati ambang, yang mengubah baris "loss tiba-tiba meloncat ke nilai sangat besar" pada tabel diagnostik menjadi bukan peristiwa. Dan learning rate schedules: warmup singkat dari hampir nol selama beberapa ratus langkah pertama, karena estimasi varians Adam buruk sampai ia melihat beberapa gradien dan langkah ukuran penuh yang diambil berdasarkan sampah bisa merusak inisialisasi; lalu cosine decay menuju nol, karena mengakhiri run dengan ukuran langkah yang sama seperti saat memulai berarti bergetar di sekitar minimum alih-alih menetap di sana.

Paruh kedua: model yang fit sempurna dan tidak memprediksi apa pun

Tautan ke bagian: Paruh kedua: model yang fit sempurna dan tidak memprediksi apa pun

Semua sejauh ini tentang membuat loss turun. Sekarang paruh yang lebih sulit, karena loss turun bukan tujuan — itu proxy untuk tujuan, dan proxy itu gagal dengan cara yang spesifik dan terkenal.

Dua belas titik dari fungsi mulus dengan sedikit noise. Fit polinomial dengan derajat meningkat:

derajattrain RMSEtest RMSE
10.7644990.6985
30.2526050.3031
50.1644370.1568
90.0889600.2347
110.0000001.2094

Derajat 11 melalui 12 titik melewati setiap titik persis — train error nol hingga enam angka desimal — dan delapan kali lebih buruk daripada derajat 5 pada data yang belum dilihatnya. Minta derajat 3 dan derajat 11 memprediksi pada x=3.25x = 3.25, tepat di luar rentang training:

TEXT
degree  3: predicts   -1.053   (truth -0.012)
degree 11: predicts  +61.224   (truth -0.012)

Enam puluh satu, padahal jawabannya kira-kira nol. Model tidak mempelajari fungsinya; ia mempelajari dua belas titik, dan di antara titik-titik itu ia melakukan apa pun yang diminta aritmetika.

Ini adalah overfitting, dan kebalikannya — derajat 1, yang sama sekali tidak bisa merepresentasikan kurva dan buruk di mana-mana — adalah underfitting. Penjelasan klasik membagi error harapan model menjadi tiga bagian: bias, error karena model terlalu kaku untuk merepresentasikan kebenaran; variance, error karena model begitu fleksibel sampai mengejar noise dalam sampel khusus ini; dan noise tak-tereduksi, yang tidak bisa diperbaiki apa pun. Model sederhana bias, model fleksibel high-variance, dan resep klasiknya adalah menemukan titik manis di tengah — derajat 5 pada tabel di atas.

Alat standar semuanya menyerang komponen variance:

  • Regularisasi L2 (weight decay) menambahkan λw2\lambda \lVert w \rVert^2 ke loss, menarik bobot menuju nol dan membuat fungsi lebih mulus. Pada tabel di atas, koefisien terbesar derajat 11 yang menyebabkan kerusakan; menghukum ukuran menjinakkannya.
  • L1 menambahkan λwi\lambda \sum |w_i| sebagai gantinya. Perbedaannya bukan kosmetik: gradien L2 sebanding dengan bobot sehingga menyusut saat bobot menyusut, mendekati nol tanpa pernah tiba, sementara gradien L1 adalah konstanta ±λ\pm\lambda yang terus mendorong sampai akhir. Karena itu L1 menghasilkan bobot yang persis nol — ia memilih fitur. L2 menghasilkan bobot kecil. Gunakan L2 saat kamu menginginkan kemulusan, L1 saat kamu menginginkan sparsity.
  • Dropout7 menolkan subset acak aktivasi pada setiap langkah training, sehingga tidak ada unit yang bisa mengandalkan unit tertentu lain selalu hadir.
  • Early stopping memantau validation loss dan berhenti saat loss itu berbalik naik.
  • Data augmentation membuat lebih banyak contoh training dari yang kamu punya, menyerang masalah pada sumbernya: overfitting adalah kekurangan data sama besarnya dengan kelebihan parameter.
  • Cross-validation membagi data menjadi kk bagian dan melatih kk kali, yang membeli estimasi test error yang andal saat datamu terlalu sedikit untuk menyisihkan held-out set.

Double descent, atau mengapa bagian sebelumnya bukan keseluruhan cerita

Tautan ke bagian: Double descent, atau mengapa bagian sebelumnya bukan keseluruhan cerita

Sekarang fakta yang mematahkan gambarnya.

Kisah bias-variance mengatakan bahwa setelah titik manis, lebih banyak parameter berarti generalisasi lebih buruk. Model bahasa modern punya jauh lebih banyak parameter daripada yang diizinkan aturan klasik untuk data yang mereka lihat, dan menggeneralisasi dengan sangat baik. Keduanya benar, dan mendamaikannya adalah hal paling berguna dalam bab ini.

Empat puluh titik training, input dua puluh dimensi, fitur ReLU acak, dan jumlah fitur PP disapu dari 2 hingga 5000 — dengan solusi minimum-norm dipilih setiap kali ada banyak solusi yang fit:

PPP/nP/ntrain RMSEtest RMSEw\lVert w \rVert
100.250.88221.25201.89
200.500.59621.16342.59
300.750.38961.53234.15
380.950.17693.716310.25
401.000.00005.814014.83
421.050.00003.16239.35
601.500.00001.10582.78
2005.000.00000.66380.98
150037.500.00000.58590.33
5000125.000.00000.56640.18

Baca dalam tiga bagian. Hingga P/n=0.5P/n = 0.5, cerita klasik berlaku persis: error turun, lalu mulai naik. Pada P=n=40P = n = 40interpolation threshold, saat model punya parameter persis cukup untuk melewati setiap titik training — test error memuncak, di 5.81, lima kali lebih buruk daripada model kecil. Puncak itu adalah peringatan klasik, dan itu nyata.

Lalu ia turun lagi. Dan terus turun, melewati P=5nP = 5n, melewati P=37nP = 37n, sampai ke P=125nP = 125n, tempat test error 0.5664 lebih baik daripada model under-parameterised terbaik yang pernah dicapai. Model dengan 5000 parameter yang di-fit pada 40 titik adalah model terbaik di tabel.

Ini adalah double descent,89 dan mekanismenya terlihat di kolom terakhir. Begitu P>nP > n, ada tak hingga banyaknya pengaturan parameter yang fit data training secara persis, dan mana yang kamu dapat bergantung pada cara memilih. Solusi minimum-norm memilih yang terkecil, dan w\lVert w \rVert menunjukkan artinya: ia memuncak di 14.83 tepat pada threshold — ketika hanya ada satu solusi interpolasi dan kamu terjebak dengannya, seberapa ekstrem pun — lalu turun monoton saat PP tumbuh, karena lebih banyak parameter berarti lebih banyak solusi interpolasi untuk dipilih, yang berarti solusi terkecil yang tersedia makin kecil. Pada P=5000P = 5000 norm-nya 0.18, delapan puluh kali lebih kecil daripada di threshold.

Jadi parameter tambahan tidak menambah kompleksitas. Mereka menambah pilihan, dan aturan seleksi membelanjakan pilihan itu untuk kesederhanaan. Regularisasi tidak berada di fungsi loss; ia berada di algoritme. gradient descent dari inisialisasi kecil punya bias terdokumentasi menuju solusi norm kecil, itulah sebabnya perilaku ini muncul di jaringan nyata yang dilatih dengan cara biasa, bukan hanya pada aljabar linear di atas.

Konsekuensi praktisnya, yang menjadi sandaran Bab 10: "model punya lebih banyak parameter daripada data, jadi ia akan overfit" bukan argumen yang valid. Itu aturan yang baik saat model hidup di kiri threshold. Semua yang menarik sekarang hidup jauh di kanannya, tempat aturan itu berbalik.

Alat dalam bab ini cukup untuk melatih jaringan yang bekerja pada data yang bisa kamu masukkan ke tabel: baris angka, satu kolom label.

Bahasa bukan itu. Sebelum model bisa memprediksi kata berikutnya, sesuatu harus memutuskan apa sebenarnya "kata" itu — dan jawabannya bukan huruf ataupun kata, melainkan vocabulary yang dipelajari model dari byte mentah data training. Keputusan itu, yang dibuat sekali sebelum training dimulai, menentukan berapa banyak hal yang bisa dikatakan model, berapa biaya sebuah request, dan mengapa model yang bisa lulus ujian hukum tidak bisa menghitung huruf dalam strawberry dengan andal.

Bab 7 membangun tokenizer.


Untuk residual connections yang digunakan di atas, He et al., Deep Residual Learning for Image Recognition (arXiv:1512.03385). Building makemore Part 3: Activations & Gradients, BatchNorm dari Andrej Karpathy menjelaskan diagnostik histogram aktivasi pada model nyata dan merupakan pembahasan praktik terbaik untuk paruh pertama bab ini. Kuliah 8 dan 11–13 dari Learning From Data oleh Yaser Abu-Mostafa memberikan teori generalisasi klasik dengan benar, termasuk bagian-bagian yang bab ini padatkan menjadi satu paragraf.

  1. Glorot, X. dan Bengio, Y. Understanding the difficulty of training deep feedforward neural networks. AISTATS (2010). Argumen pelestarian varians direproduksi dalam kotak di atas.

  2. He, K., Zhang, X., Ren, S. dan Sun, J. Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification. arXiv:1502.01852 (2015).

  3. Ioffe, S. dan Szegedy, C. Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. arXiv:1502.03167 (2015). Perhatikan bahwa penjelasan "internal covariate shift" pada judul sejak itu sudah banyak diperdebatkan; layer-nya bekerja, tetapi penjelasan awal tentang mengapa ia bekerja masih dipersoalkan.

  4. Ba, J. L., Kiros, J. R. dan Hinton, G. E. Layer Normalization. arXiv:1607.06450 (2016).

  5. Kingma, D. P. dan Ba, J. Adam: A Method for Stochastic Optimization. arXiv:1412.6980 (2014).

  6. Loshchilov, I. dan Hutter, F. Decoupled Weight Decay Regularization. arXiv:1711.05101 (2017).

  7. Srivastava, N., Hinton, G., Krizhevsky, A., Sutskever, I. dan Salakhutdinov, R. Dropout: A Simple Way to Prevent Neural Networks from Overfitting. JMLR 15, hlm. 1929–1958 (2014).

  8. Belkin, M., Hsu, D., Ma, S. dan Mandal, S. Reconciling modern machine-learning practice and the classical bias–variance trade-off. PNAS 116(32), hlm. 15849–15854 (2019). Paper yang memberi nama fenomena ini.

  9. Nakkiran, P., Kaplun, G., Bansal, Y., Yang, T., Barak, B. dan Sutskever, I. Deep Double Descent: Where Bigger Models and More Data Hurt. arXiv:1912.02292 (2019). Menunjukkan efeknya pada deep network nyata, dan di sepanjang sumbu training time serta sumbu ukuran model.


Dibuat oleh

David Vicente Campos

Pendiri NeuraLIA Labs & salah satu pendiri MyRealFood

Saya seorang insinyur komputer lulusan Universitas León. Saya ikut mendirikan MyRealFood, tempat saya sebagai CTO membangun aplikasi yang telah digunakan jutaan orang untuk makan lebih sehat, dan saya mendirikan NeuraLIA Labs, tempat saya membangun produk AI. Di sini saya menulis tentang hal-hal yang harus saya pahami sepanjang perjalanan, sebagaimana dulu saya berharap ada yang menjelaskannya kepada saya.

Selengkapnya tentang penulis

Diterbitkan oleh NeuraLIA Labs.

Dapatkan postingan baru di inbox kamu

Berita AI, panduan, dan update produk — email singkat saat kami menerbitkan sesuatu yang layak kamu baca.

Indeks kursus

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev11 menit baca

Model AI Jev dibuat untuk keputusan, bukan prosa

Jev dari TypeSafe AI menarik perhatian karena memperlakukan kecerdasan software sebagai persoalan probabilitas: pilih cabang yang tepat, sertakan keyakinan, dan hindari membayar LLM untuk menulis teks saat kode membutuhkan keputusan.

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering11 menit baca

Rekayasa konteks untuk agen AI jangka panjang

Agen yang berjalan lama tidak gagal hanya karena window-nya kecil. Mereka gagal ketika file, output tool, dan riwayat lama menggeser tugas yang seharusnya diselesaikan agen.

Siap membiarkan LIA yang memilih?

Berkarya dengan semua model AI dalam satu tempat — mulai gratis hari ini.