«Это 24-й день моего участия в ноябрьском испытании обновлений. Подробную информацию об этом событии см.:Вызов последнего обновления 2021 г."
Используйте VAE для создания изображений лиц
Справочное сообщение в блоге с базовыми знаниями о вариационных автоэнкодерах (VAE)«Подробное объяснение и реализация вариационного автоэнкодера (VAE) (реализовано с помощью TensorFlow2)». В качестве приложения VAE мы будем использовать VAE для создания некоторых изображений лиц с управляемыми атрибутами. Доступные наборы данных о лицах включают:
- Celeb A: это популярный набор данных в академических кругах, поскольку он содержит аннотации черт лица и не может использоваться в коммерческих целях.
- Flickr-Faces-HQ Dataset, FFHQ: этот набор данных бесплатен для коммерческого использования и содержит изображения с высоким разрешением.
Сетевая архитектура
Входная форма сети (112, 112, 3), а размер изображения можно настроить во время предварительной обработки данных. Из-за сложности набора данных количество фильтров можно увеличить, чтобы увеличить пропускную способность сети. Следовательно, сверточные слои в кодировщике следующие:
a) Conv2D(filters = 32, kernel_size=(3,3), strides = 2)
b) Conv2D(filters = 32, kernel_size=(3,3), strides = 2)
c) Conv2D(filters = 64, kernel_size=(3,3), strides = 2)
d) Conv2D(filters = 64, kernel_size=(3,3), strides = 2)
реконструкция лица
Давайте сначала посмотрим на реконструированный эффект изображения VAE:
Хотя восстановленные изображения не идеальны, они, по крайней мере, выглядят хорошо. VAE удается изучить некоторые особенности входного изображения и использовать их для рисования новых лиц. Видно, что VAE лучше реконструирует женские лица. Это потому чтоCeleb_A数据集
Доля женщин выше. Вот почему оттенки мужской кожи, как правило, более молодые и женственные.
Глядя на фон изображения, из-за разнообразия фона изображения кодировщик не может кодировать каждую деталь до малых размеров, поэтому мы видим, что VAE кодирует цвета фона, а декодер создает размытый фон на основе этих цветов.
Создавайте новые лица
Чтобы сгенерировать новое изображение, мы выбираем случайные числа из стандартного распределения Гаусса и передаем их декодеру:
z_samples = np.random.normal(loc=0., scale=1, size=(image_num, z_dim))
images = vae.decoder(z_samples.astype(np.float32))
Однако некоторые из сгенерированных лиц выглядят ужасно!
Мы можем использовать трюки с выборкой, чтобы улучшить точность изображения.
Советы по выборке
Видно, что обученный VAE может очень хорошо реконструировать лицо. Однако есть проблемы с изображениями, созданными путем случайной выборки скрытых переменных. Чтобы отладить проблему, изображения в наборе данных передаются в декодер VAE для получения среднего значения и дисперсии скрытого пространства. Затем наносится среднее значение каждой переменной скрытого пространства:
Теоретически они должны иметь среднее значение 0 и дисперсию 1, но случайно выбранные выборки не всегда соответствуют ожидаемому декодером распределению. Вот тут-то и появляется трюк с выборкой, собирая среднее стандартное отклонение скрытой переменной (скалярное значение), которое используется для создания нормально распределенных выборок (200-мерных). Затем к нему было добавлено среднее значение (200 измерений).
да, результирующее изображение теперь выглядит намного лучше!
Далее мы рассмотрим, как выполнять редактирование атрибутов лица вместо создания случайных лиц.
Управление атрибутами лица
скрытое пространство
По сути, скрытое пространство означает все возможные значения скрытой переменной. В нашем VAE это 200-мерный вектор (или 200 переменных). Мы хотим, чтобы каждая переменная содержала уникальную семантику, такую как z[0] для глаз, z[1] для цвета глаз и т. д. Все никогда не бывает так просто. Предполагая, что информация закодирована во всех скрытых векторах, скрытое пространство можно исследовать с помощью векторной арифметики.
контроль собственности
Объясните принципы управления атрибутами на двухмерном примере. Предположим, вы сейчас находитесь в точке (0,0) на карте, а пункт назначения находится в (x, y). Следовательно, направление к месту назначения (x-0, y-0) делится на норму L2 (x, y), которая может быть выражена как (x_dot, y_dot). Таким образом, каждый раз, когда вы двигаетесь (x_dot, y_dot), вы движетесь к месту назначения. Каждый раз, когда вы двигаетесь (-2 * x_dot, -2 * y_dot), вы будете удаляться от пункта назначения в два раза больше шагов.
Точно так же, если мы знаем вектор направления атрибута улыбки, мы можем добавить его к скрытой переменной, чтобы привязать атрибут улыбки к лицу:
new_z_samples = z_samples + smiling_magnitude*smiling_vector
smile_magnitude — это скалярное значение, которое мы установили, поэтому следующим шагом будет выяснить, как получить smile_vector.
найти вектор атрибута
Набор данных Celeb A поставляется с аннотациями атрибутов лица для каждого изображения. Теги являются двоичными и указывают, присутствует ли в изображении определенный атрибут. Мы будем использовать метки и закодированные скрытые переменные, чтобы найти наш вектор ориентации:
- Используйте образцы из тестового набора данных или обучающего набора данных и создавайте скрытые векторы с помощью декодера VAE.
- Разделите скрытые векторы на две группы: с (положительный вектор) или без (отрицательный вектор) одним интересующим нас атрибутом.
- Вычислите среднее положительного и отрицательного векторов отдельно.
- Вектор направления атрибута получается путем вычитания среднего отрицательного вектора из среднего положительного вектора.
В функции препроцессора возвращаем метку интересующего нас атрибута. Затем используйте лямбда-функцию для сопоставления с конвейером данных:
def preprocess_attrib(sample, attribute):
image = sample['image']
image = tf.image.resize(image, [112,112])
image = tf.cast(image, tf.float32)/255.
return image, sample['attributes'][attribute]
ds = ds.map(lambda x: preprocess_attrib(x, attribute))
Редактирование атрибутов лица
После извлечения вектора атрибутов сделайте следующее:
- Сначала мы получаем изображения из набора данных и ставим их первыми для сравнения.
- Кодируйте лица как скрытые переменные, затем декодируйте их, чтобы сгенерировать новые лица и поместить их в середину.
- Затем мы постепенно увеличиваем вектор атрибутов вправо.
- Точно так же мы постепенно уменьшаем вектор атрибута влево.
На изображении ниже показано изображение, созданное путем интерполяции скрытых векторов:
Затем мы можем попробовать изменить несколько атрибутов лица вместе. На изображении ниже изображение слева генерируется случайным образом и используется в качестве эталона. Справа новое изображение после некоторых операций со скрытым пространством:
Виджет доступен в блокнотах Jupyter.