Часть 2. Вариационный автоэнкодер.
В прошлой статье мы познакомились с автоэнкодером — простой архитектурой, которая учится сжимать данные в компактное представление (латент) и восстанавливать их обратно. Мы посмотрели, как автоэнкодер работает на примере датасета MNIST и цифры «7», а также выяснили его главный недостаток: в латентном пространстве разные объекты оказываются отдельными «островками» точек, между которыми остаются пустоты. Если попробовать сэмплировать или интерполировать между этими точками, на выходе чаще всего получится нечто размытое или вовсе бессмысленное.
Если вы ещё не читали эту часть, рекомендую сначала заглянуть сюда, чтобы лучше понять отправную точку нашего путешествия:
Но на этом история не заканчивается. У исследователей возник закономерный вопрос: а можно ли сделать так, чтобы латентное пространство было не «рваным» и дырявым, а гладким и связным, чтобы любая точка в нём соответствовала осмысленному объекту?
Ответом на этот вопрос стала архитектура VAE — вариационный автоэнкодер.
В отличие от обычного AE, он кодирует каждую картинку не в одну фиксированную точку, а в целое распределение. Благодаря этому латентное пространство заполняется плавно, а генерация новых данных становится возможной.
Что такое распределение
Когда мы говорим, что VAE кодирует картинку не в точку, а в распределение, может возникнуть резонный вопрос: а что это вообще значит?
Проще всего объяснить это через пример из жизни.
Представьте, что мы измеряем рост людей. Мы точно знаем: один человек может быть 170 см, другой — 181, третий — 165. Но если мы возьмём много людей и построим график их роста, получится характерная «колоколообразная кривая». У большинства рост около среднего значения (например, 175 см), и чем дальше мы от него отходим, тем реже встречаются такие люди.
Эта кривая и есть пример распределения — оно показывает, с какой вероятностью встречаются разные значения.
Нормальное распределение
Та самая колоколообразная кривая называется нормальным распределением.
У него есть два ключевых параметра:
- среднее значение (μ) — определяет, где находится «центр» кривой;
- стандартное отклонение (σ) — показывает, насколько широко данные разбросаны вокруг центра.
Очень многие величины в мире подчиняются именно нормальному распределению:
- рост людей;
- ошибки при измерениях;
- колебания температуры.
Поэтому, когда мы строим модели в машинном обучении, нормальное распределение становится удобным и универсальным инструментом. Оно настолько хорошо описывает естественный разброс данных, что его можно встретить почти везде.
Вернёмся к нашему примеру с датасетом MNIST. Если взять все изображения цифры «7» и измерить какой-нибудь их признак — например, наклон линии или толщину штриха, — то мы, скорее всего, получим именно нормальное распределение.
- Большинство «семёрок» будут иметь средний наклон и среднюю толщину.
- Иногда встретятся экземпляры чуть более наклонённые влево или вправо.
- Совсем необычные варианты будут редкими.
Это распределение разброса признаков и есть то, что так хорошо ловит нормальное распределение: много типичных объектов и всё меньше редких по мере удаления от «среднего».
От идеи автоэнкодера к вариационному автоэнкодеру
Вспомним, как работает обычный автоэнкодер. Он получает на вход картинку, например «7», и сжимает её в один единственный латент — точку в пространстве. Декодер затем пытается по этой точке восстановить исходное изображение.
Но тут возникает идея: а почему бы не пойти дальше?
Мы только что говорили про распределения. Если в реальном мире большинство признаков (например, наклон или толщина штриха у рукописных цифр) подчиняются нормальному распределению, то почему бы вместо одной точки в латентном пространстве не хранить целое распределение?
То есть, когда мы подаём картинку «7» в энкодер, он может не просто сказать: «вот конкретный код этой картинки», как это делает AE. Вместо этого он может выдать параметры распределения — среднее значение μ и разброс σ. Эти параметры задают целое облако возможных латентов.
И тогда в латентном пространстве мы будем хранить не одну-единственную «7», а целое «семейство» семёрок, похожих на исходную.
Так мы приходим к ключевой идее вариационного автоэнкодера (VAE):
кодировать каждую картинку не в точку, а в распределение.
От точки к облаку: как VAE сглаживает пространство
В обычном автоэнкодере каждая картинка превращается в одну точку латентного пространства. В VAE вместо точки мы получаем распределение возможных значений. Удобно мыслить о нём как об окружности в двумерной картинке (в центре — μ, радиус задаёт σ); в реальности размерностей больше, поэтому это облако или эллипсоид в многомерном пространстве.
Что это даёт?
- Похожим картинкам соответствуют близкие центры (μ), а их окружности перекрываются.
- Даже для разных цифр эти облака местами могут соприкасаться и частично накладываться.
В итоге вместо россыпи разрозненных «островков» мы получаем гладкий материк: между образами есть мостики, и движение по латенту становится осмысленным. Если идти от области «7» к области «9», декодер будет порождать плавные переходы — гибридные формы, которые постепенно превращаются из одной цифры в другую. Любая точка из «обжитых» областей даёт правдоподобное изображение, а не случайный мусор.
Ещё одна важная деталь: во время обучения VAE специальный штраф (KL-дивергенция) мягко подтягивает облака к общему знаменателю — стандартному нормальному распределению. Это помогает «сшивать» пространство и уменьшать дырки между облаками. Полностью их убрать невозможно (данные не заполняют весь многомерный объём), но латент становится заметно более связным, чем в обычном AE.
Итог: представление «не точкой, а облаком» превращает латент в непрерывную карту, по которой можно безопасно перемещаться — генерировать новые варианты знакомых образов и делать интерполяции между разными классами.
Где VAE спотыкается
У VAE есть один заметный минус: он генерирует размытые картинки. На простых примерах вроде MNIST это не бросается в глаза — цифры маленькие, чёрно-белые и низкого разрешения, так что «мыльность» не портит впечатление. Но если мы попросим VAE сгенерировать лицо человека или фотографию предмета, результат получится таким, что вряд ли устроит кого-то: детали будут смазанными, черты расплывшимися.
Почему так происходит? Представим себе цифру «7». В датасете MNIST она встречается во множестве вариантов:
- с наклоном влево,
- с наклоном вправо,
- с толстой или тонкой линией,
- написанная плавным движением или резким штрихом.
Энкодер VAE переводит каждую такую «7» в распределение латентов. А декодеру приходится учиться восстанавливать цифру из любой точки этого облака. Чтобы справиться с такой задачей, он невольно выбирает компромисс — рисует среднюю семёрку, которая хоть как-то похожа на все варианты сразу. Но средний вариант всегда чуть размытый.
Поэтому, когда мы говорим о генерации фотографий высокого качества, VAE оказывается недостаточен. Он хорош для обучения структуры данных, но не умеет в реализм.
Итоги
Мы начали с автоэнкодера и увидели его главный недостаток — «дырявое» латентное пространство, в котором интерполяции и новые сэмплы почти всегда давали мусор.
Затем познакомились с вариационным автоэнкодером. Его ключевая идея проста: вместо того чтобы кодировать каждую картинку в одну точку, он переводит её в распределение. В латентном пространстве это превращает отдельные точки в облака, которые могут перекрываться, образуя гладкую и связную структуру. Благодаря этому VAE уже умеет не только восстанавливать изображения, но и генерировать новые варианты и даже делать плавные переходы между разными объектами.
Однако у этой модели есть серьёзные ограничения. VAE часто генерирует размытые картинки, потому что усредняет разные варианты внутри распределения. Для маленьких картинок вроде цифр MNIST это не проблема, но если речь идёт о лицах или предметах — результат будет слишком «мыльным» и неубедительным.
Именно эта проблема подтолкнула исследователей к созданию новых подходов — сначала GAN, а затем и диффузионных моделей. В следующей статье мы разберём, как GAN смогли добиться куда большей реалистичности изображений.
Если ты дочитал до этого момента, то похоже тебе и правда интересна эта тема.
А теперь, если отбросить все эти умные размышления - можешь попробовать различные способы генерации от популярных нейросетей в нашем телеграм-боте:
Уже доступна Nano Bana