Подробное объяснение и реализация вариационного автоэнкодера (VAE) (реализовано с помощью TensorFlow2)

искусственный интеллект глубокое обучение
Подробное объяснение и реализация вариационного автоэнкодера (VAE) (реализовано с помощью TensorFlow2)

«Это 9-й день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."

Введение в ВАЕ

Вариационные автокодировщики (VAE) принадлежат к семейству генеративных моделей. Генератор VAE способен производить значимые выходные данные из векторов в непрерывном скрытом пространстве. Исследуйте возможные свойства вывода декодера через скрытые векторы.

В GAN основное внимание уделяется тому, как получить модель, которая аппроксимирует распределение входных данных. VAE пытается смоделировать входные распределения в несвязанном непрерывном скрытом пространстве.

В VAE основное внимание уделяется вариативному выводу со скрытым кодированием. Таким образом, VAE обеспечивает подходящую основу для скрытого обучения переменных и эффективного байесовского вывода.

Конструктивно VAE аналогичны автоэнкодерам. Он также состоит из кодировщика (также называемого моделью распознавания или вывода) и декодера (также называемого генеративной моделью). И VAE, и автоэнкодеры пытаются реконструировать входные данные, изучая скрытые векторы. Однако, в отличие от автоэнкодера, скрытое пространство ВАЭ непрерывно, а в качестве генеративной модели используется сам декодер.

Принцип VAE

В генеративной модели нейронная сеть используется для аппроксимации истинного распределения входных данных:

xPθ(x)(1)х \sim P_θ(x) \qquad(1)

в,θθпредставляет параметры модели.

В машинном обучении для выполнения определенного вывода желательно найти входxxи скрытые переменныеzzсовместное распределение междуPθ(x,z)P_θ (х, г). Скрытые переменные кодируют определенные свойства, наблюдаемые на входе. Как и в случае с данными о лицах, это могут быть выражения лица, прически, цвет волос, пол и т. д.

Pθ(x,z)P_θ (х, г)На самом деле это распределение входных данных и их свойства.Pθ(x)P_θ(х)Его можно рассчитать из предельного распределения:

Pθ(x)=Pθ(x,z)dz(2)P_θ(x)=\int P_θ(x,z)dz \qquad(2)

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

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

Используя теорему Байеса, можно найти альтернативное выражение уравнению (2):

Pθ(x)=Pθ(xz)P(z)dz(3)P_θ(x)=\int P_θ(x|z)P(z)dz \qquad(3)

в,P(z)P(z)даzzпредварительное распределение . Оно не обусловлено никаким наблюдением. еслиzzявляется дискретным иPθ(xz)P_θ(х|z)является распределением Гаусса, тоPθ(x)P_θ(х)представляет собой смесь распределений Гаусса. еслиzzнепрерывно, то распределение ГауссаPθ(x)P_θ(х)Непредсказуемый.

На практике, если попытаться построить приближение без подходящей функции потерьPθ(xz)P_θ(х|z), он будет игнорироватьzzи получить тривиальное решение,Pθ(xz)=Pθ(x)P_θ(x|z)=P_θ(x). Следовательно, уравнение (3) не может датьPθ(x)P_θ(х)хорошая оценка. Формула (2) также может быть выражена как:

Pθ(x)=Pθ(zx)P(x)dz(4)P_θ(x)=\int P_θ(z|x)P(x)dz \qquad(4)

но,Pθ(zx)P_θ(z|x)Также сложно решить. Цель VAE состоит в том, чтобы найти оценочное распределение, которое аппроксимируетPθ(zx)P_θ(z|x), то есть при вводеxxВ случае скрытого кодированияzzОценка условного распределения .

Вариационный вывод

так какPθ(zx)P_θ(z|x)Простая в обращении, VAE представляет вариационную модель вывода (кодер):

Qф(zx)Pθ(zx)(5)Q_\phi (z|x) \ приблизительно P_θ(z|x) \qquad(5)

Qф(zx)Q_\phi (z|x)можно хорошо оценитьPθ(zx)P_θ(z|x). Он параметризуем и прост в обращении. Параметры могут быть оптимизированы с помощью глубоких нейронных сетейффприближатьQф(zx)Q_\phi (z|x). ОбычноQф(zx)Q_\phi (z|x)Выберите в качестве многомерного распределения Гаусса:

Qф(zx)=N(z;мю(x),diag(о(x)2))(6)Q_\phi (z|x)=\mathcal N(z;\mu(x),diag(\sigma(x)^2)) \qquad(6)

значитмю(x)\mu(x)и стандартное отклонениео(x)\sigma (x)Оба рассчитываются нейронной сетью кодировщика с использованием входных данных. Диагональное матричное представлениеzzЭлементы в независимы друг от друга.

Основное уравнение VAE

модель выводаQф(zx)Q_\phi (z|x)ввод отxxСоздать скрытый векторzz.Qф(zx)Q_\phi (z|x)Аналогично кодировщику в модели автоэнкодера. с другой стороны,Pθ(xz)P_θ(х|z)Восстановите ввод из скрытого кода z.Pθ(xz)P_θ(х|z)действует как декодер в модели автоэнкодера. чтобы оценитьPθ(x)P_θ(х), необходимо определить, чтоQф(zx)Q_\phi (z|x)иPθ(xz)P_θ(х|z)Отношение.

еслиQф(zx)Q_\phi (z|x)даPθ(zx)P_θ(z|x), то дивергенция Кульбака-Лейблера (КЛ) определяет расстояние между этими двумя условными плотностями:

DKL(Qф(zx)Pθ(zx))=EzQ[logQф(zx)logPθ(zx)](7)D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z|x)] \ четверка (7)

Используя теорему Байеса:

Pθ(zx)=Pθ(xz)Pθ(z)Pθ(x)(8)P_θ(z|x)=\frac{P_θ(x|z)P_θ(z)}{P_θ(x)} \qquad(8)

Перепишем уравнение (7) уравнением (8), при этом из-заlogPθ(x)logP_θ(х)Это не зависит отzQz\sim Q:

DKL(Qф(zx)Pθ(zx))=EzQ[logQф(zx)logPθ(xz)logPθ(z)]+logPθ(x)(9)D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(x|z)-logP_θ (z)] + logP_θ(x)\qquad (9)

Измените приведенную выше формулу и используйте:

EzQ[logQф(zx)logPθ(z)]=DKL(Qф(zx)Pθ(z))(10)\mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z)] = D_{KL}(Q_\phi (z|x) \| P_θ(z)) \qquad (10)

получить:

logPθ(x)DKL(Qф(zx)Pθ(zx))=EzQ[logPθ(xz)]DKL(Qф(zx)Pθ(z))(11)logP_θ(x)-D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logP_θ(x|z)] - D_{KL} (Q_\phi (z|x) \| P_θ(z))\qquad (11)

Приведенная выше формула является основой VAE. левый элементPθ(x)P_θ(х), что сводит к минимумуQф(zx)Q_\phi (z|x)с правдойPθ(zx)P_θ(z|x)разница в расстоянии. Логарифмы не меняют положения максимума (или минимума). Учитывая, что можно хорошо оценитьPθ(zx)P_θ(z|x)Модель вывода ,DKL(Qф(zx)Pθ(zx))D_{KL}(Q_\phi (z|x) \| P_θ(z|x))около нуля.

первый элемент справаPθ(zx))P_θ(z|x))Подобно декодеру, этот декодер берет выборки из модели логического вывода для восстановления входных данных.

Второй элементQф(zx)Q_\phi (z|x)иPθ(z)P_θ (г)KL расстояние между. Левая часть формулы также называется нижней границей доказательства (ELBO). Поскольку KL всегда положителен, ELBOlogPθ(x)logP_θ(х)нижний предел . Путем оптимизации параметров нейронной сетиффиθθмаксимизировать ELBO означает:

  1. DKL(Qф(zx)Pθ(zx))0D_{KL}(Q_\phi (z|x) \| P_θ(z|x))\to 0или вzzатрибут средней парыxxЗакодированная модель вывода оптимизирована.
  2. правильноlogPθ(xz)logP_θ(х|z)максимизировать или из скрытого вектораzzрефакторингxx, модель декодера оптимизирована.

Метод оптимизации

В правой части формулы есть две важные части информации о функции потерь VAE. элемент декодераEzQ[logPθ(xz)]\mathbb E_{z\sim Q}[logP_θ(x|z)]Генератор представлений берет из выходных данных модели выводаzzобразцы для восстановления ввода. Максимизация этого срока означает восстановление потериLR\mathcal L_Rминимизировать. MSE можно использовать, если предполагается, что распределение изображений (данных) является гауссовым.

Если каждый пиксель (данные) считается распределенным по Бернулли, то функция потерь представляет собой двоичную перекрестную энтропию.

второй разделDKL(Qф(zx)Pθ(z))- D_{KL}(Q_\phi (z|x) \| P_θ(z)),так какQфQ_\phiявляется распределением Гаусса. как правилоPθ(z)=P(z)=N(0,1)P_θ(z)=P(z)=\mathcal N(0,1), что также является средним значением00Распределение Гаусса со стандартным отклонением, равным 1,0. Термин KL можно упростить до:

DKL(Qф(zx)Pθ(z))=12j=0J(1+log(оj)2(мюj)2(оj)2)(12)- D_{KL}(Q_\phi (z|x) \| P_θ(z))=\frac{1}{2} \sum_{j=0}^J (1+log(\sigma_j)^2- (\mu_j)^2-(\sigma_j)^2)\qquad(12)

вJJдаzzизмерение. и рассчитываются по модели вывода оxxФункция. максимизироватьDKL-D_{KL}:нооj1\sigma_j \to 1,мюj0\mu_j \to 0.P(z)=N(0,1)P(z)=\mathcal N(0,1)Выбор обусловлен свойствами изотропного единичного распределения Гаусса, которое может быть преобразовано в произвольное распределение с заданной соответствующей функцией.

Согласно уравнению (12), потери KLLKL\mathcal L_{KL}заDKLD_{KL}. Таким образом, функция потерь VAE определяется как:

LVAE=LR+LKL(13)\mathcal L_{VAE}=\mathcal L_R + \mathcal L_{KL}\qquad (13)

Учитывая модели кодировщика и декодера, перед созданием и обучением VAE необходимо решить еще одну проблему.

Трюк с репараметризацией

В левой части рисунка ниже показана сеть VAE. Кодер получает вводxxи оценить скрытый векторzzСреднее значение многомерного гауссовского распределениямюмюи стандартное отклонениеоо. Декодер из скрытого вектораzzвыборка для восстановления ввода какxx.

VAE

Но обратное распространение градиентов не проходит через случайно выбранные блоки. В то время как нейронная сеть может предоставлять случайные входные данные, градиенты не могут проходить через случайные слои. Решение этой проблемы состоит в том, чтобы использовать в качестве входных данных процесс «выборки», как показано в правой части рисунка. Выборка рассчитывается как:

Sample=мю+εо(14)Образец=\mu + εσ\qquad(14)

еслиεεиооТогда в векторной формеεоεσявляется поэлементным умножением. Используя уравнение (14), предположим, что образцы поступают непосредственно из скрытого пространства. Этот метод называется приемом репараметризации. После выборки на входе сеть VAE можно обучить с помощью знакомых алгоритмов оптимизации, таких как SGD, Adam или RMSProp.

реализация VAE

Чтобы облегчить визуализацию базовой кодировки,zzРазмер установлен на 2. Кодер представляет собой просто двухуровневый MLP, где второй уровень генерирует среднее значение и логарифмическую дисперсию. Логарифмическая дисперсия используется для упрощения вычисления потерь KL и трюка репараметризации. Третий вывод энкодера сделан с использованием трюка перепараметризацииzzвыборка. В функции выборкиe0.5logо2=о2=оe^{0.5log\sigma^2}=\sqrt{\sigma^2}=\sigma,так како>0о > 0является стандартным отклонением распределения Гаусса.

Декодер также представляет собой двухуровневый MLP, которыйzzобразцов отбираются для аппроксимации входных данных. Сеть 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 модель логического вывода можно отбросить. Чтобы создать новый значимый результат, изεεНарисуйте образцы из распределения Гаусса:

解码器

Показать результаты

潜矢量可视化

潜矢量可视化

图片生成

图片生成