«Это 16-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."
Разнообразная трансформация изображения с BicyleGAN
Pix2pix
иCycleGAN
— это очень популярная GAN, имеющая множество вариантов не только в академических кругах, но и множество приложений, основанных на ней. Однако у них обоих есть недостаток — вывод изображения почти всегда будет выглядеть одинаково. Например, если бы мы выполнили преобразование зебры в лошадь, преобразованная фотография одной и той же лошади всегда имела бы одинаковый внешний вид и оттенок. Это связано с неотъемлемыми свойствами GAN, которые учатся отфильтровывать случайный шум. Чтобы выполнить разнообразное преобразование изображений, в этой статье подробно объясняетсяBicycleGAN
Как решить эту проблему, чтобы создавать более насыщенные изображения и использовать преимуществаTensorflow2
ДостигнутоBicycleGAN
.
Отображение эффекта BicyleGAN
использоватьBicyleGAN
Изображение может быть преобразовано различными способами для получения различных стилей и цветов:
Архитектура BicycleGAN
с началаBicycleGAN
Перед этим позвольте мне дать вам краткое введение. Когда вы слышите это имя в первый раз, вы можете подуматьBicycleGAN
даCycleGAN
вариант , но на самом деле это связано сCycleGAN
Это не имеет значения, вместо этого это правильноpix2pix
улучшение.
pix2pix
— это взаимно однозначное отображение, при котором выход для заданного входа всегда одинаков. При попытке добавить шум на вход генератора сеть игнорирует шум и не производит никаких изменений в выходном изображении. Следовательно, нам нужно найти способ заставить генератор не игнорировать шум, а использовать его для генерации разноплановых изображений, т.е. отображения «один ко многим».
На картинке нижеBicycleGAN
Связанные модели и конфигурации.图(a)
это конфигурация для вывода, изображение A комбинируется с шумом для создания изображения, что можно рассматривать какcGAN
. В BicyleGAN форма(256, 256, 3)
Образ А обусловлен, в то время как скрытое кодированиеДискретизированный шум представляет собой одномерный вектор размера 8.图(b)
даpix2pix + 噪声
конфигурация обучения. и图(c)
и图(d)
Две конфигурации задаютсяBicycleGAN
Используйте при обучении:
короче,BicycleGAN
Можно найти взаимосвязь между скрытым кодированием z и целевым изображением B, поэтому генератор может научиться генерировать разные изображения при разных z.. Как показано на рисунке выше, BicycleGAN работает, комбинируяcVAE-GAN
иcLR-GAN
Обе модели делают это.
cVAE-GAN
VAE-GAN
Авторы утверждают, что,Потери не являются хорошей мерой визуального качества изображения. Например, если изображение сдвинуто на несколько пикселей вправо, человеческий глаз может выглядеть так же, но это приведет к увеличению изображения.потеря. Так что используйтеGAN
Дискриминатор, чтобы узнать целевую функцию, чтобы судить, является ли поддельное изображение реальным, и использоватьVAE
Как генератор, результирующие изображения более четкие. Если игнорировать图(c)
изображения в,ЭтоVAE-GAN
, так какэто условие, оно становится условиемcVAE-GAN
. Этапы обучения следующие:
-
VAE
поставить реальные фотографииКодируйте скрытые коды в многомерные распределения Гаусса, а затем производите выборку из них для создания зашумленных входных данных. Этот процесс является стандартным рабочим процессом VAE; - использовать изображениякак условие и из скрытого вектораДискретизированный шум используется для создания поддельных изображений..
Поток данных в обучении ( 图(c)
сплошные стрелки на ), функция полных потерь состоит из трех потерь:
- : против потери
- :потеря реконструкции
- :Потеря дивергенции
cLR-GAN(Conditional Latent Regressor GAN)
существуетcVAE-GAN
, реальное изображение B кодируется, чтобы обеспечить реальную выборку скрытого вектора и выборку из него. но,cLR-GAN
обрабатывается по-другому, который сначала использует генератор для создания поддельных изображений из случайного шума, а затем для поддельного изображенияЗакодируйте и, наконец, вычислите его отличие от входного случайного шума.
Шаги прямого расчета следующие:
- Во-первых, что-то вроде
cGAN
, случайным образом сгенерируйте некоторый шум, затем объедините изображение A, чтобы создать поддельное изображение.. - После этого используйте
VAE-GAN
Тот же кодировщик псевдоизображениякодируются как скрытые векторы. - Наконец, образец из закодированного латентного вектора, а с входным шумомПодсчитайте потери.
Поток данных ( 图(d)
сплошные стрелки в ), есть две потери:
- : против потери
-
:шум
N(z)
между базовым кодомпотеря
Путем объединения этих двух потоков данных получается двойной цикл отображения между выходом и скрытым пространством.BicycleGAN
серединаbi
От бимап (биективный), который является математическим термином, который просто означает взаимно однозначное отображение и является обратимым. при этих обстоятельствах,BicycleGAN
Сопоставьте выходные данные со скрытым пространством и аналогичным образом сопоставьте скрытое пространство с выходными данными. Общие потери выглядят следующим образом:
В конфигурации по умолчанию,,.
Реализация BicycleGAN
BicycleGAN
Существует три типа сетей - генератор, дискриминатор и кодер. заcVAE-GAN
иcLR-GAN
Использование отдельных дискриминаторов улучшает качество изображения, поэтому мы будем использовать четыре сети — генератор, кодировщик и два дискриминатора.
Вставьте скрытую кодировку в генератор
Есть два способа вставить скрытые кодировки в генератор, как показано на следующем рисунке:
- Объединить с входным изображением;
- Вставьте его в другие слои в пути понижающей дискретизации генератора.
Эксперименты показали, что первый работает хорошо.
Существуют различные способы комбинирования входов и условий разной формы.BicycleGAN
Используемый метод заключается в повторном скрытом кодировании несколько раз, а затем объединении с входным изображением.
существуетBicycleGAN
, длина скрытого кода равна 8, мы извлекли 8 выборок из распределения шума, и каждая выборка была повторена H × W раз, чтобы сформировать форму(H, W, 8)
тензор. Другими словами, в 8 каналах его(H,W)
Карты объектов все одинаковые. Следующий код показывает объединение и объединение возможных кодировок:
input_image = layers.Input(shape=image_shape, name='input_image')
input_z = layers.Input(shape=(self.z_dim,), name='z')
z = layers.Reshape((1,1, self.z_dim))(input_z)
z_tiles = tf.tile(z, [self.batch_size, self.input_shape[0], self.input_shape[1], self.z_dim])
x = layers.Concatenate()([input_image, z_tiles])
Следующим шагом является создание двух моделей, а именноcVAE-GAN
иcLR-GAN
, чтобы объединить сети и создать прямой поток информации.
cVAE-GAN
Создать нижеcVAE-GAN
Код модели, реализация форвардного расчета:
images_A_1 = layers.Input(shape=input_shape, name='ImageA_1')
images_B_1 = layers.Input(shape=input_shape, name='ImageB_1')
z_encode, self.mean_encode, self.logvar_encode = self.encoder(images_B_1)
fake_B_encode = self.generator([images_A_1, z_encode])
encode_fake = self.discriminator_1(fake_B_encode)
encode_real = self.discriminator_1(images_B_1)
kl_loss = - 0.5 * tf.reduce_sum(1 + self.logvar_encode - tf.square(self.mean_encode) - tf.exp(self.logvar_encode))
self.cvae_gan = Model(inputs=[images_A_1, images_B_1], outputs=[encode_real, encode_fake, fake_B_encode, kl_loss])
Мы использовали в моделиПотеря дивергенции. Поскольку его можно рассчитать непосредственно из среднего значения и логарифмической дисперсииkl_loss
, без передачи внешних меток на этапе обучения, что делает его более простым и эффективным.
cLR-GAN
НижеcLR-GAN
Реализация форвардного расчета:
images_A_2 = layers.Input(shape=input_shape, name='ImageA_2')
images_B_2 = layers.Input(shape=input_shape, name='ImageB_2')
z_random = layers.Input(shape=(self.z_dim,), name='z')
fake_B_random = self.generator([images_A_2, z_random])
_, mean_random, _ = self.encoder(fake_B_random)
random_fake = self.discriminator_2(fake_B_random)
random_real = self.discriminator_2(images_B_2)
self.clr_gan = Model(inputs=[images_A_2, images_B_2, z_random],
outputs=[random_real, random_fake, mean_random])
Теперь, когда мы определили модель, следующим шагом будет реализация шага обучения.
этапы обучения
Обе модели обучаются вместе, но с разными парами изображений. Таким образом, на каждом этапе обучения мы извлекаем данные дважды, по одному разу для каждой модели, это делается путем создания конвейера данных, который будет вызываться дважды для загрузки данных:
images_A_1, images_B_1 = next(data_generator)
images_A_2, images_B_2 = next(data_generator)
self.train_step(images_A_1, images_B_1, images_A_2, images_B_2)
Мы можем проводить обучение, используя два разных метода. Один из них — определить и скомпилировать модель Keras с оптимизатором и функцией потерь, а затем вызватьtrain_on_batch()
для выполнения шага обучения, который хорошо работает на четко определенных моделях. Кроме того, мы также можем использоватьtf.GradientTape
чтобы лучше контролировать обновления градиента.BicycleGAN
Есть две модели, у них общий генератор и энкодер, но нам нужно обновить их параметры с разными комбинациями функций потерь, что делаетtrain_on_batch
метод невозможен без изменения исходных настроек. Поэтому мы используемtf.GradientTape
Объедините генератор и дискриминатор этих двух моделей в один шаг обучения следующим образом:
- Первый шаг — выполнить прямой проход и собрать выходные данные обеих моделей:
def train_step(self, images_A_1, images_B_1, images_A_2, images_B_2):
z = tf.random.normal((self.batch_size, self.z_dim))
real_labels = tf.ones((self.batch_size, self.patch_size, self.patch_size, 1))
fake_labels = tf.zeros((self.batch_size, self.patch_size, self.patch_size, 1))
with tf.GradientTape() as tape_e, tf.GradientTape() as tape_g, tf.GradientTape() as tape_d1, tf.GradientTape() as tape_d2:
encode_real, encode_fake, fake_B_encode, kl_loss = self.cvae_gan([images_A_1, images_B_1])
random_real, random_fake, mean_random = self.clr_gan([images_A_2, images_B_2, z])
- Затем мы обновляем дискриминатор с помощью обратного распространения градиента:
# discriminator loss
self.d1_loss = self.mse(real_labels, encode_real) + self.mse(fake_labels, encode_fake)
gradients_d1 = tape_d1.gradient(self.d1_loss, self.discriminator_1.trainable_variables)
self.optimizer_d1.apply_gradients(zip(gradients_d1, self.discriminator_1.trainable_variables))
self.d2_loss = self.mse(real_labels, random_real) + self.mse(fake_labels, random_fake)
gradients_d2 = tape_d2.gradient(self.d2_loss,self.discriminator_2.trainable_variables)
self.optimizer_d2.apply_gradients(zip(gradients_d2, self.discriminator_2.trainable_variables))
- Затем мы рассчитываем потери на основе выходных данных модели. и
CycleGAN
сходство,BicycleGAN
также использоватьLSGAN
Функция потерь, среднеквадратическая ошибка:
self.LAMBDA_IMAGE = 10
self.LAMBDA_LATENT = 0.5
self.LAMBDA_KL = 0.01
# Generator and Encoder loss
self.gan_1_loss = self.mse(real_labels, encode_fake)
self.gan_2_loss = self.mse(real_labels, random_fake)
self.image_loss = self.LAMBDA_IMAGE * self.mae(images_B_1, fake_B_encode)
self.kl_loss = self.LAMBDA_KL * kl_loss
self.latent_loss = self.LAMBDA_LATENT * self.mae(z, mean_random)
- Наконец, есть обновления весов генератора и энкодера.Скрытая потеря кодирования используется только для обновления генератора, а не кодировщика. Одновременная оптимизация потерь заставит их скрывать информацию, относящуюся к скрытому кодированию, без изучения значимых закономерностей в скрытом кодировании. Следовательно, потери необходимо вычислять отдельно для генератора и энкодера и соответственно обновлять веса:
encoder_loss = self.gan_1_loss + self.gan_2_loss + self.image_loss + self.kl_loss
generator_loss = encoder_loss + self.latent_loss
gradients_generator = tape_g.gradient(generator_loss, self.generator.trainable_variables)
self.optimizer_generator.apply_gradients(zip(gradients_generator, self.generator.trainable_variables))
gradients_encoder = tape_e.gradient(encoder_loss, self.encoder.trainable_variables)
self.optimizer_encoder.apply_gradients(zip(gradients_encoder, self.encoder.trainable_variables))
Результаты обучения и анализ
Для обучения BicycleGAN вы можете выбирать между двумя наборами данных — эскизами строительных конструкций или эскизами кромок обуви. Изображения набора данных обуви проще и, следовательно, их легче обучать, поэтому возьмите это обучение в качестве примера. Следующие изображенияBicycleGAN
Показать пример результатов обучения. Первое изображение — это штриховой рисунок, второе изображение — это реальное изображение, соответствующее штриховому рисунку, и сгенерированы четыре изображения справа:
Видно, что разница между разными изображениями, созданными одним и тем же штриховым рисунком, в основном заключается в цвете. Все они почти идеально отражают структуру обуви, но с точки зрения захвата деталей эффект не очень идеален, и более отличные характеристики модели можно получить за счет увеличения обучения и настройки гиперпараметров.