Вы можете найти исходный код этого сообщения по адресу https://github.com/alimirzaei/adverserial-autoencoder-keras

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

Генеративные состязательные сети (GAN) - это архитектуры глубоких нейронных сетей, состоящие из двух сетей, противопоставляющих друг друга (таким образом, «состязательные»). Сеть генератора пытается сгенерировать поддельные изображения, чтобы обмануть дискриминатор, а дискриминатор пытается правильно различать поддельные и настоящие изображения. GAN был представлен в статье Яна Гудфеллоу и других исследователей из Монреальского университета, в том числе Йошуа Бенжио, в 2014 году. По этой схеме генератор учится генерировать выборку на основе распределения обучающих данных.

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

Состязательный автоэнкодер

В этом разделе я реализовал приведенный выше рисунок. Желаемое распределение для скрытого пространства предполагается гауссовым. Во всех реализациях в этом посте я использовал Python в качестве языка программирования и Keras в качестве основы для глубокого обучения.

Я реализую схему AAE для генерации изображений MNIST. Набор данных MNIST содержит 60 000 рукописных числовых изображений, и каждый размер изображения составляет 28x28. Таким образом, количество входных элементов будет 28x28 = 784.

Кодировщик

Как было предложено в документе, мы использовали два полностью связанных (каждый слой имеет 1000 нейронов) слоя в качестве скрытых слоев кодировщика и 8 полностью связанных слоев нейронов в качестве выходного слоя кодировщика. Для скрытых слоев используется функция активации Relu, а выходной слой не имеет функции активации (линейной). В таблице ниже приведены подробные сведения о кодировщике.

________________________________________________________
Layer (type) Output Shape Param #
========================================================
flatten_1 (Flatten) (None, 7) 0
________________________________________________________
dense_1 (Dense) (None, 1000) 785000
________________________________________________________
dense_2 (Dense) (None, 1000) 1001000
________________________________________________________
dense_3 (Dense) (None, 8) 8008
========================================================
Total params: 1,794,008
Trainable params: 1,794,008
Non-trainable params: 0
________________________________________________________

Декодер

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

_______________________________________________________
Layer (type) Output Shape Param #
=======================================================
dense_4 (Dense) (None, 1000) 9000
_______________________________________________________
dense_5 (Dense) (None, 1000) 1001000
_______________________________________________________
dense_6 (Dense) (None, 784) 784784
_______________________________________________________
reshape_1 (Reshape) (None, 28, 28) 0
=======================================================
Total params: 1,794,784
Trainable params: 1,794,784
Non-trainable params: 0
_______________________________________________________

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

Роль дискриминатора - классифицировать поддельные и считывать скрытые коды, поэтому на выходе получается один нейрон. Подробная сводка дискриминатора проиллюстрирована в следующей таблице. Функция активации для двух скрытых слоев - Relu, а для выходного слоя - сигмовидная.

_____________________________________________________
Layer (type) Output Shape Param #
=====================================================
dense_7 (Dense) (None, 1000) 9000
_____________________________________________________
dense_8 (Dense) (None, 1000) 1001000
_____________________________________________________
dense_9 (Dense) (None, 1) 1001
=====================================================
Total params: 1,011,001
Trainable params: 1,011,001
Non-trainable params: 0
\end{lstlisting}

Обучение

Я обучил сеть с размером пакета 100. Для каждой партии выполняются следующие процедуры:

1- Обучить дискриминатор: мы загружаем 50 обучающих изображений в кодировщик и принимаем полученные скрытые коды как поддельные (метка = 0). Мы также генерируем 50 выборок из желаемого распределения, 8-мерного распределения Гаусса, и принимаем их за реальные (метка = 1). После генерации этих скрытых кодов мы обучаем дискриминатор с этими образцами и соответствующими им метками. Сеть будет обучена на основе ошибки классификации.
2- Обучить автоэнкодер для ошибки реконструкции: 100 образцов обучающих изображений подаются в автоэнкодер (кодировщик и декодер), и автокодер будет обучен на основе ошибки восстановления (MSE).
3- Обучающий генератор (кодировщик): на этом этапе мы должны обучить генератор (кодировщик) генерировать скрытые коды, такие же, как и дискретизированные. Другими словами, кодировщик должен быть обучен таким образом, чтобы он вводил в заблуждение дискриминатор. Для этой цели мы фиксируем веса дискриминатора и обучаем кодировщик и дискриминатор вместе, чтобы дискриминатор классифицировал скрытые коды изображений фида как реальные (метка = 1).

Полученные результаты

На следующих рисунках показаны сгенерированные изображения после 1000 и 4000 эпох. Как показано, изображения четкие и не размытые, как в вариационном автоэнкодере. SGD используется для дискриминатора и генератора со скоростью обучения 0,01 $ и ADAM со скоростью обучения 0,001 для фазы восстановления.

Включение информации на этикетке в состязательную регуляризацию

Предыдущий раздел полностью без присмотра. В сценариях, где данные помечены, мы можем включить информацию о ярлыках на этапе обучения противников, чтобы лучше формировать распределение скрытого кода. Предлагаемая схема представлена ​​на следующем рисунке. В этой схеме делается попытка сопоставить скрытые коды каждого числа с определенным распределением Гаусса. Кроме того, на дискриминатор подается оперативный код этикетки. В нашей реализации мы использовали смесь из 10 гауссовых распределений. Мы обучили эту схему в полунезависимой манере. для этой цели предполагается дополнительный размер для однократного энкодера (11 размеров). Если метка образца не предоставлена, 11-й элемент кода равен единице, и сгенерированный образец выбирается из всей смеси гауссовского типа.

Реализация и результаты

Я обучил AAE с полуконтролем, используя 40000 меченых образцов и 20000 немаркированных образцов. Детали архитектуры сети такие же, как и у предыдущей. Условно сгенерированные образцы показаны на следующем изображении:

а скрытые коды некоторых тестовых изображений показаны на следующем рисунке. Детали реализации доступны в исходном коде.

Контролируемый состязательный автоэнкодер

В этом разделе основное внимание уделяется полностью контролируемым сценариям и обсуждается архитектура состязательных автоэнкодеров, которые могут отделять информацию о метке класса от информации о стиле изображения.
Чтобы включить информацию о метке, документ изменяет сетевую архитектуру из предыдущего раздела. для предоставления декодеру однократного векторного кодирования метки (следующий рисунок). Декодер использует как горячий вектор, идентифицирующий метку, так и скрытый код z, чтобы восстановить изображение. Эта архитектура заставляет сеть сохранять всю информацию независимо от метки в скрытом коде z.

Реализация и результаты

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

Заключение

В этом проекте я реализовал три схемы от AAE: Original AAE, Semi-Supervised и Supervised. Подробности реализации приведены в исходных кодах. Алгоритмы оптимизации и скорость их обучения выбираются таким образом, чтобы сети сходились правильно.

Исходный код

Https://github.com/alimirzaei/adverserial-autoencoder-keras

Библиография

[1] Махзани, Алиреза и др. «Состязательные автоэнкодеры». Препринт arXiv arXiv: 1511.05644 (2015).