Prediksi Next-Token: Embeddings, dan Arti Perplexity
Latih model karakter pada 32.033 nama, lihat gradient descent menemukan ulang tabel hitungan, lalu mengapa perplexity jarang cocok.
Di halaman ini
Berikut sepuluh nama yang dihasilkan oleh program yang belum pernah melihat satu kata pun:
cexze momakurailezitynn konimittain llayn ka
da moliellavo emia sade ftlspTak satu pun adalah nama. Hampir semuanya sedang mencoba. Mereka bisa dilafalkan, berakhir di tempat nama biasanya berakhir, dan salah satunya — emia — hanya terpaut satu huruf dari nama sungguhan. Program yang menghasilkannya menyimpan 729 angka, tidak punya konsep tentang kata, suku kata, atau manusia, dan di-fit lewat satu pass menghitung pasangan huruf yang bersebelahan.
Pada akhir bab ini, sebuah neural network akan memangkas skor program itu sepertiga pada pengukuran yang sama. Bagian yang layak kamu tunggu adalah apa yang pertama kali dilakukan network tersebut: ia mereproduksi tabel hitungan hingga tiga angka desimal pada setiap baris yang datanya cukup banyak, tanpa diminta, karena kedua objek itu adalah jawaban untuk pertanyaan yang sama. Semua setelah itu adalah hal yang tak pernah bisa dilakukan oleh penghitungan.
Objective adalah identitas, bukan pilihan desain
Tautan ke bagian: Objective adalah identitas, bukan pilihan desainBab 7 meninggalkan kamu dengan deretan bilangan bulat dan tanpa alasan mengapa satu bilangan harus mengikuti bilangan lain. Inilah alasannya, dan ia adalah satu baris dari Bab 2.
Language model adalah fungsi yang mengambil token sejauh ini dan mengembalikan distribusi atas token mana yang muncul berikutnya: satu angka per entri vocabulary, non-negatif, dan jumlahnya satu. Tidak ada yang lain. Untuk beranjak dari situ ke probabilitas sebuah dokumen utuh, terapkan aturan rantai probabilitas:
Itu adalah identitas, benar untuk urutan apa pun dari apa pun, tanpa asumsi tambahan. Jadi model yang melakukan pekerjaan kecil — next token dengan token-token sebelumnya — sudah melakukan pekerjaan besar untuk memberi probabilitas pada setiap dokumen yang mungkin, secara persis dan gratis. Pembingkaian populer bahwa ini trik murah (“ia hanya memprediksi kata berikutnya”) membalik logikanya: memprediksi next token adalah memodelkan distribusi gabungan. Tidak pernah ada hal kedua yang harus dilakukan.
Loss-nya mengikuti sama mekanisnya. Di setiap posisi, model menghasilkan distribusi dan kebenarannya adalah satu token yang diketahui, jadi cross-entropy dari Bab 4 berlaku tanpa perubahan:
Itu adalah average negative log-likelihood — resep Bab 2 dengan distribusi kategorikal di slot tempat Gaussian sebelumnya berada. Dan karena distribusi sejatinya one-hot, entropinya nol, jadi menurut identitas Bab 4, cross-entropy sama dengan KL divergence: menurunkan angka ini dan menarik keyakinan model ke arah data adalah tindakan yang sama.
Satu konsekuensi layak mendapat kalimatnya sendiri, karena ini fakta ekonomis di bawah seluruh bidang ini. Labelnya adalah data, digeser satu posisi. Tidak ada yang menganotasi apa pun. Satu triliun token teks adalah satu triliun contoh yang sudah berlabel, itulah mengapa korpus training model modern adalah “internet” dan bukan “dataset yang dibuat seseorang”.
Baseline yang jujur: menghitung
Tautan ke bagian: Baseline yang jujur: menghitungSebelum network apa pun, baseline-nya: 32.033 nama, satu per baris, dan tugas menghasilkan lebih banyak nama, satu huruf demi satu huruf.1
Vocabulary-nya adalah 26 huruf ditambah simbol batas . yang menandai awal sekaligus akhir sebuah nama, jadi model harus belajar di mana nama dimulai dan di mana ia berhenti. Itu berarti 27 simbol, dan model terkecil yang mungkin adalah tabel seberapa sering setiap simbol mengikuti setiap simbol lain.
N = torch.zeros((27, 27), dtype=torch.int32)
for w in words:
cs = ["."] + list(w) + ["."]
for a, b in zip(cs, cs[1:]):
N[stoi[a], stoi[b]] += 1
P = N.float()
P = P / P.sum(1, keepdim=True) # one distribution per row Dua baris aritmetika dan modelnya sudah di-fit — dan ini bukan heuristik: membagi hitungan dengan total baris adalah estimasi maximum-likelihood untuk distribusi kategorikal, yaitu resep Bab 2 dengan kalkulusnya sudah dikerjakan.
names: 32033 train/val/test: 25626 / 3203 / 3204
training bigrams: 182583
the six most likely letters after 'a':
a -> '.' 0.1944 a -> 'n' 0.1600 a -> 'r' 0.0967
a -> 'l' 0.0749 a -> 'h' 0.0690 a -> 'y' 0.0606Ambil sample darinya — pilih satu huruf dari baris huruf saat ini, pindah ke baris itu, ulangi sampai simbol batas muncul — dan kamu mendapat nama-nama di awal bab ini. Mereka gagal dengan cara yang spesifik dan informatif: masuk akal secara lokal, omong kosong secara global. Setiap pasangan huruf bersebelahan dalam momakurailezitynn adalah pasangan yang muncul dalam nama sungguhan; hanya saja ada tujuh belas pasangan itu berderet. Model punya memori satu huruf, jadi ia tidak bisa tahu bahwa ia sudah berjalan terlalu lama.
Perplexity, dan cara membacanya
Tautan ke bagian: Perplexity, dan cara membacanyaLoss pada nama-nama held-out adalah 2,4546 nats. Angka itu tidak berarti apa-apa sendirian, itulah mengapa perplexity ada:
Ditulis lengkap, tanpa library yang mengerjakan semuanya:
@torch.no_grad()
def perplexity(logits, Y):
logp = F.log_softmax(logits, dim=1) # log q for every symbol
chosen = logp[torch.arange(len(Y)), Y] # log q of the one that came next
return torch.exp(-chosen.mean()) Eksponensiasi membatalkan logaritma dan mengembalikan angka itu ke satuan menghitung sesuatu. Cara paling bersih untuk melihat apa yang dihitungnya adalah mengukur model yang tidak tahu apa-apa sama sekali — model yang memberi probabilitas pada setiap simbol tanpa memedulikan konteks:
uniform over 27 symbols loss 3.2958 nats ppl 27.000
bigram counts, add-one smoothed loss 2.4546 nats ppl 11.642Tepat 27,000, karena . Perplexity adalah jumlah efektif opsi yang sama-sama mungkin yang sedang dipilih model. Perplexity 27 berarti “tidak tahu, bisa apa saja”. Nilai 11,642 pada count model berarti satu huruf konteks membuatnya setidaknya sama tidak yakinnya dengan seseorang yang memilih buta dari sekitar dua belas opsi, bukan dua puluh tujuh — itulah mengapa perplexity dikutip dan loss mentah tidak.
Ada dua hal yang salah dengannya, dan yang kedua sering salah dalam paper terbitan.
Probabilitas nol fatal. Dari 729 sel dalam tabel, 113 tidak pernah muncul saat training — 15,5% tabel kosong. Itu tidak masalah sampai held-out set mendarat di salah satunya, dan tujuh bigram dalam validation memang begitu, di antaranya d→q, z→j, dan q→o dua kali. Probabilitas nol berarti log , yang berarti loss tak hingga dan perplexity tak hingga: satu nama dari tiga ribu menghancurkan metrik. Tambalan biasanya adalah menambahkan 1 ke setiap hitungan sebelum normalisasi, yang biayanya hampir tidak ada di sini (2,4546 alih-alih 2,4524). Tapi tambalan itu adalah pengakuan. Count model tidak bisa generalise sama sekali. Ia tidak punya cara untuk menduga bahwa q→o masuk akal karena q→u umum dan o berperilaku seperti u di tempat lain, sebab ia tidak punya konsep bahwa dua simbol bisa mirip satu sama lain. Setiap sel dipelajari sendirian, dan memperbaiki itulah tujuan sisa bab ini.
Perplexity adalah harga per token, dan token adalah parameter bebas. Ini kesalahan yang terus muncul saat model dibandingkan, dan mudah terlihat begitu kamu melihatnya. Ambil korpus prosa Inggris yang sama dari Bab 7, interpolated bigram model yang sama, dan ubah hanya cara teksnya dipotong:
| unit | vocabulary | token di test | cross-entropy | perplexity | bits per character |
|---|---|---|---|---|---|
| karakter | 76 | 14.469 | 2,5217 | 12,45 | 3,6378 |
| BPE, 512 merge | 329 | 6.871 | 3,8547 | 47,21 | 2,6407 |
| BPE, 2.048 merge | 1.820 | 4.233 | 5,7468 | 313,20 | 2,4254 |
| kata | 2.991 | 6.284 | 3,5627 | 35,26 | 2,2322 |
Perplexity bervariasi 25 kali lipat di baris-baris itu. Tidak ada yang berubah pada model; hanya ukuran benda yang diprediksi. Memprediksi satu kata utuh lebih sulit daripada memprediksi satu huruf, jadi biayanya lebih tinggi per prediksi — dan jumlah prediksi yang harus dibuat lebih sedikit.
Sekarang baca kolom terakhir, yang membagi total biaya dengan jumlah karakter dan mengubahnya menjadi bit. Kolom itu mengurutkan ulang tabel. Menurut perplexity, peringkatnya adalah karakter, kata, BPE-512, BPE-2048; menurut bits per character, peringkatnya adalah kata, BPE-2048, BPE-512, karakter. Model karakter berpindah dari posisi pertama ke terakhir. Model 2.048-merge, yang menurut perplexity tampak 6,6 kali lebih buruk daripada model 512-merge, sebenarnya lebih baik dari keduanya pada 2,4254 bit dibanding 2,6407.
Jadi perplexity hanya bisa dibandingkan antara dua model yang memakai tokenizer yang sama, dan model dengan tokenizer berbeda hanya bisa dibandingkan dalam bits per character — besaran yang diukur Shannon pada 1951 dengan meminta subjek manusia menebak huruf berikutnya dari teks Inggris, dan dibatasi kira-kira satu bit per karakter.2 Bigram terbaik kita berada di 2,23 bit, ringkasan yang adil tentang seberapa jauh bab ini masih harus berjalan.
Hal yang sama, dipelajari
Tautan ke bagian: Hal yang sama, dipelajariSekarang bangun model yang sama sebagai network. Ia akan membutuhkan aritmetika berkali-kali lipat lebih banyak untuk sampai ke tempat yang sama, dan sampai ke tempat yang sama itulah intinya.
Ganti tabel dengan satu matriks bobot berbentuk . Ubah huruf saat ini menjadi vektor one-hot, kalikan, dan sebut hasilnya logits — skor yang belum dinormalisasi dari Bab 4. Lalu softmax, lalu cross-entropy, lalu gradient descent.
W = torch.randn((27, 27), requires_grad=True)
for step in range(3000):
logits = W[xs]
loss = F.cross_entropy(logits, ys)
W.grad = None
loss.backward()
W.data -= 50.0 * W.gradBaris yang disorot berisi definisi yang layak dimiliki. Mengalikan vektor one-hot dengan matriks memilih satu baris darinya, jadi perkalian itu adalah lookup — dan setiap implementasi melewati aritmetikanya dan melakukan lookup langsung, itulah W[xs].
Itu adalah embedding table. Matriks dengan satu baris per entri vocabulary, diindeks oleh token id. Tidak ada geometri, tidak ada semantik, tidak ada algoritma terpisah: tabel lookup yang isinya kebetulan dipelajari oleh gradient descent bersama semua hal lain. Setiap klaim mistis tentang “embedding space” berakhir di sini.
Latih dan lihat ke mana ia bergerak:
step 1 train 3.7550 val 3.3882 max gap to the count table 0.757269
step 100 train 2.4732 val 2.4726 max gap to the count table 0.388354
step 1000 train 2.4557 val 2.4549 max gap to the count table 0.041862
step 3000 train 2.4547 val 2.4544 max gap to the count table 0.004048Kolom terakhir adalah selisih absolut terbesar antara sel mana pun dari softmax(W) dan sel yang cocok pada count table, dan nilainya menuju nol. Setelah 3.000 langkah, ketidaksepakatan terbesar di mana pun dalam 729 sel adalah 0,004048 dan mean-nya 0,000224. Sel terburuk adalah q→i, terlihat dua belas kali di seluruh training set; di antara 22 baris dengan lebih dari seribu kemunculan, ketidaksepakatan terburuk adalah 0,000562.
count table network
a -> '.' 0.1945 0.1945
a -> 'n' 0.1601 0.1601
a -> 'r' 0.0967 0.0967Gradient descent, mulai dari angka acak dan tidak diberi tahu apa pun selain “buat log-probability huruf berikutnya besar”, menemukan ulang tabel hitungan. Dan memang harus begitu: hitungan adalah estimasi maximum-likelihood, cross-entropy adalah negative log-likelihood, jadi kedua prosedur mengoptimalkan objective yang sama dan objective itu punya satu optimum. Network tidak mempelajari sesuatu yang mirip menghitung. Ia konvergen ke penghitungan, perlahan.
Ini memunculkan pertanyaan wajar: kenapa ada orang yang repot melakukannya. Karena count table tidak punya tempat lagi untuk melangkah dari sini, sementara network punya.
Context adalah bottleneck, bukan capacity
Tautan ke bagian: Context adalah bottleneck, bukan capacityPerluas model agar melihat lebih dari satu karakter sebelumnya. Ini arsitektur Bengio tahun 2003, leluhur langsung setiap model dalam sisa kursus ini:4 ambil tiga karakter terakhir, petakan masing-masing melalui embedding table menjadi baris 10 dimensi, konkatenasi baris-baris itu menjadi 30 angka, dorong melalui hidden layer dari Bab 5, dan akhiri dengan output layer yang menghasilkan satu logit per entri vocabulary.
C = torch.randn((27, 10)) # the embedding table
W1 = torch.randn((3 * 10, 200)) # the hidden layer from Chapter 5
W2 = torch.randn((200, 27)) # one output per vocabulary entry
emb = C[X].view(-1, 30) # three lookups, concatenated
h = torch.tanh(emb @ W1 + b1)
logits = h @ W2 + b2
loss = F.cross_entropy(logits, Y)Perhatikan apa yang baru dan apa yang tidak. Hidden layer adalah milik Bab 5, tanpa perubahan; loss adalah milik Bab 4, tanpa perubahan. Yang baru adalah embedding table di depan dan output layer selebar vocabulary Bab 7 — dan bagian kedua itu adalah bagian mahal dari setiap language model yang pernah dibangun, karena vocabulary sungguhan punya 100.000 entri dan perkalian matriks ini berjalan di setiap posisi.
Kode yang sama, dilatih secara identik, hanya dengan ukuran context window yang diubah:
| context | parameter | validation loss | validation perplexity |
|---|---|---|---|
| counting, 1 karakter | 729 | 2,4546 | 11,642 |
| neural, 1 karakter | 7.897 | 2,4577 | 11,678 |
| neural, 3 karakter | 11.897 | 2,1145 | 8,285 |
| neural, 8 karakter | 21.897 | 2,0506 | 7,773 |
Baris kedua adalah yang menarik. Network dengan hidden layer 200-unit dan parameter sebelas kali lebih banyak daripada count table berkinerja persis sebaik count table dan tidak lebih baik. Capacity tidak pernah menjadi batasannya. Satu karakter context mengizinkan loss tertentu dan apa pun yang kamu tempelkan tidak bisa turun di bawahnya, karena informasinya tidak ada.
Beri tiga karakter dan perplexity turun dari 11,68 ke 8,29 — pemangkasan 29%, dibeli dengan 4.000 parameter ekstra. Ia mengalahkan counting di sini tepat karena alasan yang didiagnosis sebelumnya: count model atas context tiga karakter membutuhkan baris, sebagian besar kosong atau berisi satu observasi, dan ia mempelajari semuanya sendirian. Network berbagi. Jika a, e, dan i berakhir dengan baris embedding yang mirip, apa yang dipelajarinya setelah bra berpindah ke bre tanpa pernah melihat bre. Transfer itulah seluruh nilai embedding table, dan itulah celah antara baris dua dan tiga.
Sample-nya membaik sesuai itu:
deliah nellara joce kael quintis
salayson reety khyrmin mahnen madiaryxiaMasih bukan daftar nama sungguhan. Tapi deliah, nellara, dan kael tidak akan terasa janggal di daftar seperti itu, dan monster yang terus berlari sudah hilang: yang terpanjang dari dua puluh sample count model adalah sembilan belas huruf, yang terpanjang dari dua puluh sample model ini adalah tiga belas.
Apa yang sebenarnya ada di dalam embedding table
Tautan ke bagian: Apa yang sebenarnya ada di dalam embedding tableTabelnya adalah : satu baris berisi sepuluh angka per karakter, semuanya diinisialisasi acak dan hanya digerakkan oleh gradient dari next-character loss. Tidak ada yang memasukkan apa pun ke sana. Jadi apa yang akhirnya ada di dalamnya?
Alat untuk bertanya adalah cosine similarity, yaitu dot product dari Bab 1 setelah panjangnya dibagi habis:
Ia mengukur sudut antara dua vektor dan mengabaikan panjangnya, yang memang kamu inginkan saat panjang baris mencerminkan seberapa sering token-nya muncul, bukan apa maknanya. Normalisasikan setiap vektor ke panjang 1 terlebih dulu — seperti yang dilakukan sistem nyata, sekali, saat indexing — dan cosine similarity hanyalah dot product.
Berikut nearest neighbours dari beberapa karakter dalam tabel yang sudah dilatih:
'c' -> 'k':+0.598 'j' -> 'z':+0.650 'i' -> 'y':+0.541
'u' -> 'e':+0.482 'a' -> 'h':+0.367 '.' -> 'q':+0.077Sebagian dari itu sesuai janji folklor. c dan k bisa saling menggantikan dalam nama, begitu juga i dan y; j dan z sama-sama konsonan langka yang kebanyakan muncul di awal dan berperilaku mirip. Simbol batas . tidak dekat dengan apa pun — 0,077 dari huruf terdekatnya — karena ia satu-satunya simbol yang menandai posisi, bukan bunyi.
Dan sebagian tidak. Nearest neighbour dari a adalah h, bukan vokal lain. Dirata-ratakan atas semua pasangan:
mean cosine, vowel to vowel : +0.1889
mean cosine, consonant to consonant : +0.0765
mean cosine, vowel to consonant : -0.0042Vokal lebih mirip satu sama lain daripada dengan konsonan, dan efeknya nyata tetapi kecil. Diuji terhadap 2.000 kelompok acak berisi lima huruf, 58 kelompok itu terpisah setidaknya sebersih ini — celah yang signifikan sekitar . Jadi nyata, tetapi sama sekali bukan pulau geometris yang tegas seperti yang disiratkan cerita populer tentang embeddings.
Itulah deskripsi jujur sebuah embedding table dan layak kamu pegang untuk sisa kursus ini. Ia bukan peta makna. Ia adalah perubahan koordinat, dipelajari alih-alih dirancang, yang satu-satunya tugasnya adalah memudahkan pekerjaan layer berikutnya — kalimat yang sama dipakai Bab 5 untuk hidden layer yang melipat bidang untuk menyelesaikan XOR. Struktur apa pun yang kamu temukan di dalamnya ada karena ia menurunkan loss, dan struktur yang tidak menurunkan loss memang tidak ada.
word2vec, GloVe, dan aritmetika yang dikutip semua orang
Tautan ke bagian: word2vec, GloVe, dan aritmetika yang dikutip semua orangJika bagian yang berguna adalah tabelnya, kamu bisa mengejarnya secara langsung. Itulah word2vec: pertahankan embedding lookup, buang language model.5
Objective skip-gram with negative sampling adalah satu baris. Untuk pasangan (pusat, konteks) sungguhan yang diambil dari korpus, dorong dot product mereka naik; untuk pasangan palsu yang diambil dari distribusi noise, dorong turun:6
Itu adalah klasifikasi biner — “apakah dua kata ini benar-benar muncul bersama?” — dan murah tepat karena ia tidak pernah menyentuh vocabulary penuh, yang membuat training pada miliaran kata praktis pada 2013. GloVe tiba di vektor serupa dari arah lain, dengan memfaktorkan matriks hitungan co-occurrence global alih-alih streaming melalui contoh.7 Keduanya di-fit persis pada statistik yang dipakai untuk membangun count table. Mereka adalah penghitungan, dikompresi.
Dilatih pada text8 — 17.005.207 kata dari Wikipedia bahasa Inggris, 71.290 di antaranya muncul setidaknya lima kali, 100 dimensi, tiga pass — vektornya keluar dengan properti yang membuatnya terkenal:
king -> charles 0.700, son 0.693, queen 0.686, henry 0.669, throne 0.667
physics -> chemistry 0.672, electromagnetism 0.661, quantum 0.654, theoretical 0.624
guitar -> bass 0.733, vocals 0.732, acoustic 0.728, guitars 0.703, drums 0.685
three -> seven 0.892, two 0.877, one 0.875, five 0.871, four 0.870Tidak ada yang memberi kategori untuk instrumen atau numeral. Sekarang bagian yang terkenal: ambil king, kurangi man, tambahkan woman, lalu cari vektor terdekat dengan hasilnya.
king - man + woman
nothing excluded : king 0.693, elizabeth 0.657, wife 0.629, woman 0.607
a, b, c excluded : elizabeth 0.657, wife 0.629, mary 0.607 (queen is 4th, 0.604)Vektor terdekat dengan king - man + woman adalah king. Itu bukan keanehan dari satu contoh. Evaluation set Mikolov mengajukan pertanyaan berbentuk a : b :: c : ? — 8.869 pertanyaan semantik (paris : france :: rome : italy) dan 10.675 pertanyaan sintaktik (walking : walked :: swimming : swam) — dan dari 4.103 pertanyaan semantik yang bisa dijawab vocabulary ini, pemenangnya adalah salah satu dari tiga kata input 99,8% dari waktu. Demonstrasi yang diterbitkan tidak menyebutkannya, karena aturan scoring standar menghapus a, b, dan c sebelum melihat. Itu aturan yang sah, dan ia bekerja lebih keras daripada aritmetikanya:
| cara jawaban dipilih | semantik | sintaktik |
|---|---|---|
| offset, dengan input dikecualikan (standar) | 17,0% | 11,9% |
| offset, tanpa ada yang dikecualikan | 0,1% | 0,4% |
nearest neighbour dari c saja, input dikecualikan | 13,1% | 9,3% |
nearest neighbour dari b saja, input dikecualikan | 2,3% | 0,4% |
Baris ketiga adalah yang perlu direnungkan. Buang a dan b, jangan lakukan aritmetika sama sekali, kembalikan apa pun yang paling dekat dengan c — dan kamu mempertahankan 77% skor semantik. Sebagian besar yang tampak seperti penalaran analogis adalah kedekatan plus aturan yang melarang jawaban yang jelas, persis seperti yang diukur Linzen pada vektor yang dilatih dengan benar dan seperti yang direplikasi baseline di atas.8 Vektor khusus ini kecil — 17 juta kata dibanding miliaran di balik model yang diterbitkan — jadi baca persentasenya sebagai bentuk, bukan state of the art. Bentuk itulah yang bertahan di setiap skala: aritmetikanya nyata, dan jauh lebih lemah daripada satu demonstrasi yang dikutip semua orang.
Static dan contextual: satu vektor per kata, atau satu per kemunculan
Tautan ke bagian: Static dan contextual: satu vektor per kata, atau satu per kemunculanSemua sejauh ini punya batas keras yang tertanam dalam struktur datanya. Tabel punya satu baris per token. Kata bank mendapat satu vektor, vektor yang sama dalam kalimat tentang sungai dan kalimat tentang hipotek — harus begitu, karena lookup berdasarkan id tidak bisa bergantung pada hal lain.
Perbaikannya adalah berhenti membaca vektor dari tabel dan mulai menghitungnya dari kalimat. Itulah contextual embedding, diperkenalkan oleh ELMo pada 2018 dan dijadikan standar oleh BERT pada tahun yang sama.910 Diukur pada model sungguhan, angkanya lebih tajam daripada penjelasannya:
sentence A: "He sat on the bank of the river and watched the water go by."
sentence B: "She deposited the cheque at the bank on the corner of the street."
static vector for 'bank' (a row of the input embedding table)
cosine A vs B ........................ 1.000000
contextual vector for 'bank', layer by layer
layer | A vs B | A vs another river sentence | B vs another money sentence
0 | 0.9512 | 0.9512 | 0.9359
4 | 0.5647 | 0.8987 | 0.7716
9 | 0.4284 | 0.8699 | 0.7568
12 | 0.5278 | 0.8702 | 0.7335Baris pertama persis, bukan perkiraan: vektor static untuk bank adalah 768 angka yang sama di kedua kalimat, jadi cosine-nya 1 by construction. Sembilan layer kemudian, dua kemunculan itu berada di 0,43, sementara bank dalam dua kalimat sungai berbeda tetap di 0,87. Tidak ada sense yang dilabeli di mana pun dalam proses ini; sense terpisah karena memisahkannya membuat training objective — menebak token tersembunyi dari tetangganya — lebih mudah dipenuhi.
Dua detail layak diperhatikan. Layer 0 sudah 0,9512, bukan 1,0, karena position embeddings sudah ditambahkan dan kata itu berada di tempat berbeda dalam tiap kalimat. Dan similarity naik lagi pada layer 11 dan 12: layer akhir pretrained model terspesialisasi untuk training objective-nya, dan sering kali bukan tempat terbaik untuk mengambil representasi.
Tampilkan detail
Opsional: weight tying.
Dalam bert-base-uncased, embedding table adalah — 23.440.896 angka, 21,4% dari 109.482.240 parameter model. Dalam language model kecil, fraksinya lebih besar lagi, itulah mengapa satu trik hampir universal: input table dan output layer yang menghasilkan logits adalah matriks yang sama, dipakai sekali lewat row lookup dan sekali dalam bentuk transposed.11 Output layer sudah memberi setiap entri vocabulary sebuah vektor — ia mengambil dot product terhadap masing-masing — dan tying mengatakan vektor yang dipakai untuk membaca token dan vektor yang dipakai untuk menulisnya seharusnya objek yang sama. Ia memangkas parameter dan meningkatkan perplexity sekaligus, hal yang cukup langka untuk diperhatikan.
Embedding model bukan language model
Tautan ke bagian: Embedding model bukan language modelUntuk mencari korpus berdasarkan makna, kamu membutuhkan satu vektor per kalimat. Dengan vektor-vektor itu, pencariannya trivial — inilah seluruh semantic retrieval, dan Bab 19 membahas segala hal di sekitarnya:
E = normalise(embed(sentences)) # (200, d), every row of length 1
q = normalise(embed([query])) # (1, d)
scores = q @ E.T # one matrix multiply
top5 = scores[0].argsort()[::-1][:5]Jadi satu-satunya pertanyaan nyata adalah dari mana embed berasal. Langkah yang jelas adalah mengambil pretrained language model, menjalankan setiap kalimat melaluinya, lalu merata-ratakan vektor token. Inilah metode itu dibanding empat alternatif, dinilai dengan dua cara: rank correlation antara cosine dan penilaian similarity manusia atas 1.379 pasangan benchmark STS, dan top-1 retrieval pada index yang dibangun dari 200 pasangan paling kuat terparafrasekan — satu sisi tiap pasangan di-index, sisi lain dipakai sebagai query.
| cara kalimat di-embed | rank correlation | top-1 pada index 200 kalimat |
|---|---|---|
| binary word overlap (tanpa model sama sekali) | 0,5500 | 89,0% |
| mean dari vektor static yang dilatih di atas | 0,5263 | 85,5% |
BERT, token [CLS] | 0,2030 | 67,0% |
| BERT, mean dari vektor token | 0,4729 | 84,0% |
| MiniLM, dilatih secara contrastive | 0,8203 | 92,0% |
Baca tiga baris tengah dibanding dua baris pertama. Pretrained transformer 109 juta parameter, digunakan dengan cara yang jelas, lebih buruk dalam menilai similarity kalimat daripada menghitung berapa banyak kata yang dimiliki dua kalimat bersama — dan lebih buruk daripada merata-ratakan vektor text8 100 dimensi yang baru dilatih tadi. Token [CLS], yang masih direkomendasikan tutorial karena BERT dipretrain dengan objective tingkat kalimat yang melekat padanya, lebih buruk daripada setengah dari itu.
Ini bukan cacat pada BERT. Ini objective-nya. Language model dilatih agar hidden states-nya memprediksi token; tidak ada di sana yang meminta dua parafrasa berakhir dekat satu sama lain, dan tidak ada yang memberi reward geometri di mana cosine berarti “makna yang sama”. Baris terakhir adalah model berukuran seperlima (22.713.216 parameter) yang dilatih pada loss yang sepenuhnya berbeda: contrastive learning, dengan contoh berupa pasangan — pertanyaan dan jawabannya, kalimat dan parafrasanya — dan objective menarik pasangan benar agar mendekat sambil mendorong sampled negatives menjauh. Itulah kontribusi Sentence-BERT dan asal-usul seluruh industri embedding-model.12 Dense Passage Retrieval menerapkan resep yang sama langsung ke search, dengan satu encoder untuk query dan satu untuk passage.13
Jadi, aturan praktisnya:
Embedding model bukan language model yang layer terakhirnya dilepas. Ia adalah model berbeda dengan objective berbeda, biasanya jauh lebih kecil, yang cosine-nya berarti apa yang kamu inginkan karena ia dilatih pada pasangan yang menjadikan hal itu targetnya. Tabel di atas adalah biaya ketika yang satu digantikan dengan yang lain.
Dan keluarga model ini gagal pada urutan kata. “The dog bit the man” dan “the man bit the dog” punya bag of words yang identik, jadi word overlap dan rata-rata vektor static memberi cosine persis 1,000000, dan mean-pooled BERT, yang memang melihat posisi, masih mendarat hampir di sana — dan MiniLM yang dilatih secara contrastive masih menaruh keduanya di 0,979. Jika retrieval task kamu bergantung pada siapa melakukan apa kepada siapa, tidak ada cosine threshold yang akan menyelamatkanmu.
Bab 19 membangun sistem retrieval produksi di atas pijakan ini dan sampai pada cut-off cosine yang konkret. Pengukuran terakhir dalam bab ini adalah yang membuat angka seperti itu bisa dipertanggungjawabkan, bukan sihir.
Kutukan dimensionality, dalam satu tabel
Tautan ke bagian: Kutukan dimensionality, dalam satu tabelEmbeddings nyata punya ratusan atau ribuan komponen, dan jarak berperilaku aneh di sana. Ambil 1.000 titik acak dalam unit cube berdimensi dan lihat rasio antara jarak terbesar dan terkecil di antara pasangan mana pun:
| dimensi | pasangan terdekat | pasangan terjauh | rasio |
|---|---|---|---|
| 2 | 0,0007 | 1,3612 | 1921,66 |
| 10 | 0,2361 | 2,3397 | 9,91 |
| 100 | 3,0047 | 5,1752 | 1,72 |
| 1.000 | 11,7809 | 14,0306 | 1,19 |
| 10.000 | 39,6152 | 42,0125 | 1,06 |
Dalam sepuluh ribu dimensi, pasangan titik terjauh hanya 6% lebih jauh daripada pasangan terdekat. Semuanya kira-kira berjarak sama dari yang lain, “nearest neighbour” berhenti membawa banyak informasi, dan itulah curse of dimensionality — sekaligus salah satu alasan vector database besar tidak melakukan exact nearest-neighbour search. Sisi lain dari koin yang sama adalah hal yang membuat cosine threshold bisa dipakai: diukur atas seribu pasangan vektor unit acak, mean cosine berada di dalam 100 dimensi dan dalam 768, dengan standard deviation 0,0968 dan 0,0357 — dan dalam 768 dimensi hanya 0,2% pasangan acak yang melebihi 0,1 dalam nilai absolut. Similarity terukur 0,4 karena itu bukan “40% mirip”; ia jauh di luar apa pun yang dihasilkan kebetulan, itulah mengapa threshold antara 0,3 dan 0,7 memisahkan signal dari noise, bukan duduk di tengah-tengahnya.
Ke mana ini berlanjut
Tautan ke bagian: Ke mana ini berlanjutModel dalam bab ini membaca jumlah tetap karakter sebelumnya, melakukan lookup masing-masing, dan menempelkan hasilnya bersama-sama secara berurutan. Desain itu punya dua masalah, dan keduanya adalah masalah yang sama.
Lihat lagi tabel context: berpindah dari tiga karakter ke delapan hampir menggandakan parameter dan hanya membeli 0,06 nats. Biaya tumbuh linear dengan context — setiap posisi ekstra membutuhkan slab-nya sendiri pada matriks bobot pertama — sedangkan manfaatnya tidak. Dorong hingga seribu token dan layer pertama saja lebih berat daripada sisa model, sebagian besar dihabiskan pada posisi yang tidak relevan untuk prediksi tertentu.
Itulah masalah kedua: model tidak punya cara untuk memutuskan token sebelumnya mana yang penting. Posisi dua punya bobotnya sendiri dan posisi tujuh punya bobotnya sendiri, secara permanen, apa pun isinya. Saat model mengeja nell, karakter penentunya adalah yang tepat sebelumnya. Saat sebuah kalimat mengandung pronomina, kata yang menetapkan referennya mungkin berada empat puluh token di belakang — dan tidak ada slot tetap yang bisa ditugaskan untuk “empat puluh di belakang”, karena lain kali bisa jadi enam.
Yang kita inginkan adalah model yang menghitung, untuk setiap prediksi, seberapa besar setiap token sebelumnya harus dihitung — bobot atas context yang dihasilkan oleh konten, bukan ditetapkan oleh tata letak. Tulis itu dengan hati-hati dan ia bermula sebagai sesuatu yang sepenuhnya biasa: rata-rata atas token-token sebelumnya. Lalu biarkan bobot rata-rata itu dipelajari, dan biarkan mereka bergantung pada token mana yang sedang bertanya.
Itulah attention, dan itu Bab 9.
Sumber dan metode
Tautan ke bagian: Sumber dan metodeJuga layak dibaca berdampingan: bab 3 dari Speech and Language Processing karya Jurafsky dan Martin, yang membahas n-gram model, smoothing, dan perplexity jauh lebih hati-hati daripada ruang yang tersedia di sini, termasuk mengapa interpolation dan back-off mengalahkan menambahkan satu; catatan Stanford CS229 §17.1–17.2 untuk language modelling dari sisi probabilistik; dan paper Linzen di atas, yang singkat dan layak dibaca penuh.
Referensi
Tautan ke bagian: Referensi-
Contoh generasi nama, dataset, dan progresi dari count table ke network bergaya Bengio mengikuti seri building makemore dari Andrej Karpathy, yang dua bagian pertamanya adalah pendamping terbaik untuk bab ini. ↩
-
Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), hlm. 50–64 (1951). Subjek manusia menebak huruf berikutnya dari bahasa Inggris tertulis, dan pengukuran bits-per-character yang asli. ↩
-
Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Teorema source coding, dan identifikasi prediksi dengan kompresi. ↩
-
Bengio, Y., Ducharme, R., Vincent, P. dan Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, hlm. 1137–1155 (2003). Arsitektur yang dipakai di atas: satu embedding per kata, dikonkatenasi dalam window tetap, melalui hidden layer, ke softmax atas vocabulary. ↩
-
Mikolov, T., Chen, K., Corrado, G. dan Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW dan skip-gram, serta analogy set yang dipakai di atas. ↩
-
Mikolov, T., Sutskever, I., Chen, K., Corrado, G. dan Dean, J. Distributed Representations of Words and Phrases and their Compositionality. arXiv:1310.4546 (2013). Negative sampling, subsampling kata-kata sering, dan distribusi noise yang dipangkatkan 3/4 seperti dipakai di atas. ↩
-
Pennington, J., Socher, R. dan Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Word vectors dari faktorisasi matriks co-occurrence global, bukan dari window lokal yang di-stream. ↩
-
Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016, arXiv:1606.07736. Sumber baseline tanpa offset yang direplikasi di atas. ↩
-
Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: satu vektor per kemunculan, dihitung oleh bidirectional language model. ↩
-
Devlin, J., Chang, M.-W., Lee, K. dan Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). Model yang diukur dalam eksperimen bank. ↩
-
Press, O. dan Wolf, L. Using the Output Embedding to Improve Language Models. arXiv:1608.05859 (2016), dan Inan, H., Khosravi, K. dan Socher, R. Tying Word Vectors and Word Classifiers. arXiv:1611.01462 (2016). Dua argumen independen untuk trik yang sama. ↩
-
Reimers, N. dan Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). Pengukuran pembukanya — mean-pooled BERT kalah dari rata-rata vektor static pada sentence similarity — adalah yang direproduksi tabel di atas. ↩
-
Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Contrastive training untuk retriever dua-encoder; leluhur langsung retrieval stack Bab 19. ↩