Изменения

Перейти к: навигация, поиск

Generative Adversarial Nets (GAN)

11 728 байт добавлено, 22:18, 13 ноября 2018
Первая стабильная версия с исправлениями
[[File:Арх_ган.png|450px|thumb|Оригинальная архитектура GAN]]
'''Порождающие состязательные сети''' (англ. ''Generative Adversarial Nets, GAN'') {{---}} это алгоритм машинного обучения, входящий в семейство [[:Порождающие модели|порождающих моделей]] и построенный на комбинации из двух нейронных сетей, одна из которых генерирует образцы, а другая же пытается отличить настоящие образцы от сгенерированных. Впервые такие сети были представлены Иэном Гудфеллоу в 2014 году.

==Постановка задачи и метод==
Имеется множество образцов <tex>X</tex> из распределения <tex>p_{data}</tex>, заданного на <tex> \mathbb R^n </tex>, а также некоторое пространство латентных факторов <tex>Z</tex> из распределения <tex>p_{z}</tex>, например, случайные вектора из равномерного распределения <tex> \mathbb U^p(0,1) </tex>.

Рассмотрим две нейронные сети: первая {{---}} ''генератор'' <tex> G: Z \rightarrow \mathbb R^n </tex> с параметрами <tex>\theta</tex>, цель которой сгенерировать похожий образец из <tex>p_{data}</tex>, и вторая {{---}} ''дискриминатор'' <tex>D: \mathbb R^n \rightarrow \mathbb [0,1] </tex> с параметрами <tex>\gamma</tex>, цель которой выдавать максимальную оценку на образцах из <tex>X</tex> и минимальную на сгенерированных образцах из <tex>G</tex>. Распределение, порождаемое генератором будем обозначать <tex>p_{gen}</tex>. Так же заметим, что в текущем изложении не принципиальны архитектуры нейронных сетей, поэтому можно считать, что параметры <tex>\theta</tex> и <tex>\gamma</tex> являются просто параметрами многослойных персептронов.

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

Наша задача выучить распределение <tex>p_{gen}</tex> так, чтобы оно как можно лучше описывало <tex>p_{data}</tex>. Зададим функцию ошибки для получившейся модели. Со стороны дискриминатора мы хотим распознавать образцы из <tex>X</tex> как правильные, т.е в сторону единицы, и образцы из <tex>G</tex> как неправильные, т.е в сторону нуля, таким образом нужно максимизировать следующую величину:

<center> <tex>\mathop{E}\limits_{x \sim p_{data}}[logD(x)] + \mathop{E}\limits_{x \sim p_{gen}}[log(1-D(x))]</tex>, где <tex>\mathop{E}\limits_{x \sim p_{gen}}[log(1-D(x))] = \mathop{E}\limits_{z \sim p_{z}}[log(1-D(G(z))]</tex> </center>

Со стороны же генератора требуется научиться "обманывать" дискриминатор, т.е минимизировать по <tex>p_{gen}</tex> второе слагаемое предыдущего выражения. Другими словами, <tex>G</tex> и <tex>D</tex> играют в так называемую ''минимаксную игру'', решая следующую задачу оптимизации:

<center> <tex> \min\limits_{G}\max\limits_{D} \mathop{E}\limits_{x \sim p_{data}}[logD(x)] + \mathop{E}\limits_{z \sim p_{z}}[log(1-D(G(z))] </tex> </center>

Теоретическое обоснование того, что такой метод заставляет <tex>p_{gen}</tex> сходится к <tex>p_{data}</tex> описано в исходной статье. <ref> [https://arxiv.org/pdf/1406.2661.pdf Ian J. Goodfellow {{---}} Generative Adversarial Nets]</ref>

==Оригинальный алгоритм обучения GAN==
В процессе обучения требуется делать два шага оптимизации поочередно: сначала обновлять веса генератора <tex>\theta</tex> при фиксированном <tex>\gamma</tex>, а затем веса дискриминатора <tex>\gamma</tex> при фиксированном <tex>\theta</tex>. На практике дискриминатор обновляется <tex>k</tex> раз вместо одного; <tex>k</tex> является гиперпараметром.

<font color=green>// num_iteration {{---}} число итераций обучения </font>
'''for''' i = 1..num_iteration '''do'''
'''for''' j = 1..k '''do'''
Сэмплируем мини-батч $\{z_1, . . . , z_m\}$ из распределения $p_z$.
Сэмплируем мини-батч $\{x_1, . . . , x_m\}$ из распределения $p_{data}$.
Обновляем дискриминатор в сторону возрастания его градиента:
<tex>\mathop{\nabla}_{\gamma} { \frac{1}{m} \sum_{t = 1}^m \limits} [logD(x_t)] + [log(1-D(G(z_t))] </tex>
'''end''' '''for'''
Сэмплируем мини-батч $\{z_1, . . . , z_m\}$ из распределения $p_z$.
Обновляем генератор в сторону убывания его градиента:
<tex>\mathop{\nabla}_{\theta} { \frac{1}{m} \sum_{t = 1}^m \limits} [log(1-D(G(z_t))] </tex>
'''end''' '''for'''

Обновления на основе градиента могут быть сделаны любым стандартным способом, например, [[:Cтохастический градиентный спуск|стохастическим градиентным спуском]] (SGD). В оригинальной статье использовался SGD с импульсом.

==Улучшение обучения GAN==

Большинство GAN'ов подвержено следующим проблемам:
* Несходимость (non-convergence): параметры модели дестабилизируются и не сходятся,
* Схлопывание мод распределения (mode collapse): генератор коллапсирует, т.е выдает ограниченное количество разных образцов,
* Исчезающий градиент (diminished gradient): дискриминатор становится слишком "сильным", а градиент генератора исчезает и обучение не происходит,
* Высокая чувствительность к гиперпараметрам.

Универсального подхода к их решению нет, но существуют практические советы<ref> [https://github.com/soumith/ganhacks How to Train a GAN? Tips and tricks to make GANs work]</ref>, которые могут помочь. Основными из них являются:
# Нормализация данных. Все признаки в диапазоне $[-1; 1]$.
# Замена функции ошибки для $G$ с $\min log (1-D)$ на $\max log D$, потому что исходный вариант имеет маленький градиент на раннем этапе обучения и большой градиент при сходимости, а предложенный наоборот.
# Сэмплирование из многомерного нормального распределения вместо равномерного.
# Использование батч нормализационный слой (batch normalization layer) в $G$ и $D$.
# Использовать метки для данных, если они имеются, т.е обучать дискриминатор еще и классифицировать образцы.<ref> [https://arxiv.org/pdf/1610.09585.pdf Augustus Odena {{---}} Conditional Image Synthesis with Auxiliary Classifier GANs]</ref>

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

* CycleGAN<ref> [https://junyanz.github.io/CycleGAN/ Jun-Yan Zhu & Taesung Park {{---}} Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks]</ref>: меняет изображения из одного домена в другой. Например, меняет на фотографии лошадей на зебр,
* SRGAN<ref> [https://arxiv.org/abs/1609.04802 Christian Ledig {{---}} Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network]</ref>: создает изображения с высоким разрешением из более низкого разрешения,
* Pix2Pix<ref> [https://phillipi.github.io/pix2pix/ Phillip Isola {{---}} Image-to-Image Translation with Conditional Adversarial Nets]</ref>: создает изображения по семантической окраске,
* StackGAN<ref> [https://arxiv.org/abs/1612.03242 Han Zhang {{---}} StackGAN: Text to Photo-realistic Image Synthesis with Stacked Generative Adversarial Networks]</ref>: создает изображения по заданному тексту,
* MidiNet<ref> [https://arxiv.org/abs/1703.10847 Li-Chia Yang {{---}} MIDINET: A CONVOLUTIONAL GENERATIVE ADVERSARIAL NETWORK FOR SYMBOLIC-DOMAIN MUSIC GENERATION]</ref>: генерирует последовательность нот, таким образом, создает мелодию.

==См. также==
*[[:Порождающие модели|Порождающие модели]]
*[[:Variational autoencoder (VAE)|Variational autoencoder (VAE)]]
==Примечания==
<references/>
== Источники информации ==
* Сергей Николенко, Артур Кадурин, Екатерина Архангельская. Глубокое обучение. Погружение в мир нейронных сетей. — «Питер», 2018. — С. 348-360.
* [https://medium.com/@jonathan_hui/gan-why-it-is-so-hard-to-train-generative-advisory-networks-819a86b3750b Medium | GAN — Why it is so hard to train Generative Adversarial Networks! ]
[[Категория: Машинное обучение]]
[[Категория: Порождающие модели]]
21
правка

Навигация