Predykcja następnego token: embeddingi i znaczenie perplexity
Trenuj model znakowy na 32 033 imionach i zobacz, jak gradient descent odtwarza tabelę zliczeń — oraz czemu perplexity rzadko się zgadza.
Na tej stronie
Oto dziesięć imion wygenerowanych przez program, który nigdy nie widział słowa:
cexze momakurailezitynn konimittain llayn ka
da moliellavo emia sade ftlspŻadne z nich nie jest imieniem. Prawie wszystkie próbują nim być. Da się je wymówić, kończą się tam, gdzie kończą się imiona, a jedno z nich — emia — dzieli od prawdziwego imienia tylko jedna litera. Program, który je wygenerował, przechowuje 729 liczb, nie ma pojęcia słowa, sylaby ani osoby, a został dopasowany jednym przebiegiem zliczania sąsiednich par liter.
Do końca tego rozdziału sieć neuronowa obniży wynik tego programu o jedną trzecią na tej samej miarze. Warto zostać dla tego, co sieć robi najpierw: odtwarza tabelę zliczeń do trzech miejsc po przecinku w każdym dobrze obsadzonym wierszu, bez promptu, ponieważ oba obiekty są odpowiedziami na to samo pytanie. Wszystko później jest tym, czego samo zliczanie nigdy nie mogłoby zrobić.
Cel jest tożsamością, nie decyzją projektową
Link do sekcji: Cel jest tożsamością, nie decyzją projektowąRozdział 7 zostawił cię z sekwencją liczb całkowitych i bez powodu, dla którego jedna miałaby następować po drugiej. Oto ten powód, w jednym wierszu z rozdziału 2.
Model językowy to funkcja, która bierze dotychczasowe tokeny i zwraca rozkład tego, który token pojawi się następny: jedna liczba na każdy element słownika, nieujemna, sumująca się do jedności. Nic więcej. Aby przejść od tego do prawdopodobieństwa całego dokumentu, zastosuj regułę łańcuchową prawdopodobieństwa:
To tożsamość, prawdziwa dla dowolnej sekwencji czegokolwiek, bez żadnych założeń. Model, który wykonuje małe zadanie — następny token przy danych poprzednich — wykonał już duże zadanie przypisania prawdopodobieństwa każdemu możliwemu dokumentowi, dokładnie i za darmo. Popularne przedstawianie tego jako taniej sztuczki („on tylko przewiduje następne słowo”) odwraca logikę: przewidywanie następnego token jest modelowaniem rozkładu łącznego. Nigdy nie było drugiej rzeczy do zrobienia.
Loss wynika równie mechanicznie. W każdej pozycji model tworzy rozkład , a prawdą jest pojedynczy znany token, więc entropia krzyżowa z rozdziału 4 stosuje się bez zmian:
To średnia ujemna log-wiarygodność — przepis z rozdziału 2 z rozkładem kategorycznym w miejscu, w którym wcześniej siedział Gauss. A ponieważ prawdziwy rozkład jest one-hot, jego entropia wynosi zero, więc na mocy tożsamości z rozdziału 4 entropia krzyżowa równa się dywergencji KL: obniżanie tej liczby i przyciąganie przekonań modelu do danych to ten sam akt.
Jedna konsekwencja zasługuje na osobne zdanie, bo jest ekonomicznym faktem pod całą dziedziną. Etykiety to dane przesunięte o jedną pozycję. Nikt niczego nie anotuje. Bilion tokenów tekstu to bilion wstępnie oznaczonych przykładów, dlatego korpusem treningowym nowoczesnego modelu jest „internet”, a nie „zbiór danych, który ktoś zbudował”.
Uczciwa linia bazowa: zliczanie
Link do sekcji: Uczciwa linia bazowa: zliczaniePrzed jakąkolwiek siecią, linia bazowa: 32 033 imiona, jedno w wierszu, i zadanie generowania kolejnych po jednej literze naraz.1
Słownik to 26 liter plus symbol graniczny . oznaczający zarówno początek, jak i koniec imienia, więc model musi nauczyć się, gdzie imiona się zaczynają i gdzie się kończą. To 27 symboli, a najmniejszy możliwy model jest tabelą tego, jak często każdy symbol następował po każdym innym symbolu.
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 Dwie linie arytmetyki i model jest dopasowany — i nie jest to heurystyka: dzielenie zliczeń przez sumy wierszy jest estymatorem największej wiarygodności dla rozkładu kategorycznego, czyli przepisem z rozdziału 2 z już wykonaną analizą matematyczną.
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.0606Losuj z niego — wybierz literę z wiersza bieżącej litery, przejdź do tego wiersza, powtarzaj, aż pojawi się symbol graniczny — a dostaniesz imiona z początku tego rozdziału. Ponoszą porażkę w konkretny i pouczający sposób: lokalnie wiarygodne, globalnie bezsensowne. Każda sąsiednia para liter w momakurailezitynn jest parą występującą w prawdziwych imionach; po prostu jest ich siedemnaście z rzędu. Model ma jedną literę pamięci, więc nie może wiedzieć, że ciągnie to zbyt długo.
Perplexity i jak ją czytać
Link do sekcji: Perplexity i jak ją czytaćLoss na odłożonych imionach wynosi 2,4546 nata. Sama ta liczba nic nie znaczy, dlatego istnieje perplexity:
Rozpisane, bez biblioteki wykonującej pracę:
@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()) Potęgowanie odwraca logarytm i zwraca liczbę do jednostek liczenia rzeczy. Najprościej zobaczyć, co ona liczy, mierząc model, który nie wie absolutnie nic — taki, który przypisuje prawdopodobieństwo każdemu symbolowi niezależnie od kontekstu:
uniform over 27 symbols loss 3.2958 nats ppl 27.000
bigram counts, add-one smoothed loss 2.4546 nats ppl 11.642Dokładnie 27,000, bo . Perplexity to efektywna liczba jednakowo prawdopodobnych opcji, spośród których wybiera model. Perplexity równa 27 oznacza „nie mam pojęcia, może być cokolwiek”. Wynik 11,642 modelu zliczeń oznacza, że jedna litera kontekstu zostawia go tak niepewnym, jak kogoś, kto wybiera na ślepo z około dwunastu opcji zamiast z dwudziestu siedmiu — dlatego cytuje się perplexity, a nie surowy loss.
Dwie rzeczy idą z nią źle, a druga idzie źle także w publikowanych pracach.
Zerowe prawdopodobieństwa są śmiertelne. Z 729 komórek tabeli 113 nigdy nie występuje w treningu — puste jest 15,5% tabeli. To w porządku, dopóki zbiór odłożony nie trafi w jedną z nich, a siedem bigramów w walidacji trafia, między innymi d→q, z→j oraz q→o dwa razy. Prawdopodobieństwo zero oznacza log , czyli nieskończony loss i nieskończoną perplexity: jedno imię na trzy tysiące niszczy metrykę. Zwykłą łatką jest dodanie 1 do każdego zliczenia przed normalizacją, co tutaj kosztuje prawie nic (2,4546 zamiast 2,4524). Ale łatka jest przyznaniem się. Model zliczeń w ogóle nie potrafi generalizować. Nie ma jak podejrzewać, że q→o jest wiarygodne, bo q→u jest częste, a o zachowuje się gdzie indziej jak u, skoro nie ma pojęcia, że dwa symbole mogą być do siebie podobne. Każda komórka jest uczona osobno, a naprawieniu tego służy reszta rozdziału.
Perplexity to cena za token, a token jest swobodnym parametrem. To błąd, który pojawia się nieustannie, gdy porównuje się modele, i łatwo go zobaczyć, kiedy tylko spojrzysz. Weź ten sam korpus angielskiej prozy z rozdziału 7, ten sam interpolowany model bigramowy, i zmień wyłącznie sposób pocięcia tekstu:
| jednostka | słownik | tokeny w teście | entropia krzyżowa | perplexity | bity na znak |
|---|---|---|---|---|---|
| znaki | 76 | 14 469 | 2,5217 | 12,45 | 3,6378 |
| BPE, 512 scaleń | 329 | 6 871 | 3,8547 | 47,21 | 2,6407 |
| BPE, 2048 scaleń | 1 820 | 4 233 | 5,7468 | 313,20 | 2,4254 |
| słowa | 2 991 | 6 284 | 3,5627 | 35,26 | 2,2322 |
Perplexity zmienia się między tymi wierszami 25-krotnie. Nic w modelu się nie zmieniło; zmienił się tylko rozmiar rzeczy przewidywanej. Przewidzenie całego słowa jest trudniejsze niż przewidzenie litery, więc kosztuje więcej na predykcję — a predykcji do wykonania jest mniej.
Teraz przeczytaj ostatnią kolumnę, która zamiast tego dzieli całkowity koszt przez liczbę znaków i zamienia go na bity. Ona przestawia tabelę. Według perplexity ranking to znaki, słowa, BPE-512, BPE-2048; według bitów na znak to słowa, BPE-2048, BPE-512, znaki. Model znakowy przechodzi z pierwszego miejsca na ostatnie. Model z 2048 scaleniami, który według perplexity wygląda 6,6 razy gorzej niż model z 512 scaleniami, w rzeczywistości jest lepszy z tej dwójki: 2,4254 bita wobec 2,6407.
Dlatego perplexity jest porównywalna tylko między dwoma modelami, które współdzielą tokenizer, a modele z różnymi tokenizerami można porównywać tylko w bitach na znak — wielkości, którą Shannon mierzył w 1951 roku, każąc ludziom zgadywać następną literę angielskiego tekstu, i którą ograniczył z grubsza do jednego bitu na znak.2 Nasz najlepszy bigram siedzi na 2,23 bita, co uczciwie podsumowuje, jak daleko ten rozdział musi jeszcze dojść.
To samo, wyuczone
Link do sekcji: To samo, wyuczoneTeraz zbuduj ten sam model jako sieć. Wymaga ona o rzędy wielkości więcej arytmetyki, aby dojść do tego samego miejsca, i właśnie dojście do tego samego miejsca jest tu sednem.
Zastąp tabelę jedną macierzą wag o kształcie . Zamień bieżącą literę na wektor one-hot, pomnóż i nazwij wynik logits — nienormalizowanymi wynikami z rozdziału 4. Potem softmax, potem entropia krzyżowa, potem 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.gradWyróżniony wiersz zawiera definicję, którą warto mieć. Mnożenie wektora one-hot przez macierz wybiera jeden jej wiersz, więc mnożenie jest lookupiem — a każda implementacja pomija arytmetykę i robi lookup bezpośrednio, czyli właśnie tym jest W[xs].
To jest embedding table. Macierz z jednym wierszem na każdy element słownika, indeksowana przez token id. Bez geometrii, bez semantyki, bez osobnego algorytmu: tabela lookup, której zawartość akurat jest uczona przez gradient descent razem z całą resztą. Każde mistyczne twierdzenie o „embedding space” sprowadza się do tego miejsca.
Wytrenuj ją i zobacz, dokąd zmierza:
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.004048Ostatnia kolumna to największa bezwzględna różnica między dowolną komórką softmax(W) a odpowiadającą jej komórką tabeli zliczeń — i schodzi do zera. Po 3000 kroków największa niezgoda gdziekolwiek w 729 komórkach wynosi 0,004048, a średnia 0,000224. Najgorsza komórka to q→i, widziana dwanaście razy w całym zbiorze treningowym; wśród 22 wierszy z ponad tysiącem wystąpień najgorsza niezgoda wynosi 0,000562.
count table network
a -> '.' 0.1945 0.1945
a -> 'n' 0.1601 0.1601
a -> 'r' 0.0967 0.0967Gradient descent, startując od losowych liczb i nie dostając nic poza poleceniem „zwiększ log-prawdopodobieństwo następnej litery”, na nowo odkrył tabelę zliczeń. I musiał: zliczenia są estymatorem największej wiarygodności, entropia krzyżowa jest ujemną log-wiarygodnością, więc obie procedury optymalizują ten sam cel, a ten cel ma jedno optimum. Sieć nie nauczyła się czegoś podobnego do zliczania. Zbiegała do zliczania, powoli.
Co rodzi uczciwe pytanie, po co ktokolwiek miałby się tym trudzić. Bo tabela zliczeń nie ma już dokąd pójść, a sieć ma.
Wąskim gardłem jest kontekst, nie pojemność
Link do sekcji: Wąskim gardłem jest kontekst, nie pojemnośćRozszerz model tak, aby patrzył na więcej niż jeden poprzedni znak. To architektura Bengio z 2003 roku, bezpośredni przodek każdego modelu w dalszej części tego kursu:4 weź ostatnie trzy znaki, przeprowadź każdy przez embedding table do 10-wymiarowego wiersza, sklej wiersze w 30 liczb, przepchnij je przez warstwę ukrytą z rozdziału 5, a na końcu użyj warstwy wyjściowej generującej jeden logit na każdy element słownika.
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)Zwróć uwagę, co jest nowe, a co nie. Warstwa ukryta to ta z rozdziału 5, bez zmian; loss to ten z rozdziału 4, bez zmian. Nowościami są embedding table na wejściu i warstwa wyjściowa tak szeroka jak słownik z rozdziału 7 — i właśnie ta druga część jest kosztownym fragmentem każdego kiedykolwiek zbudowanego modelu językowego, bo prawdziwy słownik ma 100 000 elementów, a to mnożenie macierzy wykonuje się w każdej pozycji.
Ten sam kod, trenowany identycznie, ze zmienionym wyłącznie rozmiarem context window:
| kontekst | parametry | validation loss | validation perplexity |
|---|---|---|---|
| zliczanie, 1 znak | 729 | 2,4546 | 11,642 |
| neuronowy, 1 znak | 7 897 | 2,4577 | 11,678 |
| neuronowy, 3 znaki | 11 897 | 2,1145 | 8,285 |
| neuronowy, 8 znaków | 21 897 | 2,0506 | 7,773 |
Drugi wiersz jest interesujący. Sieć z 200-jednostkową warstwą ukrytą i jedenastokrotnie większą liczbą parametrów niż tabela zliczeń działa dokładnie tak dobrze jak tabela zliczeń i ani trochę lepiej. Pojemność nigdy nie była ograniczeniem. Jedna litera kontekstu dopuszcza pewien loss i nic, co do niej przykręcisz, nie zejdzie niżej, bo informacji tam nie ma.
Daj jej trzy znaki, a perplexity spada z 11,68 do 8,29 — o 29%, za cenę 4000 dodatkowych parametrów. Pokonuje tu zliczanie dokładnie z powodu zdiagnozowanego wcześniej: model zliczeń nad trzyznakowymi kontekstami potrzebuje wierszy, z których większość jest pusta albo zawiera pojedynczą obserwację, i uczy każdy osobno. Sieć współdzieli. Jeśli a, e i i skończą z podobnymi wierszami embedding, to to, czego nauczy się po bra, przenosi się na bre, nawet jeśli nigdy nie widziała bre. Ten transfer jest całą wartością embedding table i jest różnicą między drugim a trzecim wierszem.
Próbki odpowiednio się poprawiają:
deliah nellara joce kael quintis
salayson reety khyrmin mahnen madiaryxiaTo wciąż nie jest lista prawdziwych imion. Ale deliah, nellara i kael nie wyglądałyby na niej obco, a potwory ciągnące się bez końca zniknęły: najdłuższa z dwudziestu próbek modelu zliczeń ma dziewiętnaście liter, najdłuższa z dwudziestu próbek tego modelu ma trzynaście.
Co naprawdę jest w embedding table
Link do sekcji: Co naprawdę jest w embedding tableTabela to : po jednym wierszu dziesięciu liczb na znak, wszystkie zainicjalizowane losowo i przesuwane wyłącznie przez gradient loss następnego znaku. Nikt niczego tam nie włożył. Co więc się w niej znalazło?
Narzędziem do pytania o to jest podobieństwo cosinusowe, czyli iloczyn skalarny z rozdziału 1 po podzieleniu przez długości:
Mierzy kąt między dwoma wektorami i ignoruje ich długości, a tego właśnie chcesz, gdy długość wiersza odzwierciedla, jak często pojawiał się jego token, a nie co oznacza. Najpierw znormalizuj każdy wektor do długości 1 — tak jak robią prawdziwe systemy, raz, podczas indeksowania — a podobieństwo cosinusowe jest po prostu iloczynem skalarnym.
Oto najbliżsi sąsiedzi kilku znaków w wytrenowanej tabeli:
'c' -> 'k':+0.598 'j' -> 'z':+0.650 'i' -> 'y':+0.541
'u' -> 'e':+0.482 'a' -> 'h':+0.367 '.' -> 'q':+0.077Część z tego jest tym, co obiecuje folklor. c i k są w imionach wymienne, podobnie i i y; j i z to rzadkie, przeważnie początkowe spółgłoski, które zachowują się podobnie. Symbol graniczny . nie jest blisko niczego — 0,077 do najbliższej litery — bo jest jedynym symbolem oznaczającym pozycję, a nie dźwięk.
A część nie. Najbliższym sąsiadem a jest h, nie kolejna samogłoska. Średnio po wszystkich parach:
mean cosine, vowel to vowel : +0.1889
mean cosine, consonant to consonant : +0.0765
mean cosine, vowel to consonant : -0.0042Samogłoski są bardziej podobne do siebie nawzajem niż do spółgłosek, a efekt jest rzeczywisty, ale mały. W teście przeciw 2000 losowo wybranych grup po pięć liter 58 z tych grup oddziela się co najmniej równie czysto — luka istotna na poziomie około . A więc realna, ale zupełnie niepodobna do wyrazistej geometrycznej wyspy sugerowanej przez popularne opowieści o embeddings.
To uczciwy opis embedding table i warto go zachować na resztę kursu. Nie jest mapą znaczenia. Jest zmianą współrzędnych, wyuczoną zamiast zaprojektowanej, której jedynym zadaniem jest ułatwić pracę następnej warstwie — to samo zdanie, którego rozdział 5 użył dla warstwy ukrytej składającej płaszczyznę, aby rozwiązać XOR. Każda struktura, którą w niej znajdziesz, jest tam dlatego, że obniżyła loss, a struktury, która nie obniża loss, po prostu tam nie ma.
word2vec, GloVe i arytmetyka, którą wszyscy cytują
Link do sekcji: word2vec, GloVe i arytmetyka, którą wszyscy cytująJeśli użyteczną częścią jest tabela, możesz polować bezpośrednio na nią. To jest word2vec: zostaw embedding lookup, wyrzuć model językowy.5
Cel skip-gram with negative sampling to jeden wiersz. Dla prawdziwej pary (centrum, kontekst) wziętej z korpusu podbij ich iloczyn skalarny; dla fałszywych par wylosowanych z rozkładu szumu obniż go:6
To klasyfikacja binarna — „czy te dwa słowa naprawdę wystąpiły razem?” — i jest tania właśnie dlatego, że nigdy nie dotyka pełnego słownika, co w 2013 roku uczyniło praktycznym trening na miliardach słów. GloVe dochodzi do podobnych wektorów z drugiej strony, faktoryzując macierz globalnych zliczeń współwystępowania zamiast strumieniować przykłady.7 Oba są dopasowywane do dokładnie tej statystyki, z której zbudowano tabelę zliczeń. Są zliczaniem, skompresowanym.
Wytrenowane na text8 — 17 005 207 słowach angielskiej Wikipedii, z których 71 290 występuje co najmniej pięć razy, 100 wymiarów, trzy przebiegi — wektory wychodzą z właściwością, która je rozsławiła:
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.870Nikt nie dostarczył kategorii instrumentów ani liczebników. Teraz słynna część: weź king, odejmij man, dodaj woman i znajdź wektor najbliższy wynikowi.
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)Najbliższym wektorem do king - man + woman jest king. To nie kaprys jednego przykładu. Zbiór ewaluacyjny Mikolova stawia pytania postaci a : b :: c : ? — 8869 semantycznych (paris : france :: rome : italy) i 10 675 składniowych (walking : walked :: swimming : swam) — a wśród 4103 pytań semantycznych, na które ten słownik potrafi odpowiedzieć, zwycięzca jest jednym z trzech słów wejściowych w 99,8% przypadków. Opublikowane demonstracje o tym nie wspominają, bo standardowa reguła punktacji usuwa a, b i c przed sprawdzeniem. To prawomocna reguła i wykonuje więcej pracy niż arytmetyka:
| jak wybierana jest odpowiedź | semantyczne | składniowe |
|---|---|---|
| offset, z wykluczonymi wejściami (standard) | 17,0% | 11,9% |
| offset, bez żadnych wykluczeń | 0,1% | 0,4% |
najbliższy sąsiad samego c, wejścia wykluczone | 13,1% | 9,3% |
najbliższy sąsiad samego b, wejścia wykluczone | 2,3% | 0,4% |
Trzeci wiersz jest tym, przy którym warto się zatrzymać. Wyrzuć a i b, nie rób żadnej arytmetyki, zwróć cokolwiek jest najbliżej c — i zachowujesz 77% wyniku semantycznego. Większość tego, co wygląda jak rozumowanie analogiczne, to bliskość plus reguła zakazująca oczywistych odpowiedzi, co Linzen zmierzył na poprawnie wytrenowanych wektorach i co powyższe baseline’y replikują.8 Te konkretne wektory są małe — 17 milionów słów wobec miliardów stojących za opublikowanymi modelami — więc czytaj procenty jako kształt, nie stan techniki. Kształt przetrwa w każdej skali: arytmetyka jest realna i znacznie słabsza niż jedna demonstracja, którą cytują wszyscy.
Statyczne i kontekstowe: jeden wektor na słowo albo jeden na wystąpienie
Link do sekcji: Statyczne i kontekstowe: jeden wektor na słowo albo jeden na wystąpienieWszystko dotąd ma twarde ograniczenie wpisane w strukturę danych. Tabela ma jeden wiersz na token. Słowo bank dostaje jeden wektor, ten sam w zdaniu o rzece i w zdaniu o kredycie hipotecznym — z konieczności, bo lookup po id nie może zależeć od niczego innego.
Naprawa polega na tym, aby przestać czytać wektor z tabeli i zacząć obliczać go ze zdania. To contextual embedding, wprowadzone przez ELMo w 2018 roku i w tym samym roku uczynione standardem przez BERT.910 Zmierzone na prawdziwym modelu, liczby są ostrzejsze niż wyjaśnienie:
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.7335Pierwszy wiersz jest dokładny, nie przybliżony: statyczny wektor dla bank to te same 768 liczb w obu zdaniach, więc cosinus z konstrukcji wynosi 1. Dziewięć warstw później dwa wystąpienia siedzą na 0,43, podczas gdy bank w dwóch różnych zdaniach rzecznych pozostaje na 0,87. Nikt nigdzie w tym procesie nie oznaczał znaczenia; znaczenia rozdzieliły się, bo rozdzielenie ich ułatwia spełnienie celu treningowego — zgadnięcia ukrytego token z sąsiadów.
Dwa szczegóły wynagradzają uwagę. Warstwa 0 ma już 0,9512 zamiast 1,0, bo dodano position embeddings, a słowo siedzi w innym miejscu w każdym zdaniu. I podobieństwo znów rośnie w warstwach 11 i 12: końcowe warstwy modelu pretrained są wyspecjalizowane pod jego cel treningowy i często nie są najlepszym miejscem do pobierania reprezentacji.
Pokaż szczegóły
Opcjonalnie: weight tying.
W bert-base-uncased embedding table to — 23 440 896 liczb, 21,4% z 109 482 240 parametrów modelu. W małym modelu językowym ten udział jest jeszcze większy, dlatego jedna sztuczka jest niemal powszechna: tabela wejściowa i warstwa wyjściowa produkująca logits to ta sama macierz, używana raz przez lookup wiersza i raz po transpozycji.11 Warstwa wyjściowa już przypisuje każdemu elementowi słownika wektor — bierze iloczyn skalarny z każdym z nich — a tying mówi, że wektor używany do czytania token i wektor używany do jego pisania powinny być tym samym obiektem. Jednocześnie tnie parametry i poprawia perplexity, co jest dość rzadkie, by warto było to zauważyć.
Embedding model nie jest modelem językowym
Link do sekcji: Embedding model nie jest modelem językowymAby przeszukiwać korpus po znaczeniu, potrzebujesz jednego wektora na zdanie. Mając je, wyszukiwanie jest trywialne — to całość wyszukiwania semantycznego, a rozdział 19 dotyczy wszystkiego wokół niego:
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]Jedynym prawdziwym pytaniem jest więc, skąd bierze się embed. Oczywistym ruchem jest wziąć pretrained model językowy, przepuścić przez niego każde zdanie i uśrednić wektory tokenów. Oto ta metoda wobec czterech alternatyw, oceniona na dwa sposoby: korelacją rang między cosinusem a ludzkimi ocenami podobieństwa dla 1379 par benchmarku STS oraz top-1 retrieval na indeksie zbudowanym z 200 najmocniej sparafrazowanych z tych par — jedna strona każdej pary w indeksie, druga użyta jako zapytanie.
| jak osadzane jest zdanie | korelacja rang | top-1 na indeksie 200 zdań |
|---|---|---|
| binarne nakładanie się słów (bez żadnego modelu) | 0,5500 | 89,0% |
| średnia statycznych wektorów wytrenowanych wyżej | 0,5263 | 85,5% |
BERT, token [CLS] | 0,2030 | 67,0% |
| BERT, średnia wektorów tokenów | 0,4729 | 84,0% |
| MiniLM, trenowany kontrastywnie | 0,8203 | 92,0% |
Czytaj środkowe trzy wiersze względem pierwszych dwóch. Pretrained transformer z 109 milionami parametrów, użyty w oczywisty sposób, jest gorszy w ocenianiu podobieństwa zdań niż zliczanie, ile słów dwa zdania współdzielą — i gorszy niż uśrednienie 100-wymiarowych wektorów text8 wytrenowanych przed chwilą. Token [CLS], który tutoriale wciąż polecają, bo BERT był pretrained z dołączonym celem na poziomie zdania, jest gorszy niż połowa tego wyniku.
To nie jest defekt BERT. To cel. Model językowy jest trenowany tak, aby jego stany ukryte przewidywały token; nic tam nie prosi, aby dwie parafrazy znalazły się blisko siebie, i nic nie nagradza geometrii, w której cosinus znaczy „to samo znaczenie”. Ostatni wiersz to model pięciokrotnie mniejszy (22 713 216 parametrów), trenowany na zupełnie innym loss: contrastive learning, gdzie przykładami są pary — pytanie i odpowiedź, zdanie i parafraza — a cel przyciąga prawdziwe pary do siebie, jednocześnie odpychając próbkowane negatywy. To wkład Sentence-BERT i źródło całej branży embedding model.12 Dense Passage Retrieval stosuje ten sam przepis bezpośrednio do wyszukiwania, z jednym encoderem dla zapytań i jednym dla fragmentów.13
A więc praktyczna reguła:
Embedding model nie jest modelem językowym z usuniętą ostatnią warstwą. To inny model na innym celu, zwykle znacznie mniejszy, którego cosinus znaczy to, co chcesz, żeby znaczył, ponieważ był trenowany na parach, gdzie to było celem. Powyższa tabela pokazuje koszt podstawienia jednego za drugi.
I ta rodzina zawodzi przy szyku słów. „The dog bit the man” i „the man bit the dog” mają identyczne worki słów, więc nakładanie słów i średnia statycznych wektorów dają im cosinus dokładnie 1,000000, a mean-pooled BERT, który widzi pozycję, wciąż ląduje prawie tam — i kontrastywnie trenowany MiniLM nadal umieszcza je na 0,979. Jeśli twoje zadanie retrieval zależy od tego, kto co komu zrobił, żaden próg cosinusa cię nie uratuje.
Rozdział 19 buduje produkcyjny system retrieval na tym fundamencie i dochodzi do konkretnego progu cosinusa. Ostatni pomiar w tym rozdziale sprawia, że taka liczba jest możliwa do obrony, a nie magiczna.
Klątwa wymiarowości w jednej tabeli
Link do sekcji: Klątwa wymiarowości w jednej tabeliPrawdziwe embeddings mają setki albo tysiące składowych, a odległości zachowują się tam dziwnie. Weź 1000 losowych punktów w kostce jednostkowej o wymiarach i spójrz na stosunek największej do najmniejszej odległości między dowolnymi dwoma z nich:
| wymiary | najbliższa para | najdalsza para | stosunek |
|---|---|---|---|
| 2 | 0,0007 | 1,3612 | 1921,66 |
| 10 | 0,2361 | 2,3397 | 9,91 |
| 100 | 3,0047 | 5,1752 | 1,72 |
| 1000 | 11,7809 | 14,0306 | 1,19 |
| 10 000 | 39,6152 | 42,0125 | 1,06 |
W dziesięciu tysiącach wymiarów najdalsza para punktów jest tylko o 6% dalej od siebie niż najbliższa para. Wszystko jest mniej więcej równoodległe od wszystkiego innego, „najbliższy sąsiad” przestaje nieść wiele informacji, i to jest klątwa wymiarowości — a także jeden z powodów, dla których duże bazy wektorowe nie wykonują dokładnego wyszukiwania najbliższego sąsiada. Druga strona tej samej monety sprawia, że progi cosinusa są użyteczne: mierzone na tysiącu par losowych wektorów jednostkowych, średni cosinus siedzi na w 100 wymiarach i w 768, z odchyleniami standardowymi 0,0968 i 0,0357 — a w 768 wymiarach tylko 0,2% losowych par przekracza 0,1 co do wartości bezwzględnej. Zmierzone podobieństwo 0,4 nie znaczy więc „podobne w 40%”; leży daleko poza tym, co produkuje przypadek, dlatego progi między 0,3 a 0,7 oddzielają sygnał od szumu, zamiast siedzieć pośrodku niego.
Dokąd to prowadzi dalej
Link do sekcji: Dokąd to prowadzi dalejModel w tym rozdziale czyta stałą liczbę poprzednich znaków, wyszukuje każdy z nich i skleja wyniki w kolejności. Ten projekt ma dwa problemy, które są tym samym problemem.
Spójrz jeszcze raz na tabelę kontekstu: przejście z trzech znaków do ośmiu prawie podwoiło liczbę parametrów i kupiło 0,06 nata. Koszt rośnie liniowo z kontekstem — każda dodatkowa pozycja potrzebuje własnej płyty pierwszej macierzy wag — a korzyść nie. Wypchnij to do tysiąca tokenów, a sama pierwsza warstwa przeważa nad resztą modelu, w większości wydana na pozycje, które nie mają znaczenia dla danej predykcji.
I to jest drugi problem: model nie ma sposobu zdecydować, które z poprzednich tokenów mają znaczenie. Pozycja druga dostaje własne wagi, pozycja siódma własne, na stałe, cokolwiek w nich jest. Gdy model literuje nell, decydującym znakiem jest ten bezpośrednio poprzedni. Gdy zdanie zawiera zaimek, słowo ustalające jego odniesienie może być czterdzieści tokenów wcześniej — i żadnego stałego slotu nie da się przypisać do „czterdzieści wcześniej”, bo następnym razem będzie to sześć.
Chcemy modelu, który dla każdej predykcji oblicza, jak bardzo każdy wcześniejszy token powinien się liczyć — wagi nad kontekstem tworzone przez treść, a nie ustalone układem. Zapisz to uważnie, a zaczyna się jako coś całkiem przyziemnego: średnia z poprzednich tokenów. Potem pozwól, aby wagi tej średniej były uczone, i pozwól, aby zależały od token, który zadaje pytanie.
To jest attention i jest tematem rozdziału 9.
Źródła i metoda
Link do sekcji: Źródła i metodaWarto też czytać równolegle: rozdział 3 książki Jurafsky’ego i Martina Speech and Language Processing, który omawia modele n-gramowe, smoothing i perplexity znacznie staranniej, niż jest tu na to miejsce, w tym dlaczego interpolacja i back-off biją dodawanie jedynki; notatki Stanford CS229 §17.1–17.2 o modelowaniu języka od strony probabilistycznej; oraz wspomniany wyżej artykuł Linzena, krótki i wart przeczytania w całości.
Przypisy
Link do sekcji: Przypisy-
Przykład generowania imion, zbiór danych i przejście od tabeli zliczeń do sieci w stylu Bengio podążają za serią Andreja Karpathy’ego building makemore, której pierwsze dwie części są najlepszym uzupełnieniem tego rozdziału. ↩
-
Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), s. 50–64 (1951). Ludzie zgadujący następną literę angielskiego tekstu oraz oryginalny pomiar bitów na znak. ↩
-
Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Twierdzenie o kodowaniu źródłowym oraz utożsamienie predykcji z kompresją. ↩
-
Bengio, Y., Ducharme, R., Vincent, P. and Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, s. 1137–1155 (2003). Architektura użyta wyżej: jeden embedding na słowo, konkatenowany przez stałe okno, przez warstwę ukrytą, do softmax nad słownikiem. ↩
-
Mikolov, T., Chen, K., Corrado, G. and Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW i skip-gram oraz zbiór analogii użyty wyżej. ↩
-
Mikolov, T., Sutskever, I., Chen, K., Corrado, G. and Dean, J. Distributed Representations of Words and Phrases and their Compositionality. arXiv:1310.4546 (2013). Negative sampling, subsampling częstych słów i rozkład szumu podniesiony do potęgi 3/4 użyty wyżej. ↩
-
Pennington, J., Socher, R. and Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Wektory słów z faktoryzacji globalnej macierzy współwystępowania zamiast strumieniowanych lokalnych okien. ↩
-
Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016, arXiv:1606.07736. Źródło baseline’ów bez offsetu zreplikowanych wyżej. ↩
-
Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: jeden wektor na wystąpienie, obliczany przez dwukierunkowy model językowy. ↩
-
Devlin, J., Chang, M.-W., Lee, K. and Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). Model zmierzony w eksperymencie z bank. ↩
-
Press, O. and Wolf, L. Using the Output Embedding to Improve Language Models. arXiv:1608.05859 (2016), oraz Inan, H., Khosravi, K. and Socher, R. Tying Word Vectors and Word Classifiers. arXiv:1611.01462 (2016). Dwa niezależne argumenty za tą samą sztuczką. ↩
-
Reimers, N. and Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). Jego początkowy pomiar — mean-pooled BERT wypadający gorzej niż uśrednione statyczne wektory w podobieństwie zdań — jest tym, co odtwarza powyższa tabela. ↩
-
Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Kontrastywny trening retrievera z dwoma encoderami; bezpośredni przodek stosu retrieval z rozdziału 19. ↩