自上而下,先搭骨架,在实现
1. 主网络:net
1. init
1. 初始化编码器类
2. 初始化解码器类
2. forward
1. 获取编码器输出:$\delta $ 和 $\mu$(方差)
2. 获取一个标准正态分布
3. 获取log标准方差`tf.sqrt(tf.exp(方差))`
4. 获取解码器的输入(编码器的最后输出):decode_x = $\delta$ x 标准正态分布+ log标准方差
5. 获取解码的输出
3. backward
1. loss(1):编码器的输出-输入的平方差
2. loss(2):KL散度
3. 总loss:loss(1)+ loss(2)
1. 可以在损失前加一个变量,用于对单个损失的提升(重点损失)
4. 测试:获取解码器 生成的图片:
1. 生成一个标准的正态分布
2. 使用解码器做一个前向计算
2. 子网络:编码器
1. 返回$\delta $ 和 $log $方差
2. 一个输入,
3. 一次激活
4. 两个输出,两个权重,无激活
3. 子网络:解码器
1. 全连接
2. 一个输入
3. 一个输出
4. 无激活函数:因为所需输出不是概率而是图片
知识点:
实现代码1:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as plt
mnist = input_data.read_data_sets(r'C:\Users\liev\Desktop\myproject\yin_test\MNIST_DATA_TensorFlow',one_hot=True)
# 编码类
class EncodeNet:
def __init__(self):
# 定义输入层到第一隐层的全连接权重和偏值
self.encode_w = tf.Variable(tf.truncated_normal([784, 100], stddev=0.01))
self.encode_b = tf.Variable(tf.zeros([100]))
# 定义第一隐层delta 输出的权重
self.log_var_w = tf.Variable(tf.truncated_normal([100,128], stddev=0.01))
# 定义第一隐层mu 输出的权重
self.mean_w = tf.Variable(tf.truncated_normal([100,128], stddev=0.01), dtype=tf.float32)
def forward(self,in_x):
# 第一层:编码输入层 in_x:[None,784] w:[784,100] b:[100]
self.mlp_layer = tf.nn.relu(tf.add(tf.matmul(in_x, self.encode_w), self.encode_b))
# 第一层:编码输出delta层 mlp_layer:[100,100] w:[100,128]
self.log_var = tf.matmul(self.mlp_layer, self.log_var_w)
# 第一层:编码输出mu 层 mlp_layer:[100,100] w:[100,128]
self.mean = tf.matmul(self.mlp_layer, self.mean_w)
# 返回 delta层 和mu 层 shape=[100,1]
return self.log_var, self.mean
# 解码类
class DecodNet:
def __init__(self):
# 定义解码输入层到全连接层的权重和偏值
self.hidden_w = tf.Variable(tf.truncated_normal([128, 100], stddev=0.01),dtype=tf.float32)
self.hidden_b = tf.Variable(tf.zeros([100]))
# 定义解码全连接层到全连接输出层的权重和偏值
self.out_w = tf.Variable(tf.truncated_normal([100, 784], stddev=0.01), dtype=tf.float32)
def forward(self,decode_x):
# 第二层:全连接隐层 decode_x:[100,100] w:[100,256] b:[256]
self.hidden_layer = tf.nn.relu(tf.add(tf.matmul(decode_x, self.hidden_w), self.hidden_b))
# 第三层: 全连接输出层 hidden_layer:[100,256] w:[ 256,784] b:[784]
self.out_layer = tf.matmul(self.hidden_layer, self.out_w)
# 返回最后输出层 out_layer:[100,784]
return self.out_layer
# VAE训练网络
class VAEnet:
def __init__(self):
self.encode = EncodeNet() # 实例化encoding
self.decode = DecodNet() # 实例化decoding
self.in_x = tf.placeholder(dtype=tf.float32, shape=[100, 784])
def forward(self):
self.mean, self.log_var = self.encode.forward(self.in_x)
# 获取一个标准正态分布
self.I = tf.random_normal([128])
# 获取log mu
self.log_var = tf.sqrt(tf.exp(self.log_var))
# 获取解码器的输入
self.decode_in_x = tf.add(self.log_var * self.I, self.mean)
# 获取解码器的输出
self.decode_y = self.decode.forward(self.decode_in_x)
def backward(self):
# 控制图片的损失
decode_loss = tf.reduce_mean((self.decode_y-self.in_x)**2)
# 控制正态分布的损失
encode_loss = tf.reduce_mean(0.5*(self.log_var**2+self.mean**2-self.decode_in_x**2-1))
self.loss = tf.add(encode_loss, decode_loss)
self.opt = tf.train.AdamOptimizer().minimize(self.loss)
def decoding(self):
I = tf.random_normal(shape=[1, 128])
return self.decode.forward(I)
if __name__ == '__main__':
vae = VAEnet()
vae.forward()
vae.backward()
test_output = vae.decoding()
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
saver = tf.train.Saver()
plt.ion()
for epoch in range(100000):
xs, xy = mnist.train.next_batch(100)
_loss,_= sess.run([vae.loss, vae.opt], feed_dict={vae.in_x: xs})
if epoch % 100 == 0:
print(_loss)
test_img_data = sess.run([test_output])
test_img = np.reshape(test_img_data, [28, 28])
plt.imshow(test_img)
plt.pause(0.1)
# saver.save(sess,r'E:\PycharmProjects\TensorflowTest\log\VAEtrain.ckpt')
输出:
-0.12601617
1.0237081
0.044569284
0.06023733
0.35098344
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
for i in range(1000):
xs, xy = mnist.train.next_batch(100)
d, e = sess.run([vae.decode_loss, vae.encode_loss],feed_dict={vae.in_x: xs})
print('d_loss:\t',d, 'e_loss:\t',e)
d_loss: 3.4304707e-05 e_loss: 0.109002136
结果:
截断参数越低,生成的越快,更模糊