变分自编码其实就是在编码过程中改变样本的分布,“学习样本的规律”,具体指的就是样本的分布,假设知道样本的分布函数,就可以从这些函数中随便取一个样本,然后进行网络解码层前向传导,这样就可以生成一个新的样本。
为了得到这这个样本的分布函数,模型训练的目的将不再是这样的样本本身,而是通过加一个约束项,将网络生成一个服从高斯分布的数据集,这样按照高斯分布里的均值和方差规则就可以取任意相关的数据,然后通过解码层还原成样本。
使用自编码模型进行模拟MNIST数据的生成
1.引入库,定义占位符
编码器为两个全连接层,第一个全连接层有784个维度的输入变化256个维度的输出;第二个全连接层并列连结了两个输出网络,每个网络都输出了两个维度的输出。然后将两个输出通过一个公式计算,输入到一个2节点为开始的解码部分,接着后面为两个全连接层的解码器,第一层由两个维度输入256个维度的输出,第二层有256个维度的输入到784个维度的输出。如下图所示。
在下面的代码中,引入了一个scipy库,后面的可视化会用到。头文件引入之后,定义操作符x和z.x用原始的图片输入,z用于中间节点解码器的输入。
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from scipy.stats import norm
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/data/")
n_input = 784
n_hidden_1 = 256
n_hidden_2 = 2
x = tf.placeholder(tf.float32, [None, n_input])
zinput = tf.placeholder(tf.float32, [None, n_hidden_2])
2.定义学习参数
mean_w1与mean_b1生成的是mean的权重,log_sigma_w1与log_sigma_b1生成的是log_sigma的权重。
这里初始化w的权重与之前不同,使用了很小的值(方差为0.001的truncated_nomal)。这里设置的非常小心,由于在计算KL离散度时计算的是与标准高斯分布的距离,如果网络初始生成的模型均值方差都很大,那么与标准高斯分布距离就会非常大,这样会导致模型训练不出来,成成NAN的情况。
weights = {
'w1':tf.Variable(tf.truncated_normal(