ЗАНЯТИЕ 5
Генеративно-соревновательные сети GAN
План
Введение
Генеративно-соревновательная сеть (англ. Generative adversarial network, сокращённо GAN) — алгоритм машинного обучения без учителя, построенный на комбинации из двух нейронных сетей, одна из которых генерирует образцы,а другая старается отличить правильные («подлинные») образцы от ложных.

Впервые архитектура GAN была описана Яном Гудфеллоу из компании Google в 2014 году. Ян Лекун, директор Facebook по исследованиям искусственного интеллекта, назвал состязательную тренировку сетей «самой интересной идеей в машинном обучении за последние 10 лет».
Достижения GAN в генерации изображений
В большинстве случаев техника GAN применяется для получения фотореалистичных изображений. Наибольшего успеха удалось достичь в генерации человеческих лиц, а также других объектов. Ниже представлено несколько примеров.

Человеческие лица:
Сгенерированные спальни (2015 год):
Разные сгенерированные фотографии (2018 год):
В трансляции изображений также используется генеративно-соревновательный принцип. Перевод фотографии из дневной в ночную (2016 год):
Перевод наброска в фотографию (2016 год):
Трансляция изображений может применяться как для объектов, так и для стиля. Например, перевод фотографии в рисунок, превращение лошади в зебру, зимы в лето, спутниковой фотографии в схематичную карту (2017 год):
Ниже представлен пример достижения GAN в генерации изображений по тексту (2016 год):
Стоит обратить внимание на дефекты, которые были видны и ранее, но в данном примере выражены наиболее явно.

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

Важным выводом, касающимся всех этих примеров, является то, что нейросеть не знает правильный ответ на поставленную задачу генерации. Она не знает, как мы будем выглядеть в старости, что было на исчезнувшей части снимка, как выглядит наша голова в профиль по фотографии в анфас. Технология сверхразрешения для фотографии додумывает, что могло бы быть в каждом конкретном пикселе, который мы приближаем. Это похоже на сон, где мы пытаемся разглядеть подробности и они домысливаются. Поэтому CSI zoom enhancement на нейросетях сделать не получится.
Принцип работы генеративно-соревновательных сетей
Вспомним, как ранее мы использовали нейронные сети для MNIST. Конвертация признаков в свойства позволяла отнести изображение к одному из 10 классов. Но что, если мы захотим конвертировать свойства в признаки? В принципе, в этой задаче нет ничего невероятного — числа на входе, числа на выходе. В таком случае мы сможем получать новые, уникальные изображения.
Какая проблема возникнет с таким генератором?

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

Возьмём одну сеть, которая будет классифицировать изображения (её будем называть дискриминатором в терминологии GAN), и вторую сеть, которая будет генерировать изображения.

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

Но разбирать вручную все подобные истинным изображения и добавлять их в базу — это большая работа. Отсюда возникает следующая идея: давайте при улучшении дискриминатора ВСЕ изображения генератора помечать, как ошибочные, а как истинные помечать только изображения из реальной выборки. Запомните это место и этот принцип определения функции потерь для обучения дискриминатора. Далее мы будем запускать обучение дискриминатора и генератора в цикле до удовлетворительных результатов.
Структурная схема. Генератор и дискриминатор. Латентное пространство
Рассмотрим GAN на примере бинарной классификации истина-ложь. Признаками для примера будем использовать изображения. Пример такой задачи: определение галактик на фотографиях космоса. Если на снимке изображена галактика, то мы отнесем его к истинному классу. Если что-то другое, то это ложный класс.
Первое, что нам нужно для генерации разных изображений — это случайный вектор (Random noise). Пространство, из которого берётся вектор, называется латентным. Длина вектора (размерность латентного пространства) должна быть больше, чем количество разных независимых свойств изображения, которые мы хотим получить. Если длина равна 0, то нет элемента случайности и генератор будет всегда производить одно и то же изображение. Если длина равна 1, то можно использовать шкалу, вдоль которой будут расположены генерируемые изображения.

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

Вторая важная часть GAN — это дуэт генератора и дискриминатора (классификатора). Ранее мы заявляли, что генератор можно сделать, если все его изображения будут помечены, как ложные для дискриминатора. На схеме выше это показано, но как проходит само обучение?
Обучение GAN
Начнём с обучения классификатора. Для этого возьмем массив истинных и ложных объектов и натренируем сеть на этой выборке. Далее построим сеть из этого экземпляра классификатора (дискриминатора) с присоединенным к нему необученным генератором. Мы пользуемся тем, что можно создавать сети из других сетей.
Какие будут размерности входов и выходов этой склеенной сети?

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

Итак, мы обучили дискриминатор, а затем генератор. Можно ли считать, что задача выполнена? Нет, так как генератор мог научиться выдавать одно и то же изображение, которое классификатор считает истинным, и посчитать, что больше ему учиться нечему. Нужно не дать этому способу обучения закрепиться, признать его неверным. Пусть генератор ищет принцип генерации, а не конечный ответ. Для этого нужно переобучить дискриминатор, но уже не по изначальной выборке, а взяв из неё только изображения, причисленные к истинному классу, ложные же объекты взять у генератора. Для этого запустим генератор, чтобы он создавал новые изображения.
Какой функцией tensorflow мы воспользуемся?

В результате мы получим выборку из истинных и ложных объектов, для которых предыдущие достижения генератора уже не подходят. Ему придётся искать новые.

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


Виды GAN

Существует множество модификаций алгоритмов GAN, которые появились для решения специфических проблем в выбранной области.

Рассмотрим некоторые из них:
Свёрточные DCGAN (Deep convolutional generative adversarial network)
Особенностью этого вида GAN является использование свёрточных сетей, которые наилучшим образом подходят для работы с изображениями. Также с ними отлично работает применяемый здесь метод глубинного обучения. В таком случае может возникнуть вопрос: если с классификатором и свёртками всё понятно, то как быть с генератором и развёртками? Ведь слои у него расширяются, а не сужаются.
Какой должна быть математическая операция для развёртки?
Условные CGAN (Conditional Generative Adversarial Network)
Эта модификация GAN применяется, когда нам нужна не бинарная классификация (деление на истину и ложь), а набор разных классов. Тогда появляется условие для генерации: сгенерировать конкретный класс. На изображении ниже синим нарисовано латентное пространство, а зелёным one-hot кодированный класс.
Что такое one-hot?
Цикличные CycleGAN (Cycle Generative Adversarial Network)
Название происходит из принципа работы сетей, обучающихся одновременно и циклически. Используются 2 генератора и 2 дискриминатора, изображения на входе и на выходе. В итоге мы получим перенос стиля, но есть нюанс, отличающий CycleGAN от обычного Style transfer. Мы будем учиться не на парах изображений, где показана нужная нам трансформация (в Style transfer), а на неспаренном наборе (в CycleGAN).
В результате получим подобные трансформации:
Описание процесса с точки зрения математики:

Возьмем генераторы G и F, которые переводят из множества X в Y. Каждому соответствует свой дискриминатор D.

Дальше циклично обучаем уже 2 генератора и 2 дискриминатора, но дополнительно соблюдаем условие, согласно которому двойное преобразование должно возвращать картину к исходному состоянию:

F (G (x))≈x, x∈X
G (F (y))≈y, y∈Y


Парные CoGAN (Coupled Generative Adversarial Networks)
Если мы решаем 2 похожих задачи и используем одинаковые архитектуры, то можно решать задачи синхронно и обмениваться весами. Чем меньше используется весов, тем быстрее происходит обучение. Задачи можно считать похожими, потому что в обоих случаях мы имеем дело с изображениями, пусть и разного типа.
Подход CoGAN со временем был заменён другими, более общими приёмами экономии вычислений на обучении.
ProGAN устойчивого роста (Progressively Growing Generative Adversarial Networks)
Обратите внимание на иллюстрацию ниже:
Идея подхода заключается в следующем: если мы хотим при помощи свёрточных сетей сразу сгенерировать изображение высокого разрешения, то обучение займет слишком много времени. Поэтому лучше сделать связку генератор-дискриминатор на низком разрешении, а потом встроить слои более высокого разрешения, которые обучатся на основе уже обученных слоёв более низкого разрешения. Идея простая в формулировке, но на самом деле за ней скрывается необходимость убирать и добавлять слои, да еще и делать это с медленно меняющимся коэффициентом функции потерь, которая постепенно меняет задачу для слоёв от генерации изображений низкого разрешения к задаче снабжения данными следующих слоёв.
Вассерштейн WGAN (Wasserstein Generative Adversarial Networks)
В этом подходе с помощью математики решается проблема исчезающего градиента для идеально разделимых множеств. Как именно это происходит, показано на графике. Если множества идеально разделимы, то обучение тормозится. Чтобы управлять этим эффектом, можно применить специальные функции потерь.
Повышение качества распознавания за счет дообучения
Мы расширяем выборку для обучения, когда используем генератор. Поэтому можно защитить классификатор от примеров, похожих на истинные классы, генерируя такие примеры и вводя их в класс ложных.
Стойкость классификатора повышается.
Задание
Дописать код в блокноте для обучения GAN. Получить анимацию обучения, код генерации которой уже написан в блокноте.
Дополнительное задание высокой сложности
Посмотреть анимацию обучения, найти в ней странности и объяснить причину долгого обучения GAN. При необходимости можно либо менять параметры анимации, либо сделать дополнительный вывод данных из программы для анализа. Можно подстраивать другие параметры или применить приёмы, описанные в этой статье. Результатом должно стать существенное ускорение обучения.
Made on
Tilda