Siirry sisältöön
8/30Luku 8/30

Next-token-ennustus: embedding ja mitä perpleksisyys tarkoittaa

Opeta merkkimalli 32 033 nimellä ja katso, kuinka gradient descent löytää laskentataulukon uudelleen — ja miksi perpleksisyydet eivät täsmää.

Tällä sivulla

Tässä on kymmenen nimeä ohjelmalta, joka ei ole koskaan nähnyt sanaa:

TEXT
cexze   momakurailezitynn   konimittain   llayn   ka
da      moliellavo          emia          sade    ftlsp

Yksikään niistä ei ole nimi. Lähes kaikki niistä yrittävät olla. Ne ovat lausuttavissa, ne päättyvät sinne missä nimet päättyvät, ja yksi niistä — emia — on yhden kirjaimen päässä oikeasta nimestä. Ohjelmassa, joka ne tuotti, on 729 lukua, sillä ei ole käsitystä sanasta, tavusta tai ihmisestä, ja se sovitettiin yhdellä vierekkäisten kirjainparien laskentakierroksella.

Tämän luvun loppuun mennessä neuroverkko on leikannut saman ohjelman pistemäärästä kolmanneksen samalla mittarilla. Se osa, jonka vuoksi kannattaa jatkaa, on se mitä verkko tekee ensin: se toistaa laskentataulukon kolmen desimaalin tarkkuudella jokaisella hyvin edustetulla rivillä, pyytämättä, koska nämä kaksi objektia ovat vastauksia samaan kysymykseen. Kaikki sen jälkeen on sitä, mihin laskeminen ei olisi koskaan pystynyt.

Tavoite on identiteetti, ei suunnitteluvalinta

Linkki osioon: Tavoite on identiteetti, ei suunnitteluvalinta

Luku 7 jätti sinulle kokonaislukujen jonon eikä mitään syytä sille, miksi yhden pitäisi seurata toista. Tässä on syy, ja se on yksi rivi luvusta 2.

Kielimalli on funktio, joka ottaa tähänastiset tokenit ja palauttaa jakauman siitä, mikä token tulee seuraavaksi: yksi luku jokaista sanaston alkiota kohti, ei-negatiivinen, summaltaan yksi. Ei muuta. Jotta tästä saadaan todennäköisyys kokonaiselle dokumentille, sovelletaan todennäköisyyden ketjusääntöä:

P(x1,x2,,xT)=t=1TP(xtx1,,xt1)P(x_1, x_2, \ldots, x_T) = \prod_{t=1}^{T} P(x_t \mid x_1, \ldots, x_{t-1})

Se on identiteetti, tosi mille tahansa mistä tahansa koostuvalle jonolle, ilman lisäoletuksia. Malli, joka tekee pienen työn — seuraava token edellisten perusteella — on siis jo tehnyt suuren työn: se antaa todennäköisyyden jokaiselle mahdolliselle dokumentille, täsmällisesti ja ilmaiseksi. Suosittu kehystys halpana temppuna (”se vain ennustaa seuraavan sanan”) kääntää logiikan väärinpäin: seuraavan tokenin ennustaminen on yhteisjakauman mallintamista. Mitään toista tehtävää ei koskaan ollut.

Loss seuraa yhtä mekaanisesti. Jokaisessa kohdassa malli tuottaa jakauman qq ja totuus on yksi tunnettu token, joten luvun 4 ristientropia pätee muuttumattomana:

L=1Tt=1Tlogqθ(xtx<t)L = -\frac{1}{T}\sum_{t=1}^{T} \log q_\theta(x_t \mid x_{<t})

Se on keskimääräinen negatiivinen log-likelihood — luvun 2 resepti, jossa Gaussin jakauman paikalla on kategorinen jakauma. Ja koska todellinen jakauma on one-hot, sen entropia on nolla, joten luvun 4 identiteetin mukaan ristientropia on yhtä suuri kuin KL-divergenssi: tämän luvun pienentäminen ja mallin uskomusten vetäminen kohti dataa ovat sama teko.

Yksi seuraus ansaitsee oman virkkeensä, koska se on koko alan alla oleva taloudellinen tosiasia. Tunnisteet ovat data, yhden kohdan verran siirrettynä. Kukaan ei annotoi mitään. Biljoona tekstin tokenia on biljoona valmiiksi tunnistettua esimerkkiä, minkä vuoksi modernin mallin koulutuskorpus on ”internet” eikä ”jonkun rakentama datasetti”.

Rehellinen lähtötaso: laskeminen

Linkki osioon: Rehellinen lähtötaso: laskeminen

Ennen mitään verkkoa lähtötaso: 32 033 nimeä, yksi per rivi, ja tehtävä tuottaa niitä lisää kirjain kerrallaan.1

Sanasto on 26 kirjainta plus rajamerkki ., joka merkitsee sekä nimen alkua että loppua, joten mallin täytyy oppia, mistä nimet alkavat ja mihin ne pysähtyvät. Siinä on 27 symbolia, ja pienin mahdollinen malli on taulukko siitä, kuinka usein kukin symboli seurasi kutakin toista symbolia.

bigram.pyPYTHON
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   

Kaksi riviä aritmetiikkaa ja malli on sovitettu — eikä se ole heuristiikka: lukumäärien jakaminen rivisummilla on suurimman uskottavuuden estimaatti kategoriselle jakaumalle, eli luvun 2 resepti laskettuna valmiiksi.

TEXT
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.0606

Ota siitä näytteitä — valitse kirjain nykyisen kirjaimen riviltä, siirry sille riville, toista kunnes rajamerkki tulee vastaan — ja saat tämän luvun alussa olevat nimet. Ne epäonnistuvat täsmällisellä ja opettavaisella tavalla: paikallisesti uskottavia, kokonaisuutena järjettömiä. Jokainen vierekkäinen kirjainpari sanassa momakurailezitynn on pari, joka esiintyy oikeissa nimissä; niitä vain on seitsemäntoista peräkkäin. Mallilla on yhden kirjaimen muisti, joten se ei voi tietää jatkuneensa liian pitkään.

Perpleksisyys ja miten sitä luetaan

Linkki osioon: Perpleksisyys ja miten sitä luetaan

Loss erillisillä validointinimillä on 2,4546 natia. Se luku ei yksinään tarkoita mitään, ja siksi perpleksisyys on olemassa:

PPL=exp ⁣(1Ttlogq(xtx<t))=eL\mathrm{PPL} = \exp\!\left(-\frac{1}{T}\sum_t \log q(x_t \mid x_{<t})\right) = e^{L}

Kirjoitettuna auki, ilman että kirjasto tekee työn:

perplexity.pyPYTHON
@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())             

Eksponentointi kumoaa logaritmin ja palauttaa luvun asioiden laskemisen yksiköihin. Siistein tapa nähdä mitä se laskee on mitata mallia, joka ei tiedä yhtään mitään — sellaista, joka antaa todennäköisyyden 1/271/27 jokaiselle symbolille kontekstista riippumatta:

TEXT
uniform over 27 symbols            loss 3.2958 nats   ppl  27.000
bigram counts, add-one smoothed    loss 2.4546 nats   ppl  11.642

Täsmälleen 27,000, koska elog27=27e^{\log 27} = 27. Perpleksisyys on yhtä todennäköisten vaihtoehtojen efektiivinen määrä, joiden väliltä malli valitsee. Perpleksisyys 27 tarkoittaa ”ei aavistustakaan, voi olla mitä tahansa”. Laskentamallin 11,642 tarkoittaa, että yhden kirjaimen konteksti jättää sen yhtä epävarmaksi kuin jonkun, joka valitsee sokkona noin kahdestatoista vaihtoehdosta kahdenkymmenenseitsemän sijaan — siksi perpleksisyys mainitaan ja raakaa loss-lukua ei.

Kaksi asiaa menee siinä pieleen, ja toinen niistä menee pieleen julkaistuissa artikkeleissa.

Nollatodennäköisyydet ovat kohtalokkaita. Taulukon 729 solusta 113 ei koskaan esiinny koulutuksessa — 15,5 % siitä on tyhjää. Se on kunnossa, kunnes validointijoukko osuu yhteen niistä, ja seitsemän bigramia validoinnissa osuu, niiden joukossa dq, zj ja qo kahdesti. Todennäköisyys nolla tarkoittaa log -\infty, mikä tarkoittaa ääretöntä lossia ja ääretöntä perpleksisyyttä: yksi nimi kolmesta tuhannesta tuhoaa mittarin. Tavallinen paikkaus on lisätä 1 jokaiseen lukumäärään ennen normalisointia, mikä maksaa täällä lähes ei mitään (2,4546 eikä 2,4524). Mutta paikkaus on tunnustus. Laskentamalli ei pysty yleistämään lainkaan. Sillä ei ole keinoa epäillä, että qo on uskottava, koska qu on yleinen ja o käyttäytyy muualla kuten u, sillä sillä ei ole käsitystä siitä, että kaksi symbolia voivat muistuttaa toisiaan. Jokainen solu opitaan yksin, ja sen korjaamista varten tämän luvun loppu on olemassa.

Perpleksisyys on hinta per token, ja token on vapaa parametri. Tämä on virhe, joka näkyy jatkuvasti malleja verrattaessa, ja sen huomaa helposti kun katsoo. Ota sama englanninkielisen proosan korpus luvusta 7, sama interpoloitu bigram-malli, ja muuta vain sitä, miten teksti pilkotaan:

yksikkösanastotokenit testissäristientropiaperpleksisyysbittiä per merkki
merkit7614 4692,521712,453,6378
BPE, 512 mergeä3296 8713,854747,212,6407
BPE, 2 048 mergeä1 8204 2335,7468313,202,4254
sanat2 9916 2843,562735,262,2322

Perpleksisyys vaihtelee näillä riveillä kertoimella 25. Mikään mallissa ei muuttunut; vain ennustettavan asian koko muuttui. Kokonaisen sanan ennustaminen on vaikeampaa kuin kirjaimen ennustaminen, joten se maksaa enemmän per ennuste — ja ennusteita on vähemmän tehtävänä.

Lue nyt viimeinen sarake, joka jakaa kokonaiskustannuksen sen sijaan merkkien määrällä ja muuntaa sen biteiksi. Se järjestää taulukon uudelleen. Perpleksisyyden mukaan järjestys on merkit, sanat, BPE-512, BPE-2048; bitteinä per merkki se on sanat, BPE-2048, BPE-512, merkit. Merkkimalli putoaa ensimmäiseltä sijalta viimeiseksi. 2 048 mergen malli, joka näyttää perpleksisyyden perusteella 6,6 kertaa huonommalta kuin 512 mergen malli, on itse asiassa parempi näistä kahdesta: 2,4254 bittiä vastaan 2,6407.

Perpleksisyys on siis vertailukelpoinen vain kahden sellaisen mallin välillä, joilla on sama tokenizer, ja eri tokenizereilla varustettuja malleja voidaan vertailla vain bitteinä per merkki — suureena, jonka Shannon mittasi vuonna 1951 pyytämällä ihmiskoehenkilöitä arvaamaan englanninkielisen tekstin seuraavan kirjaimen, ja jonka hän rajasi noin yhteen bittiin per merkki.2 Paras bigramimme on 2,23 bitissä, mikä on reilu yhteenveto siitä, kuinka paljon tällä luvulla on vielä kuljettavaa.

Rakennetaan nyt sama malli verkkona. Se tarvitsee kertaluokkia enemmän aritmetiikkaa päätyäkseen samaan paikkaan, ja samaan paikkaan päätyminen on koko pointti.

Korvaa taulukko yhdellä painomatriisilla WW, jonka muoto on 27×2727 \times 27. Muunna nykyinen kirjain one-hot-vektoriksi, kerro, ja kutsu tulosta logits — luvun 4 normalisoimattomiksi pisteiksi. Sitten softmax, sitten ristientropia, sitten gradient descent.

neural_bigram.pyPYTHON
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.grad

Korostettu rivi sisältää määritelmän, joka kannattaa pitää. One-hot-vektorin kertominen matriisilla valitsee siitä yhden rivin, joten kertolasku on haku — ja jokainen toteutus ohittaa aritmetiikan ja tekee haun suoraan, mitä W[xs] on.

Se on embedding table. Matriisi, jossa on yksi rivi per sanaston alkio, indeksoituna token id:llä. Ei geometriaa, ei semantiikkaa, ei erillistä algoritmia: hakutaulukko, jonka sisältö vain sattuu opittavaksi gradient descentin avulla kaiken muun mukana. Jokainen mystinen väite ”embedding-avaruudesta” päätyy lopulta tähän.

Kouluta se ja katso, minne se menee:

TEXT
  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.004048

Viimeinen sarake on suurin itseisarvoinen ero minkä tahansa softmax(W)-solun ja laskentataulukon vastaavan solun välillä, ja se menee nollaan. 3 000 askeleen jälkeen suurin erimielisyys missään 729 solusta on 0,004048 ja keskiarvo 0,000224. Huonoin solu on qi, joka nähtiin koko koulutusjoukossa kaksitoista kertaa; niiden 22 rivin joukossa, joilla on yli tuhat esiintymää, huonoin erimielisyys on 0,000562.

TEXT
                 count table   network
    a -> '.'        0.1945     0.1945
    a -> 'n'        0.1601     0.1601
    a -> 'r'        0.0967     0.0967

Gradient descent, joka aloitti satunnaisluvuista eikä saanut muuta ohjetta kuin ”tee seuraavan kirjaimen log-todennäköisyydestä suuri”, löysi laskentataulukon uudelleen. Ja sen oli pakko: lukumäärät ovat suurimman uskottavuuden estimaatti, ristientropia on negatiivinen log-likelihood, joten molemmat menettelyt optimoivat samaa tavoitetta ja sillä tavoitteella on yksi optimum. Verkko ei oppinut jotain laskemisen kaltaista. Se konvergoitui laskemiseen, hitaasti.

Mikä herättää reilun kysymyksen siitä, miksi kukaan vaivautuisi. Koska laskentataulukolla ei ole tästä eteenpäin mitään minne mennä, ja verkolla on.

Context window on pullonkaula, ei kapasiteetti

Linkki osioon: Context window on pullonkaula, ei kapasiteetti

Laajenna malli katsomaan useampaa kuin yhtä edellistä merkkiä. Tämä on Bengion vuoden 2003 arkkitehtuuri, kaikkien tämän kurssin loppuosan mallien suora esi-isä:4 ota kolme viimeistä merkkiä, kuvaa kukin embedding tableen 10-ulotteiseksi riviksi, ketjuta rivit 30 luvuksi, työnnä ne luvun 5 hidden layerin läpi ja päätä output layeriin, joka tuottaa yhden logitin per sanaston alkio.

mlp.pyPYTHON
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)

Huomaa, mikä on uutta ja mikä ei. Hidden layer on luvun 5 kerros, muuttumaton; loss on luvun 4 loss, muuttumaton. Uutta ovat embedding table edessä ja output layer, joka on yhtä leveä kuin luvun 7 sanasto — ja juuri tämä toinen on jokaisen koskaan rakennetun kielimallin kallis osa, koska oikeassa sanastossa on 100 000 alkiota ja tämä matriisikertolasku ajetaan jokaisessa kohdassa.

Sama koodi, koulutettuna identtisesti, vain context windowin kokoa muuttaen:

contextparametritvalidoinnin lossvalidoinnin perpleksisyys
laskeminen, 1 merkki7292,454611,642
neuroverkko, 1 merkki7 8972,457711,678
neuroverkko, 3 merkkiä11 8972,11458,285
neuroverkko, 8 merkkiä21 8972,05067,773

Toinen rivi on kiinnostava. Verkko, jossa on 200 yksikön hidden layer ja yksitoista kertaa enemmän parametreja kuin laskentataulukossa, suoriutuu täsmälleen yhtä hyvin kuin laskentataulukko eikä paremmin. Kapasiteetti ei koskaan ollut rajoite. Yhden merkin context sallii tietyn lossin, eikä mikään siihen pultattu voi mennä sen alle, koska informaatio ei ole siellä.

Anna sille kolme merkkiä ja perpleksisyys putoaa 11,68:sta 8,29:ään — 29 %:n leikkaus, ostettuna 4 000 lisäparametrilla. Se päihittää laskemisen tässä juuri aiemmin diagnosoidusta syystä: kolmen merkin konteksteihin perustuva laskentamalli tarvitsee 273=19,68327^3 = 19{,}683 riviä, joista useimmat ovat tyhjiä tai sisältävät yhden havainnon, ja se oppii jokaisen yksin. Verkko jakaa. Jos a, e ja i päätyvät samankaltaisiin embedding-riveihin, se mitä se oppii kohdan bra jälkeen siirtyy kohtaan bre ilman että se olisi koskaan nähnyt bre. Tämä siirto on embedding tablen koko arvo, ja se on rivien kaksi ja kolme välinen ero.

Näytteet paranevat vastaavasti:

TEXT
deliah   nellara   joce     kael      quintis
salayson  reety    khyrmin  mahnen    madiaryxia

Ei vieläkään lista oikeita nimiä. Mutta deliah, nellara ja kael eivät näyttäisi sellaisella listalla vääriltä, ja venyvät hirviöt ovat poissa: laskentamallin kahdestakymmenestä näytteestä pisin on yhdeksäntoista kirjainta, tämän mallin kahdestakymmenestä pisin on kolmetoista.

Mitä embedding tablen sisällä oikeasti on

Linkki osioon: Mitä embedding tablen sisällä oikeasti on

Taulukko on 27×1027 \times 10: yksi kymmenen luvun rivi per merkki, kaikki alustettu satunnaisesti ja liikutettu vain seuraavan merkin lossin gradientilla. Kukaan ei laittanut sinne mitään. Mitä sinne siis päätyi?

Kysymisen työkalu on kosinisamankaltaisuus, joka on luvun 1 pistetulo, josta pituudet on jaettu pois:

cos(a,b)=abab\cos(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a} \cdot \mathbf{b}}{\lVert \mathbf{a} \rVert \, \lVert \mathbf{b} \rVert}

Se mittaa kahden vektorin välistä kulmaa ja sivuuttaa niiden pituudet, mitä haluat silloin kun rivin pituus heijastaa sitä, kuinka usein sen token esiintyi, eikä sitä mitä se tarkoittaa. Normalisoi jokainen vektori ensin pituuteen 1 — kuten oikeat järjestelmät tekevät kerran indeksointiaikana — ja kosinisamankaltaisuus on yksinkertaisesti pistetulo.

Tässä ovat muutaman merkin lähimmät naapurit koulutetussa taulukossa:

TEXT
  'c' -> 'k':+0.598      'j' -> 'z':+0.650      'i' -> 'y':+0.541
  'u' -> 'e':+0.482      'a' -> 'h':+0.367      '.' -> 'q':+0.077

Osa siitä on sitä, mitä kansanperinne lupaa. c ja k ovat nimissä keskenään vaihdettavissa, samoin i ja y; j ja z ovat molemmat harvinaisia, enimmäkseen alussa esiintyviä konsonantteja, jotka käyttäytyvät samalla tavalla. Rajamerkki . ei ole lähellä oikein mitään — 0,077 lähimpään kirjaimeensa — koska se on ainoa symboli, joka merkitsee sijaintia eikä ääntä.

Ja osa siitä ei ole. a:n lähin naapuri on h, ei toinen vokaali. Keskimäärin kaikkien parien yli:

TEXT
mean cosine, vowel to vowel         : +0.1889
mean cosine, consonant to consonant : +0.0765
mean cosine, vowel to consonant     : -0.0042

Vokaalit muistuttavat toisiaan enemmän kuin konsonantteja, ja ilmiö on todellinen mutta pieni. Kun sitä testataan 2 000 satunnaisesti valittua viiden kirjaimen ryhmää vastaan, 58 näistä ryhmistä erottuu vähintään yhtä siististi — ero on merkitsevä noin tasolla p=0.03p = 0.03. Todellinen siis, mutta ei lainkaan sellainen terävä geometrinen saareke, jota popularisoidut kertomukset embeddingeistä antavat ymmärtää.

Tämä on rehellinen kuvaus embedding tablesta, ja siitä kannattaa pitää kiinni kurssin loppuun asti. Se ei ole merkityksen kartta. Se on koordinaattien vaihto, opittu eikä suunniteltu, jonka ainoa tehtävä on tehdä seuraavan kerroksen työ helpoksi — sama lause, jota luku 5 käytti hidden layerista, joka taittoi tason ratkaistakseen XOR:n. Kaikki rakenne, jonka siitä löydät, on siellä koska se laski lossia, ja rakenne, joka ei laske lossia, ei yksinkertaisesti ole siellä.

word2vec, GloVe ja kaikkien siteeraama aritmetiikka

Linkki osioon: word2vec, GloVe ja kaikkien siteeraama aritmetiikka

Jos hyödyllinen osa on taulukko, voit tavoitella sitä suoraan. Se on word2vec: pidä embedding-haku, heitä kielimalli pois.5

Skip-gram with negative sampling -tavoite on yksi rivi. Oikealle (keskus, konteksti) -parille, joka on poimittu korpuksesta, työnnä niiden pistetuloa ylös; kk:lle kohinajakaumasta poimitulle valheparille työnnä sitä alas:6

logσ(vcvo)+i=1klogσ(vcvni)\log \sigma(\mathbf{v}_c \cdot \mathbf{v}_o) + \sum_{i=1}^{k} \log \sigma(-\mathbf{v}_c \cdot \mathbf{v}_{n_i})

Se on binääriluokittelua — ”esiintyivätkö nämä kaksi sanaa oikeasti yhdessä?” — ja se on halpaa juuri siksi, ettei se koskaan koske koko sanastoon, mikä teki miljardien sanojen kouluttamisesta käytännöllistä vuonna 2013. GloVe päätyy samankaltaisiin vektoreihin toisesta suunnasta, faktoroimalla globaalien yhteisesiintymälaskurien matriisin sen sijaan että se virtaisi esimerkkien läpi.7 Molemmat sovitetaan täsmälleen siihen statistiikkaan, josta laskentataulukko rakennettiin. Ne ovat laskemista, pakattuna.

Kun vektorit koulutetaan aineistolla text8 — 17 005 207 englanninkielisen Wikipedian sanaa, joista 71 290 esiintyy vähintään viisi kertaa, 100 ulottuvuutta, kolme kierrosta — niihin ilmestyy ominaisuus, joka teki niistä kuuluisia:

TEXT
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.870

Kukaan ei antanut kategoriaa soittimille tai lukusanoille. Nyt kuuluisa osa: ota king, vähennä man, lisää woman ja etsi tulosta lähin vektori.

TEXT
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)

Lähin vektori kohteelle king - man + woman on king. Se ei ole yhden esimerkin oikku. Mikolovin arviointijoukko esittää kysymyksiä muodossa a : b :: c : ? — 8 869 semanttista (paris : france :: rome : italy) ja 10 675 syntaktista (walking : walked :: swimming : swam) — ja niiden 4 103 semanttisen kysymyksen joukossa, joihin tämä sanasto pystyy vastaamaan, voittaja on yksi kolmesta syötesanasta 99,8 % ajasta. Julkaistut demonstraatiot eivät mainitse tätä, koska vakiopisteytyssääntö poistaa a, b ja c ennen katsomista. Se on legitiimi sääntö, ja se tekee enemmän työtä kuin aritmetiikka:

miten vastaus valitaansemanttinensyntaktinen
offset, syötteet poissuljettuina (vakio)17,0 %11,9 %
offset, mitään poissulkematta0,1 %0,4 %
pelkän c lähin naapuri, syötteet poissuljettuina13,1 %9,3 %
pelkän b lähin naapuri, syötteet poissuljettuina2,3 %0,4 %

Kolmas rivi on se, jonka äärelle kannattaa pysähtyä. Heitä pois a ja b, älä tee lainkaan aritmetiikkaa, palauta mikä tahansa on lähimpänä kohdetta c — ja säilytät 77 % semanttisesta pistemäärästä. Suurin osa siitä, mikä näyttää analogiselta päättelyltä, on läheisyyttä plus sääntö, joka kieltää ilmeiset vastaukset; juuri tätä Linzen mittasi kunnolla koulutetuilla vektoreilla ja mitä yllä olevat baseline-arvot toistavat.8 Nämä nimenomaiset vektorit ovat pieniä — 17 miljoonaa sanaa verrattuna julkaistujen mallien takana oleviin miljardeihin — joten lue prosentit muotona, älä alan huipputasona. Muoto säilyy jokaisessa mittakaavassa: aritmetiikka on todellista, ja paljon heikompaa kuin se yksi demonstraatio, jota kaikki siteeraavat.

Staattinen ja kontekstuaalinen: yksi vektori per sana tai yksi per esiintymä

Linkki osioon: Staattinen ja kontekstuaalinen: yksi vektori per sana tai yksi per esiintymä

Kaikessa tähän asti on datarakenteeseen sisäänrakennettu kova raja. Taulukossa on yksi rivi per token. Sana bank saa yhden vektorin, saman lauseessa joesta ja lauseessa asuntolainasta — väistämättä, koska haku id:n perusteella ei voi riippua mistään muusta.

Korjaus on lakata lukemasta vektoria taulukosta ja alkaa laskea sitä lauseesta. Se on kontekstuaalinen embedding, jonka ELMo esitteli vuonna 2018 ja jonka BERT teki standardiksi samana vuonna.910 Oikealla mallilla mitattuna luvut ovat terävämpiä kuin selitys:

TEXT
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.7335

Ensimmäinen rivi on tarkka, ei likimääräinen: sanan bank staattinen vektori on samat 768 lukua molemmissa lauseissa, joten kosini on rakenteen vuoksi 1. Yhdeksän kerrosta myöhemmin kaksi esiintymää ovat tasolla 0,43, kun taas bank kahdessa eri jokilauseessa pysyy tasolla 0,87. Kukaan ei merkinnyt merkityksiä missään vaiheessa; merkitykset erkanivat, koska niiden erottaminen helpottaa koulutustavoitteen — piilotetun tokenin arvaamista sen naapureista — täyttämistä.

Kaksi yksityiskohtaa maksaa huomion takaisin. Kerros 0 on jo 0,9512 eikä 1,0, koska position embeddings on lisätty ja sana sijaitsee eri kohdassa kummassakin lauseessa. Ja samankaltaisuus nousee taas kerroksissa 11 ja 12: esikoulutetun mallin viimeiset kerrokset ovat erikoistuneet sen koulutustavoitteeseen, eivätkä ne usein ole paras paikka ottaa representaatiota.

Näytä lisätiedot

Valinnainen: weight tying.

Kohdassa bert-base-uncased embedding table on 30,522×76830{,}522 \times 768 — 23 440 896 lukua, 21,4 % mallin 109 482 240 parametrista. Pienessä kielimallissa osuus on vielä suurempi, minkä vuoksi yksi temppu on lähes universaali: syötteen taulukko ja logits tuottava output layer ovat sama matriisi, jota käytetään kerran rivihakuna ja kerran transponoituna.11 Output layer antaa jo jokaiselle sanaston alkiolle vektorin — se ottaa pistetulon jokaista vastaan — ja tying sanoo, että tokenin lukemiseen käytetyn vektorin ja sen kirjoittamiseen käytetyn vektorin pitäisi olla sama objekti. Se leikkaa parametreja ja parantaa perpleksisyyttä samalla kertaa, mikä on tarpeeksi harvinaista huomattavaksi.

Embedding model ei ole kielimalli

Linkki osioon: Embedding model ei ole kielimalli

Jotta korpuksesta voi hakea merkityksen perusteella, tarvitset yhden vektorin per lause. Kun ne ovat olemassa, haku on triviaalia — tämä on koko semanttinen retrieval, ja luku 19 käsittelee kaikkea sen ympärillä:

search.pyPYTHON
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]

Ainoa todellinen kysymys on siis, mistä embed tulee. Ilmeinen liike on ottaa esikoulutettu kielimalli, ajaa jokainen lause sen läpi ja keskiarvoistaa token-vektorit. Tässä on tuo menetelmä neljää vaihtoehtoa vastaan kahdella tavalla pisteytettynä: järjestyskorrelaatio kosinin ja ihmisten samankaltaisuusarvioiden välillä STS-benchmarkin 1 379 parilla, sekä top-1 retrieval indeksillä, joka on rakennettu näiden parien 200 vahvimmin parafrasoidusta parista — jokaisen parin toinen puoli indeksoidaan, toista käytetään kyselynä.

miten lause upotetaanjärjestyskorrelaatiotop-1 200 lauseen indeksissä
binäärinen sanojen päällekkäisyys (ei mallia lainkaan)0,550089,0 %
yllä koulutettujen staattisten vektorien keskiarvo0,526385,5 %
BERT, [CLS] token0,203067,0 %
BERT, token-vektorien keskiarvo0,472984,0 %
MiniLM, kontrastiivisesti koulutettu0,820392,0 %

Lue keskimmäiset kolme riviä kahta ensimmäistä vasten. 109 miljoonan parametrin esikoulutettu transformer, käytettynä ilmeisellä tavalla, on huonompi arvioimaan lauseiden samankaltaisuutta kuin se, että lasketaan montako sanaa kahdella lauseella on yhteistä — ja huonompi kuin hetki sitten koulutettujen 100-ulotteisten text8-vektorien keskiarvo. [CLS] token, jota tutoriaalit yhä suosittelevat, koska BERT esikoulutettiin siihen liitetyllä lausetason tavoitteella, on huonompi kuin puolet siitä.

Tämä ei ole BERTin vika. Se on tavoitteen seuraus. Kielimalli koulutetaan niin, että sen hidden statet ennustavat tokenin; mikään siinä ei pyydä kahta parafraasia päätymään lähelle toisiaan, eikä mikään palkitse geometriaa, jossa kosini tarkoittaa ”samaa merkitystä”. Viimeinen rivi on malli, joka on viidesosan kokoinen (22 713 216 parametria) ja koulutettu kokonaan eri lossilla: contrastive learning, jossa esimerkit ovat pareja — kysymys ja sen vastaus, lause ja sen parafraasi — ja tavoite vetää oikeat parit yhteen samalla kun se työntää poimitut negatiivit erilleen. Se on Sentence-BERTin panos ja koko embedding model -teollisuuden alkuperä.12 Dense Passage Retrieval soveltaa samaa reseptiä suoraan hakuun, yhdellä encoderilla kyselyille ja yhdellä passageille.13

Käytännön sääntö siis:

Embedding model ei ole kielimalli, josta viimeinen kerros on poistettu. Se on eri malli eri tavoitteella, yleensä paljon pienempi, ja sen kosini tarkoittaa sitä mitä haluat sen tarkoittavan, koska se koulutettiin pareilla, joissa juuri se oli kohde. Yllä oleva taulukko on hinta siitä, että korvaa toisen toisella.

Ja perhe epäonnistuu sanajärjestyksessä. ”The dog bit the man” ja ”the man bit the dog” sisältävät identtiset sanapussit, joten sanojen päällekkäisyys ja staattisten vektorien keskiarvo antavat niille kosiniksi täsmälleen 1,000000, ja mean-pooled BERT, joka kyllä näkee sijainnin, päätyy silti melkein samaan — ja kontrastiivisesti koulutettu MiniLM antaa niille yhä 0,979. Jos retrieval-tehtäväsi ratkaisee se, kuka teki mitä kenelle, mikään kosiniraja ei pelasta sinua.

Luku 19 rakentaa tuotantotason retrieval-järjestelmän tälle perustalle ja päätyy konkreettiseen kosinirajaan. Tämän luvun viimeinen mittaus on se, joka tekee sellaisesta luvusta puolustettavan eikä taikuutta.

Ulottuvuuksien kirous yhdessä taulukossa

Linkki osioon: Ulottuvuuksien kirous yhdessä taulukossa

Oikeissa embeddingeissä on satoja tai tuhansia komponentteja, ja etäisyydet käyttäytyvät siellä oudosti. Ota 1 000 satunnaista pistettä yksikkökuutiosta dd ulottuvuudessa ja katso suurimman ja pienimmän minkä tahansa kahden pisteen välisen etäisyyden suhdetta:

ulottuvuudetlähin parikaukaisin parisuhde
20,00071,36121921,66
100,23612,33979,91
1003,00475,17521,72
1 00011,780914,03061,19
10 00039,615242,01251,06

Kymmenessä tuhannessa ulottuvuudessa kaukaisin pistepari on vain 6 % kauempana toisistaan kuin lähin pari. Kaikki on suunnilleen yhtä kaukana kaikesta muusta, ”lähin naapuri” lakkaa kantamasta paljon informaatiota, ja se on ulottuvuuksien kirous — sekä yksi syy siihen, etteivät suuret vektoritietokannat tee tarkkaa lähimmän naapurin hakua. Saman kolikon toinen puoli tekee kosinirajoista toimivia: tuhannella satunnaisten yksikkövektorien parilla mitattuna keskimääräinen kosini on 0.0052-0.0052 100 ulottuvuudessa ja +0.0003+0.0003 768:ssa, keskihajonnoilla 0,0968 ja 0,0357 — ja 768 ulottuvuudessa vain 0,2 % satunnaisista pareista ylittää itseisarvoltaan 0,1. Mitattu samankaltaisuus 0,4 ei siis ole ”40 % samanlainen”; se on kaukana kaiken sattuman tuottaman ulkopuolella, minkä vuoksi rajat 0,3:n ja 0,7:n välillä erottavat signaalin kohinasta eivätkä istu sen keskellä.

Tämän luvun malli lukee kiinteän määrän edellisiä merkkejä, hakee jokaisen taulukosta ja liimaa tulokset järjestyksessä yhteen. Tällä rakenteella on kaksi ongelmaa, ja ne ovat sama ongelma.

Katso context-taulukkoa uudelleen: siirtyminen kolmesta merkistä kahdeksaan lähes kaksinkertaisti parametrit ja osti 0,06 natia. Kustannus kasvaa lineaarisesti contextin mukana — jokainen lisäpaikka tarvitsee oman lohkonsa ensimmäisestä painomatriisista — eikä hyöty kasva. Työnnä se tuhanteen tokeniin ja pelkkä ensimmäinen kerros painaa enemmän kuin muu malli, suurin osa siitä käytettynä sijainteihin, joilla ei ole merkitystä millekään annetulle ennusteelle.

Mikä on toinen ongelma: mallilla ei ole mitään tapaa päättää, mitkä aiemmista tokeneista merkitsevät. Paikka kaksi saa omat painonsa ja paikka seitsemän omansa, pysyvästi, mitä niissä sitten onkin. Kun malli tavailee nell, ratkaiseva merkki on välittömästi edeltävä. Kun lause sisältää pronominin, sen viittauskohteen ratkaiseva sana voi olla neljäkymmentä tokenia takana — eikä mitään kiinteää lokeroa voi nimetä ”neljäkymmentä taaksepäin”, koska seuraavalla kerralla se on kuusi.

Haluamme mallin, joka laskee jokaiselle ennusteelle, kuinka paljon kunkin aiemman tokenin pitäisi merkitä — painot contextin yli, jotka syntyvät sisällöstä eivätkä ole asettelun määräämiä. Kirjoita se tarkasti ylös ja se alkaa täysin arkisena asiana: keskiarvona aiemmista tokeneista. Anna sitten tuon keskiarvon painojen olla opittuja, ja anna niiden riippua siitä, mikä token kysyy.

Se on attention, ja se on luku 9.


Kannattaa lukea rinnalla myös Jurafskyn ja Martinin Speech and Language Processing -teoksen luku 3, joka käsittelee n-gram-malleja, smoothingia ja perpleksisyyttä paljon huolellisemmin kuin tässä on tilaa, mukaan lukien miksi interpolointi ja back-off voittavat ykkösen lisäämisen; Stanfordin CS229-muistiinpanojen §17.1–17.2 kielimallinnuksesta probabilistiselta puolelta; sekä yllä mainittu Linzenin artikkeli, joka on lyhyt ja lukemisen arvoinen kokonaan.

  1. Nimigenerointiesimerkki, datasetti ja eteneminen laskentataulukosta Bengio-tyyliseen verkkoon seuraavat Andrej Karpathyn building makemore -sarjaa, jonka kaksi ensimmäistä osaa ovat tämän luvun paras kumppani.

  2. Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), s. 50–64 (1951). Ihmiskoehenkilöt arvaamassa englannin tekstin seuraavaa kirjainta sekä alkuperäinen bits-per-character-mittaus.

  3. Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Lähdekoodausteoreema sekä ennustamisen ja pakkaamisen samaistaminen.

  4. Bengio, Y., Ducharme, R., Vincent, P. ja Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, s. 1137–1155 (2003). Yllä käytetty arkkitehtuuri: embedding per sana, ketjutettuna kiinteän ikkunan yli, hidden layerin kautta, softmaxiin sanaston yli.

  5. Mikolov, T., Chen, K., Corrado, G. ja Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW ja skip-gram sekä yllä käytetty analogiajoukko.

  6. Mikolov, T., Sutskever, I., Chen, K., Corrado, G. ja Dean, J. Distributed Representations of Words and Phrases and their Compositionality. arXiv:1310.4546 (2013). Negative sampling, yleisten sanojen alinäytteistys ja yllä käytetty 3/4-potenssiin korotettu kohinajakauma.

  7. Pennington, J., Socher, R. ja Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Sanavektorit globaalin yhteisesiintymämatriisin faktoroinnista virtaavien paikallisten ikkunoiden sijaan.

  8. Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016, arXiv:1606.07736. Yllä toistettujen offsetittomien baselinejen lähde.

  9. Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: yksi vektori per esiintymä, laskettuna kaksisuuntaisella kielimallilla.

  10. Devlin, J., Chang, M.-W., Lee, K. ja Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). bank-kokeessa mitattu malli.

  11. Press, O. ja Wolf, L. Using the Output Embedding to Improve Language Models. arXiv:1608.05859 (2016), sekä Inan, H., Khosravi, K. ja Socher, R. Tying Word Vectors and Word Classifiers. arXiv:1611.01462 (2016). Kaksi riippumatonta argumenttia samalle tempulle.

  12. Reimers, N. ja Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). Sen avaava mittaus — mean-pooled BERT häviää keskiarvoistetuille staattisille vektoreille lausesamankaltaisuudessa — on se, minkä yllä oleva taulukko toistaa.

  13. Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Kahden encoderin retrieval-mallin kontrastiivinen koulutus; luvun 19 retrieval-pinon suora esi-isä.


Tekijä

David Vicente Campos

NeuraLIA Labsin perustaja ja MyRealFoodin toinen perustaja

Olen valmistunut tietotekniikan insinööriksi Leónin yliopistosta. Olin mukana perustamassa MyRealFoodia, jossa teknologiajohtajana rakensin sovelluksen, jota miljoonat ihmiset ovat käyttäneet syödäkseen paremmin, ja perustin NeuraLIA Labsin, jossa rakennan tekoälytuotteita. Täällä kirjoitan siitä, mitä minun on pitänyt ymmärtää matkan varrella, niin kuin olisin toivonut jonkun selittävän asiat minulle.

Lisää kirjoittajasta

Julkaisija: NeuraLIA Labs.

Uudet julkaisut suoraan sähköpostiisi

AI-uutisia, oppaita ja tuoteuutisia — lyhyt sähköposti, kun julkaisemme jotain aikasi arvoista.

Kurssin hakemisto

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev9 min lukuaikaa

Jev AI -malli on rakennettu päätöksiä, ei proosaa varten

TypeSafe AI:n Jev herättää huomiota, koska se käsittelee ohjelmistojen älykkyyttä todennäköisyysongelmana: valitse oikea haara, liitä mukaan varmuus ja vältä maksamasta LLM:lle tekstin kirjoittamisesta, kun koodi tarvitsee päätöksen.

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering9 min lukuaikaa

Kontekstisuunnittelu pitkän aikavälin AI-agenteille

Pitkäkestoiset agentit eivät epäonnistu vain siksi, että ikkuna on pieni. Ne epäonnistuvat, kun tiedostot, työkalujen tulosteet ja vanhentunut historia syrjäyttävät tehtävän, joka agentin piti saada valmiiksi.

Valmis antamaan LIA:n valita puolestasi?

Rakenna kaikilla tekoälymalleilla yhdessä paikassa — aloita ilmaiseksi jo tänään.