• Русский
  • Векторы и эмбеддинги

    После токенизации текст превращается в список целых чисел: The cat sat («кот сидел») становится [976, 9059, 10139]. Нейросеть умеет только складывать и умножать числа, так что напрашивается идея подать ей эти ID напрямую. Это не работает: ID — всего лишь номер в списке словаря, и зависит он от того, в каком порядке токенизатор выучил свои кусочки. Вот настоящие ID из токенизатора GPT-4o (английские слова, потому что для них нашлись отдельные токены):

    ТокенID
    ·dog (собака)6 446
    ·cat (кот)9 059
    ·catalog (каталог)20 913
    ·kitten (котёнок)114 502

    Если верить этим числам, «каталог» примерно в девять раз ближе к «коту», чем «котёнок». А в русском тексте «·котёнок» вообще распадается на три токена — ·кот, ён, ок, — и ни один из их номеров не говорит, что это молодой кот. Любая арифметика над ID была бы арифметикой над случайностями нумерации, и ничто выученное про «кота» не перенеслось бы на «котёнка».

    Модели нужно другое: такое описание каждого токена, в котором у похожих токенов похожие числа. Одного числа для этого мало: котёнок живой, это животное, кошачье, детёныш, маленький и ещё много чего. Поэтому каждый токен получает целый список чисел — вектор, в котором хватает места для многих свойств сразу.

    Что означают числа

    Представьте, что на каждое слово заполняется анкета: живое ли оно? животное? кошачье? детёныш? королевское? женское? техника? На каждый вопрос отвечает одно число. У слов с похожим смыслом похожие анкеты: «кот» и «котёнок» различаются только строкой «детёныш», а у «машины» с ними почти ничего общего.

    Рисунок 3.1 · Что означают числа вектора
    🌱🐾🐱🍼👑♀⚙️
    кот0.90.90.90.10.00.00.0
    котёнок0.90.90.90.90.00.00.0
    собака0.90.90.10.10.00.00.0
    щенок0.90.90.10.90.00.00.0
    король0.90.20.00.10.90.00.0
    королева0.90.20.00.10.90.90.0
    машина0.00.00.00.00.00.00.9

    🌱 живое🐾 животное🐱 кошачье🍼 детёныш👑 королевское♀ женское⚙️ техника

    Каждое число отвечает на один вопрос о слове. Таблицу можно читать как анкету.

    Косинусное сходство со словом «кот»
    котёнок · 0,900.90
    собака · 0,860.86
    щенок · 0,740.74
    король · 0,500.50
    королева · 0,410.41
    машина · 0,000.00
    Каждая строка — вектор одного слова, каждый столбец — одно число. Выберите слово и посмотрите, у каких слов векторы ближе всего (сходство оценивается числом от −1 до 1 — косинусным сходством, о нём ниже). Потом переключитесь на выученные измерения: числа полностью меняются, а все сходства остаются ровно такими же.

    Настоящие модели устроены так же, но с одним важным отличием: вопросы никто не выбирает. Числа сначала случайные, а обучение шаг за шагом подправляет их, оставляя то, что помогает предсказать следующий токен. Токены, которые употребляются похоже, получают похожие векторы, потому что так предсказывать проще. Получается как в выученном виде на рисунке.

    Этот вид — та же анкета после случайного поворота всего пространства: поворот перемешивает все числа между собой, но не меняет углов между векторами, поэтому все сходства сохраняются. Информация на месте, просто размазана сразу по всем числам. Отдельное число, скажем 1 234-е в векторе ·cat, обычно не означает ничего, чему можно дать название. Смысл несёт весь узор целиком — направление, в котором смотрит вектор. (Исследователям всё же удаётся находить направления с понятным смыслом — об этом глава 6.)

    Списки чисел как стрелки

    Почему про список чисел говорят, что он куда-то «смотрит»? Потому что вектор — упорядоченный набор чисел, например (0,8; −1,2; 0,3)(0{,}8;\ -1{,}2;\ 0{,}3), — можно нарисовать. Вектор из двух чисел — это стрелка на бумаге из начала координат в точку (x, y), из трёх — стрелка в комнате. Два списка с похожими числами — это две стрелки, которые смотрят почти в одну сторону.

    Языковые модели используют куда больше трёх чисел:

    МодельЧисел на токен (dmodeld_\text{model})
    GPT-2 small768
    Llama 3 8B4 096
    GPT-3 175B12 288

    Число с буквой B в названии модели — количество параметров в миллиардах: у Llama 3 8B их около 8 миллиардов.

    Представить 4 096 измерений невозможно, но геометрия работает точно так же: у векторов есть длина, они куда-то направлены, а угол между двумя векторами говорит, насколько они похожи.

    Таблица эмбеддингов

    Значит, модели нужен вектор для каждого токена словаря. Все они хранятся в одной большой матрице — таблице эмбеддингов, по строке на токен. Превратить токен в вектор значит просто прочитать его строку: ID по-прежнему нужен, но только как адрес строки, а не как смысл.

    Рисунок 3.2 · Поиск эмбеддингов в таблице
    The0·cat1·sat2·on3·the4·mat5
    Таблица эмбеддингов · 8 токенов × 6 чисел
    d0d1d2d3d4d5
    0 The−0.67−0.19−1.29−0.80−0.370.86
    1 ·cat−0.19−1.26−0.47−2.300.400.70
    2 ·sat1.050.270.780.720.30−1.01
    3 ·on1.70−0.62−0.72−0.410.340.23
    4 ·the−0.30−0.86−0.210.23−0.220.16
    5 ·mat1.46−0.990.56−0.30−0.050.25
    6 .0.351.440.65−0.80−0.85−0.14
    7 ·dog−1.04−0.140.06−0.870.88−0.23
    Результат · по строке на токен

    Пусто: нажмите «пуск».

    1/8

    Токенизатор превратил текст в ID. ID — это просто номер строки, никакого смысла в нём пока нет.

    Каждый ID токена выбирает одну строку таблицы. Сложив строки, получаем матрицу с одной строкой на токен — это вход первого блока трансформера.

    Таблица для словаря в 200 000 токенов и 4 096 измерений содержит 819 миллионов чисел — заметную долю параметров небольшой модели. Как и все остальные веса, таблица начинает со случайных значений и выучивается при обучении.

    Поиск в таблице — это умножение матриц

    Запишите токен 3 как one-hot-вектор: всюду нули, кроме единицы на позиции 3. Умножение его на таблицу эмбеддингов EE выбирает строку 3: при умножении вектора на матрицу каждая строка матрицы умножается на соответствующее число вектора, и строки складываются, а здесь все строки, кроме третьей, умножаются на 0. Значит, «взять строку» и «умножить на EE» — одна и та же операция, и поэтому таблицу можно обучать теми же градиентами (сигналами, по которым обучение подправляет каждое число), что и всё остальное.

    Как измерить сходство: скалярное произведение

    Мы всё время говорим о «похожих векторах». Чтобы с этим считать, модели нужно число, которое говорит, насколько два вектора похожи. Инструмент, которым она пользуется везде, — скалярное произведение: перемножить соответствующие числа и сложить.

    a⋅b=a1b1+a2b2+⋯+adbd=∣a∣ ∣b∣cos⁡θ\begin{aligned} \mathbf{a} \cdot \mathbf{b} &= a_1 b_1 + a_2 b_2 + \dots + a_d b_d \\ &= |\mathbf{a}|\,|\mathbf{b}| \cos\theta \end{aligned}

    Здесь ∣a∣|\mathbf{a}| — длина стрелки (по теореме Пифагора a12+⋯+ad2\sqrt{a_1^2 + \dots + a_d^2}), а θ\theta — угол между стрелками. Вторая форма объясняет смысл: скалярное произведение велико, когда векторы длинные и смотрят в одну сторону. Если разделить на длины, останется cos⁡θ\cos\theta — косинусное сходство. Оно меняется от −1-1 (противоположные направления) через 00 (перпендикулярны, не связаны) до +1+1 (одно направление).

    Например, возьмём a=(3; 2)\mathbf{a} = (3;\ 2) и b=(1; 3)\mathbf{b} = (1;\ 3) — с этих стрелок начинается рисунок ниже. Скалярное произведение: 3⋅1+2⋅3=93 \cdot 1 + 2 \cdot 3 = 9. Длины: 13≈3,61\sqrt{13} \approx 3{,}61 и 10≈3,16\sqrt{10} \approx 3{,}16, значит, cos⁡θ=9/(3,61⋅3,16)≈0,79\cos\theta = 9 / (3{,}61 \cdot 3{,}16) \approx 0{,}79: стрелки расходятся примерно на 38° и смотрят в целом в одну сторону.

    Рисунок 3.3 · Скалярное произведение и косинусное сходство
    ab
    a
    (3.0, 2.0)
    b
    (1.0, 3.0)
    a · b
    3.0×1.0 + 2.0×3.0 = 9.00
    |a|, |b|
    3.61, 3.16
    угол
    38°
    cos θ
    0.79
    −10+1

    смотрят в одну сторону: похожий смысл

    Перетаскивайте концы векторов a и b (или выберите кружок и двигайте стрелками). Бледная оранжевая полоса — проекция b на a: скалярное произведение равно |a|, умноженной на длину этой «тени», и отрицательно, когда тень смотрит назад.

    Скалярное произведение встретится в следующих главах ещё не раз: внимание построено на скалярных произведениях между токенами, а последний шаг модели оценивает каждый токен словаря скалярным произведением с последним вектором. Этот последний шаг, обратный эмбеддинг (unembedding), — вторая таблица с одной строкой на токен. Многие модели просто переиспользуют для него таблицу эмбеддингов (связывание весов, weight tying): токен получает высокую оценку, когда итоговый вектор смотрит туда же, куда эмбеддинг самого токена.

    Смысл становится геометрией

    Вернёмся к утверждению из начала главы: обучение даёт похожие векторы токенам, которые употребляются похоже. Почему? Допустим, и после «кошки», и после «котёнка» часто идёт «мурлычет». Оценка для «мурлычет» — это скалярное произведение с вектором, который модель строит из уже прочитанных слов, поэтому проще всего дать высокую оценку после любого из двух слов, если их векторы смотрят в одну сторону. Повторите это на миллиардах предложений — и «кошка» окажется рядом с «котёнком», а «Париж» — недалеко от «Рима». Никто не велит модели так делать: это просто самый дешёвый способ хорошо предсказывать следующий токен.

    Ещё удивительнее, что смысл приобретают направления. Шаг от «мужчины» к «женщине» — примерно та же стрелка, что шаг от «короля» к «королеве». Это знаменитая аналогия из word2vec (Mikolov et al., 2013) — раннего метода, который выучивает по одному неизменному вектору на слово:

    король⃗−мужчина⃗+женщина⃗≈королева⃗\begin{aligned} &\vec{\text{король}} - \vec{\text{мужчина}} + \vec{\text{женщина}} \\ &\approx \vec{\text{королева}} \end{aligned}

    Ниже — построенное вручную трёхмерное пространство с такими свойствами. Настоящие пространства эмбеддингов выучиваются и устроены сложнее, но кластеры и параллельные стрелки — реальные явления. (Это упрощение: в настоящих пространствах word2vec аналогия выполняется лишь приблизительно и не для всех отношений, а ближайшее слово ищут среди всех, кроме трёх исходных, — как и на рисунке.)

    Рисунок 3.4 · Пространство эмбеддингов, которое можно вращать
    Выберите аналогию и следите за стрелками: разность между двумя словами переносится на третье, и ближайшее слово к точке, куда она попадает, и есть ответ. Нажмите на любое слово, чтобы увидеть его ближайших соседей по косинусному сходству.
    Что означают измерения

    В этом игрушечном пространстве направления «женское», «королевское» и «молодое» расставлены вручную. Но даже здесь это не оси: шаг к «женскому», например, меняет сразу все три координаты. Таблица настоящей модели похожа на выученный вид рисунка 3.1: ни у одного отдельного измерения нет чистого смысла, и единица смысла — направление, то есть смесь измерений. Поиском таких направлений занимаются исследования интерпретируемости — попытки понять, что происходит внутри обученных моделей.

    Одно слово — разные векторы

    Таблица эмбеддингов даёт каждому токену ровно один вектор, где бы он ни встретился. Это статический эмбеддинг. Но «ключ» во фразе «из-под камня бил ключ» и «ключ» в замке — разные слова с одинаковым написанием. Таблица не может знать, какое из них имеется в виду, и её вектор для «ключа» оказывается компромиссом между обоими значениями.

    Трансформер исправляет это по ходу чтения. В каждом слое (одном блоке трансформера; в модели их десятки) внимание подмешивает в вектор каждого токена информацию от соседей (глава 5). К средним слоям вектор «ключа» в одной фразе притянут к «воде», а в другой — к «замку». С такими контекстными эмбеддингами и работает остальная модель.

    Рисунок 3.5 · Статические и контекстные эмбеддинги
    ключ
    родникручейводаисточникзамокдверьоткрытьотмычкаключ
    вода0.73
    двери и замки0.71

    косинусное сходство

    Прямо из таблицы эмбеддингов у «ключа» один вектор — компромисс между обоими значениями. Он висит между двумя группами и не близок ни к одной.

    Пунктирный кружок — место, куда «ключ» ставит таблица эмбеддингов. Выберите фразу и посмотрите, как контекст утягивает вектор в одну из двух окрестностей. Полоски показывают косинусное сходство с каждой группой слов.

    В этом главное отличие от старых векторов слов вроде word2vec, которые на поиске в таблице и останавливались. В трансформере поиск — лишь отправная точка.

    Эмбеддинги для поиска

    Та же идея работает и для целых текстов. Модель эмбеддингов читает предложение или абзац и выдаёт один вектор на весь текст — обычно усредняя итоговые векторы токенов или беря вектор специального токена. Её обучают так, чтобы тексты с похожим смыслом оказывались рядом, даже если у них нет ни одного общего слова: «Как сбросить пароль?» попадает рядом с «Я забыл логин».

    Так работает семантический поиск: один раз получить эмбеддинги всех документов, получить эмбеддинг вопроса и вернуть документы с наибольшим косинусным сходством. Это поисковая половина генерации с извлечением (RAG), о которой рассказывает глава 15.

    Итоги

    • ID токенов — произвольные метки, поэтому каждый токен описывается вектором: списком чисел, в котором у похожих токенов похожие значения.
    • Числа выучиваются, а не выбираются; смысл несёт направление вектора, а не отдельное число.
    • Каждый ID токена выбирает одну выученную строку таблицы эмбеддингов — вектор из сотен или тысяч чисел.
    • Скалярное произведение и косинусное сходство измеряют, насколько два вектора смотрят в одну сторону.
    • Обучение раскладывает пространство так, что связанные токены оказываются рядом, а устойчивые отношения превращаются в параллельные направления.
    • Векторы из таблицы статичны; внимание превращает их в контекстные, зависящие от окружающих слов.

    У таблицы эмбеддингов есть слепое пятно: вектор слова «мать» один и тот же, стоит ли оно первым или последним. Следующая глава добавляет позицию.