FastText

Материал из MachineLearning.

Версия от 05:40, 17 июля 2026; Aleksandr Iakovlev (Обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск
Статья написана с использованием LLM GPT-5.6 Sol xhigh и проверено участником Aleksandr Iakovlev 09:40, 17 июля 2026 (MSD)


Содержание

FastText (стилизованное название библиотеки — fastText) — семейство методов и программная библиотека для обучения статических векторных представлений слов и быстрой классификации текстов. Отличительная особенность модели представлений слов состоит в том, что слово описывается не только собственным вектором, но и суммой векторов его символьных n-грамм. Благодаря совместному использованию параметров между похожими словоформами модель может строить векторы редких и отсутствовавших в словаре слов. FastText был разработан в лаборатории Facebook AI Research (FAIR); исходный код открыт в 2016 году.[1]

Название FastText употребляется в трёх связанных, но различных смыслах:

  • подсловная модель представлений слов — расширение skip-gram, предложенное П. Бояновским и соавторами;[1]
  • эффективный линейный классификатор текстов — модель А. Жулена и соавторов, использующая усреднённые признаки слов и n-грамм слов;[1]
  • библиотека fastText — реализация на C++ с интерфейсом командной строки, официальными привязками Python и WebAssembly.

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

История

Непосредственным предшественником подсловной модели является skip-gram из семейства Word2vec. В Word2vec каждому слову словаря соответствует отдельная строка матрицы параметров. Такая параметризация не разделяет статистическую информацию между родственными словоформами и не даёт собственного вектора слову вне словаря.

В июле 2016 года были опубликованы предварительные версии двух работ FAIR: о быстром классификаторе текстов и о представлениях слов с подсловной информацией. 18 августа 2016 года FAIR объявила об открытии библиотеки fastText.[1] Работа о классификации вышла в сборнике EACL 2017, а работа о символьных n-граммах — в пятом томе TACL в 2017 году.[1][1]

Позднее библиотека получила официальные привязки для Python, квантование моделей, автоматический подбор гиперпараметров и WebAssembly-интерфейс. Последняя версия, отмеченная в официальном репозитории как выпуск, — 0.9.2. 19 марта 2024 года владелец архивировал репозиторий: код и документация остаются доступными, но репозиторий работает в режиме только для чтения.[1]

Подсловная модель представлений слов

Связь со skip-gram

Пусть корпус задан последовательностью слов w_1,\ldots,w_T, а C_t — мультимножество контекстных слов в окне вокруг w_t. Обычная skip-gram-модель максимизирует вероятность контекстов при центральных словах. При полном softmax

p(c\mid w)=\frac{\exp(s(w,c))}{\sum_{u\in V}\exp(s(w,u))},

где V — словарь, а s — скалярная оценка совместимости. Вычислять знаменатель по всему словарю дорого, поэтому на практике применяются отрицательное сэмплирование или иерархический softmax. FastText сохраняет постановку skip-gram, но заменяет атомарный входной вектор слова композицией подсловных векторов.

Символьные n-граммы

К началу и концу слова добавляются специальные символы границы. Для слова машина рассматривается строка <машина>. При стандартных длинах от 3 до 6 среди её n-грамм находятся:

  • 3-граммы: <ма, маш, аши, шин, ина, на>;
  • 4-граммы: <маш, маши, ашин, шина, ина>;
  • более длинные фрагменты, например машин, машина и <машин.

Границы позволяют различать одинаковые последовательности внутри слова и у его края. Для словарного слова к набору признаков добавляется также отдельный идентификатор самого слова. Обозначим множество его признаков через G_w, вектор признака g — через z_g\in\mathbb R^d, а выходной вектор контекстного слова c — через v_c. В статье Бояновского и соавторов оценка имеет вид

s(w,c)=\sum_{g\in G_w} z_g^{\mathsf T}v_c.

Таким образом, входное представление слова является суммой подсловных векторов. В официальной реализации скрытый вектор и возвращаемый методом get_word_vector вектор вычисляются как среднее соответствующих строк матрицы, то есть сумма дополнительно делится на |G_w|. Это нормировка масштаба, а не замена принципа композиции.

Хеширование n-грамм

Хранить отдельную строку матрицы для каждой встретившейся символьной n-граммы не требуется. Строка g отображается функцией FNV-1a в один из B бакетов:

h(g)={\rm FNV1a}(g)\bmod B.

Вектором n-граммы служит строка z_{h(g)} общей таблицы бакетов. Значение B ограничивает память независимо от числа различных подстрок; стандартное значение для unsupervised-режима библиотеки — 2 000 000. Обратная сторона хеширования — коллизии: разные n-граммы могут обновлять один вектор. Увеличение B уменьшает число коллизий, но линейно увеличивает память. Сам список строк n-грамм в модель не сохраняется, поэтому по одному индексу бакета нельзя однозначно восстановить исходную подстроку.

Целевая функция

При отрицательном сэмплировании для наблюдаемой пары центрального и контекстного слов (w,c) выбираются k шумовых слов n_1,\ldots,n_k. Обозначив логистическую функцию через \sigma(x)=(1+e^{-x})^{-1}, минимизируемый функционал можно записать как

\mathcal L_{\rm SGNS}=-\sum_{t=1}^{T}\sum_{c\in C_t}\left[\log\sigma(s(w_t,c))+\sum_{i=1}^{k}\log\sigma(-s(w_t,n_i))\right].

Градиент положительной пары сближает составной вектор w_t с выходным вектором c, а градиенты шумовых пар раздвигают их. Обновление распределяется по всем бакетам из G_{w_t}; поэтому наблюдение одной словоформы обучает признаки, которые могут участвовать в других словах. Это главное отличие от SGNS в обычном Word2vec, а не новая схема выбора контекста.

Редкие и неизвестные слова

Если редкое слово отфильтровано параметром minCount, оно теряет отдельную словарную строку, но его характерные подстроки могут обучаться в составе более частых слов. Для неизвестного на этапе применения слова w\notin V библиотека строит его символьные n-граммы, хеширует их и складывает доступные векторы бакетов:

\hat z_w=\frac{1}{|G_w|}\sum_{g\in G_w}z_{h(g)}.

Поэтому OOV-слово получает вычислимое представление без повторного обучения и без специального токена неизвестного слова. Качество, однако, зависит от того, насколько его фрагменты были обучены на содержательном материале. Опечатка или новая словоформа часто наследует полезный вектор, но случайная строка, идентификатор или слово с обманчивым орфографическим сходством могут получить плохое представление. FastText не устраняет многозначность: у одного написания по-прежнему один статический вектор.

Пошаговый алгоритм для одного слова

Для центрального слова машина один шаг обучения выглядит так:

  1. добавить границы < и >;
  2. перечислить символьные n-граммы длины от minn до maxn и добавить словарный идентификатор слова;
  3. вычислить для каждой n-граммы FNV1a(ngram) mod bucket;
  4. сложить или усреднить строки входной матрицы по полученным индексам;
  5. выбрать наблюдаемое контекстное слово, например едет, и neg шумовых слов;
  6. вычислить положительную и отрицательные логистические потери;
  7. обновить выходные векторы контекстов и все входные строки, участвовавшие в композиции слова.

В псевдокоде:

grams    = char_ngrams("<машина>", minn, maxn)
indices  = [word_id("машина")] + [vocab_size + FNV1a(g) mod bucket for g in grams]
hidden   = average(input_matrix[indices])
targets  = [("едет", +1)] + [(n, -1) for n in sample_negative_words(neg)]
for target, sign in targets:
    loss += -log(sigmoid(sign * dot(hidden, output_vector[target])))
backpropagate loss to output_vector and every input_matrix[indices]

Классификация текстов

Supervised-модель fastText не следует смешивать с подсловной skip-gram-моделью. В исходной работе о классификации документ представляется мешком слов и, при необходимости, n-грамм слов; эти n-граммы передают часть информации о локальном порядке. В библиотеке символьные n-граммы в supervised-режиме по умолчанию отключены (minn=maxn=0), но могут быть включены явно. Параметр wordNgrams относится именно к последовательностям слов.

Пусть x содержит m признаков документа, A\in\mathbb R^{F\times d} — таблица их эмбеддингов, а B\in\mathbb R^{L\times d} — параметры L меток. Скрытое представление равно

h(x)=\frac{1}{m}\sum_{i\in x}A_i.

Для обычного softmax вероятность класса y равна

p(y\mid x)=\frac{\exp(B_y^{\mathsf T}h(x))}{\sum_{j=1}^{L}\exp(B_j^{\mathsf T}h(x))},

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

При большом числе классов полный softmax заменяется иерархическим softmax. Метки размещаются в листьях дерева Хаффмана, а каждому внутреннему узлу соответствует бинарный классификатор. Если путь к метке y содержит узлы q_1,\ldots,q_{\ell(y)} и направления b_j(y)\in\{-1,+1\}, то

p(y\mid x)=\prod_{j=1}^{\ell(y)}\sigma\!\left(b_j(y)u_{q_j}^{\mathsf T}h(x)\right).

Для одного примера обновляются только узлы его пути. Стоимость вывода сокращается с O(Ld) для полного softmax до O(\ell(y)d), обычно порядка O(d\log L). Дерево Хаффмана даёт более короткие пути частым меткам и уменьшает среднюю стоимость. Для настоящей многометочной классификации библиотека также предоставляет независимые классификаторы one-vs-all; вероятности обычного softmax взаимно конкурируют и не всегда подходят для этой постановки.

Параметры и вычислительная сложность

Основные параметры обучения представлений слов:

  • dim — размерность d (по умолчанию 100);
  • ws — максимальный радиус контекстного окна (5);
  • epoch — число проходов по корпусу (5);
  • lr — начальная скорость обучения (0,05 для unsupervised-режима);
  • minCount — минимальная частота словарного слова (5);
  • minn, maxn — минимальная и максимальная длина символьной n-граммы (3 и 6);
  • bucket — число хеш-бакетов (2 000 000);
  • neg — число отрицательных примеров (5);
  • t — порог субсэмплирования частых слов (10^{-4});
  • thread — число потоков обучения.

Пусть q — среднее число подсловных признаков центрального слова, k — число отрицательных примеров, r — среднее число контекстных слов, а T — число токенов за все эпохи. Один шаг SGNS требует порядка O((q+k)d) операций, а обучение — O(Tr(q+k)d). Оценка не учитывает небольшие затраты на токенизацию и хеширование. Входная матрица unsupervised-модели содержит строки словаря и бакетов, выходная — строки контекстных слов, поэтому основная память имеет порядок

O\!\left((2|V|+B)d\right).

Увеличение диапазона n-грамм повышает q; увеличение bucket почти не меняет число операций на пример, но увеличивает память. Многопоточное обучение выполняется асинхронным стохастическим градиентным спуском, поэтому точная воспроизводимость чисел между запусками с разным числом потоков не гарантируется.

Морфологически богатые языки

Подсловная композиция особенно полезна языкам с большим числом словоформ: формы с общим корнем и аффиксами совместно обучают часть параметров. Для русского слова машинами признаки маш, машин и фрагменты окончания связывают его с формами машина, машины и машиной. Это снижает разреженность без обязательной лемматизации и было основной мотивацией многоязычных экспериментов авторов.[1]

Символьная n-грамма не является морфемой. Модель не знает правил словоизменения, может переоценивать случайное сходство написаний и хуже описывает неконкатенативную морфологию или семантику, не выраженную локальными подстроками. Результат зависит от токенизации, регистра, нормализации Unicode и состава корпуса. Официальный токенизатор разделяет текст по ограниченному набору ASCII-символов пробела; необычные пробельные символы UTF-8 следует нормализовать заранее.[1]

Сравнение с другими моделями

Метод Единица параметризации Неизвестные слова Зависимость от контекста Характерные свойства
FastText (представления слов) слово и хешированные символьные n-граммы вектор составляется из n-грамм один вектор на написание быстрый, учитывает орфографическую и морфологическую структуру
Word2vec отдельное слово словаря собственного вектора обычно нет один вектор на слово та же основа CBOW/skip-gram, меньше параметров композиции
GloVe отдельное слово и глобальные счётчики совместной встречаемости собственного вектора обычно нет один вектор на слово явно использует глобальную матрицу совместной встречаемости
Контекстные модели (ELMo, BERT и последующие) токены или подсловные токены вместе с окружением применяют собственную подсловную токенизацию вектор зависит от предложения лучше различают значения, но обычно требуют больше памяти и вычислений

FastText предпочтителен, когда нужны компактные статические признаки, быстрый CPU-вывод, обработка множества словоформ или сильная базовая модель классификации. Контекстная модель предпочтительнее, если смысл омонима и дальние связи в предложении критичны. Сопоставление не следует трактовать как универсальный рейтинг: методы решают разные задачи и зависят от данных и критерия качества.

Достоинства и ограничения

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

Ограничения следуют из тех же упрощений. Представления статичны и не различают значения слова в разных контекстах. Хеш-коллизии смешивают несвязанные признаки. Орфографическая близость не гарантирует семантическую, а качество OOV не возникает «из ничего»: нужны обученные родственные n-граммы. Мешок признаков классификатора теряет дальний порядок слов; n-граммы слов передают лишь локальный порядок. В библиотеке отсутствует встроенная сложная лингвистическая предобработка. Наконец, официальный репозиторий архивирован, что важно учитывать при выборе зависимости для нового программного проекта.

Библиотека и пример использования

Официальная библиотека написана на C++11 и распространяется по лицензии MIT.[1] Она поддерживает команды skipgram, cbow, supervised, test, predict, print-word-vectors, квантование и автоматический подбор гиперпараметров. Бинарный файл .bin хранит полную модель и позволяет строить векторы OOV; текстовый .vec содержит только экспортированные векторы слов словаря и сам по себе подсловного вывода не обеспечивает.

Безопасный воспроизводимый пример предполагает уже установленный локальный исполняемый файл и подготовленный UTF-8-корпус corpus.txt; команды не загружают данные и не изменяют системные каталоги:

fasttext skipgram -input corpus.txt -output model_ru -dim 100 -ws 5 -minn 3 -maxn 6 -bucket 2000000 -neg 5 -epoch 5 -thread 4
fasttext print-word-vectors model_ru.bin < queries.txt

В queries.txt помещают по одному слову на строку, включая редкие или отсутствовавшие в корпусе формы. Для классификации каждая строка обучающего файла должна содержать хотя бы одну метку с префиксом __label__, например __label__science новый метод обработки текста:

fasttext supervised -input train.txt -output classifier -loss hs -wordNgrams 2 -dim 100 -epoch 25 -thread 4
fasttext test classifier.bin test.txt 1

Разбиение на обучение и контроль, кодировку, нормализацию и параметры необходимо фиксировать отдельно; напечатанные программой показатели относятся только к переданным данным. Универсальных значений качества эти команды не обещают.

См. также

Литература