Към съдържанието
8/30Глава 8 от 30

Предсказване на следващия token: embedding-и и какво означава перплексията

Обучете символен модел върху 32 033 имена и вижте как gradient descent преоткрива таблица с брояния — и защо perplexity рядко съвпада.

На тази страница

Ето десет имена, произведени от програма, която никога не е виждала дума:

TEXT
cexze   momakurailezitynn   konimittain   llayn   ka
da      moliellavo          emia          sade    ftlsp

Нито едно от тях не е име. Почти всички обаче се опитват. Произносими са, завършват там, където завършват имената, а едно от тях — emia — е само на една буква от истинско. Програмата, която ги е произвела, съдържа 729 числа, няма понятие за дума, сричка или човек и е напасната с едно-единствено преминаване на броене на съседни двойки букви.

До края на тази глава една невронна мрежа ще намали оценката на тази програма с една трета по същата мярка. Частта, заради която си струва да останете, е какво прави мрежата първо: тя възпроизвежда таблицата с брояния до три знака след десетичната запетая във всеки добре запълнен ред, без prompt, защото двата обекта са отговори на един и същ въпрос. Всичко след това е онова, което броенето никога не би могло да направи.

Глава 7 ви остави с редица от цели числа и без причина едно да следва друго. Ето причината, и тя е един ред от Глава 2.

Езиковият модел е функция, която взема tokens дотук и връща разпределение за това кой token идва следващ: по едно число за всеки елемент от речника, неотрицателно, със сбор едно. Нищо друго. За да стигнете от това до вероятност за цял документ, приложете верижното правило на вероятностите:

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

Това е тъждество, вярно за всяка редица от каквото и да било, без никакви допускания. Затова модел, който върши малката задача — следващ token при дадени предишните — вече е свършил голямата задача да присвои вероятност на всеки възможен документ, точно и безплатно. Популярното представяне на това като евтин трик („той само предсказва следващата дума“) обръща логиката наопаки: предсказването на следващия token е моделиране на съвместното разпределение. Никога не е имало второ нещо за правене.

Загубата следва също толкова механично. На всяка позиция моделът произвежда разпределение qq, а истината е един известен token, така че крос-ентропията от Глава 4 се прилага без промяна:

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

Това е средната отрицателна log-likelihood — рецептата от Глава 2 с категорийно разпределение в слота, където беше гаусовото. И понеже истинското разпределение е one-hot, ентропията му е нула, така че по тъждеството от Глава 4 крос-ентропията е равна на KL дивергенцията: да намалявате това число и да придърпвате убежденията на модела към данните е един и същ акт.

Едно следствие заслужава собствено изречение, защото е икономическият факт под цялата област. Етикетите са данните, изместени с една позиция. Никой не анотира нищо. Един трилион tokens текст са един трилион предварително етикетирани примера, затова обучителният корпус на съвременен модел е „интернетът“, а не „набор от данни, който някой е построил“.

Преди всяка мрежа — базовата линия: 32 033 имена, по едно на ред, и задачата да се произвеждат още такива, буква по буква.1

Речникът е 26 букви плюс граничен символ ., който маркира и началото, и края на име, така че моделът трябва да научи къде започват имената и къде спират. Това са 27 символа, а най-малкият възможен модел е таблица на това колко често всеки символ е следвал всеки друг символ.

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   

Два реда аритметика и моделът е напаснат — и това не е евристика: деленето на броянията на сумите по редове е оценката по максимално правдоподобие за категорийно разпределение, тоест рецептата от Глава 2 с вече свършеното смятане.

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

Вземете проби от него — изберете буква от реда на текущата буква, преминете към този ред, повтаряйте, докато се появи граничният символ — и получавате имената в началото на тази глава. Те се провалят по конкретен и информативен начин: локално правдоподобни, глобално безсмислени. Всяка съседна двойка букви в momakurailezitynn е двойка, която се среща в истински имена; просто тук има седемнадесет такива поред. Моделът има памет от една буква, затова не може да знае, че продължава прекалено дълго.

Загубата върху отделените за проверка имена е 2.4546 ната. Това число само по себе си не означава нищо, затова съществува perplexity:

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}

Изписано изцяло, без библиотека да върши работата:

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

Експоненцирането отменя логаритъма и връща числото в единиците на броене на неща. Чистият начин да видите какво брои е да измерите модел, който не знае абсолютно нищо — такъв, който присвоява вероятност 1/271/27 на всеки символ независимо от контекста:

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

Точно 27.000, защото elog27=27e^{\log 27} = 27. Perplexity е ефективният брой еднакво вероятни опции, между които моделът избира. Perplexity от 27 означава „нямам представа, може да е всичко“. 11.642 за модела с броене означава, че една буква контекст го оставя толкова несигурен, колкото някой, който избира на сляпо между около дванадесет опции вместо двадесет и седем — затова се цитира perplexity, а не суровата загуба.

Две неща се объркват при него, а второто се обърква и в публикувани статии.

Нулевите вероятности са фатални. От 729 клетки в таблицата 113 никога не се срещат при обучението — 15.5 % от нея е празна. Това е наред, докато отделеният набор не попадне в такава клетка, а седем bigrams във валидацията го правят, сред тях dq, zj и qo два пъти. Вероятност нула означава log -\infty, което означава безкрайна загуба и безкрайна perplexity: едно име на три хиляди унищожава метриката. Обичайният пластир е да се добави 1 към всяко броене преди нормализиране, което тук почти не струва нищо (2.4546 вместо 2.4524). Но пластирът е признание. Моделът с броене изобщо не може да обобщава. Няма как да подозира, че qo е правдоподобно, защото qu е често, а o се държи като u на други места, понеже няма понятие, че два символа могат да си приличат. Всяка клетка се учи отделно и поправянето на това е смисълът на останалата част от тази глава.

Perplexity е цена на token, а token е свободен параметър. Това е грешката, която постоянно се появява при сравняване на модели, и се вижда лесно, щом погледнете. Вземете същия корпус от английска проза от Глава 7, същия интерполиран bigram модел, и променете само как се нарязва текстът:

единицаречникtokens в тестакрос-ентропияperplexityбитове на символ
символи7614,4692.521712.453.6378
BPE, 512 сливания3296,8713.854747.212.6407
BPE, 2,048 сливания1,8204,2335.7468313.202.4254
думи2,9916,2843.562735.262.2322

Perplexity варира 25 пъти между тези редове. Нищо в модела не се е променило; промени се само размерът на нещото, което се предсказва. Предсказването на цяла дума е по-трудно от предсказването на буква, затова струва повече на предсказване — и има по-малко предсказвания за правене.

Сега прочетете последната колона, която вместо това дели общата цена на броя символи и я преобразува в битове. Тя пренарежда таблицата. По perplexity класацията е символи, думи, BPE-512, BPE-2048; по битове на символ тя е думи, BPE-2048, BPE-512, символи. Символният модел пада от първо на последно място. Моделът с 2,048 сливания, който по perplexity изглежда 6.6 пъти по-лош от този с 512 сливания, всъщност е по-добрият от двата — 2.4254 бита срещу 2.6407.

Затова perplexity е сравнима само между два модела, които споделят tokenizer, а модели с различни tokenizers могат да се сравняват само в битове на символ — величината, която Шанън измерва през 1951 г., като кара участници да отгатват следващата буква в английски текст, и която ограничава приблизително до един бит на символ.2 Най-добрият ни bigram е на 2.23 бита, което е честно обобщение на това колко път още има тази глава.

Сега изградете същия модел като мрежа. Ще са му нужни порядъци повече аритметика, за да стигне до същото място, а стигането до същото място е целият смисъл.

Заменете таблицата с една матрица от тегла WW с форма 27×2727 \times 27. Превърнете текущата буква в one-hot вектор, умножете и наречете резултата logits — ненормализираните оценки от Глава 4. После softmax, после крос-ентропия, после 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

Маркираният ред съдържа дефиниция, която си струва да имате. Умножаването на one-hot вектор по матрица избира един неин ред, така че умножението е lookup — и всяка имплементация пропуска аритметиката и прави lookup директно, което е W[xs].

Това е embedding таблица. Матрица с по един ред за всеки елемент от речника, индексирана по token id. Без геометрия, без семантика, без отделен алгоритъм: lookup таблица, чието съдържание просто се учи чрез gradient descent заедно с всичко останало. Всяко мистично твърдение за „embedding space“ стига в основата си дотук.

Обучете я и вижте накъде отива:

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

Последната колона е най-голямата абсолютна разлика между която и да е клетка на softmax(W) и съответстващата клетка от таблицата с брояния, и тя отива към нула. След 3,000 стъпки най-голямото разминаване където и да е сред 729-те клетки е 0.004048, а средното е 0.000224. Най-лошата клетка е qi, видяна дванадесет пъти в целия обучителен набор; сред 22-та реда с повече от хиляда срещания най-лошото разминаване е 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, започвайки от случайни числа и без да му е казано нищо освен „направи log-вероятността на следващата буква голяма“, преоткри таблицата с брояния. И трябваше: броянията са оценката по максимално правдоподобие, крос-ентропията е отрицателната log-likelihood, така че и двете процедури оптимизират една и съща цел, а тази цел има един оптимум. Мрежата не научи нещо подобно на броене. Тя конвергира към броене, бавно.

Това повдига справедливия въпрос защо изобщо някой би си направил труда. Защото таблицата с брояния няма накъде да отиде оттук, а мрежата има.

Разширете модела така, че да гледа повече от един предишен символ. Това е архитектурата на Бенжио от 2003 г., директният предшественик на всеки модел в останалата част от този курс:4 вземете последните три символа, прекарайте всеки през embedding таблица до 10-мерен ред, конкатенирайте редовете в 30 числа, прекарайте ги през скрития слой от Глава 5 и завършете с изходен слой, който произвежда по един logit за всеки елемент от речника.

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)

Забележете кое е ново и кое не е. Скритият слой е този от Глава 5, без промяна; загубата е тази от Глава 4, без промяна. Новостите са embedding таблицата отпред и изходен слой, широк колкото речника от Глава 7 — а именно вторият е скъпата част на всеки езиков модел, строен някога, защото истинският речник има 100,000 елемента и това матрично умножение се изпълнява на всяка позиция.

Същият код, обучен по същия начин, като е променен само размерът на context window:

contextпараметривалидационна загубавалидационна perplexity
броене, 1 символ7292.454611.642
невронен, 1 символ7,8972.457711.678
невронен, 3 символа11,8972.11458.285
невронен, 8 символа21,8972.05067.773

Вторият ред е интересният. Мрежа със скрит слой от 200 единици и единадесет пъти повече параметри от таблицата с брояния се представя точно толкова добре, колкото таблицата с брояния, и нито малко по-добре. Капацитетът никога не е бил ограничението. Един символ context позволява определена загуба и нищо, което добавите отгоре, не може да падне под нея, защото информацията не е там.

Дайте ѝ три символа и perplexity пада от 11.68 на 8.29 — намаление с 29 %, купено с 4,000 допълнителни параметра. Тук тя побеждава броенето точно по причината, диагностицирана по-рано: модел с броене върху трисимволни контексти се нуждае от 273=19,68327^3 = 19{,}683 реда, повечето от тях празни или с едно-единствено наблюдение, и учи всеки самостоятелно. Мрежата споделя. Ако a, e и i се окажат с подобни embedding редове, това, което научи след bra, се пренася към bre, без някога да е виждала bre. Този пренос е цялата стойност на embedding таблицата и той е разликата между редове две и три.

Пробите се подобряват съответно:

TEXT
deliah   nellara   joce     kael      quintis
salayson  reety    khyrmin  mahnen    madiaryxia

Все още не е списък с истински имена. Но deliah, nellara и kael не биха изглеждали неуместно в такъв, а чудовищата без край са изчезнали: най-дългото от двадесет проби от модела с броене е деветнадесет букви, най-дългото от двадесет от този модел е тринадесет.

Какво всъщност има вътре в embedding таблицата

Връзка към раздела: Какво всъщност има вътре в embedding таблицата

Таблицата е 27×1027 \times 10: по един ред от десет числа за всеки символ, всички инициализирани случайно и местени само от gradient на загубата за следващ символ. Никой не е сложил нищо вътре. И така, какво се е озовало там?

Инструментът за питане е косинусова близост, тоест скаларното произведение от Глава 1 с разделени дължини:

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

Тя измерва ъгъла между два вектора и игнорира дължините им, което е нужно, когато дължината на реда отразява колко често се е появявал неговият token, а не какво означава. Първо нормализирайте всеки вектор до дължина 1 — както правят реалните системи, веднъж, по време на индексиране — и косинусовата близост е просто скаларното произведение.

Ето най-близките съседи на няколко символа в обучената таблица:

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

Част от това е, което фолклорът обещава. c и k са взаимозаменяеми в имена, както и i и y; j и z са редки, предимно начални съгласни, които се държат сходно. Граничният символ . не е близо до нищо — 0.077 до най-близката буква — защото е единственият символ, който маркира позиция, а не звук.

А част от това не е така. Най-близкият съсед на a е h, не друга гласна. Осреднено върху всички двойки:

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

Гласните си приличат повече една на друга, отколкото на съгласните, и ефектът е реален, но малък. Тествано срещу 2,000 случайно избрани групи от пет букви, 58 от тези групи се отделят поне толкова чисто — разлика, значима на около p=0.03p = 0.03. Значи е реална, но изобщо не прилича на ясния геометричен остров, който популярните разкази за embeddings внушават.

Това е честното описание на embedding таблица и си струва да го запазите за останалата част от курса. Тя не е карта на значение. Тя е смяна на координати, научена вместо проектирана, чиято единствена работа е да улесни работата на следващия слой — същото изречение, което Глава 5 използва за скрития слой, който сгъна равнината, за да реши XOR. Всяка структура, която намерите в нея, е там, защото е намалила загубата, а структура, която не намалява загубата, просто я няма.

word2vec, GloVe и аритметиката, която всички цитират

Връзка към раздела: word2vec, GloVe и аритметиката, която всички цитират

Ако полезната част е таблицата, можете да преследвате директно нея. Това е word2vec: запазете embedding lookup, изхвърлете езиковия модел.5

Целта skip-gram with negative sampling е един ред. За реална двойка (център, context), извлечена от корпуса, бутнете скаларното им произведение нагоре; за kk фалшиви двойки, извлечени от шумово разпределение, бутнете го надолу: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})

Това е бинарна класификация — „срещали ли са се тези две думи наистина заедно?“ — и е евтина точно защото никога не докосва целия речник, което направи практично обучението върху милиарди думи през 2013 г. GloVe стига до подобни вектори от другата посока, като факторизира матрицата на глобалните брояния на съвместни срещания, вместо да минава потоково през примери.7 И двете се напасват към точно статистиката, от която беше построена таблицата с брояния. Те са броене, компресирано.

Обучени върху text8 — 17,005,207 думи от английската Wikipedia, 71,290 от тях срещащи се поне пет пъти, 100 измерения, три преминавания — векторите излизат със свойството, което ги направи известни:

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

Никой не е подал категория за инструменти или за числителни. Сега известната част: вземете king, извадете man, добавете woman и намерете най-близкия вектор до резултата.

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)

Най-близкият вектор до king - man + woman е king. Това не е странност на един пример. Оценъчният набор на Миколов задава въпроси от формата a : b :: c : ? — 8,869 семантични (paris : france :: rome : italy) и 10,675 синтактични (walking : walked :: swimming : swam) — и сред 4,103 семантични въпроса, на които този речник може да отговори, победителят е една от трите входни думи 99.8 % от времето. Публикуваните демонстрации не го споменават, защото стандартното правило за оценяване изтрива a, b и c преди търсенето. Това е легитимно правило и то върши повече работа от аритметиката:

как се избира отговорътсемантичнисинтактични
offset, с изключени входове (стандартно)17.0 %11.9 %
offset, без нищо изключено0.1 %0.4 %
най-близък съсед само на c, входове изключени13.1 %9.3 %
най-близък съсед само на b, входове изключени2.3 %0.4 %

Третият ред е този, с който трябва да поседите. Изхвърлете a и b, не правете никаква аритметика, върнете каквото е най-близо до c — и запазвате 77 % от семантичния резултат. Повечето от това, което изглежда като аналогично разсъждение, е близост плюс правило, което забранява очевидните отговори — точно това измери Линзен върху правилно обучени вектори и което базовите линии по-горе възпроизвеждат.8 Тези конкретни вектори са малки — 17 милиона думи срещу милиардите зад публикуваните модели — така че четете процентите като форма, не като state of the art. Формата е това, което оцелява при всеки мащаб: аритметиката е реална и далеч по-слаба от единствената демонстрация, която всички цитират.

Статични и контекстуални: един вектор на дума или един на срещане

Връзка към раздела: Статични и контекстуални: един вектор на дума или един на срещане

Всичко дотук има твърда граница, вградена в структурата на данните. Таблицата има един ред на token. Думата bank получава един вектор, същият в изречение за река и в изречение за ипотека — по необходимост, защото lookup по id не може да зависи от нищо друго.

Поправката е да спрете да четете вектора от таблицата и да започнете да го изчислявате от изречението. Това е contextual embedding, въведен от ELMo през 2018 г. и превърнат в стандарт от BERT същата година.910 Измерени върху реалния модел, числата са по-ясни от обяснението:

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

Първият ред е точен, не приблизителен: статичният вектор за bank е същите 768 числа и в двете изречения, така че косинусът е 1 по конструкция. Девет слоя по-късно двете срещания са на 0.43, докато bank в две различни речни изречения остава на 0.87. Никой никъде не е етикетирал значение в този процес; значенията се разделиха, защото разделянето им прави обучителната цел — отгатване на скрит token от съседите му — по-лесна за удовлетворяване.

Две подробности заслужават внимание. Слой 0 вече е 0.9512, а не 1.0, защото са добавени positional embeddings и думата стои на различно място във всяко изречение. И близостта пак се покачва в слоеве 11 и 12: финалните слоеве на pretrained модел са специализирани към неговата обучителна цел и често не са най-доброто място, от което да вземете representation.

Покажи подробности

По избор: weight tying.

В bert-base-uncased embedding таблицата е 30,522×76830{,}522 \times 768 — 23,440,896 числа, 21.4 % от 109,482,240-те параметъра на модела. В малък езиков модел делът е още по-голям, затова един трик е почти универсален: входната таблица и изходният слой, който произвежда logits, са една и съща матрица, използвана веднъж чрез lookup по редове и веднъж транспонирана.11 Изходният слой вече присвоява вектор на всеки елемент от речника — той взема скаларно произведение срещу всеки от тях — а tying казва, че векторът, използван за четене на token, и векторът, използван за писането му, трябва да са един и същ обект. Това едновременно намалява параметрите и подобрява perplexity, което е достатъчно рядко, за да се отбележи.

За да търсите в корпус по смисъл, ви трябва по един вектор за изречение. Щом ги имате, търсенето е тривиално — това е цялата semantic retrieval, а Глава 19 е за всичко около нея:

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]

Така че единственият реален въпрос е откъде идва embed. Очевидният ход е да вземете pretrained езиков модел, да прекарате всяко изречение през него и да осредните token векторите. Ето този метод срещу четири алтернативи, оценени по два начина: ранговата корелация между косинусова близост и човешки оценки за сходство върху 1,379-те двойки от STS benchmark, и top-1 retrieval върху индекс, построен от 200-те най-силно парафразирани двойки — едната страна на всяка двойка е индексирана, другата се използва като query.

как е embedded изречениеторангова корелацияtop-1 върху индекс от 200 изречения
бинарно припокриване на думи (без модел изобщо)0.550089.0 %
средно на статичните вектори, обучени по-горе0.526385.5 %
BERT, token [CLS]0.203067.0 %
BERT, средно на token вектори0.472984.0 %
MiniLM, обучен контрастивно0.820392.0 %

Прочетете средните три реда спрямо първите два. Pretrained transformer със 109 милиона параметъра, използван по очевидния начин, е по-лош в оценяването на сходство между изречения, отколкото броенето на това колко думи споделят две изречения — и по-лош от осредняване на 100-мерните text8 вектори, обучени преди малко. Token [CLS], който уроците още препоръчват, защото BERT е бил pretrained с прикрепена към него цел на ниво изречение, е по-лош от половината от това.

Това не е дефект в BERT. Това е целта. Езиковият модел се обучава така, че неговите hidden states да предсказват token; нищо там не иска две парафрази да се окажат близо една до друга и нищо не възнаграждава геометрия, в която косинусът означава „същото значение“. Последният ред е модел с една пета от размера (22,713,216 параметъра), обучен върху напълно различна загуба: контрастивно обучение, при което примерите са двойки — въпрос и неговият отговор, изречение и неговата парафраза — а целта придърпва истинските двойки заедно и отблъсква sampled negatives. Това е приносът на Sentence-BERT и произходът на цялата индустрия на embedding model.12 Dense Passage Retrieval прилага същата рецепта директно към търсенето, с един encoder за заявки и един за пасажи.13

И така, практическото правило:

Embedding model не е езиков модел с премахнат последен слой. Това е различен модел с различна цел, обикновено много по-малък, чийто косинус означава това, което искате да означава, защото е обучен върху двойки, при които това е било target. Таблицата по-горе е цената на замяната на едното с другото.

И семейството се проваля при реда на думите. „The dog bit the man“ и „the man bit the dog“ имат идентични торби от думи, така че припокриването на думи и средното на статичните вектори им дават косинус точно 1.000000, а mean-pooled BERT, който все пак вижда позиция, пак стига почти дотам — и контрастивно обученият MiniLM все пак ги поставя на 0.979. Ако retrieval задачата ви зависи от това кой какво е направил на кого, никакъв косинусов праг няма да ви спаси.

Глава 19 изгражда production retrieval система върху тази основа и стига до конкретен косинусов праг. Последното измерване в тази глава е това, което прави такова число защитимо, а не магическо.

Проклятието на размерността в една таблица

Връзка към раздела: Проклятието на размерността в една таблица

Реалните embeddings имат стотици или хиляди компоненти, а разстоянията там горе се държат странно. Вземете 1,000 случайни точки в единичния куб с dd измерения и погледнете отношението между най-голямото и най-малкото разстояние между които и да е две от тях:

измерениянай-близка двойканай-далечна двойкаотношение
20.00071.36121921.66
100.23612.33979.91
1003.00475.17521.72
1,00011.780914.03061.19
10,00039.615242.01251.06

В десет хиляди измерения най-далечната двойка точки е само с 6 % по-далеч една от друга от най-близката двойка. Всичко е приблизително равноотдалечено от всичко останало, „най-близък съсед“ спира да носи много информация и това е проклятието на размерността — както и една причина големите векторни бази данни да не правят exact nearest-neighbour search. Другата страна на същата монета е това, което прави косинусовите прагове работещи: измерено върху хиляда двойки случайни единични вектори, средният косинус стои на 0.0052-0.0052 в 100 измерения и +0.0003+0.0003 в 768, със стандартни отклонения 0.0968 и 0.0357 — а в 768 измерения само 0.2 % от случайните двойки надвишават 0.1 по абсолютна стойност. Следователно измерена близост 0.4 не е „40 % сходни“; тя е далеч извън всичко, което случайността произвежда, затова праговете между 0.3 и 0.7 отделят сигнала от шума, вместо да стоят по средата му.

Моделът в тази глава чете фиксиран брой предишни символи, прави lookup на всеки от тях и слепва резултатите в ред. Този дизайн има два проблема, и те са един и същ проблем.

Погледнете отново таблицата за context: преминаването от три символа към осем почти удвои параметрите и купи 0.06 ната. Цената расте линейно с context — всяка допълнителна позиция се нуждае от собствен блок от първата матрица с тегла — а ползата не. Избутайте го до хиляда tokens и само първият слой тежи повече от останалата част на модела, като по-голямата част е изразходвана за позиции, които нямат значение за дадено предсказване.

Което е вторият проблем: моделът няма как да реши кои от предишните tokens имат значение. Позиция две получава свои тегла и позиция седем получава свои, завинаги, каквото и да има в тях. Когато моделът изписва nell, решаващият символ е този непосредствено преди него. Когато изречение съдържа местоимение, думата, която определя референта му, може да е четиридесет tokens назад — и на „четиридесет назад“ не може да се присвои фиксиран слот, защото следващия път ще бъде шест.

Това, което искаме, е модел, който изчислява за всяко предсказване колко трябва да тежи всеки по-ранен token — тегла върху context, произведени от съдържанието, а не фиксирани от оформлението. Запишете го внимателно и то започва като нещо съвсем обикновено: средно върху предишните tokens. После оставете теглата на това средно да се учат и да зависят от това кой token задава въпроса.

Това е attention и е Глава 9.


Също си струва да четете паралелно: глава 3 от Speech and Language Processing на Jurafsky и Martin, която разглежда n-gram модели, изглаждане и perplexity много по-внимателно, отколкото има място тук, включително защо интерполацията и back-off побеждават добавянето на едно; бележките на Stanford CS229 §17.1–17.2 за езиково моделиране от вероятностната страна; и статията на Linzen по-горе, която е кратка и си струва да бъде прочетена изцяло.

  1. Примерът за генериране на имена, наборът от данни и прогресията от таблица с брояния до мрежа в стил Бенжио следват поредицата building makemore на Andrej Karpathy, чиито първи две части са най-добрият спътник към тази глава.

  2. Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), pp. 50–64 (1951). Участници, които отгатват следващата буква в английски текст, и първоначалното измерване в битове на символ.

  3. Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Теоремата за кодиране на източник и отъждествяването на предсказването с компресията.

  4. Bengio, Y., Ducharme, R., Vincent, P. and Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, pp. 1137–1155 (2003). Архитектурата, използвана по-горе: embedding на дума, конкатениран върху фиксиран прозорец, през скрит слой, до softmax върху речника.

  5. Mikolov, T., Chen, K., Corrado, G. and Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW и skip-gram, както и наборът с аналогии, използван по-горе.

  6. 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 на чести думи и шумовото разпределение, повдигнато на степен 3/4, използвано по-горе.

  7. Pennington, J., Socher, R. and Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Вектори на думи от факторизация на глобалната матрица на съвместни срещания вместо от поточни локални прозорци.

  8. Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016, arXiv:1606.07736. Източникът на offset-free базовите линии, възпроизведени по-горе.

  9. Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: един вектор на срещане, изчислен от двупосочен езиков модел.

  10. Devlin, J., Chang, M.-W., Lee, K. and Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). Моделът, измерен в експеримента с bank.

  11. Press, O. and Wolf, L. Using the Output Embedding to Improve Language Models. arXiv:1608.05859 (2016), and Inan, H., Khosravi, K. and Socher, R. Tying Word Vectors and Word Classifiers. arXiv:1611.01462 (2016). Два независими аргумента за един и същ трик.

  12. Reimers, N. and Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). Началното му измерване — mean-pooled BERT се представя по-слабо от осреднени статични вектори при сходство между изречения — е това, което таблицата по-горе възпроизвежда.

  13. Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Контрастивно обучение на retriever с два encoder-а; директният предшественик на retrieval стека от Глава 19.


Създадено от

David Vicente Campos

Основател на NeuraLIA Labs и съосновател на MyRealFood

Компютърен инженер съм, завършил Университета в Леон. Съосновах MyRealFood, където като CTO създадох приложението, което милиони хора са използвали, за да се хранят по-здравословно, и основах NeuraLIA Labs, където изграждам AI продукти. Тук пиша за това, което трябваше да разбера по пътя, така, както ми се иска някой да ми го беше обяснил.

Още за автора

Публикувано от NeuraLIA Labs.

Получавайте нови публикации във входящата си поща

Новини за AI, ръководства и продуктови обновления — кратък имейл, когато публикуваме нещо, което си заслужава.

Индекс на курса

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev12 мин четене

AI моделът Jev е създаден за решения, не за проза

Jev на TypeSafe AI привлича внимание, защото разглежда софтуерната интелигентност като проблем на вероятностите: изберете правилния клон, добавете увереност и не плащайте на LLM да пише текст, когато кодът има нужда от решение.

Abstract legal research workspace with documents, search nodes and governance controls.
openai11 мин четене

Astra for Law на OpenAI е правна AI система, не нов модел

Правният старт на OpenAI е не толкова за нов базов модел, колкото за системата около него: домейн извличане, надеждни инструменти, права, бенчмаркове и пътища за преглед.

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering12 мин четене

Инженеринг на контекста за AI агенти с дълъг хоризонт

Дълго работещите агенти не се провалят само защото прозорецът е малък. Те се провалят, когато файлове, изходи от инструменти и остаряла история изтласкат задачата, която агентът е трябвало да завърши.

Готови ли сте LIA да избира вместо вас?

Създавайте с всички AI модели на едно място — започнете безплатно още днес.