Этот пост в блоге направлен на обеспечение полного интуитивного понимания генерирующих состязательных сетей вместе с математикой, которая связана с ними, включая реализацию тензорного потока.

Примечание. Читатель должен иметь базовое представление о глубоком обучении.

В статье 2014 года Иэн Гудфеллоу, доктор философии. Студент Монреальского университета представил доклад под названием Generative Adversarial Nets вместе со своими наставниками из Милы, включая Йошуа Бенжио и Аарон Курвиль. Эта статья была процитирована более 5000 раз, и ее рецензировали все ведущие пионеры глубокого обучения. Читайте ниже, что Ян Лекун говорит о Гане.

Генеративные состязательные сети - самая интересная идея в машинном обучении за последние десять лет, - Ян Лекун (Facebook AI Director)

Это явный признак того, что Generative Adversarial Networks делает что-то действительно интересное. С этого момента мы будем называть генерирующие состязательные сети как сети Гана. Gan интересны тем, что они могут научиться приближенно распределять данные (то есть имитировать реальные данные), что очень мощно, поскольку теперь они могут генерировать изображения, аудиоклипы, видео, которых в действительности не существует. В некотором смысле можно предположить, что Ганы - художники. Одна из известных цитат Ричарда Фейнмана, объясняющая интуицию Гана.

То, что я не могу создать, я не понимаю - Ричард Фейнман (американский физик-теоретик)

Результаты, полученные с помощью gan’s, довольно убедительны: в октябре 2018 года французский дом Christie’s продал на аукционе портрет (рис. 1.0) за 432000 долларов, который был выставлен Gan.

Зачем нужны генеративные состязательные модели?

Этот раздел представляет собой краткое изложение сообщения в блоге о Gan’s by OpenAI. Идея заключается в том, что если Gan's станет лучше создавать данные, тогда он также сможет понимать данные, которые присутствуют в мире, намного лучше, чем любые другие алгоритмы. Когда они узнают основные представления данных, они поймут их лучше. Модели Гана относятся к классу генеративных моделей и основаны на подходе дифференцируемых сетей генераторов, поэтому они являются одним из способов достижения этой цели, другие популярные способы:

  1. Вариационные автоэнкодеры.
  2. Rnn’s аналогично LSTM’s или PixelRnn’s.
  3. РНН-РБМ для последовательного вывода.
  4. Свёрточные машины Больцмана и многое другое.

Подробнее об этих моделях позже, но идея остается той же: все эти архитектуры пытаются изучить базовые представления, которые определяют данные. Генеративные модели обычно относятся к активной области исследований, называемой обучение представлений, то есть обучение представлениям из немаркированных данных. Все вышеперечисленное работает по-разному, но, тем не менее, все они пытаются узнать распределение вероятностей.

Как работает Ган?

Идея, лежащая в основе идеи Гана, интуитивно понятна, она состоит из двух архитектур: Дискриминатора, который оценивает вероятность того, что выборка реальна, и Генератора, который пытается сгенерировать данные, близкие к реальным. Со временем Дискриминатор становится лучше в различении, а Генератор - в генерации выборок, более близких к реальным выборкам (рис. 1.1 для иллюстрации). Цели этих двух моделей противоположны, когда Генератор максимизирует вероятность ошибки Дискриминатора, в то же время Дискриминатор старается изо всех сил предсказать правильный ярлык - настоящий или фальшивый. Эта идея также становится интересной, если хорошо подумать, что одна модель помогает другой стать лучше.

Рассмотрим рис. 1.2. Здесь p (x) (синий справа) - истинное распределение изображения, а pθ (x) (зеленый) - точки, взятые из распределения Гаусса, прошедшего через нашу нейронную сеть. Первоначально точки будут полностью случайными, но, как и в случае с обучением, θ параметра нашей модели оптимизирована, чтобы минимизировать разницу между двумя распределениями (с помощью расхождения KL или любых других средств).

И генератор, и дискриминатор могут иметь одинаковую архитектуру или разные. В исходной статье Гана они использовали многослойный перцептрон, предоставляя случайный шум в качестве входных данных для генератора, а другая модель многослойного персептрона используется в качестве дискриминатора, который обнаруживает, является ли выборка сгенерированного перцептрона или настоящий. В последнем разделе этой статьи мы будем создавать нашу собственную Генеративную нейронную сеть, используя архитектуру на основе свертки, известную как DCGAN (Deep Convolutional Generative Adversarial Networks), но сначала давайте поместим математику, лежащую в основе теории Гана, в правильное положение. Я постараюсь сделать математику настолько простой, насколько это возможно, но убедитесь, что ваши основы изложены в правильном порядке.

Формулировка целевой функции

Цель состоит в том, чтобы изучить распределение генератора Pg, которое определяет реальные данные x,, передавая случайный шум z в качестве входных данных через нейронную сеть G (z; θg), где θg - параметры нейронной сети Генератора, представьте любую нейронную сеть как a, Universal function approximator, мы также определим другую нейронная сеть D (x; θd) дискриминатор, эта сеть даст вероятность d (x) [от 0 до 1], что x пришел из реальных данных, а не Pg, пока G обучается минимизировать log (1 - D (G (z))), D обучается предсказывать правильную метку. Член минимизации G, равный log (1 - D (G (z))), имеет смысл, поскольку изначально вероятность D (G (z)) будет низкой, поскольку генератор только что начал генерировать выборки, и это будет легко для дискриминатор, чтобы предсказать, является ли образец настоящим или поддельным, поэтому общий результат log (1 - D (G (z))) будет большим. Итак, когда цель G - минимизировать, цель D - максимизировать, рассматривайте всю эту ситуацию как игру min-max V (D, G).

Разбивая вышеупомянутое уравнение,

Во-первых, Ex∼pdata (x) [log (D (x))] - ожидание [максимизации того, что сгенерированная выборка x действительна].

Во-вторых, Ez∼pz (z) [log (1 - D (G (z)))] - ожидание [минимизации того, что сгенерированная выборка не является реальной.]

Вышеприведенное уравнение, по сути, представляет собой игру с минимальным и максимальным значением, в которой один пытается его минимизировать, а другой - максимизировать. Давайте разберемся с этой минимальной и максимальной игровой ситуацией на примере регуляризации L2 в машинном обучении. В регуляризации член регуляризации не позволяет весам быть очень маленькими, но в то же время оптимизатор минимизирует общую целевую функцию, что обычно приводит к небольшим значениям весов. Эта ситуация аналогична ситуации минимума-максимума Гана, но с той разницей, что и минимизация, и максимизация Ингана контролируются самим оптимизатором.

В идеале наилучшее значение D (x) было бы 0,5, это означает, что он не может различить реальный образец или поддельный, т.е.

D ∗ (x) = Pdata (x) / (Pdata (x) + Pg (x)) и Pg = Pdata.

Идея одновременного обучения D (x; θd) и G (z; θg) выглядит хорошо в теории, но на практике мы обычно обучаем D (x; θd) k раз за каждый раз, когда мы обучаем G (z; θg), так что дискриминатор всегда сильнее генератора.

Обучение генеративным состязательным сетям.

Рассмотрим рис. нижеприведенный.

Идея проста - обучить сеть некоторому количеству итераций, пока результаты не станут удовлетворительными.

Повторите следующие шаги для N итераций:

Шаг 1: для каждой из n итераций K итераций:
1.select a mini-batch of noise samples (z1....zm)
2.select a mini-batch of real-data samples (r1....rm)
3.train the discriminator with using max-min loss function [eq(1)] over m samples.

Шаг 2. Для следующей итерации:
1.select a mini-batch (z1.....zm) from p(z)
2.train the generator by minimizing the log probability of generator making mistake.

В первоначальной статье упоминалось использование SGD для обучения, но рекомендуется использовать более мощные оптимизаторы, такие как Adam, Adagrad, rms-prop и т. Д.

Что такое DCGAN?

DCGAN или Deep Convolutional Generative Adversarial Networks - большое улучшение по сравнению с предыдущими Gan. Хотя теоретически архитектура Гана выглядит простой на практике, но обучить Гана действительно сложно. Причина в том, что градиенты должны проходить через дискриминатор и генератор, и из-за этого обучение Гана становится нестабильным. Мы рассмотрим эти темы в более поздней части этой статьи, но сначала давайте попробуем понять архитектуру DCGAN.

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

  1. Замените весь уровень пула на чередующиеся свертки, при таком подходе сеть вместо того, чтобы полагаться на уровни пула (максимальный пул или средний пул) для выполнения пространственной понижающей дискретизации, сеть учится сама.
  2. Удалите все полностью связанные уровни, чтобы создать более глубокую архитектуру, поскольку полносвязные уровни мешают конвергенции сети.
  3. Используйте BatchNormalization, чтобы стабилизировать поток градиентов между глубокими слоями.
  4. Использование активации ReLu для всех слоев в генераторе, кроме выходного слоя, который использует tanh, а в дискриминаторе используется сигмоид или softmax.

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

если вы не знаете о транспонированной свертке, то почитайте сообщение в блоге Наоки Сибуя.

Построение генерирующей состязательной сети с глубокой сверткой.

Код для этой демонстрации взят из оригинальной реализации DCGAN tensorlayer с изменениями для работы с набором данных Sully Chen и послойной визуализацией, чтобы действительно понять, как сеть обучается. Набор данных был создан для обучения беспилотного автомобиля, он содержит 63 тыс. Изображений вождения по дороге с соответствующим углом поворота и другими значениями, такими как педаль газа и т. Д. Основная идея использования этого набора данных заключается в том, чтобы увидеть, насколько хорошо Ган может имитировать реальные сцены вождения, такие как другие пешеходы, автомобили и т. д. Если вы посмотрите на картину в целом, этот эксперимент великолепен, поскольку теперь вместо того, чтобы полагаться на камеру, прикрепленную перед вашим автомобилем, для захвата изображений дорог, вы можете генерировать бесконечное количество данных просто сидя в комнате. Хотя насколько хороша идея обучить беспилотный автомобиль с помощью сгенерированных изображений? Я оставлю это для дальнейшего обсуждения.

Примечание. Все веса модели инициализируются с помощью инициализатора Glorot. Типичная инициализация Glorot выглядит примерно так:

step1: std_dev = sqrt (2.0 / (fan-in + fan-out))
step2: weights = нормальное распределение (среднее = 0,0, стандартное отклонение)

если вы хотите узнать больше об инициализаторе Glorot или о том, почему он используется, нажмите здесь.

Реализация генератора в Tensorflow

Давайте посмотрим на код генератора. Последовательность кода выглядит следующим образом:

1. Определение параметров генератора, таких как размер выходного изображения, параметры фильтра, инициализация гаммы.

2. Входной слой имеет 100 измерений, то есть 100 случайных чисел, сгенерированных из равномерного распределения со средним значением = 0 и standard_dev = 1.0.

3. Входной слой связан с плотным слоем с 64 * 8 * 64 * 64 единицами.

4. Изменение формы плотного слоя: высота = 64, ширина = 64, глубина = 512.

5. Нормализация с использованием пакетной нормализации с гаммой, выбранной из равномерного распределения со средним значением = 1.0, std_dev = 0.02 с активацией ReLu.

6. DeConv2d или просто транспонированный сверточный слой с ядром = (5,5), stride = (h = 2, w = 2) с глубиной 64 * 4 с нулевым заполнением.

7. Пакетная нормализация с активацией ReLu.

8. DeConv2d или просто транспонированный слой свертки с ядром = (5,5), stride = (h = 2, w = 2) с глубиной 64 * 4 с нулевым заполнением.

9. Пакетная нормализация с активацией ReLu.

10. DeConv2d или просто транспонированный сверточный слой с ядром = (5,5), stride = (h = 2, w = 2) с глубиной 64 * 4 с нулевым заполнением с активацией tanh.

Реализация Дискриминатора в Tensorflow

  1. Определение параметров модели, таких как размер выходного изображения, параметры фильтра, инициализатор гаммы.
  2. Слой свертки с размером ядра = (5,5) с шагом = (h = 2, w = 2), с активацией Relu и с нулевым заполнением.
  3. Слой свертки с размером ядра = (5,5) с шагом = (h = 2, w = 2), с активацией Relu и с нулевым заполнением.
  4. Пакетная нормализация с гаммой = нормальное распределение (среднее значение = 1,0, std_dev = 0,02).
  5. Слой свертки с размером ядра = (5,5) с шагом = (h = 2, w = 2), с активацией Relu и с нулевым заполнением.
  6. Пакетная нормализация с гаммой = нормальное распределение (среднее значение = 1,0, std_dev = 0,02).
  7. Слой свертки с размером ядра = (5,5) с шагом = (h = 2, w = 2), с активацией Relu и с нулевым заполнением.
  8. Пакетная нормализация с гаммой = нормальное распределение (среднее значение = 1,0, std_dev = 0,02).
  9. Сгладить слой.
  10. Выходной слой с 1 скрытой единицей с активацией сигмовидной формы.

Давайте сравним полученные нами результаты с реальными

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

Теперь сгенерированные образцы,

Как вы можете видеть, образцы из модели 1-й эпохи просто могут получить суть данных, но по мере увеличения количества эпох результат становится лучше, а в 10-м он становится действительно лучше. Сеть обучена 30 эпохам, давайте их визуализируем. Изображения расположены в ряд с 11-й по 30-ю эпоху.

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

Потери в генераторе и дискриминаторе.

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

Epoch: [ 2/30] [ 139/ 997] time: 0.4634, d_loss: 0.67223823, g_loss: 0.71121359
Epoch: [ 2/30] [ 140/ 997] time: 0.4640, d_loss: 1.28069568, g_loss: 1.98622787
Epoch: [ 2/30] [ 141/ 997] time: 0.4628, d_loss: 1.44974589, g_loss: 0.46058652
Epoch: [ 2/30] [ 142/ 997] time: 0.4819, d_loss: 1.02387762, g_loss: 1.69937968
Epoch: [ 2/30] [ 143/ 997] time: 0.4781, d_loss: 0.59786928, g_loss: 1.81390572
Epoch: [ 2/30] [ 144/ 997] time: 0.4632, d_loss: 0.96302533, g_loss: 0.62419045
Epoch: [ 2/30] [ 145/ 997] time: 0.4622, d_loss: 0.62077224, g_loss: 1.15416789
Epoch: [ 2/30] [ 146/ 997] time: 0.4726, d_loss: 0.57695013, g_loss: 1.11101508
Epoch: [ 2/30] [ 147/ 997] time: 0.4843, d_loss: 0.64481205, g_loss: 1.35732222
Epoch: [ 2/30] [ 148/ 997] time: 0.4617, d_loss: 0.46775422, g_loss: 1.74343204
Epoch: [ 2/30] [ 149/ 997] time: 0.4668, d_loss: 0.60213166, g_loss: 0.84854925
Epoch: [ 2/30] [ 150/ 997] time: 0.4637, d_loss: 0.75188828, g_loss: 1.56600714
Epoch: [ 2/30] [ 151/ 997] time: 0.4644, d_loss: 0.80763638, g_loss: 0.80851054
Epoch: [ 2/30] [ 152/ 997] time: 0.4685, d_loss: 0.66286641, g_loss: 0.79960334
Epoch: [ 2/30] [ 153/ 997] time: 0.4619, d_loss: 0.64668310, g_loss: 1.32020211
Epoch: [ 2/30] [ 154/ 997] time: 0.4742, d_loss: 0.46545416, g_loss: 1.55003786
Epoch: [ 2/30] [ 155/ 997] time: 0.4970, d_loss: 0.94472808, g_loss: 0.49848381
Epoch: [ 2/30] [ 156/ 997] time: 0.4768, d_loss: 0.78345346, g_loss: 1.03955364

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

Интерпретация Гана с использованием послойной визуализации как генератора, так и дискриминатора

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

Примечание: все послойные выходные данные получены до нормализации после обучения сети с 30 эпохами на Sully Chen.

Генератор

Уровень 1. Как и ожидалось, изначально сеть создает лишь небольшой шум.

Уровень 2. Сеть начинает генерировать некоторые шаблоны.

Уровень 3: появляются полезные шаблоны.

Слой 4: финальные узоры, к которым будет применена активация tanh.

Дискриминатор

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

Уровень 2: вывод 2-го слоя выполняется после вывода 1-го. Мы не многого можем понять, но все это важно для самой сети.

Уровень 3. Размер становится меньше, и прогноз становится актуальным только для сети.

Уровень 4. Когда сеть становится глубже, трудно дать какую-либо интерпретацию, но именно так это происходит в сети.

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

Проблемы с Ганом

В теории работа гана звучит хорошо, и кажется, что он должен сходиться к глобальным минимумам, но на практике, когда и Генератор G, и Дискриминатор D представлены в виде нейронной сети, вероятность конвергенции резко снижается, и в большинстве случаев конвергенция останавливается на точка перевала.

При обучении Гана в основном наблюдаются следующие проблемы:

  1. Проблема равновесия по Нэшу: эта проблема в основном существует из-за минимальной и максимальной формулировки Гана. В этой ситуации обе части функции могут достичь оптимального значения только в одной точке, а в состоянии покоя они остаются нестабильными. Следующий пример взят из книги по глубокому обучению. Рассмотрим функцию F (u, v) = uv, где мы должны минимизировать значение u и максимизировать значение v, тогда единственное оптимальное значение F (u, v ) существуют при u = v = 0.
  2. Свертывание режима: в этой ситуации Ган не может захватить все классы данных и может генерировать только определенные типы шаблонов. Обычно эта проблема не возникает, но в случае ее возникновения могут возникнуть проблемы.
  3. Уменьшение градиентов. Эта ситуация довольно распространена, когда градиенты дискриминатора или генератора становятся настолько маленькими, что почти останавливают обучение других. В основном это происходит в случае дискриминатора, поскольку он становится намного лучше, поэтому градиенты становятся настолько маленькими, что генератор не может узнать распределение. Чтобы избежать этой проблемы, желательно не обучать дискриминатор перед тренировкой всего гана.

Стабилизация Gan’s по-прежнему является активной областью исследований в сообществе глубокого обучения, многие академические институты и организации работают в этой области. Если вы хотите узнать больше о текущих проблемах, связанных с оформлением заказа Ганом, то этот отличный пост в блоге от Jonathan hui.

Приложения

Хотя Gan были созданы с учетом того, чтобы синтезировать данные и, по сути, создавать модели, чтобы узнать больше о представлении, которое представляет собой данные реального мира навсегда, но, к сожалению, большинство текущих способов использования Gan были не такими дружелюбными, и многие из них были даже катастрофическими, одним из известных примеров является deep fakes , идея состоит в том, чтобы создавать фальшивые изображения людей, которые что-то говорят или делают. Эти попытки могут нанести серьезный ущерб как обществу, так и стране. Несмотря на это, есть несколько классных приложений гана,

  1. В онлайн-индустрии одежды покупатель может увидеть, как выглядит одежда, прежде чем покупать ее, примерив ее на искусственно созданных виртуальных версиях.
  2. При создании мультфильмов персонажей, скорее, полагаются на дорогостоящее программное обеспечение.
  3. В создании контента, а не в студии. Классический пример этого недавно продемонстрировал Китай, когда его государственное информационное агентство Синьхуа загрузило клип, в котором ведущий новостей ИИ рассказывает, а не какой-то реальный человек. Хотя они не раскрыли свою модель, я делаю обоснованное предположение.

Резюме

Генеративные состязательные сети в настоящее время являются одним из самых многообещающих методов глубокого обучения. Они построены на идее, которая чрезвычайно проста и кажется наиболее общей. Наш, кажется, хороший эксперимент с gan’s, я напишу об этом больше в моих будущих блогах. Полный код для этого можно найти здесь.

использованная литература

Первоначальная статья Гана: https://arxiv.org/abs/1406.2661

Документ DCGAN: https://arxiv.org/abs/1511.06434

Реализация tenorlayer dcgan: https://github.com/tensorlayer/dcgan

CNNVIS (библиотека визуализации): https://github.com/InFoCusp/tf_cnnvis

Блог Generative Models от openAI

Проблемы с Ганом: https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b

Github / carpedm20 / DCGAN-tenorflow

Курс AppliedAI

Инициализатор Glorot: andyljones.tumblr.com/post/110998971763/an-explanation-of-xavier-initialization

Книга по глубокому обучению: www.deeplearningbook.org/