Введение
Генеративно-состязательные сети (Generative Adversarial Networks, GAN) – это большой класс генеративных моделей, общая черта которых заключается в том, что они обучаются одновременно с другой сетью, которая старается отличить сгенерированные объекты от настоящих. В этом параграфе мы рассмотрим основы основ GAN-ов, интуитивное объясним принципы их работы, а также детально погрузимся в многочисленные приёмы и модификации оригинального подхода, которые применяются в наиболее успешных моделях. Мы также приведём примеры нескольких типов практических задач, в которых применяются генеративно-состязательные сети.
Генеративно-состязательные сети — это неявная генеративная модель. То есть она не восстанавливает плотность данных в явном виде, но умеет сэмплировать из распределения данных. Самый простой и эффективный дизайн генеративных моделей, которые умеют только сэмплировать, но не умеют оценивать плотность, – это отображение одних случайных величин в другие.
Подобного вида модель после обучения работает следующим образом: пусть – случайная величина, обозначающая сэмпл из распределения нужных нам данных (например, картинок с нарисованными цифрами), а – сэмпл из какого-то распределения, который нам легко получить (например, каждая его компонента берётся из стандартного нормального). Тогда, если у нас есть обученная функция , которая переводит сэмплы из в сэмплы из , то процесс генерации происходит в два этапа: сначала мы случайным образом получаем вектор , а затем отображаем его в :
Ключевым вопросом в таких моделях является соотношение размерностей и . Есть генеративные модели, где . Примером таких подходов являются, например, нормализующие потоки. В случае генеративных состязательных сетей (как и другого класса популярных генеративных моделей, вариационных автоэнкодеров), . Поэтому работу этих моделей можно рассматривать как поиск многообразия размерности среди всех случайных примеров из домена, на котором определяется . Например, в случае генерации цифр это соответствует поиску в домене , где – это ширина картинки, а – её высота, подмножества, в котором каждый элемент изображает какую-либо цифру. Таким образом, задача обучения генеративных состязательных сетей может рассматриваться как задача компрессии данных в низкоразмерное представление.
Основы обучения GAN-ов
Классическая аналогия того, как учатся GANы — это фальшивомонетчик и полицейский. Задача фальшивомонетчика — научиться создавать купюры, которые полицейский не сможет отличить от реальных. Задача полицейского — научиться отличать купюры фальшивомонетчика от настоящих.
Чтобы понять, как обучаются GANы, надо представить себе следующий мысленный эксперимент. Допустим, фальшивомонетчик и полицейский — друзья, которые решили поучиться друг у друга. Фальшивомонетчик создаёт несколько фальшивых купюр и показывает полицейскому. Полицейский говорит фальшивомонетчику, какие из его купюр, по его мнению, поддельные, а какие — настоящие. Фальшивомонетчик запоминает отзыв полицейского и в следующий раз улучшит свои купюры на основе отзыва от полицейского. Сам полицейский при этом тоже учится: он запоминает, что купюры, которые он видел — поддельные.
В нашем мысленном эксперименте представим, что фальшивомонетчик взаимодействует с полицейским много раз. Что получается в результате? С каждым разом купюры фальшивомонетчика всё труднее отличить от настоящих. И с каждым разом умение выявлять поддельные купюры у полицейского выше.
Важный вопрос для понимания работы GANов: в какой момент мы можем утверждать, что фальшивомонетчик хорошо подделывает купюры?
Ответ:
Когда фальшивомонетчик сможет обманывать сильного полицейского. В начале нашего эксперимента полицейский плохо отличает подделку от оригинала. Поэтому обмануть его можно купюрами плохого качества. Нам же интересно получить фальшивомонетчика, который будет выдавать купюры, неотличимые от оригинала даже профессионалом.
Рассмотрим задачу обучения более формально. Пусть у нас есть генератор (фальшивомонетчик) с параметрами , и дискриминатор (полицейский) с параметрами . Генератор отображает векторы в , распределение которых приближает реальное распределение данных . Дискриминатор каждому реальному сэмплу и фейковому ставит в соответствие вероятность , которая оценивает степень принадлежности к реальным данным, т.е. он решает задачу бинарной классификации. Самый простой способ это сделать – при помощи минимизации бинарной кросс-энтропии:
Учитывая обозначение , и то, что мы пытаемся максимизировать вероятность принадлежности к реальным данным, как её оценивает дискриминатор, задачу, которую решает генератор, можно расписать следующим образом (используя свойство выпуклости логарифма):
Это равенство позволяет записать задачи, которые решают генератор и дискриминатор, вместе. (Мы также избавимся от лишних минусов, сделав так, чтобы дискриминатор решал задачу максимизации.)
Получается, что на самом деле генератор и дискриминатор пытаются оптимизировать одну функцию: генератор её минимизирует, а дискриминатор максимизирует. Обозначим эту функцию (минус бинарную кросс-энтропию) как . Тогда эту задачу оптимизации можно записать в сокращённом виде:
По параметрам дискриминатора минимум бинарной кросс-энтропии (или минимум по ) достигается на следующей функции – оптимальном дискриминаторе для фиксированного генератора:
Её оптимальность нетрудно проверить, используя выпуклость логарифма. Учитывая это, и формулу для , интуицию работы метода обучения GANов со стороны генератора можно сформулировать следующим образом:
- Мы замеряем, насколько реалистичными являются сгенерированные сэмплы , используя для этого оптимальный дискриминатор .
- Мы хотим увеличить отклик дискриминатора на каждом сэмпле, т.е. пытаемся модифицировать каждый предсказанный элемент так, чтобы на нём стало выше значение .
Ещё более простую интуицию для этой задачу можно сформулировать следующим образом. Как нужно модифицировать плотность , чтобы она стала ближе к , если к плотности распределения мы имеем доступ только через сэмплы из него? Визуализацию желаемых градиентов по случайным сэмплам для задачи сопоставления двух гауссиан можно видеть на графике ниже, где .
Направленные вниз стрелки показывают, насколько нужно уменьшить координаты точек из распределения , чтобы получилось нечто максимально похожее на . То есть на самом деле точки будут сдвигаться на то же самое расстояние влево.
Формализуем эту интуицию, и заодно поймём, почему вообще такой метод должен работать. Подставив выражение для оптимального дискриминатора в , мы можем избавиться от внутренней максимизации в исходной задаче и оставить только внешнюю минимизацию по параметрам генератора. Тем самым, мы получим в явном виде функцию потерь, которую минимизирует генератор (обозначим её за ). Для неё мы распишем математическое ожидание через интеграл и упростим дроби:
Упростим выражение для ещё раз, прибавив и отняв константу , а также учитывая, что и :
Здесь означает, как обычно, KL-дивергенцию
которая показывает, насколько два распределения отличаются друг от друга. Через обозначает ещё один вид дивергенции (её называют дивергенцией Йенсена-Шеннона). Получается, что при оптимальном дискриминаторе генератор, решая внешнюю задачу оптимизации, уменьшает расстояние между распределениями реальных и фейковых данных, действительно приближая их друг к другу!
Исходя из этого, и в предположении достаточной capacity генератора и дискриминатора (т.е. предполагая, что их параметризация позволяет достичь оптимума), мы можем сформулировать первый, наивный алгоритм обучения генеративно-состязательных сетей.
-
Решить внутреннюю задачу максимизации по , повторяя шаги ниже до сходимости по параметрам дискриминатора к оптимальному значению :
— Составить мини-батч сэмплов шума из .
— Составить мини-батч сэмплов данных из .
— Обновить дикриминатор, сделав шаг вверх по его градиенту: -
Сделать шаг SGD для внешней задачи минимизации по :
— Составить мини-батч сэмплов шума из .
— Обновить генератор, сделав шаг вниз по его градиенту:где через мы для краткости обозначили .
Какие у этого наивного подхода могут быть недостатки? Во-первых, он очень медленный, потому что необходимо обучать дискриминатор до сходимости, чтобы сделать всего один шаг по градиенту генератора. Но вторая проблема намного серьёзнее: функция потерь генератора может насыщаться и выдавать близкие к нулю градиенты. Проиллюстрируем это на примере обучения простой модели, которая будет сэмплировать из одномерной гауссианы с заданными параметрами.
Распределение в этом случае известно, а распределение мы можем получить с помощью методов оценки плотности по сэмплам. Визуализируем эти плотности, а также градиент по сэмплам из генератора (a). Видно, что в случае, когда пики распределений плохо пересекаются друг с другом, градиент будет равен нулю на большинстве сэмплов, которые выдаёт генератор, т.е. они никак не будут использоваться для обучения. Чтобы понять причину происходящего, давайте посмотрим на градиент функции потерь генератора. На точках, далёких от основной «массы» , дискриминатор выдаёт что-то близкое к нулю, то есть знаменатель градиента практически не будет ни на что влиять, а в числителе тоже будет практически ноль: ведь если мы немного поменяем параметры генератора, то «плохие» точки по-прежнему будут далеки от , так что изменение лосса будет пренебрежимо малым, и градиент тоже.
Это приводит к тому, что обучение происходит недостаточно эффективно: мы тратим время на вычисление сэмплов, которые не делают никакой вклад в обновление параметров генератора. Но более существенная проблема возникает в вырожденном случае: если изначально два распределения практически не пересекаются своими плотностями (b): в этом случае процесс обучения практически не идёт. Часто ли встречается такая вырожденная ситуация на практике? Довольно часто! Достаточно представить себе ситуацию, когда мы хотим генерировать реалистичные изображения лиц, а генератор в начале обучения вместо этого выдаёт случайный шум. Из-за наличия такой проблемы описанная выше функция потерь генератора называется «сатурирующей».
В оригинальном подходе по обучению генеративно-состязательных сетей было предложено два решения этой проблемы. Во-первых, мы можем обучать дискриминатор на каждой итерации не до сходимости, а с небольшим фиксированным числом шагов (на практике чаще всего используется ). Это позволяет существенно улучшить исходную ситуацию с переобучением дискриминатора. Также мы могли бы улучшить функцию потерь для генератора, сделав так, чтобы она сглаживала выходы дискриминатора около нуля. В качестве такой функции изначально был предложен логарифм. Нетрудно видеть, что оптимум улучшенной функции потерь («несатурирующий лосс») совпадает с исходной, что позволяет сохранить все описанные выше теоретические гарантии:
Точка минимума у новой функции потерь та же, что у исходной, а градиенты оказываются ненулевыми на всех сгенерированных сэмплах.
Помимо этого, на практике вместо обычного метода стохастического градиентного спуска используются его модификации, которые учитывают и первые, и вторые моменты градиентов например, Adam. Вообще, GAN-ы – довольно капризные модели, и настоятельно рекомендуется использовать готовые реализации с GitHub, оставляя большую часть гиперпараметров без изменений. Наиболее критичными среди них являются learning rate и расписание (то есть количество обновлений дискриминатора на одно обновление генератора).
Метрики качества
После успешного обучения генератора хотелось бы также понять, насколько хорошо он работает. Для этого рассмотрим на примере задачи генерации изображений типовые ошибки, которые может совершать GAN. Наиболее частая проблема – плохое качество или наличие артефактов – вызвана ограничениями, связанными с capacity генератора и несовершенством самих методов обучения. Здесь всё просто: наша генеративная модель плохо работает, и мы это видим на сгенерированных сэмплах. Более скрытым видом ошибок является так называемый mode collapse: обученный генератор выдаёт реалистично выглядящие картинки, но они не покрывают всё разнообразие распределения . Например, если наша модель учится генерировать изображения с животными, то она может проигнорировать более редкие виды, а научиться генерировать только наиболее часто встречающиеся. Более экстремальная форма подобного поведения – это когда модель вообще выдаёт вариацию одной картинки. Иногда в литературе общее качество результатов работы нейросети, по аналогии с задачей классификации, измеряется точностью метода (precision), а отсутствие mode collapse измеряется полнотой (recall).
Самый простой и действенный способ измерить как precision, так и recall – сгенерировать данные и посмотреть на них, дав экспертную оценку уровня их реализма. Не стоит им пренебрегать! Формализовать этот подход в метрику можно в виде эксперимента, который в литературе называется user study. Например, мы можем сделать опрос экспертов, которым будем показывать два примера, настоящий и сгенерированный, и попросить их угадать, где фейк. Тогда процент неправильных ответов будет являться метрикой качества для нашего метода. Такой опрос в основном показывает степень реализма полученных результатов: есть ли в них какие-то заметные артефакты, соответствуют ли они реальным примерам по своей структуре, и так далее. Отчасти он также замеряет разнообразие примеров: то, насколько они хорошо покрывают носитель распределения . Если обученная модель генерирует очень похожие друг на друга примеры (то есть имеет место существенный mode collapse), то эксперт через несколько примеров научится определять ненастоящие. С другой стороны, если сэмплы в целом разнообразные, но всё равно не полностью покрывают основу целевого распределения, то user study не позволит обнаружить эту проблему.
Frechet Inception Distance
Есть метрики, с помощью которых можно автоматически проводить тестирование, похожее на user study. Для изображений наиболее используемой является Frechet Inception Distance (FID). Чтобы её посчитать, нам в идеале понадобится нейросеть, предобученная на датасете, который мы генерируем, но на практике во всех случаях используется модель Inception v3, предобученная на датасете ImageNet (отсюда слово Inception в названии метрики).
Для того, чтобы понять идею этой метрики, рассмотрим следующий пример: если выходом нейросети является класс (число), то его вероятность можно смоделировать мультиномиальным распределением. Гипотетически, чтобы сравнить два распределения картинок и , нам достаточно измерить расстояние между двумя мультиномиальными распределениями, построенными на выходах предобученного классификатора после прогона датасетов реальных и сгенерированных данных. Если в распределении примеров из каких-то классов будет меньше или больше, чем в , то такая метрика будет отличная от нуля.
Понятно, что это слишком грубое приближение расстояния между двумя распределениями, т.к. оно практически никак не учитывает реализм получаемых картинок. Поэтому вместо выходов нейросети в FID было предложено использовать признаки с её глубоких слоёв. Они кодируют высокоуровневую семантику изображений, потому что по этим признакам модель предсказывает вероятность принадлежности картинки к тому или иному классу. При этом в них остаётся довольно много информации об исходном изображении и свойств локальных признаков (текстур), которые могут помочь распознать артефакты. Метрика FID работает таким образом, что сравнивает два распределения высокоуровневых признаков для реальных и сгенерированных картинок, используя в качестве их приближения многомерные гауссианы (каждая размерность соответствует одному каналу). Для измерения расстояния между этими двумя распределениями используется метрика Вассерштейна:
где и – это среднее и матрица ковариаций глубоких признаков , которые считаются по выборке из реальных картинок. При этом как средние, так и матрицы ковариаций считаются по объединению всех признаков со всех картинок без учёта пространственной размерности, т.е. по второй размерности матрицы . То же самое делается для сгенерированных картинок, для них средние и ковариации обозначены как и . Минимум этой метрики равен нулю, и достигается в случае, когда статистики, посчитанные по двум распределениям, совпадают. На практике эта метрика используется как для измерения реализма изображений, так и для детектирования mode collapse.
Интерполяции в скрытом пространстве
Ещё один способ измерения качества, который мы рассмотрим, напрямую связан с тем, что генеративно-состязательные модели эффективно занимаются кодированием потенциально высокоразмерных данных в низкоразмерное представление. Но как для нейросети с большим числом параметров проверить, занимается ли она реальным кодированием или простым запоминанием выборки?
Рассмотрим следующий пример. Пусть наша генеративная модель к случайным векторам применяет их функцию распределения и отображает векторы в равномерно распределённые на отрезке числа . Упорядочим наш датасет. В качестве случайного сэмпла пусть наша модель выдаёт ту картинку, чей индекс, поделённый на размер датасета, ближе всего к . Другими словами, наша генеративная модель будет выдавать случайные картинки из датасета вместо генерации новых картинок. Методы оценки качества, которые мы описали выше, пропустят эту проблему: ведь «сгенерированные» картинки будут в точности совпадать с настоящими. Поэтому для полной проверки качества работы генеративной модели важно понимать, действительно ли она производит сжатие выборки в низкоразмерное представление или просто запоминает обучающие примеры.
Одним из тестов на подобное поведение является интерполяция между сгенерированными примерами. Возьмём два случайных вектора и из . Рассмотрим все векторы, которые лежат между ними $z = \alpha z_1 + (1 - \alpha) z_2,\ \alpha \in [0, 1]$. К каждому такому вектору применим наш генератор и получим для промежуточных векторов и для и . Для правильно обученного GANа мы должны увидеть следующую картинку: при изменении коэффициента изображение должно плавно меняться и перетекать из в . При этом каждая промежуточная картинка должна быть так же реалистичным сэмплом.
Качество такой интерполяции сложно измерить численно, но если мы видим, что промежуточные результаты меняются случайно без какой-либо связи с семантикой интерполируемых примеров, то это говорит о плохом качестве генератора. Стоит упомянуть, что для сэмплов из нормального распределения, которое обычно имеют векторы , намного лучше работает интерполяция по сфере (Slerp), потому что в многомерном пространстве векторы практически всегда будут лежать в объёме вокруг сферы диаметра , где – размерность вектора .
Интерполяция в скрытом пространстве с недавних пор стала использоваться для генерации анимаций и видео. Ведь анимация — это последовательность кадров, плавно переходящих друг в друга. И если у нас есть обученный GAN для генерации картинок, то нам нужно лишь найти путь в скрытом пространстве таким образом, чтобы набор сгенерированных картинок складывался в анимацию. Более того, в скрытом пространстве можно находить различные интерпретируемые пути. Например, путь, при движении по которому размывается задний фон или меняется причёска. Почитать подробнее про это можно тут.
Ближайшие соседи
Ещё одним способом проверить, не запомнил ли генератор датасет, является поиск ближайших соседей по датасету. Для этого следует сгенерировать несколько изображений. Для каждого изображения нужно найти несколько ближайших соседей из датасета. В качестве признаков для картинок можно взять признаки с последних слоёв сети Inception. На соседей стоит посмотреть глазами. Если мы увидим, что ближайшие соседи из датасета визуально совпадают со сгенерированными сэмплами, то это значит, что генератор запомнил сэмплы из датасета.
Базовые модели
Чтобы лучше понимать современные модели, давайте сначала рассмотрим более базовые модели. Хотя они редко используются напрямую, многие идеи из них легли в основу современных моделей.
DCGAN
Наиболее простая версия генеративной модели для изображений — это DCGAN (Deep Convolutional GAN, 2015 год). Её до сих пор можно иногда встретить как в литературе, так и на практике.
В основе DCGAN лежит простая идея: нейросети, основанные на свёртках, отлично подходят для распознавания изображений, а значит вполне могут подойти и для их генерации. Единственное отличие, которое требуется – это постепенно увеличивать внутри нейросети пространственный размер признаков, а не уменьшать. Для этого в современных нейросетях делается операция nearest upsampling, очень похожая на max pooling. В nearest upsampling пространственное разрешение карты признаков увеличивается за счёт того, что каждый вектор повторяется раз по горизонтали и по вертикали. К примеру, после увеличения таким образом карты признаков, состоящей из одной единицы, мы получим квадрат размера из единиц. На практике увеличение размерности происходит по аналогии с размерами пулинга в свёрточных дискриминативных сетях и почти всегда равно .
Таким образом, генератор в случае DCGAN является последовательностью свёрток, слоёв батч нормализации, нелинейностей и слоёв upsampling, а дискриминатор – обычной классификационной нейросетью. При этом первым слоем в генераторе является линейный слой, который отображает вектор шума в карту признаков с начальным разрешением (как правило, размера ).
Хотя результаты работы DCGAN довольно смазанные, эта модель показала большие перспективы генеративных нейросетей для изображений.
Условная генерация
Допустим, что в нашем датасете есть изображения, относящиеся к разным классам, и мы хотели бы уметь генерировать изображение заданного класса. В этом случае речь идёт об условной генерации. В качестве условия может выступать не только метка класса, но и объект любой природы. Например, когда вы можете захотеть сгенерировать изображение по текстовому описанию.
Далее будем обозначать условие как . Наша задача — построить генератор, который бы моделировал $ p(x \mid y) $.
Conditional GAN
Самый основной метод условной генерации — конкатенация условия с вектором шума, который генератор принимает на вход. В статье Conditional GAN 2014 года, где предложили этот метод, рекомендовалось подавать условие не только в генератор, но и в дискриминатор.
Если мы генерируем векторные данные, то вектор на вход дискриминатора подаётся конкатенированным с . При этом если если $ y $ — это метка класса, то стоит её закодировать с помощью one-hot encoding. Если же мы работаем с изображениями, то нам из вектора условия следует сделать изображение. Например, если картинки из датасета имеют размер , то следует размножить вектор , создав из него тензор размера , где — размерность вектора . Далее полученное «изображение» конкатенируется с входным изображением.
Современные модели
Теперь на примере наиболее успешных моделей мы расскажем об улучшениях, которые во многом отходят от оригинального подхода к обучению GAN-ов и при этом значительно улучшают практические результаты, а значит расширяют практическую применимость.
В этом разделе мы рассмотрим state-of-the-art систему генерации изображений StyleGAN, методы её обращения (т.е., поиска векторов шума, соответствующих произвольной картинке), а также методы манипуляции семантикой изображений. После этого мы рассмотрим несколько примеров условных генеративных моделей, которые вместо шума принимают на вход изображения. Такие модели используются как для задачи повышения разрешения (super resolution), так и стилизации (например, превращение пейзажей в картины Моне). Мы сфокусируемся на изображениях, так как в этой области сконцентрирован как основной прогресс, так и наиболее впечатляющие применения генеративных моделей.
StyleGAN
Самой известной генеративно-состязательной моделью, работающей с изображениями, по праву считается StyleGAN, который до сих пор активно развивается и имеет большое количество расширений (например, существуют разнообразные методы его обращения).
Progressive Growing
Архитектура StyleGAN переняла progressive growing из модели Progressive Growing of GANs. Суть данной техники заключается в том, чтобы не сразу генерировать изображение высокого разрешения, а постепенно. Давайте рассмотрим это подробнее.
Мы хотим получить генератор, который генерирует изображения размера 1024x1024. Обучить такой генератор очень сложно. Поэтому мы начинаем с разрешения 4x4. У генератора мы оставляем только первый блок слоёв, который позволяет из шума получить изображение размера 4x4. У дискриминатора мы оставим, наоборот, только последний, который принимает на вход изображение размером 4x4. Такой GAN мы обучаем на изображениях из датасета (предварительно уменьшив их в размере).
Спустя сколько-то итераций мы понимаем, что сеть уже умеет генерировать маленькие изображения. В этот момент мы добавляем к генератору один блок, чтобы на выходе у неё получалось изображение размера 8x8. Так же мы добавляем один блок в начало дискриминатора, чтобы он на вход принимал изображения размера 8x8. Теперь генератор и дискриминатор состоят из двух блоков, которые мы и обучаем.
Такой процесс мы повторяем несколько раз, пока в итоге не дойдём до нужного нам разрешения 1024x1024. Эта схема в итоге показала себя действенным способом генерации реалистичных изображений высокого разрешения.
Подача шума в нейросеть
Ключевой частью StyleGAN является используемый в нём способ подачи шума в нейросеть, и именно из-за него метод и получил своё название. Для того чтобы понять, что конкретно в нём особенного, давайте подробнее посмотрим на архитектуру сети (рисунок из предыдущего раздела, модель StyleGAN справа).
Во-первых, вместо того, чтобы подавать вектор шума только в самом начале генератора, нейросеть обуславливают на него много раз на разных разрешениях признаков. Исторически, впервые похожим методом решалась задача переноса стиля одной картинки на другую, отсюда и название: a style-based generator.
В качестве метода обуславливания используются так называемые адаптивные слои. Это модификация обычных слоёв нейросетей, в которых часть параметров предсказывается другой нейросетью. Вообще говоря, адаптивным можно сделать любой вид нормализации, включая батч нормализацию, но наиболее известным примером такого слоя является адаптивная инстанс нормализация (adaptive instance normalization), и именно она использовалась в первой версии StyleGAN.
Вспомним, как именно работает неадаптивная версия этого слоя. Пусть у нас есть батч , элементы которого будем обозначать как . Здесь обозначает размер мини-батча, – количество признаков, а и – высоту и ширину. Тогда внутри слоя инстанс нормализации выполняется следующая операция:
Здесь и обозначают матрицы средних и стандартных отклонений, которые считаются отдельно для каждого элемента мини-батча и для каждого признака:
При этом и являются параметрами слоя, которые настраиваются в процессе обучения. Особенностью этого слоя является то, что, в отличие от батч нормализации, он применяется одинаковым образом как при обучении, так и во время инференса. То есть вместо того, что приближать средние и стандартные отклонения по батчу при помощи скользящих средних, как это делается в батч нормализации, мы честно каждый раз считаем эти статистики для каждой новой картинки отдельно от всех остальных. Это делает инстанс нормализацию очень популярной в области обработки и генерации изображений, где зачастую бывает невозможным обучение с большим размером мини-батча, а значит и использование батч нормализации.
Адаптивной инстанс нормализацией (AdaIN) называется слой, где и являются не обучаемыми параметрами, а нейросетями, которые предсказывают эти векторы из какого-то общего для всех слоёв адаптивной инстанс нормализации входа (обозначим его через ):
Это означает, что вместо оптимизации по векторам и будет происходить оптимизация по параметрам этих двух нейросетей. Также это означает, что у адаптивной инстанс нормализации добавляется ещё один вход помимо набора признаков , который определяет её поведение: некоторый вектор , который также называют вектором стиля.
Как правило, в качестве и используется нейросеть с одним линейным слоем или неглубокий персептрон.
Нетрудно видеть, что если в качестве вектора подавать сгенерированный шум , то это будет хорошим способом многократного обуславливания нашего генератора на вектор шума. Это позволило бы глубоким слоям нейросети выучивать лишь часть той информации о выходном изображении, которая содержится в векторе , например, глобальные признаки картинки. А информация о локальных признаках выходного изображения (текстурах) может появляться уже ближе к последним слоям на более высоком разрешении промежуточных признаков. Таким образом, у генератора нет необходимости хранить во всех своих картах признаков всю информацию о сгенерированной картинке, как это происходит в случае DCGAN: он может декодировать её напрямую из вектора шума по мере необходимости, что существенно облегчает обучение таких моделей и улучшает качество результатов.
Авторы StyleGAN пошли даже дальше: в качестве дополнительной регуляризации они специально заставляли нейросеть использовать информацию из вектора шума частями. А именно, во время обучения все слои адаптивной нормализации случайным образом делятся на две последовательно идущие группы: первая группа обуславливается при помощи одной части вектора шума , а вторая – при помощи другой части . На практике это приводит к следующему эффекту: нейросеть учиться декодировать часть признаков изображения, используя вектор , а часть – используя . Это позволяет после обучения напрямую манипулировать выходами нейросети, смешивая разные векторы стилей .
Обучение нового латентного пространства
Второе ключевое открытие авторов StyleGAN связано с задачей поиска семантически значимого редактирования векторов из выученного низкоразмерного многообразия . Зачем это нужно на практике мы уже упоминали ранее: на этом низкоразмером многообразии значительно проще семантически редактировать изображения, чем на уровне пикселей. Например, для задачи генерации лиц на многообразии за изменение возраста или гендера может отвечать простой аддитивный сдвиг вектора на . Если же мы попытаемся приблизить такую операцию в пространстве пикселей, то для этого уже понадобится большая нейросеть с сотнями тысяч или даже миллионами параметров.
При этом, как правило, мы хотим использовать наиболее простые операции редактирования. В идеале, мы бы хотели ограничить класс преобразований редактирования (а) сдвигами на какой-то вектор и (б) линейной (или сферически-линейной) интерполяцией двух векторов. С одной стороны, кажется, что так задача редактирования векторов существенно усложняется: этот класс преобразований даже менее выразителен, чем линейные операции. Но, с другой стороны, для таких простых преобразований легче гарантировать, что они не выведут нас за пределы многообразия, в котором у распределения большая «масса», т.е. того множества векторов , которые генератор чаще всего видел во время обучения. Для нормального распределения, как было сказано ранее, это многообразие можно приблизить сферой радиуса .
Но будет ли легко найти хорошо работающие преобразования на многообразии случайных векторов , взятых из нормального распределения? Авторы StyleGAN обнаружили, что если сначала пропустить векторы через многослойный персептрон , и подавать на вход свёрточного генератора его выходы , то редактировать латентные векторы на выученном многообразии станет намного проще. Это объясняется тем, что функция имеет возможность выучить достаточно сложное распределение для переменной , которое упростило бы задачу генерации картинки для свёрточной части генератора. И на практике оказывается, что такое выученное представление улучшает не только качество генерируемых картинок, но и качество результатов для семантического редактирования векторов.
Truncation trick
Последняя важная деталь, которая тем не менее очень сильно помогла авторам StyleGAN получить настолько хорошие результаты – это так называемый truncation trick. Он был впервые предложен в более ранних работах и продолжает оказывает огромное влияние на качество результатов. Его суть состоит в том, чтобы после обучения сэмплировать те примеры из латентного пространства, которые чаще всего видел генератор во время обучения. Например, если мы во время обучения брали вектор из нормального распределения, то при использовании truncation trick после обучения мы бы его сэмплировали из нормального распределения с обрезанными хвостами. Тем самым, интуитивно, мы убираем из сгенерированной выборки те примеры входных векторов, которые генератор реже видел во время обучения. Однако, нетрудно заметить что такая процедура приводит к потере разнообразия в выходных картинках. Например, если мы обрежем нормальное распределение вплоть до его среднего значения, то тогда нейросеть сможет выдавать лишь один пример. При всём при этом потеря разнообразия выходов – не такая большая проблема, т.к. обученный генератор всё ещё может часто ошибаться и выдавать маргинальные примеры. Фильтрация таких плохих примеров по какому-то выставленному порогу – в этом и есть суть применения truncation trick.
В случае StyleGAN, авторам хотелось бы применять этот трюк непосредственно на распределении в выученном латентном пространстве . Для этого они применяют простой трюк: сначала считают центр масс , усредняя векторы для большой выборки сэмплов :
а затем сдвигают каждый сгенерированный вектор по направлению к этому центру:
где – это параметр, который задаёт trade-off между качеством результатов и их разнообразием.
StyleGAN-2
Хотя работа StyleGAN показала довольно хорошие результаты, авторы статьи про StyleGAN-2 Analyzing and Improving the Image Quality of StyleGAN заметили, что в некоторых случаях она может выдавать некачественные изображения. В частности, StyleGAN в некоторых случая может выдавать изображения с артефактами.
Основной причиной этих артефактов оказалась адаптивная нормализация. Изначально, адаптивная нормализация состояла из двух частей: нормализация (на рисунке обозначена как Norm) и модуляция (на рисунке обозначена как Mod). В нормализации мы вычитали среднее и делили на стандартное отклонение. В модуляции мы умножали на новое выученное стандартное отклонение и прибавляли новое выученное среднее.
Авторы StyleGAN2 предложили несколько модификаций для этапа нормализации. Каждое изменение в статье добавляли последовательно, следя за изменением общего качества генерации.
-
Как из нормализации, так и из модуляции убрали вычитание/прибавление среднего. Нормализация и модуляция теперь выполняются независимо друг от друга и были перемещены в начало/конец стилевых блоков (см рисунок ниже, (c) Revised architecture).
-
Нормализацию из предыдущего пункта заменили на демодуляцию весов. По сути это та же нормализация, только теперь нормализуются веса свёрток, а не входные данные (см рисунок ниже, (d) Weight demodulation. Обратите внимание на ).
-
В StyleGAN используется техника progressive growing (см раздел про StyleGAN). Из-за этого StyleGAN появляются артефакты, возникающие при исследовании латентного пространства с помощью интерполяций. Некоторые объекты лиц (глаза, зубы), которые должны вращаться при вращении головы, оставались на месте. Чтобы побороть эти артефакты, вместо progressive growing в StyleGAN2 стали использовать residual connections.
Эти изменения позволили улучшить качество генерируемых изображений и избавиться от артефактов StyleGAN. Вот, например, некоторые примеры сгенерированных изображений модели StyleGAN2:
StyleGAN-ADA
Следующий шаг в развитии архитектуры StyleGAN — это статья StyleGAN-ADA. ADA расшифровывается как Adaptive Discriminator Augmentation. В данной статье авторы предложили механизм аугментации данных, который позволяет стабилизировать обучение и избежать переобучения дискриминатора.
Всего в статье использовали 18 разных аугментаций. В статье также предложили некоторую эвристику того, как понимать, насколько переобучился дискриминатор. Эвристика нужна для того, чтобы адаптивно контролировать параметр аугментации в зависимости от степени переобучения.
Основная идея алгоритма контроля в процессе обучения следующая. Изначально этот параметр равен нулю. Его значение изменяется на фиксированную величину каждые четыре мини-батча (авторы пишут, что частота обновлений не влияет на результат). Если наблюдается, что дискриминатор слишком переобучился, то параметр увеличивается. И наоборот, при низкой степени переобучении дискриминатора значение уменьшается.
Аугментация, как показали авторы, действительно помогает стабилизировать обучение при маленьком количестве данных. Однако, большой набор реальных данных всегда будет выигрывать у аугментации.
StyleGAN-T
Большинство современных моделей, которые показали впечатляющие результаты для генерации изображений, работают по схеме text to image. То есть текст является входом для нейросети, изображение — выходом. Обычно текст на входе называют prompt. По такой схеме работают модели Stable Diffusion, DALLE 2, Midjourney. Все эти модели являются диффузионными. Однако, пока что списывать GANы со счетов не стоит. Хотя качество у GANов не такое высокое, как у диффузионных моделей, а обучать их сложнее, у них есть неоспоримое преимущество — быстрая генерация изображений.
На момент написания этого параграфа самая свежая статья про генерацию изображений с помощью GANов — StyleGAN-T. Её авторы решили на основе StyleGAN сделать модель для генерации изображений из текста.
Архитектура модели StyleGAN-T очень похожа на архитектуру модели StyleGAN (за основу авторы взяли StyleGAN-XL — версию StyleGAN для больших обучающих выборок). В качестве кодировщика текста была использована предобученная модель CLIP.
На что стоит обратить внимание в данной архитектуре:
- Текст, закодированный CLIP text encoder, подаётся на вход как генератору, так и дискриминатору. Дискриминатор в данном случае классифицирует не отдельное изображение, а пару текст/изображение.
- Сгенерированное изображение пропускается через фиксированный кодировщик изображений, также взятый из модели CLIP (CLIP image encoder на рисунке архитектуры). Полученное представление изображения должно быть близко с представлением текста, полученным с помощью CLIP text encoder. Это достигается за счёт добавление CLIP guidance loss в общую функцию потерь. Для разрешения выше 64x64 авторы берут случайные кропы размера 64x64 на изображении, чтобы посчитать CLIP guidance loss.
Основное новшество модели StyleGAN-T — это лучшая GAN-модель для генерации изображений из текста. До этого большинство хорошо работающих моделей позволяли генерировать изображения для заданного класса или вообще без условий. Связать текст с изображением — гораздо более сложная задача.
Результаты генерации
Поскольку на вход модель принимает не только шум, но и закодированный текст, она позволяет делать интерполяции по пространству текста. Примеры сгенерированных изображений и интерполяций по текстовому пространству вы можете видеть на рисунке ниже.
Качество изображений StyleGAN-T отстаёт от диффузионных моделей, таких как Stable Diffusion или DALLE 2, о чём пишут сами авторы. Однако данная модель сильно выигрывает по скорости: на одной и той же видеокарте Stable Diffusion генерирует изображение за 3.7 секунды, в то время как StyleGAN-T за 0.02 секунды.
Disclaimer
Выше были перечислены лишь основные особенности данного класса генеративных моделей, на которые стоит обратить внимание. Эти соображения нашли применение в других задачах помимо генерации картинок из шума. На самом деле, список трюков и нюансов, необходимых для успешного обучения такой модели, намного обширнее. На практике для генеративных моделей настоятельно рекомендуется отталкиваться от готовых кодовых баз, внося минимальные и контролируемые изменения в процесс обучения. Особенно чувствительны генеративные модели бывают к архитектуре генератора и дискриминатора, к параметрам оптимизации (learning rate, количество обновлений весов дискриминатора на одно обновление генератора, и т.д.), а также к значениям весов лоссов (например, к весу R1 регуляризации, которую мы тут не обсуждали).
Применения генеративных состязательных нейросетей
До этого мы рассмотрели основные особенности генеративных состязательных нейросетей, а также их применение в задаче генерации изображений. В этом разделе мы рассмотрим, какие ещё задачи можно решать с помощью таких моделей.
Отметим, что задачи, которые мы рассмотрим ниже, можно решать и другими способами без ГАНов. Зачастую диффузионные модели (MidJourney, Stable Diffusion) показывают лучшие результаты в этих задачах. Тем не менее в данном же разделе мы рассмотрим именно методы на основе генеративных состязательных нейросетей.
Inpainting
Представьте, что вы хотите удалить с фотографии людей на заднем плане. Встаёт вопрос, чем их заменить? Для этого существует задача инпеинтинга (inpainting). Она заключается в том, чтобы восстановить часть изображения, которая была выделена маской. Если выделить людей или объекты на фотографии маской, то нейросеть для инпеинтинга будет способна зарисовать эти участки чем-то подходящим для конкретной фотографии.
Обычно генератор модели GANs для инпеинтинга представляют собой image-to-image модели. То есть изображение подаётся как на вход, так и на выход. То, что происходит внутри генератора, зависит от архитектуры модели. Как правило, используются U-Net-подобные архитектуры с какими-то дополнениями. Так, например, в одной из последних работ по инпеинтигу на основе GANs Resolution-robust Large Mask Inpainting with Fourier Convolutions используются Fast Fourier Convolutions.
Чтобы обучить модель инпеинтинга, нужно подготовить данные в формате пар <изображение с маской, изображение без маски>. Сделать это не сложно. Достаточно на существующем наборе изображений случайным образом выделить участки для удаления, после чего обучать нейросеть их восстанавливать.
Outpainting
Задачу inpainting можно так же превратить в задачу outpainting, то есть дорисовки изображения по краям. Для этого нужно в качестве маски подать пиксели, которые находятся за рамками изображения. При этом само исходное изображение можно уменьшить, если того требуют размерности нейросети.
Задача outpainting может быть полезна, когда хочется расширить изображение, например, чтобы увеличить его разрешение.
Редактирование изображений
До этого мы рассматривали, как можно редактировать латентное пространство обученной состязательной модели, чтобы это отражалось на сгенерированных изображениях. В 2023 году вышла работа Drag Your GAN, которая основана на этом принципе, и позволяет редактировать изображения перетаскиванием одной точки в другую.
Пример работы Drag Your GAN.cсылка на источник изображения
Метод Drag Your GAN основан на модели StyleGAN2. Ему на вход подаётся набор изначальных точек и набор конечных точек. Внутри метода поочерёдно выполняются следующие два шага:
- Обновление латентного пространства и обновления изображения с помощью оптимизации;
- Обновление координат точек (трекинг точек).
Изначально метод работает только со сгенерированным изображениями. Однако, нет проблем в том, чтобы добавить кодировщик, который бы переводил реальные изображения в латентное пространство модели. В таком случае можно будет редактировать и реальные изображения.
Демо Drag Your GAN доступно по ссылке.