Полное руководство: от основ NLP, предобработки текста и классических эмбеддингов до токенов, механизма внимания и файн-тюнинга LLM. Всё — простым языком, с математикой и схемами.
Прежде чем текст попадёт в модель, его можно рассматривать на разных уровнях детализации — от отдельных символов до целых документов. Выбор уровня влияет на то, какие закономерности модель способна уловить и насколько длинными получаются последовательности.
Отдельные символы алфавита, цифры и пунктуация. Char-level модели работают напрямую с ними — это удобно для языков без чётких границ слов и устойчиво к опечаткам, но последовательности получаются намного длиннее.
Классическая единица для большинства NLP-задач. Проблема — словоформы: «бежал», «бежит», «бегущий» формально разные слова, хотя относятся к одной лемме, из-за чего словарь быстро разрастается.
Последовательности из n соседних единиц — символов или слов. Униграммы, биграммы, триграммы позволяют захватить порядок и локальные сочетания без построения полноценной языковой модели: например, биграмма («кошка», «сидела») из предложения выше.
Уровень, на котором строится синтаксический разбор (parsing) и на котором обычно работают модели NER и извлечения отношений — сущности и связи ищутся в границах одного предложения.
Текст целиком — статья, письмо, обращение в поддержку. Здесь работают классификация документов, тематическое моделирование (topic modeling) и суммаризация, где важна общая тема, а не отдельное предложение.
Прежде чем текст можно будет векторизовать и подать в модель, он проходит через последовательность стандартных этапов очистки и нормализации. Не каждая задача требует всех этапов, но важно понимать, что делает каждый из них.
Разбиение сплошного текста на отдельные предложения. Наивный вариант — резать по «.», «!», «?», но это ломается на сокращениях («т.е.», «г.», «США») и десятичных дробях («3.14»). Поэтому используют обученные сегментаторы (например, Punkt) или языковые правила.
Приведение текста к единому виду: нижний регистр, унификация Unicode (NFC/NFKC), удаление или замена HTML-тегов, лишних пробелов, эмодзи и спецсимволов. Цель — уменьшить «случайную» вариативность, не несущую смысла для задачи.
Разбиение предложения на слова или токены — по пробелам и пунктуации (word-level) либо на суб-словные единицы. Это та же идея, что и BPE-токенизация современных LLM (раздел «Токены» ниже), только для классических NLP-пайплайнов чаще используется токенизация на уровне целых слов.
Стоп-слова — частые малоинформативные слова: предлоги, союзы, частицы («и», «в», «на», «что»). Их удаление уменьшает размер словаря и шум для моделей вроде «мешка слов». Но осторожно: в задачах тональности отрицания («не», «нет») часто несут ключевой смысл, и их удаление может всё испортить.
Оба метода приводят словоформы к общему виду, но по-разному: стемминг грубо отсекает окончания по эвристическим правилам (алгоритмы Портера, Snowball), не заботясь о существовании результата как реального слова; лемматизация приводит слово к словарной форме (лемме) с помощью морфологического анализа и словаря (pymorphy2, MyStem для русского языка).
| Исходное слово | Стемминг | Лемматизация |
|---|---|---|
| бежал | бежа | бежать |
| бегущий | бег | бежать |
| лучше | лучш | хороший |
А как же современные LLM? Модели с BPE/subword-токенизацией (раздел «Токены») обычно не требуют отдельного удаления стоп-слов, стемминга или лемматизации — сеть сама учится нужным обобщениям на больших данных. Эти этапы остаются важными для классических ML-пайплайнов, поиска по ключевым словам и там, где признаки нужно готовить вручную.
После очистки текст всё ещё остаётся последовательностью символов — модели нужны числа. Простейший способ превратить текст в вектор — посчитать, какие слова и сколько раз в нём встречаются.
Документ представляется вектором длиной со словарь V,
где на позиции каждого слова стоит число его вхождений. Порядок слов теряется полностью —
отсюда и название «мешок».
| Документ | кошка | сидела | на | плите | горячей |
|---|---|---|---|---|---|
| «Кошка сидела на плите» | 1 | 1 | 1 | 1 | 0 |
| «Кошка сидела на горячей плите» | 1 | 1 | 1 | 1 | 1 |
Ограничения BoW: вектор не различает «кошка укусила собаку» и «собака укусила кошку», размерность равна размеру словаря (десятки-сотни тысяч), а частые слова (даже после удаления стоп-слов) доминируют над редкими, но более информативными.
TF-IDF (Term Frequency – Inverse Document Frequency) уменьшает вес слов, которые встречаются почти во всех документах, и увеличивает вес тех, что специфичны для конкретного документа.
Пример: слово «плите» встречается в обоих документах — его IDF низкий. Слово «горячей» встречается только в одном — его IDF выше, и TF-IDF «подсветит» его как более различающее эти два документа.
Где используется сегодня: TF-IDF остаётся сильным бейзлайном для классификации текстов и лежит в основе поисковых ранжирующих функций (BM25 — по сути «улучшенный» TF-IDF). Но векторы по-прежнему разреженные и не отражают смысловую близость слов — для этого нужны эмбеддинги.
В отличие от BoW и TF-IDF, нейросетевые эмбеддинги представляют слово плотным вектором небольшой размерности (обычно 100–300), в котором семантически близкие слова оказываются рядом в векторном пространстве.
Word2Vec обучает эмбеддинги на простой самоконтролируемой задаче — предсказании слова по контексту или наоборот — используя два возможных варианта архитектуры:
Предсказывает целевое слово по контексту: по словам «кошка ___ на плите» модель должна угадать «сидела». Контекстные векторы усредняются, что делает CBOW быстрее и лучше подходит для частых слов.
Решает обратную задачу — предсказывает контекст по целевому слову: по слову «сидела» модель пытается угадать соседние «кошка», «на», «плите». Работает медленнее, но даёт более качественные векторы для редких слов.
В отличие от Word2Vec, который смотрит только на локальное окно вокруг слова, GloVe (Global Vectors) строит матрицу совстречаемости слов по всему корпусу и обучает векторы так, чтобы их скалярное произведение приближало логарифм числа совместных встреч.
FastText расширяет Skip-Gram идеей представлять слово как сумму векторов его символьных n-грамм. Слово «плита» раскладывается на части вроде «пли», «лит», «ита» (плюс спецсимволы границ слова), и вектор слова — их сумма.
Почему это важно для русского языка: благодаря субсловной структуре FastText умеет строить вектор даже для слова, не встречавшегося при обучении (out-of-vocabulary), и хорошо улавливает морфологию — родственные словоформы («плита», «плите», «плитой») получают близкие векторы за счёт общих n-грамм.
| Метод | Источник сигнала | OOV-слова | Морфология |
|---|---|---|---|
| Word2Vec | локальное окно контекста | нет | не учитывает |
| GloVe | глобальная матрица совстречаемости | нет | не учитывает |
| FastText | локальное окно + символьные n-граммы | да | учитывает |
Получив векторы слов, нужно уметь сравнивать их между собой и проверять, насколько хорошо они отражают реальные языковые закономерности.
Почему обычно берут косинус: длина вектора слова часто зависит от его частотности в корпусе, а не от смысла, поэтому косинусное сходство (учитывающее только угол между векторами) надёжнее отражает семантическую близость.
Проверяет сами векторы напрямую, без привязки к конкретной задаче: корреляция косинусного сходства пар слов с оценками людей (бенчмарки WordSim-353, SimLex-999), решение аналогий («король» − «мужчина» + «женщина» ≈ «королева»), качество кластеризации похожих слов.
Проверяет, насколько эмбеддинги полезны как признаки в реальной downstream-задаче: подставляем векторы в классификатор тональности, NER или систему машинного перевода и смотрим на итоговую метрику (accuracy, F1, BLEU).
Компромисс: intrinsic-оценки быстрые и дешёвые, но плохая корреляция с бенчмарком не всегда означает, что эмбеддинги бесполезны на практике. Extrinsic-оценки достовернее отражают реальную пользу, но требуют полноценного обучения downstream-модели под каждый набор эмбеддингов.
Large Language Model (LLM) — это нейронная сеть с миллиардами параметров, обученная на огромных текстовых корпусах. Её единственная задача в процессе обучения — предсказывать следующий токен (слово/символ) по предыдущим. Из этой простой задачи вырастают все остальные способности: рассуждение, перевод, написание кода.
Ключевая идея: LLM — это функция P(следующий токен | контекст). Модель не «понимает» текст в человеческом смысле — она оценивает вероятность каждого возможного продолжения и выбирает наиболее вероятное (или семплирует из распределения).
Триллионы токенов: веб-страницы, книги, код, научные статьи. GPT-4 обучен на ~13 трлн токенов.
Числа (веса) внутри сети. GPT-3 имеет 175 млрд параметров. Каждый участвует в вычислениях.
Для каждого токена модель выдаёт вектор вероятностей (logits) по всему словарю (~50к токенов).
Аналогия: представьте, что вы читаете детектив и на каждом слове загораживаете следующее — и угадываете его. Чем больше книг вы прочли, тем лучше угадываете. LLM делает то же самое, но с математической точностью и на масштабе всего интернета.
LLM не работает с буквами или словами напрямую. Текст разбивается на токены — куски текста, которые могут быть словом, частью слова или символом. Словарь строится методом BPE (Byte Pair Encoding) или SentencePiece.
Наведите на токен
Каждый токен преобразуется в числовой вектор — эмбеддинг — размерностью d_model (например, 4096 у Llama-3). Схожие по смыслу слова имеют близкие векторы в пространстве.
Зачем позиционное кодирование? Трансформер обрабатывает все токены параллельно и сам по себе «не знает» порядка. Позиционный вектор добавляется к эмбеддингу, чтобы слово «кот съел мышь» и «мышь съела кот» различались для модели.
Трансформер — это стек из N идентичных слоёв (у GPT-4 их ~96). Каждый слой принимает матрицу токен-векторов и выдаёт обновлённую матрицу того же размера. Информация течёт снизу вверх.
Каждый токен «смотрит» на все остальные токены в контексте и определяет, насколько каждый из них важен для понимания текущего токена. Механизм подробно описан в следующем разделе.
Residual connection: к выходу внимания прибавляется входной вектор. Это позволяет градиентам свободно течь при обратном распространении и предотвращает «исчезновение» информации в глубоких сетях.
Два линейных преобразования с нелинейностью между ними. Применяется независимо к каждой позиции. FFN увеличивает размерность внутри (обычно в 4×: 4096→16384→4096), «усиливая» представление.
После FFN — ещё один residual + LayerNorm. Каждый из N слоёв уточняет представление всех токенов. Нижние слои улавливают синтаксис, верхние — семантику.
Самый важный механизм в трансформере. Позволяет каждому токену «видеть» все остальные и взвешенно агрегировать их информацию. Основан на операции Q·K^T.
Аналогия: Q — это поисковый запрос в Google. K — ключевые слова страниц. V — содержимое страниц. Attention находит релевантные «страницы» (K близкие к Q) и возвращает взвешенную смесь их содержимого (V).
Нажмите на слово — увидите, как меняются веса внимания:
Веса внимания от выбранного слова:
Одной головы внимания недостаточно — разные аспекты требуют разных «взглядов». Multi-Head Attention запускает H параллельных голов, каждая со своими W_Q, W_K, W_V, и конкатенирует результаты:
Обучение — это итерационный процесс минимизации функции потерь (loss). Модель делает предсказание, сравнивает с реальным ответом, вычисляет ошибку и корректирует веса через обратное распространение ошибки.
После вычисления Loss, правило цепочки (Chain Rule) позволяет вычислить, насколько каждый вес повлиял на ошибку.
Масштаб: Llama-3 70B обучался на ~15 трлн токенов. При batch size 4М токенов это ~3.75М шагов. На каждом шаге — backward pass через 80 слоёв. Суммарно: сотни тысяч GPU-часов H100.
Проследим, как LLM обрабатывает запрос «Напиши функцию sum на Python» и генерирует ответ, задействуя все рассмотренные механизмы.
6 токенов → 6 эмбеддингов ∈ ℝ^4096 + позиционные векторы
Каждый слой применяет Multi-Head Attention (96 голов) и FFN. Слой 1: обрабатывает синтаксис («напиши» → императив → код-задача). Слои 20–40: семантические связи («sum» + «Python» → известная функция). Слои 60–80: стратегия ответа (структура кода, docstring, пример).
Голова внимания #47 слоя 38 обнаруживает: «sum» сильно аттендирует на «Python» (веса: 0.73) и «функцию» (0.18). Другие головы видят контекст «напиши» → нужен код, не определение.
Модель генерирует ответ пошагово, добавляя по одному токену за раз:
На каждом шаге: softmax(logits) → семплирование → новый токен → он добавляется к контексту
Генерация продолжается, пока не сгенерируется специальный токен <|end_of_text|>
или не достигнет max_tokens. Итоговая вероятность последовательности —
произведение вероятностей каждого токена.
Предобученная LLM — мощный «фундамент», но она обучена предсказывать текст, а не следовать инструкциям или быть полезным ассистентом. Fine-tuning адаптирует модель под конкретную задачу.
Следующий токен на триллионах токенов. Учит язык, факты, рассуждения. Base model
GPT, Llama base, Mistral base
Supervised Fine-Tuning: пары (запрос, идеальный ответ). Учит формат диалога. Instruct
ChatGPT, Claude Instant
Reinforcement Learning from Human Feedback. Модель награды + PPO. Aligned
InstructGPT, Claude, Gemini
Low-Rank Adaptation: дообучение маленьких матриц-адаптеров. Дёшево и эффективно. PEFT
Alpaca, Vicuna, домен
Вместо обновления огромной матрицы W ∈ ℝ^(d×d) добавляем две маленькие матрицы, произведение которых аппроксимирует изменение:
Модель обучается более детерминированно отвечать в нужном стиле/формате. Нижние слои (синтаксис) почти не меняются, верхние (стратегия ответа) — сильно.
Агрессивный файн-тюнинг на узких данных может «затереть» общие знания. Решение: низкий learning rate, LoRA, данные в т.ч. general-purpose.
Люди ранжируют пары ответов → Reward Model обучается предсказывать качество → PPO оптимизирует LLM по сигналу от Reward Model.
Современная альтернатива RLHF: обучение прямо на парах (хороший/плохой ответ) без отдельной Reward Model. Проще и стабильнее.
Итог: современные LLM-ассистенты (Claude, GPT-4, Gemini) = Base model (pre-training) + SFT (instruction following) + RLHF или DPO (alignment). Каждый этап добавляет новые способности, сохраняя фундаментальные знания предыдущего.
| Концепция | Роль | Ключевая формула |
|---|---|---|
| Эмбеддинг | Токен → числовой вектор | E[token_id] ∈ ℝ^d |
| Positional Encoding | Добавляет информацию о позиции | sin/cos(pos/10000^(2i/d)) |
| Attention | Контекстное взвешивание | softmax(QKᵀ/√d)·V |
| Multi-Head | Параллельные «взгляды» | Concat(head₁,...,headₕ)·Wᴼ |
| FFN | Нелинейное преобразование | max(0, xW₁)·W₂ |
| Residual | Стабильность глубоких сетей | x = LayerNorm(x + sublayer(x)) |
| TF-IDF | Классическая векторизация текста | TF(t,d) · log(N/df(t)) |
| Word2Vec | Нейросетевой эмбеддинг слова | P(context | word) |
| Softmax + Loss | Вероятности + обучение | -Σ y·log(softmax(logits)) |
| LoRA | Дешёвый файн-тюнинг | ΔW ≈ A·B, r ≪ d |