Одним из наиболее интересных вариантов использования глубокого обучения являются генеративные модели. Мы можем генерировать все, что угодно, включая текст, изображения, звуки... Различные чат-боты, автоматические машинные переводы, voice2text, text2speech, подписи к изображениям, улучшения качества изображения, преобразования изображений image2 и другие — это классные приложения, в которых есть какие-то генеративные модели под капот. Итак, я решил создать несколько аниме-девушек (конечно, для науки и исследований). Я подумал, что это будет интересный способ изучить генеративные модели глубокого обучения. Идея состоит в том, чтобы сгенерировать SmartCat chan, Smart Cat-Girl :)

В этом блоге я собираюсь представить модели генерации изображений, которые я пробовал в своем стремлении создать воображаемую вайфу. Но перед аниме-девушками я протестировал свои реализации TensorFlow на наборе данных CelebA (на результатах которых я в основном сосредоточусь в этом блоге). В своих поисках я видел мерзости, я путешествовал сквозь бурю кошмаров, переживал прозрение в психоделической пустоте и тьме.

В любом случае, мы увидим генеративные модели, такие как: генеративно-состязательная сеть (GAN), глубокая сверточная генеративно-состязательная сеть (DC-GAN) и расширение DC-GAN с использованием вариационного автоэнкодера. Реализации моделей в TensorFlow (только модели, без обучающих скриптов) находятся в этом репозитории. Обратите внимание, что это репо обязательно изменится в будущем. Используемые наборы данных: CelebA, Anime girls (взято из Интернета).

Генеративно-состязательная сеть — обзор

Генеративно-состязательная сеть (GAN) — это тип нейронной сети, которая учится генерировать данные без присмотра. Идея состоит в том, чтобы кормить нейронную сеть множеством изображений, и в результате мы получаем новые сгенерированные изображения. Внутри архитектуры GAN мы можем найти две отдельные нейронные сети: Генератор и Дискриминатор. Дискриминатор — это нейронная сеть, которая берет входное изображение и выводит, является ли это изображение реальным или поддельным. Задача генератора — создать совершенно новое изображение, которое обманет дискриминатор.

Мы можем видеть, куда это идет. Во время обучения эти две нейронные сети конкурируют друг с другом и совершенствуются на каждой итерации. Сначала генератор бросает в дискриминатор какой-то мусор, и дискриминатор смотрит на это изображение, а затем на реальные изображения. После этого дискриминатор такой: «чувак, это даже не реально!». В следующий раз генератор становится лучше и обманывает дискриминатор, создавая лучшее изображение, но после нескольких итераций дискриминатор также становится лучше в различении реальных и поддельных изображений. Это соревнование между генератором и дискриминатором проходит через итерацию обучения.

Глубокая сверточная генеративно-состязательная сеть

Простые сверточные GAN нестабильны в обучении, и большую часть времени мы не получаем желаемых фотореалистичных изображений, другими словами: мерзости. Чтобы преодолеть эту проблему, авторы оригинальной статьи Deep Convolutional Generative Adversarial Network (мне всегда становится скучно, когда мне нужно записать полное название DCGAN) предложили несколько изменений, чтобы сделать обучение более стабильным.

  1. Вместо функции объединения, уменьшающей размерность в дискриминаторе, используйте слой свертки с шагом. Другими словами, мы позволяем сети научиться уменьшать размерность. На уровне генератора мы используем деконволюцию для увеличения размеров карт объектов.
  2. Использование пакетной нормализации. Мы все видели мощь пакетной нормализации
  3. Создайте полностью свернутую сеть без полностью связанных слоев.
  4. Используйте функции активации Relu и Leaky Relu.

Мы можем видеть архитектуру на изображении ниже. Обратите внимание, что в генераторе мы начинаем с использования некоторого случайного вектора, чтобы в конце создать осмысленные изображения. Вместо случайного вектора мы можем использовать автоэнкодер, но об этом позже.

Используя DCGAN, вы получите лучший результат, не идеальный, но лучше. Вот несколько образцов сгенерированных лиц.

Ну, это нормально. Хотя должно быть лучше. Я намеренно поставил здесь более уродливую :). Отряд убийц, который вы видите здесь, был создан в середине тренировки, когда сеть не была полностью сведена. Но эй, я тоже не умею рисовать. Хоть я и не генерил вайфу (только мерзких тварей и людей-блинчиков), это все равно лучше моего арта. Я думаю, что мое искусство осталось на уровне 6-летнего, извините, если я обидел какого-то 6-летнего ребенка, читая это.

Пожалуйста, не просите меня нарисовать аниме-девушку! Одна интересная вещь заключается в том, что мы можем использовать входной вектор и выполнять над ним арифметические операции. Помимо дрянных сгенерированных изображений, результаты потрясающие. Мы можем добавить солнцезащитные очки людям без солнцезащитных очков, просто добавляя и вычитая векторы. Кроме того, мы также можем интерполировать от одного человека к другому, менять пол и даже поворачивать лицо. Вот пример интерполяции между двумя гранями.

Вариационный автоэнкодер — обзор

Вариационные автоэнкодеры — это тип автоэнкодеров (неконтролируемых обучающихся нейронных сетей), которые пытаются подогнать данные под нормальное распределение. Мы знаем, что автокодировщики пытаются сжимать данные (например, изображения) в пространство меньшего размера. Сжатие выполняется таким образом, что автоэнкодер может восстановить данные обратно в исходное пространство.

Мы видим, что автоэнкодер «кодирует» входную информацию в пространстве кодирования. Значения в пространстве кодирования определяют функции из ввода, например. цвет волос, цвет глаз, размер носа и т. д. Автоэнкодеры отлично восстанавливают входные изображения, но есть фактор ограничения. Они не могут легко генерировать новые образцы. Это сложно, потому что их пространство кодирования может быть очень грязным, поэтому мы не можем легко сэмплировать из него. В этом случае на помощь приходит вариационный автоэнкодер. Вариационные автокодировщики заставляют данные соответствовать нормальному распределению. Как только мы узнаем распределение пространства кодирования, мы можем легко сэмплировать оттуда и генерировать новые виды материала.

Структура вариационных автоэнкодеров в основном такая же, как и у простых автоэнкодеров, за исключением части кодирования. После нескольких слоев кодировщика мы определяем 2 отдельных слоя. Один слой представляет собой среднее значение, а другой слой представляет собой стандартное отклонение. Теперь мы можем сэмплировать нашу кодировку, используя выходные данные среднего и стандартного значений. В качестве функции потерь мы берем как потери реконструкции, так и потери расхождения KL.

Изображения, сгенерированные вариационными автоэнкодерами, размыты, и, если сеть плохо обучена, выдает изображения, похожие на среднее изображение. Но сочетание идеи вариационного автоэнкодера с DCGAN дает лучшие результаты при создании новых изображений.

ВАЭ — DCGAN

Мы видели, как вариационный автоэнкодер подгоняет данные под распределение Гаусса, но при этом дает довольно размытые изображения. С другой стороны, глубокие сверточные генеративно-состязательные нейронные сети производят более четкие изображения, но им не хватает фотореалистичности (ищите людей-блинчиков здесь). Объединив VAE и DCGAN, мы можем решить некоторые из этих проблем. Общая архитектура представлена ​​на изображении.

Теперь наш генератор будет создавать изображения для реконструкции на основе входного изображения (для вычисленного z) и изображения на основе случайной выборки z. После этого определим потери для дискриминатора и генератора. Потери кодировщика будут потерями расхождения KL, как мы имели в вариационном автоэнкодере. В дополнение к нашим потерям мы введем потери восприятия. По сути, мы вычисляем, в какой степени функции контента (на более высоких уровнях) схожи в кодировщике и в дискриминаторе. Мы подключаем потери восприятия от L-го слоя к потерям кодера и генератора.

При обучении GAN из-за нездоровой конкуренции наша сеть может зависнуть, а то и вовсе умереть. Нам нужно быть осторожными при определении убытков и обращать внимание на их значения. Мы также можем использовать уже предварительно обученные модели (например, VGG в ImageNet или что-то еще) для кодировщика и дискриминатора.

Я получил гораздо лучшие результаты, когда тренировал VAE-DCGAN на знаменитостях (все же лучше, чем мои рисунки). Вот несколько примеров из генератора:

Вот, вайфу идут.

Из-за не очень простого процесса обучения я генерировал только изображения 64x64. В следующий раз я попытаюсь создать более высокое разрешение с помощью DC-GAN.

Резюме

Итак, в этом блоге моей целью было создание аниме-девушек. Хотя мне не удалось создать полноразмерные изображения с высоким разрешением, мне удалось осветить идею генеративных моделей, в частности GAN, VAE, DC-GAN и VAE-DCGAN. Каждый из этих методов имеет свои плюсы и минусы, но в конечном итоге VAE-DCGAN добился наиболее реалистичных результатов.

Существует также метод генерации изображений, в котором используются рекуррентные нейронные сети, но я расскажу об этом в другом блоге (если когда-нибудь его сделаю :) ).

Одна интересная статья о создании крупномасштабных изображений, которую я не освещал в этом блоге: Прогрессивный рост GAN для улучшения качества, стабильности и разнообразия. Идея состоит в том, чтобы обучать GAN слой за слоем, и с каждым слоем мы увеличиваем размеры входных и выходных изображений. Результаты многообещающие, но, как и все остальное, я хотел бы попробовать это самостоятельно и несколько раз с треском провалиться, пока не добьюсь успеха.

В следующих блогах я продолжу изучение генеративных моделей и углублюсь в проблемы сверхвысокого разрешения.

Есть несколько статей, которые могут вас заинтересовать:

  1. Генеративно-состязательные сети
  2. Неконтролируемое репрезентативное обучение с помощью глубоких сверточных генеративно-состязательных сетей
  3. Автокодирование вариационного Байеса
  4. Вариационные подходы к автокодированию генеративно-состязательных сетей
  5. Состязательный вариационный байесовский подход: объединение вариационных автоэнкодеров и генеративно-состязательных сетей

Первоначально опубликовано на странице https://www.smartcat.io/blog/2018/going-nuts-with-generative-models-part-1/.