«Это 9-й день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Введение в ВАЕ
Вариационные автокодировщики (VAE) принадлежат к семейству генеративных моделей. Генератор VAE способен производить значимые выходные данные из векторов в непрерывном скрытом пространстве. Исследуйте возможные свойства вывода декодера через скрытые векторы.
В GAN основное внимание уделяется тому, как получить модель, которая аппроксимирует распределение входных данных. VAE пытается смоделировать входные распределения в несвязанном непрерывном скрытом пространстве.
В VAE основное внимание уделяется вариативному выводу со скрытым кодированием. Таким образом, VAE обеспечивает подходящую основу для скрытого обучения переменных и эффективного байесовского вывода.
Конструктивно VAE аналогичны автоэнкодерам. Он также состоит из кодировщика (также называемого моделью распознавания или вывода) и декодера (также называемого генеративной моделью). И VAE, и автоэнкодеры пытаются реконструировать входные данные, изучая скрытые векторы. Однако, в отличие от автоэнкодера, скрытое пространство ВАЭ непрерывно, а в качестве генеративной модели используется сам декодер.
Принцип VAE
В генеративной модели нейронная сеть используется для аппроксимации истинного распределения входных данных:
в,представляет параметры модели.
В машинном обучении для выполнения определенного вывода желательно найти входи скрытые переменныесовместное распределение между. Скрытые переменные кодируют определенные свойства, наблюдаемые на входе. Как и в случае с данными о лицах, это могут быть выражения лица, прически, цвет волос, пол и т. д.
На самом деле это распределение входных данных и их свойства.Его можно рассчитать из предельного распределения:
Другими словами, учитываются все возможные свойства, и в итоге вы получаете распределение, описывающее ввод. В данных о лице, используя признаки, включая выражение лица, прическу, цвет волос и пол, можно восстановить распределение, описывающее данные о лице.
Проблема в том, что для этого уравнения не существует аналитической формы или действительной оценки. Поэтому оптимизация с помощью нейронных сетей невозможна.
Используя теорему Байеса, можно найти альтернативное выражение уравнению (2):
в,дапредварительное распределение . Оно не обусловлено никаким наблюдением. еслиявляется дискретным иявляется распределением Гаусса, топредставляет собой смесь распределений Гаусса. еслинепрерывно, то распределение ГауссаНепредсказуемый.
На практике, если попытаться построить приближение без подходящей функции потерь, он будет игнорироватьи получить тривиальное решение,. Следовательно, уравнение (3) не может датьхорошая оценка. Формула (2) также может быть выражена как:
но,Также сложно решить. Цель VAE состоит в том, чтобы найти оценочное распределение, которое аппроксимирует, то есть при вводеВ случае скрытого кодированияОценка условного распределения .
Вариационный вывод
так какПростая в обращении, VAE представляет вариационную модель вывода (кодер):
можно хорошо оценить. Он параметризуем и прост в обращении. Параметры могут быть оптимизированы с помощью глубоких нейронных сетейприближать. ОбычноВыберите в качестве многомерного распределения Гаусса:
значити стандартное отклонениеОба рассчитываются нейронной сетью кодировщика с использованием входных данных. Диагональное матричное представлениеЭлементы в независимы друг от друга.
Основное уравнение VAE
модель выводаввод отСоздать скрытый вектор.Аналогично кодировщику в модели автоэнкодера. с другой стороны,Восстановите ввод из скрытого кода z.действует как декодер в модели автоэнкодера. чтобы оценить, необходимо определить, чтоиОтношение.
еслида, то дивергенция Кульбака-Лейблера (КЛ) определяет расстояние между этими двумя условными плотностями:
Используя теорему Байеса:
Перепишем уравнение (7) уравнением (8), при этом из-заЭто не зависит от:
Измените приведенную выше формулу и используйте:
получить:
Приведенная выше формула является основой VAE. левый элемент, что сводит к минимумус правдойразница в расстоянии. Логарифмы не меняют положения максимума (или минимума). Учитывая, что можно хорошо оценитьМодель вывода ,около нуля.
первый элемент справаПодобно декодеру, этот декодер берет выборки из модели логического вывода для восстановления входных данных.
Второй элементиKL расстояние между. Левая часть формулы также называется нижней границей доказательства (ELBO). Поскольку KL всегда положителен, ELBOнижний предел . Путем оптимизации параметров нейронной сетиимаксимизировать ELBO означает:
- или ватрибут средней парыЗакодированная модель вывода оптимизирована.
- правильномаксимизировать или из скрытого векторарефакторинг, модель декодера оптимизирована.
Метод оптимизации
В правой части формулы есть две важные части информации о функции потерь VAE. элемент декодераГенератор представлений берет из выходных данных модели выводаобразцы для восстановления ввода. Максимизация этого срока означает восстановление потериминимизировать. MSE можно использовать, если предполагается, что распределение изображений (данных) является гауссовым.
Если каждый пиксель (данные) считается распределенным по Бернулли, то функция потерь представляет собой двоичную перекрестную энтропию.
второй раздел,так какявляется распределением Гаусса. как правило, что также является средним значениемРаспределение Гаусса со стандартным отклонением, равным 1,0. Термин KL можно упростить до:
вдаизмерение. и рассчитываются по модели вывода оФункция. максимизировать:но,.Выбор обусловлен свойствами изотропного единичного распределения Гаусса, которое может быть преобразовано в произвольное распределение с заданной соответствующей функцией.
Согласно уравнению (12), потери KLза. Таким образом, функция потерь VAE определяется как:
Учитывая модели кодировщика и декодера, перед созданием и обучением VAE необходимо решить еще одну проблему.
Трюк с репараметризацией
В левой части рисунка ниже показана сеть VAE. Кодер получает вводи оценить скрытый векторСреднее значение многомерного гауссовского распределенияи стандартное отклонение. Декодер из скрытого векторавыборка для восстановления ввода как.
Но обратное распространение градиентов не проходит через случайно выбранные блоки. В то время как нейронная сеть может предоставлять случайные входные данные, градиенты не могут проходить через случайные слои. Решение этой проблемы состоит в том, чтобы использовать в качестве входных данных процесс «выборки», как показано в правой части рисунка. Выборка рассчитывается как:
еслииТогда в векторной формеявляется поэлементным умножением. Используя уравнение (14), предположим, что образцы поступают непосредственно из скрытого пространства. Этот метод называется приемом репараметризации. После выборки на входе сеть VAE можно обучить с помощью знакомых алгоритмов оптимизации, таких как SGD, Adam или RMSProp.
реализация VAE
Чтобы облегчить визуализацию базовой кодировки,Размер установлен на 2. Кодер представляет собой просто двухуровневый MLP, где второй уровень генерирует среднее значение и логарифмическую дисперсию. Логарифмическая дисперсия используется для упрощения вычисления потерь KL и трюка репараметризации. Третий вывод энкодера сделан с использованием трюка перепараметризациивыборка. В функции выборки,так какявляется стандартным отклонением распределения Гаусса.
Декодер также представляет собой двухуровневый MLP, которыйобразцов отбираются для аппроксимации входных данных. Сеть VAE просто соединяет кодер и декодер вместе. Функция потерь представляет собой сумму потерь реконструкции и потерь KL. Используйте оптимизатор Адама.
Трюк с повторным параметром
#reparameterization trick
#z = z_mean + sqrt(var) * eps
def sampling(args):
"""Reparameterization trick by sampling
Reparameterization trick by sampling fr an isotropic unit Gaussian.
#Arguments:
args (tensor): mean and log of variance of Q(z|x)
#Returns:
z (tensor): sampled latent vector
"""
z_mean,z_log_var = args
batch = keras.backend.shape(z_mean)[0]
dim = keras.backend.shape(z_mean)[1]
epsilon = keras.backend.random_normal(shape=(batch,dim))
return z_mean + keras.backend.exp(0.5 * z_log_var) * epsilon
Загрузить данные и гиперпараметры
# MNIST 数据集
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
image_size = x_train.shape[1]
original_dim = image_size * image_size
x_train = np.reshape(x_train, [-1, original_dim])
x_test = np.reshape(x_test, [-1, original_dim])
x_train = x_train.astype('float32') / 255
x_test = x_test.astype('float32') / 255
#超参数
input_shape = (original_dim,)
intermediate_dim = 512
batch_size = 128
latent_dim = 2
epochs = 50
модель VAE
#VAE model
#encoder
inputs = keras.layers.Input(shape=input_shape,name='encoder_input')
x = keras.layers.Dense(intermediate_dim,activation='relu')(inputs)
z_mean = keras.layers.Dense(latent_dim,name='z_mean')(x)
z_log_var = keras.layers.Dense(latent_dim,name='z_log_var')(x)
z = keras.layers.Lambda(sampling,output_shape=(latent_dim,),name='z')([z_mean,z_log_var])
encoder = keras.Model(inputs,[z_mean,z_log_var,z],name='encoder')
encoder.summary()
keras.utils.plot_model(encoder,to_file='vae_mlp_encoder.png',show_shapes=True)
#decoder
latent_inputs = keras.layers.Input(shape=(latent_dim,),name='z_sampling')
x = keras.layers.Dense(intermediate_dim,activation='relu')(latent_inputs)
outputs = keras.layers.Dense(original_dim,activation='sigmoid')(x)
decoder = keras.Model(latent_inputs,outputs,name='decoder')
decoder.summary()
keras.utils.plot_model(decoder,to_file='vae_mlp_decoder.png',show_shapes=True)
outputs = decoder(encoder(inputs)[2])
vae = keras.Model(inputs,outputs,name='vae_mpl')
обучение модели
if __name__ == '__main__':
parser = argparse.ArgumentParser()
help_ = "Load tf model trained weights"
parser.add_argument("-w", "--weights", help=help_)
help_ = "Use binary cross entropy instead of mse (default)"
parser.add_argument("--bce", help=help_, action='store_true')
args = parser.parse_args()
models = (encoder, decoder)
data = (x_test, y_test)
#VAE loss = mse_loss or xent_loss + kl_loss
if args.bce:
reconstruction_loss = keras.losses.binary_crossentropy(inputs,outputs)
else:
reconstruction_loss = keras.losses.mse(inputs,outputs)
reconstruction_loss *= original_dim
kl_loss = 1 + z_log_var - keras.backend.square(z_mean) - keras.backend.exp(z_log_var)
kl_loss = keras.backend.sum(kl_loss,axis=-1)
kl_loss *= -0.5
vae_loss = keras.backend.mean(reconstruction_loss + kl_loss)
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')
vae.summary()
keras.utils.plot_model(vae,to_file='vae_mlp.png',show_shapes=True)
save_dir = 'vae_mlp_weights'
if not os.path.isdir(save_dir):
os.makedirs(save_dir)
if args.weights:
filepath = os.path.join(save_dir,args.weights)
vae = vae.load_weights(filepath)
else:
#train
vae.fit(x_train,
epochs=epochs,
batch_size=batch_size,
validation_data=(x_test,None))
filepath = os.path.join(save_dir,'vae_mlp.mnist.tf')
vae.save_weights(filepath)
plot_results(models,data,batch_size=batch_size,model_name='vae_mlp')
Протестируйте обученный декодер
После обучения сети VAE модель логического вывода можно отбросить. Чтобы создать новый значимый результат, изНарисуйте образцы из распределения Гаусса:
Показать результаты
潜矢量可视化
图片生成