自编码器一般功能是压缩数据。但是变分自编码器(variational autoencoder,VAE)的主要作用却是可以生成数据。变分自编码器的这种功能可以应用到很多领域,从生成手写文字到合成音乐。
变分自编码器的实现在标准自编码器上增加了一个网络层,该网络层有2个子网络组成:均值网络和方差网络。如下图所示:
变分自编码器的训练过程与标准自编码器不同。首先是在编码器中引入了2个子网络均值和方差。其次是在编码器和解码器之间加入了一个采样层。采样层的输入为均值、方差以及高斯噪声,算法如下:
最后采样层的结果输入到解码器。在进行误差反传的时候,变分自编码器并不是简单的使用mse等损失函数,而是损失函数的基础上增加了Kullback-Leibler散度(KL算法)。增加KL算法的原因是要确定均值和方差子网络是符合正态分布的。
变分自编码器的使用是用正态分布的随机数作为解码器的输入,在输出端就可以得到与输入类似但又不同的结果(比如图像等)。这就是变分自编码器最具吸引力的地方。变分自编码器是目前比较流行的生成模型之一。
变分自编码器之所以可以生成结果,是因为它提取了输入的特征。比如输入的是人脸图片,变分自编码器相当于保留了人脸的基本特征的均值和方差信息。通过调整这些信息(输入正态分布随数),就可以得到不同的人脸图片。
变分自编码器代码:
import os
import tensorflow as tf
from tensorflow import keras
from PIL import Image
from matplotlib import pyplot as plt
from tensorflow.keras import Sequential, layers
import numpy as np
tf.random.set_seed(2322)
np.random.seed(23422)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
assert tf.__version__.startswith('2.')
# 把num张图片保存到一张
def save_images(img, name,num):
new_im = Image.new('L', (28*num, 28*num))
index = 0
for i in range(0, 28*num, 28):
for j in range(0, 28*num, 28):
im = img[index]
im = Image.fromarray(im, mode='L')
new_im.paste(im, (i, j))
index += 1
new_im.save(name