Я уверен, вы видели модели машинного обучения, которые принимают текст и предсказывают, является ли он спамом. Аналогично модель может проанализировать отзыв о фильме и определить его тональность — положительную или отрицательную, понимать что «груша» связана с «яблоком» куда больше, чем с «теплоходом».

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

Для того чтобы ввести этот объект в нашу ML модель как некое понятие, мы должны преобразовать его в определённый набор чисел. По этому набору чисел мы сможем определить, что, например, этот объект «яблоко», а не «груша».

С картинками всё просто. В чёрно-белом изображении (в градациях серого) самый яркий пиксель имеет значение 1, самый тёмный — 0, а оттенки серого имеют значения от 0 до 1. Такое числовое представление упрощает обработку изображений. Преобразовав изображение в цифровую форму на основе значений пикселей, мы можем использовать его в качестве входных данных для обучения нашей модели, позволяя нейронной сети обучаться на значениях пикселей.

Однако что делать с текстом? Как спроецировать буквы в числа?

Попытка №1: Просто пронумеруем всё подряд

У нас есть текст, и один из простых способов превратить его в числа — присвоить каждому уникальному слову уникальное число. Если вы знакомы с токенизацией, то знаете, что текст разбивается на токены, и каждому даётся уникальный номер (индекс).

Каждому слову присвоим токен
Каждому слову присвоим токен

Казалось бы, проблема решена: у нас есть числа, модель их принимает. Мы можем обучить модель, используя номера токенов в качестве входных данных. Однако этот метод подходит только для порядковых признаков (ordinal features) — случаев, когда числа подразумевают ранжирование.

Низкий, средний и высокий: где порядок токена имеет значение.

Взглянем на эти предложения.

  1. The movie was good.

  2. The movie was bad.

  3. The movie was awesome.

Первое предложение имеет положительную окраску, второе — отрицательную, а третье — снова положительную. Ключевое различие между этими предложениями кроется в словах «good» (хороший), «bad» (плохой) и «awesome» (потрясающий).

Допустим, мы присвоили им случайные токены:

  • «good» = 6

  • «bad» = 26

  • «awesome» = 27

Числа 26 и 27 близкие по значению. Это может заставить модель предположить, что слова «bad» и «awesome» похожи, в то время как слово «good» кажется совершенно другим. В реальности же «good» и «awesome» семантически близки, но из-за того, как присвоены числа, модель может неверно интерпретировать их взаимосвязь. Такое искажение может привести к неверным прогнозам, что делает простые номера токенов неподходящими в качестве входных признаков для моделей машинного обучения.

Попытка №2: One Hot Encoding и Унитарное кодирование

Проблема ложной близости чисел решается техникой One Hot Encoding. Идея проста: каждое слово представляется уникальным вектором, размер которого равен полному размеру нашего словаря.

cловарь = [The, movie, was, good, bad, awesome] — всего 6 слов

Кодируем слова:

Значения векторов для каждого слова
Значения векторов для каждого слова

Каждому слову присваивается уникальный вектор, где только одна позиция содержит «1» (указывая на наличие слова), а все остальные позиции равны «0». Этот метод устраняет проблему ранжирования, присущую методу токенизации, и гарантирует, что все слова рассматриваются как равные, без каких-либо скрытых числовых взаимосвязей.

Теперь, используя векторы One Hot Encoding, мы можем преобразовать наши обучающие данные в числовой формат, подходящий для модели.

One Hot Encoding помогает устранить непреднамеренные числовые связи, и он прост в реализации. Однако у него есть серьёзные недостатки. Он создаёт разреженные векторы (где большая часть элементов равно «0»). Это означает, что если у нас есть словарь из 20 000 слов, каждое слово будет представлено 20 000-мерным разреженным вектором. Можете сами представить, сколько необходимо памяти и вычислительных ресурсов, чтобы обрабатывать такие данные.

Кроме того, этому методу не хватает семантического и контекстуального смысла, так как One Hot Encoding рассматривает слова как полностью независимые сущности. Он не улавливает связи между словами, например, то, что «good» и «awesome» близки по значению. Эти ограничения делают использование исключительно One Hot Encoding неэффективным для масштабных задач обработки естественного языка (NLP).

Попытка №3: Мешок слов и N-граммы

Можно пойти другим путём и использовать Bag of Words (Мешок слов). Мы просто считаем, сколько раз слово встречается в предложении.

Если слово есть в предложении — ставим «1», иначе «0»
Если слово есть в предложении — ставим «1», иначе «0»

Поскольку мы рассматриваем только подсчёт отдельных слов, эта техника также называется униграммой (unigram), так как каждое слово обрабатывается независимо. Вместо использования только униграмм, мы можем рассматривать контекст из двух слов — биграммы, и подсчитывать вхождения всех возможных комбинаций из двух слов для создания вектора признаков. Это добавляет больше контекста по сравнению с One Hot Encoding или подходом «Мешка слов».

Аналогично мы можем расширить это до контекста из N-слов, называемого N-граммами (N-gram) признаками, где модель захватывает контекстную информацию длиной до «N» слов.

При использовании N-грамм в качестве признаков всё равно возникают сложности. Если набор данных велик, опять же будет существовать множество возможных комбинаций N-грамм, что приведёт к очень большому и разреженному вектору признаков, что привёдет к использованию большого кол-ва памяти и бла-бла-бла...

Из-за того, что модель может учитывать только ограниченное количество слов одновременно и эти слова обязаны идти по порядку, то N-граммы не улавливают более глубокие смыслы или связи между словами. Например, в предложении:

«The librarian was looking for a book»

Из‑за того, что слова «librarian» и «book» не являются соседними, N‑граммы не понимают, что они на самом деле связаны по смыслу.

Попытка №4: Семантика и контекст

Подходим к главному. Чтобы модель работала хорошо, она должна понимать семантику (смысл слова) и контекст (окружение).

Теперь давайте возьмём простой пример текста: 

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

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

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

Также контекст упоминает «верстак» и действие «взял». Мы можем сделать вывод, что объект — это его рабочий инструмент (¬‿¬ ).

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

Чтобы обучить модель, которая может понимать такой семантический и контекстуальный смысл, нам нужен способ кодирования наших обучающих данных в векторы признаков, которые захватывают оба аспекта. Именно здесь Эмбеддинги слов (Word Embeddings) и механизм внимания играют решающую роль.

Word Embedding (векторное представление слов) — это техника в обработке естественного языка, при которой слова представляются как плотные (почти без нулей) числовые векторы в непрерывном n-мерном векторном пространстве. Каждое слово представляется вектором фиксированной размерности, который является плотным — в отличие от One Hot Encoding, где большинство значений равны нулю.

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

Давайте разберём это на простом примере, начиная с одного измерения. Представьте числовую прямую, представляющую размер животного, и мы кодируем 10 животных, используя вектор признаков, где размер является единственным признаком. Отсюда мы видим, что животные с похожими габаритами находятся ближе друг к другу. Если мы расширим это до двух измерений — скажем, ось X представляет размер, а ось Y представляет хищность (опасность) — слова «тигр» и «лев» будут похожи и расположены ближе друг к другу (крупные и опасные), в то время как они будут дальше от слов «корова» (крупная, но безопасная) и «хомяк» (мелкий и безопасный).

Теперь, когда векторы признаков закодированы семантически, мы можем выполнять с ними математические векторные операции. Например:

V(Son) - V(Man) + V(Woman) \approx V(Daughter)

вычитание вектора (V — сокр. от Vector) «мужчина» из «сына» и последующее добавление вектора «женщина» даёт вектор, близкий к «дочери». Это показывает, что разница между «сыном» и «дочерью» аналогична разнице между «мужчиной» и «женщиной».

Возьмём другой пример:

V (Madrid) + V (Germany) - V (Spain) \approx V (Berlin)

если мы возьмём слово «Мадрид», добавим «Германия» и вычтем «Испания», ближайшим полученным словом будет «Берлин». Это работает, потому что Мадрид — столица Испании. Когда мы убираем атрибуты, связанные с Испанией, и добавляем атрибуты, связанные с Германией, результирующий вектор тесно совпадает с Берлином, столицей Германии.

Мы не можем явно определить, какие признаки содержатся в пространстве эмбеддингов и не задаём их вручную, так как это полностью зависит от обучающих данных. Однако модель улавливает определённое семантическое понимание текста и представляет его в векторном пространстве меньшей размерности (несколько сотен или тысяч измерений, в отличие от сотен тысяч, требуемых для One Hot Encoding в больших словарях). Цель состоит в том, чтобы использовать плотный вектор, который может хранить значение слов в n-мерном пространстве, называемом пространством эмбеддингов.

Мы не можем напрямую визуализировать эмбеддинги с сотнями измерений, но с помощью математических инструментов, таких как метод главных компонент (PCA), мы можем спроецировать их в меньшее количество измерений.

Ближайшие эмбеддинг-соседи слова «coffee», вычисленные PCA. Источник
Ближайшие эмбеддинг-соседи слова «coffee», вычисленные PCA. Источник

Например, в обученной модели по Word2Vec мы можем увидеть, векторы, связанные с «кофе» (чай, сахар, сыр и др.).

Как получаются эмбеддинги?

Одной из техник обучения эмбеддингов слов является Word 2 Vec, представленная Google. В статье о Word 2 Vec демонстрируются две ключевые техники: Continuous Bag of Words (CBOW)(непрерывный мешок слов) и Skip-Gram.

Короче, в CBOW мы берём окно контекстных слов и пытаемся предсказать центральное целевое слово по его соседям.

CBOW наглядно. Целевое слово «jumps»
CBOW наглядно. Целевое слово «jumps»

Например, если входные слова — «Fox» и «over», целевым словом может быть «jumps». Модель представляет собой простую нейронную сеть.

Перед тем, как загружать это предложение в модель, применим к нему One Hot Encoding.

Кодируем предложение
Кодируем предложение

Входной слой принимает векторы One Hot Encoding контекстных слов. Скрытый слой содержит нейроны в количестве, равном размерности эмбеддинга, которую мы хотим изучить.

Простая нейронная сеть для вычисления embedding
Простая нейронная сеть для вычисления embedding

Выходной слой содержит нейроны, равные размеру словаря. Матрица весов между выходным и скрытым слоями становится матрицей эмбеддингов.

Искомая матрица
Искомая матрица

Матрица эмбеддингов размером 8 на 3 становится таблицей поиска для каждого слова. Это означает, что после обучения мы можем использовать матрицу эмбеддингов для получения трёхмерного вектора для каждого слова, где каждое слово имеет своё собственное фиксированное представление. Поскольку мы обучались только на восьми словах, размер матрицы эмбеддингов составляет 8 на 3. Количество строк в матрице эмбеддингов равно количеству уникальных слов (или размеру словаря), а количество столбцов соответствует размерности эмбеддинга, которую мы выбираем для представления слов в n-мерном пространстве.

Полученная матрица
Полученная матрица

Чтобы получить значение эмбеддинга для каждого слова, мы сначала преобразуем слово в его one-hot вектор, а затем берём скалярное произведение one-hot вектора с матрицей эмбеддингов, чтобы получить вектор эмбеддинга слова.

Теперь, когда мы понимаем модель Continuous Bag of Words, понять модель Skip-gram просто. В модели Skip-Gram процесс обратный. Вместо того чтобы предсказывать центральное слово, используя контекст, мы берём центральное слово в качестве входных данных и пытаемся предсказать окружающие контекстные слова.

Skip-Gram наглядно
Skip-Gram наглядно

Оба метода хорошо работают при обучении словесных эмбеддингов.

Эмбеддинга в архитектуре «Трансформер»

В современных архитектурах (GPT или BERT) подход немного изменился. Там слой эмбеддингов не обязательно брать готовым из Word 2 Vec. Этот слой является частью самой модели и обучается с нуля или дообучается вместе с ней под конкретную задачу. В основном это предсказание следующего токена.

Структура кодировщика-декодера архитектуры Transformer
Структура кодировщика-декодера архитектуры Transformer

Давайте посмотрим на эмбеддинг, используемый в части декодера архитектуры Трансформер.

Скрытый текст
Часть декодера обведена в рамку
Часть декодера обведена в рамку

Сначала мы преобразуем текст в токены.

Слова -> токены -> нейронная сеть -> матрица эмбедингов
Слова -> токены -> нейронная сеть -> матрица эмбедингов

Для шести токенов мы получаем матрицу эмбеддингов размером 6 на размерность эмбеддинга. Слой декодера не использует модель типа Word 2 Vec.

Вместо этого он использует простую неглубокую нейронную сеть для создания эмбеддингов.

Нейронная сеть для получения эмбеддингов
Нейронная сеть для получения эмбеддингов

Входной слой принимает one-hot закодированный вектор каждого слова. Количество нейронов равно размеру словаря, а скрытый слой имеет количество нейронов, равное размерности эмбеддинга, которую мы хотим, чтобы наша модель выучила.

Веса в этом слое эмбеддинга являются обучаемыми параметрами, которые учатся представлять слова в n-мерном пространстве. Так же, как и в Word 2 Vec, веса действуют как таблица поиска для токенов, где каждый токен получает обученное значение веса. После преобразования текста в токены слой эмбеддинга предоставляет векторное представление для каждого токена. При правильном обучении эти эмбеддинги могут улавливать семантическое значение слов.

В отличие от Word 2 Vec, где мы обучаем эмбеддинги отдельно, в слое декодера слой эмбеддинга обучается вместе со всей моделью. Поскольку мы хотим, чтобы наш декодер предсказывал следующий токен, мы используем специальный слой эмбеддинга, который выдаёт векторное представление нашего входного текста. Затем этот эмбеддинг проходит через повторяющиеся блоки декодера и, наконец, попадает в выходной слой, который предсказывает следующий токен. Затем модель вычисляет ошибку и выполняет обратное распространение ошибки через все слои, используя обучающий набор данных.

Схема получения вероятности токена
Схема получения вероятности токена

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

Глядя на этот процесс, мы видим, что модель сначала представляет токены в n-мерном пространстве эмбеддингов, а затем использует это представление для предсказания следующего токена. Это отличается от Word 2 Vec, где задача состояла в предсказании центрального слова с использованием контекстных слов. Однако в больших языковых моделях цель состоит в том, чтобы предсказать следующее слово с учётом всех предыдущих слов, при этом несколько слоёв декодера дополнительно обрабатывают эмбеддинги перед генерацией следующего токена. Мы рассмотрели почти всё, что касается эмбеддингов, но осталась одна небольшая деталь для обсуждения.

Позиционное кодирование (Positional Encoding)

В отличие от RNN, которые обрабатывают каждый токен отдельно, архитектура Трансформер обрабатывает все слова параллельно. Из-за этого нам нужно сообщить модели о позиции каждого токена — по сути, какой токен идёт первым, а какой следует за ним. Чтобы достичь этого, после создания эмбеддинга мы добавляем позиционный вектор к вектору эмбеддинга, кодируя информацию о позиции каждого токена.

Эта позиционная информация может быть либо ещё одним обучаемым слоем, либо статическим числовым представлением, уникальным для каждого токена. Мы просто прибавляем этот позиционный вектор к вектору эмбеддинга, получая в результате новое представление, которое содержит как значение слова, так и информацию о его позиции. Важно отметить, что форма матрицы эмбеддингов не меняется; только её значения слегка корректируются в соответствии с позицией каждого токена.

Добавляем позиционный вектор
Добавляем позиционный вектор

Теперь эта матрица готова к подаче в механизм внимания (attention), который является первым слоем блока декодера. Как упоминалось ранее, слой эмбеддинга помогает уловить семантическое значение слов, но он не обеспечивает контекстуального понимания текста. Именно здесь механизм внимания играет решающую роль.

Заметьте — эмбеддинги немного изменились из-за контекста в тексте
Заметьте — эмбеддинги немного изменились из-за контекста в тексте

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

Детально про механизм внимания поговорим в другой раз :)


Послесловие

Вот так. Комбинируя простые решения вроде токенизации и подсчёта слов, можно постепенно прийти к трансформеру и механизму внимания.

Сегодня эмбеддинги используются везде. В рекомендательных системах, в поиске похожих картинок и, разумеется, в основе ChatGPT и других моделей.

Понимание того, как работают CBOW, Skip-Gram и Transformer — это база, с которой начинается глубокое погружение в NLP.

Спасибо за прочтение!

© 2026 ООО «МТ ФИНАНС»

Комментарии (5)


  1. webhamster
    13.01.2026 11:21

    По этому набор чисел мы сможем определить, что, например, этот объект «яблоко», а не «груша».

    Сегодня день невычитанных текстов? Только начинаю читать статью - обязательно либо путаница с ударениями, либо пропущенные слова, как будто люди забыли собственный язык.


    1. rRenegat Автор
      13.01.2026 11:21

      Спасибо за внимательность! Ошибку исправил


      1. webhamster
        13.01.2026 11:21

        Еще: "Эмбеддинга в архитектуре «Трансформер»".


  1. Diiianochka
    13.01.2026 11:21

    Наконец-то нормальное человеческое объяснение что такое эмбединг, без тонны формул и терминов


  1. enemigo
    13.01.2026 11:21

    Позволю себе поделиться своими наработками в данном направлении - может кто покритикует меня здесь конструктивно. Получется, что числа несут два разных вида информации: количественную (сколько), и порядковую (после чего), что не соответствует информационному наполнению слов. Вопрос который на первый взгляд не имееет отношения к рассматриваемой автором теме: можно ли каким-то образом выделить из чисел эти две ипостаси и использовать их по-отдельности? Например, мы хотим обрабатывать только информацию о количестве игнорируя порядок. Или порядок без знания о количестве. Я спрашиваю потому что здесь задача кодирования сводится с задаче сжатия данных. А сжатие опирается на особенности последовательностей (т.е. на свойства порядка).
    Представим себе некоторый канал связи или хранилище информации, скажем файл на диске. Байты, составляющие этот файл хранятся в определенном порядке, и когда мы запрашиваем данный файл, эти байты приходят к нам с сохранением порядка. Даже если отдельные части файла приходят к нам асинхронно по сети, мы все равно после приема упорядочиваем их в исходную последовательность.
    Теперь мы уберем требование того, чтобы передаваемые данные (неважно синхронно или асинхронно) требовали порядка, но при этом после получения сохраняли свой смысл. Это можно сделать, передавая некоторые базисные количества, например степени двойки. Тогда после получения набора базисных чисел мы можем восстановить передаваемое исходное число (или файл) независимо от порядка получения компонентов. Например, я что-то там закодировал числом 14 и хочу оперировать этим кодом без знания того что это число больше 13 и меньше 15. Тогда я разложу его в сумму 14 = 8 + 4 + 2. Восемь, четыре и два - это базисные количества и я могу их передавать в любом порядке (параллельно, последовательно или еще как-то), но после получения данных компонент их сумма всегда даст исходное число 14. Кодировка one-hot близка к данному принципу, но в ней все еще заложен порядок нулевых байт. Кстати, биологические нейроны игнорируют порядок поступающих данных, суммируя входящие заряды со всех дендридов без разбора как бы намекая, что мы на правильном пути.
    Теперь мы уберем информацию о количестве и попробуем описать только порядок. Перестановки возникают тут сами собой: из N объектов можно составить N! перестановок и присвоить каждой из них свой уникальный номер. Например, числа 9, 10 и 11 можно переставить 6 различными способами. Если у получателя сообщения уже есть эти числа, то передав 1 мы сообщим ему что правильный порядок для них 9, 10, 11. А для 6 правильный порядок обратный 11, 10, 9.
    Удивительно здесь то, что выделив две составляющие из числовой информаци объем передаваемых данных увеличился. Т.е. числа в том виде, к которому мы привыкли, уже сильно сжимают информацию и попытки №1 было бы достаточно на данном этапе пока мы не уйдем от чисел к чему-то более адекватному.