Вы можете найти исходный код этого сообщения по адресу 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).