2.8Kпросмотров
48.8%от подписчиков
9 марта 2026 г.
📷 ФотоScore: 3.1K
#ML В прошлом посте обещал рассказать на пальцах суть RQ-VAE и семантических айдишников в рекомах. Когда написал пост понял что надо сказать важную штуку: табличные автоэнкодеры работают когда объекту уже представлены векторами, то есть у товаров (например) уже есть эмбеддинги (из другой какой-то модели, например, коллаборативный или текстовой) и мы хотим получить новые, с какими-то желаемыми нами свойствами. Если просто уменьшить размеренность с минимальными потерями — возьмем ванильный табличный автоэнкодер Обычный VAE отличается от ванильного табличного автоэнкодера только одним — нашим желанием задать распределение (обычно мнгомерное нормальное, за этим есть теоретическая база — но не будем здесь) получающихся эмбеддингов — и достигаем мы это максимально в лоб — прибавкой в лосс: к точности восстановления исходных векторов (обычный MSE между входом и выходом) мы добавляем степень похожести получающегося распределения эмбеддингов на нормальное (KL loss, например, для графового VAE здесь) Ничего, кстати, не напоминает? То есть: Ванильные AE: учим сжимать данные так, чтобы потом их восстановить (MSE loss). Вариационный AE: учим сжимать данные так, чтобы потом их восстановить (MSE loss). + чтобы эмбеддинги выглядели как выборка из заданного распределения (KL-лосс).
Буковка V (вариационный) указывает на то что мы будем искать такое распределение чтобы KL-лосс был минимальный. Задача поиска функции распределения при которой функционал, получающий на вход эту функцию распределения (в нашем случае это как раз KL-лосс), достигал экстремальных значений это вариант задачи оптимизации — и в оптимизации мы часто для поиска экстремума зануляем производную. У функционалов производная называется вариацией, вот ее и зануляем, что дает название автоэнкодеру. VQ/RQ-VAE: учим сжимать данные так, чтобы потом их восстановить + чтобы эмбеддинги были дискретными токенами. Как мы этого достигнем? Можно взять набор опорных векторов (в VQ-VAE) — он называется кодбуком — и для каждого входного вектора заменять его на ближайший вектор из кодбука (схема очень напоминает разложение по базису — но не требует создания базиса со всеми его ограничениями). А можно приближать вектор по частям, добавляя опорные векторы по очереди.: Первый ближайший опорный -> записали
Взяли разность входного и первого ближайшего опорного — получили остаток (Residual — буковку R в RQ), это тоже вектор — нашли ближайший из опорных уже к нему -> записали
и тд, как в matching pursuit в обработке сигналов. В итоге на любой входной вектор получим цепочку таких опорных векторов.
Теперь каждый опорный вектор заменяем его номером в кодбуке и любой входной вектор превращается в последовательность дискретных токенов. Невероятно сильно напоминает токенизацию в NLP. Если кодбук содержит, например k = 256 векторов, а последовательность состоит из L токенов, то уникальное число комбинаций будет k^L.
Например, 4 токена достаточно чтобы закодировать 256^4 ≈ 4.3 млрд уникальных векторов (например, разных товаров). А как такое добавить в лосс (quantisation loss) — уже дело техники. И очень полезная для инференса штука: близкие вектора по построению получают похожие последовательности токенов. Например: item A → [12, 87, 5, 41]
item B → [12, 87, 6, 39]. Более того, ANN иногда вообще не нужен — ближайших можно искать просто по совпадающим токенам. UPD Замотался и забыл:
Парни навайбкодили целую либу sematic id, потестили — и работает! Будут рады если кто-то еще потестит