TensoFlow 实现 VAE(变分自编码)神经网络

TensoFlow 实现变分自编码(VAE)神经网络

文章目录

  • TensoFlow 实现变分自编码(VAE)神经网络
    • 1. 网络结构
      • 输出损失代码:
      • 变数对最后输出的影响
        • 1. 截断随机正态分布的截断参数

1. 网络结构

自上而下,先搭骨架,在实现

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. 方差和标准方差的关系
    1. 方差:无平方
    2. 标准方差:有平方
    3. 如何求损失
      1. 求图片的损失:生成图片和原有图片的损失
      2. 求正太分布的损失:匹配正态分布的损失
      3. 两者相加,优化
    4. 如何设初值
      1. 截断随机正态分布
  2. 对以下内容的更改对神经网络的损失、输出值的改变
    1. 截断随机正态分布的截断
    2. 损失函数
      1. 平方差
      2. KL散度(相对熵)
    3. 优化器的选择
      1. Adm:

实现代码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

结果:

TensoFlow 实现 VAE(变分自编码)神经网络_第1张图片

变数对最后输出的影响

1. 截断随机正态分布的截断参数

​ 截断参数越低,生成的越快,更模糊

你可能感兴趣的:(TensoFlow 实现 VAE(变分自编码)神经网络)