2024年最新变分自编码器(VAE)详解与实现(tensorflow2(1),算法的面试

(1)Python所有方向的学习路线(新版)

这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

最近我才对这些路线做了一下新的更新,知识体系更全面了。

在这里插入图片描述

(2)Python学习视频

包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。

在这里插入图片描述

(3)100多个练手项目

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。

在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

推理模型 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)从输入 x x x生成潜矢量 z z z。 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)类似于自编码器模型中的编码器。另一方面, P θ ( x ∣ z ) P_θ(x|z) Pθ​(x∣z)从潜码z重建输入。 P θ ( x ∣ z ) P_θ(x|z) Pθ​(x∣z)的作用类似于自编码器模型中的解码器。要估算 P θ ( x ) P_θ(x) Pθ​(x),必须确定其与 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)和 P θ ( x ∣ z ) P_θ(x|z) Pθ​(x∣z)的关系。

如果 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)是 P θ ( z ∣ x ) P_θ(z|x) Pθ​(z∣x)的估计值,则Kullback-Leibler(KL)散度确定这两个条件密度之间的距离:

D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( z ∣ x ) ] ( 7 ) D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) = \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z|x)] \qquad (7) DKL​(Qϕ​(z∣x)∥Pθ​(z∣x))=Ez∼Q​[logQϕ​(z∣x)−logPθ​(z∣x)](7)

使用贝叶斯定理:

P θ ( z ∣ x ) = P θ ( x ∣ z ) P θ ( z ) P θ ( x ) ( 8 ) P_θ(z|x)=\frac{P_θ(x|z)P_θ(z)}{P_θ(x)} \qquad(8) Pθ​(z∣x)=Pθ​(x)Pθ​(x∣z)Pθ​(z)​(8)

通过公式(8)改写公式(7),同时由于 l o g P θ ( x ) logP_θ(x) logPθ​(x)不依赖于 z ∼ Q z\sim Q z∼Q:

D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( x ∣ z ) − l o g P θ ( z ) ] + l o g P θ ( 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) DKL​(Qϕ​(z∣x)∥Pθ​(z∣x))=Ez∼Q​[logQϕ​(z∣x)−logPθ​(x∣z)−logPθ​(z)]+logPθ​(x)(9)

重排上式并由:

E z ∼ Q [ l o g Q ϕ ( z ∣ x ) − l o g P θ ( z ) ] = D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) ( 10 ) \mathbb E_{z\sim Q}[logQ_\phi (z|x)-logP_θ(z)] = D_{KL}(Q_\phi (z|x) \| P_θ(z)) \qquad (10) Ez∼Q​[logQϕ​(z∣x)−logPθ​(z)]=DKL​(Qϕ​(z∣x)∥Pθ​(z))(10)

公式 (10) 的左侧也称为变化下界(evidence lower bound, ELBO),可以变化得到:

l o g P θ ( x ) − D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) = E z ∼ Q [ l o g P θ ( x ∣ z ) ] − D K L ( Q ϕ ( z ∣ x ) ∥ 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) logPθ​(x)−DKL​(Qϕ​(z∣x)∥Pθ​(z∣x))=Ez∼Q​[logPθ​(x∣z)]−DKL​(Qϕ​(z∣x)∥Pθ​(z))(11)

上式是VAE的核心。左侧项 P θ ( x ) P_θ(x) Pθ​(x),它最大化地减少了 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)与真实 P θ ( z ∣ x ) P_θ(z|x) Pθ​(z∣x)之间距离的差距。对数不会改变最大值(或最小值)的位置。给定一个可以很好地估计 P θ ( z ∣ x ) P_θ(z|x) Pθ​(z∣x)的推断模型, D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) D_{KL}(Q_\phi (z|x) \| P_θ(z|x)) DKL​(Qϕ​(z∣x)∥Pθ​(z∣x))约为零。

右边的第一项 P θ ( z ∣ x ) ) P_θ(z|x)) Pθ​(z∣x))类似于解码器,该解码器从推理模型中提取样本以重建输入。

第二项是 Q ϕ ( z ∣ x ) Q_\phi (z|x) Qϕ​(z∣x)与 P θ ( z ) P_θ(z) Pθ​(z)间的KL距离。由于KL始终为正,因此ELBO是 l o g P θ ( x ) logP_θ(x) logPθ​(x)的下限。通过优化神经网络的参数 φ φ φ和 θ θ θ来最大化ELBO意味着:

  1. D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ∣ x ) ) → 0 D_{KL}(Q_\phi (z|x) \| P_θ(z|x))\to 0 DKL​(Qϕ​(z∣x)∥Pθ​(z∣x))→0或在 z z z中对属性 x x x进行编码的推理模型得到优化。

  2. 右侧的 l o g P θ ( x ∣ z ) logP_θ(x|z) logPθ​(x∣z)最大化,或者从潜在矢量 z z z重构 x x x时,解码器模型得到优化。

优化方式

公式的右侧具有有关VAE损失函数的两个重要信息。解码器项 E z ∼ Q [ l o g P θ ( x ∣ z ) ] \mathbb E_{z\sim Q}[logP_θ(x|z)] Ez∼Q​[logPθ​(x∣z)]表示生成器从推理模型的输出中获取 z z z个样本以重构输入。最大化该项意味着将重建损失 L R \mathcal L_R LR​最小化。如果图像(数据)分布假定为高斯分布,则可以使用MSE。

如果每个像素(数据)都被认为是伯努利分布,那么损失函数就是一个二元交叉熵。

第二项 − D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) - D_{KL}(Q_\phi (z|x) \| P_θ(z)) −DKL​(Qϕ​(z∣x)∥Pθ​(z)),由于 Q ϕ Q_\phi Qϕ​是高斯分布。通常 P θ ( z ) = P ( z ) = N ( 0 , 1 ) P_θ(z)=P(z)=\mathcal N(0,1) Pθ​(z)=P(z)=N(0,1),也是均值为0且标准偏差等于1.0的高斯分布。KL项可以简化为:

− D K L ( Q ϕ ( z ∣ x ) ∥ P θ ( z ) ) = 1 2 ∑ j = 0 J ( 1 + l o g ( σ 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) −DKL​(Qϕ​(z∣x)∥Pθ​(z))=21​j=0∑J​(1+log(σj​)2−(μj​)2−(σj​)2)(12)

其中 J J J是 z z z的维数。和都是通过推理模型计算得到的关于 x x x的函数。要最大化 − D K L -D_{KL} −DKL​:则 σ j → 1 \sigma_j \to 1 σj​→1, μ j → 0 \mu_j \to 0 μj​→0。 P ( z ) = N ( 0 , 1 ) P(z)=\mathcal N(0,1) P(z)=N(0,1)的选择是由于各向同性单位高斯分布的性质,可以给定适当的函数将其变形为任意分布。

根据公式(12),KL损失 L K L \mathcal L_{KL} LKL​为 D K L D_{KL} DKL​。 综上,VAE损失函数定义为:

L V A E = L R + L K L ( 13 ) \mathcal L_{VAE}=\mathcal L_R + \mathcal L_{KL}\qquad (13) LVAE​=LR​+LKL​(13)

给定编码器和解码器模型的情况下,在构建和训练VAE之前,还有一个问题需要解决。

重参数化技巧(Reparameterization trick)

下图左侧显示了VAE网络。编码器获取输入 x x x,并估计潜矢量z的多元高斯分布的均值 μ μ μ和标准差 σ σ σ。 解码器从潜矢量 z z z采样,以将输入重构为 x x x。

VAE

但是反向传播梯度不会通过随机采样块。虽然可以为神经网络提供随机输入,但梯度不可能穿过随机层。

解决此问题的方法是将“采样”过程作为输入,如图右侧所示。 采样计算为:

S a m p l e = μ + ε σ ( 14 ) Sample=\mu + εσ\qquad(14) Sample=μ+εσ(14)

如果 ε ε ε和 σ σ σ以矢量形式表示,则 ε σ εσ εσ是逐元素乘法。 使用公式(14),令采样好像直接来自于潜空间。 这项技术被称为重参数化技巧。

之后在输入端进行采样,可以使用熟悉的优化算法(例如SGD,Adam或RMSProp)来训练VAE网络。

VAE实现


为了便于可视化潜在编码,将 z z z的维度设置为2。编码器仅是两层MLP,第二层生成均值和对数方差。对数方差的使用是为了简化KL损失和重参数化技巧的计算。编码器的第三个输出是使用重参数化技巧进行的 z z z采样。在采样函数中, e 0.5 l o g σ 2 = σ 2 = σ e{0.5log\sigma2}=\sqrt{\sigma^2}=\sigma e0.5logσ2=σ2 ​=σ,因为 σ > 0 σ> 0 σ>0是高斯分布的标准偏差。

解码器也是两层MLP,它对 z z z的样本进行采样以近似输入。

VAE网络只是将编码器和解码器连接在一起。损失函数是重建损失和KL损失之和。使用Adam优化器。

导入库

from tensorflow import keras

import tensorflow as tf

import numpy as np

import os

import argparse

from matplotlib import pyplot as plt

重参数技巧

#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

绘制测试图片函数

def plot_results(models,

data,

batch_size=128,

model_name=‘vae_mnist’):

“”"Plots labels and MNIST digits as function of 2 dim latent vector

Arguments:

models (tuple): encoder and decoder models

data (tuple): test data and label

batch_size (int): prediction batch size

model_name (string): which model is using this function

“”"

encoder,decoder = models

x_test,y_test = data

xmin = ymin = -4

xmax = ymax = +4

os.makedirs(model_name,exist_ok=True)

filename = os.path.join(model_name,‘vae_mean.png’)

#display a 2D plot of the digit classes in the latent space

z,, = encoder.predict(x_test,batch_size=batch_size)

plt.figure(figsize=(12,10))

#axes x and y ranges

axes = plt.gca()

axes.set_xlim([xmin,xmax])

axes.set_ylim([ymin,ymax])

subsampling to reduce density of points on the plot

z = z[0::2]

y_test = y_test[0::2]

plt.scatter(z[:,0],z[:,1],marker=‘’)

for i,digit in enumerate(y_test):

axes.annotate(digit,(z[i,0],z[i,1]))

plt.xlabel(‘z[0]’)

plt.ylabel(‘z[1]’)

plt.savefig(filename)

plt.show()

filename = os.path.join(model_name,‘digits_over_latent.png’)

#display a 30*30 2D mainfold of digits

n = 30

digit_size = 28

figure = np.zeros((digit_size * n,digit_size * n))

#线性间隔的坐标,对应于潜在空间中数字类的二维图

grid_x = np.linspace(-4,4,n)

grid_y = np.linspace(-4,4,n)[::-1]

for i,yi in enumerate(grid_x):

for j,xi in enumerate(grid_y):

z_sample = np.array([[xi,yi]])

x_decoded = decoder.predict(z_sample)

digit = x_decoded[0].reshape(digit_size,digit_size)

figure[i * digit_size:(i+1)digit_size,jdigit_size:(j+1)*digit_size] = digit

plt.figure(figsize=(10, 10))

start_range = digit_size // 2

end_range = (n-1) * digit_size + start_range + 1

pixel_range = np.arange(start_range, end_range, digit_size)

sample_range_x = np.round(grid_x, 1)

sample_range_y = np.round(grid_y, 1)

plt.xticks(pixel_range, sample_range_x)

plt.yticks(pixel_range, sample_range_y)

plt.xlabel(“z[0]”)

plt.ylabel(“z[1]”)

plt.imshow(figure, cmap=‘Greys_r’)

plt.savefig(filename)

plt.show()

加载数据与超参数

MNIST dataset

(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’)

做了那么多年开发,自学了很多门编程语言,我很明白学习资源对于学一门新语言的重要性,这些年也收藏了不少的Python干货,对我来说这些东西确实已经用不到了,但对于准备自学Python的人来说,或许它就是一个宝藏,可以给你省去很多的时间和精力。

别在网上瞎学了,我最近也做了一些资源的更新,只要你是我的粉丝,这期福利你都可拿走。

我先来介绍一下这些东西怎么用,文末抱走。


(1)Python所有方向的学习路线(新版)

这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

最近我才对这些路线做了一下新的更新,知识体系更全面了。

在这里插入图片描述

(2)Python学习视频

包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。

在这里插入图片描述

(3)100多个练手项目

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。

在这里插入图片描述

(4)200多本电子书

这些年我也收藏了很多电子书,大概200多本,有时候带实体书不方便的话,我就会去打开电子书看看,书籍可不一定比视频教程差,尤其是权威的技术书籍。

基本上主流的和经典的都有,这里我就不放图了,版权问题,个人看看是没有问题的。

(5)Python知识点汇总

知识点汇总有点像学习路线,但与学习路线不同的点就在于,知识点汇总更为细致,里面包含了对具体知识点的简单说明,而我们的学习路线则更为抽象和简单,只是为了方便大家只是某个领域你应该学习哪些技术栈。

在这里插入图片描述

(6)其他资料

还有其他的一些东西,比如说我自己出的Python入门图文类教程,没有电脑的时候用手机也可以学习知识,学会了理论之后再去敲代码实践验证,还有Python中文版的库资料、MySQL和HTML标签大全等等,这些都是可以送给粉丝们的东西。

在这里插入图片描述

这些都不是什么非常值钱的东西,但对于没有资源或者资源不是很好的学习者来说确实很不错,你要是用得到的话都可以直接抱走,关注过我的人都知道,这些都是可以拿到的。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值