• 对抗生成网络-图像卷积-mnist数据生成(代码) 1.tf.layers.conv2d(卷积操作) 2.tf.layers.conv2d_transpose(反卷积操作) 3.tf.layers.batch_normalize(归一化操作) 4.tf.maximum(用于lrelu) 5.tf.train_variable(训练中所有参数) 6.np.random.uniform(生成正态数据


    1. tf.layers.conv2d(input, filter, kernel_size, stride, padding) # 进行卷积操作

    参数说明:input输入数据, filter特征图的个数,kernel_size卷积核的大小,stride步长,padding是否补零

    2. tf.layers.conv2d_transpose(input, filter, kernel_size, stride, padding) # 进行反卷积操作

    参数说明:input输入数据, filter特征图的个数,kernel_size卷积核的大小,stride步长, padding是否补零

    3. tf.layers.batch_normalize(input, training=False) 进行归一化操作

    参数说明:input表示输入数据, training 表示是否是在进行训练

    4.tf,maximum(alpha*layer1, layer1) 返回较大的值,这里进行的lrelu操作

    参数说明: 输入数据为两个比较大小的数

    5. tf.train_variable() 获得训练过程中的所有参数

    6. np.random.uniform(-1, 1, shape) 生成随机的正态分布的数

    参数说明, -1和1表示这个范围内的正态分布

    情景说明:这里演示的代码使用的mnist数据集,使用[batch_size, noise_size], 即[None, 100]的数据集经过反卷积生成[None, 28, 28, 1]的mnist图片,范围为-1, 1 

    模型的结构说明:

                    对于生成网络:[None, 100] - > [None, 4*4*512](全连接) -> [None, 7, 7, 256](反卷积) -> [None, 14, 14, 128](反卷积) -> [None, 28, 28, 3](反卷积) -> tf.tanh(-1, 1的变化)

                    对于判别网络:[None, 28, 28, 1] -> [None, 14, 14, 128](卷积) -> [None, 7, 7, 256](卷积) -> [None, 4, 4, 512](卷积) ->[None, 512*4*4](维度变化) ->[None, 1] (全连接) -> tf.sigmoid(0, 1的变化)

    生成网络参数说明: 第一层全连接,使用的w为 [100, 4*4*512], 使用的b为[4*4*512]

                                   第二层反卷积,使用的w为[4, 4, 512, 256], 使用的b为[256]

                                   第三层反卷积,使用的w为[3, 3, 256, 128], 使用的b为[128]

                                   第四层反卷积,使用的w为[3, 3, 128, 1], 使用的b为[1]

    判别网络参数说明:第一层卷积,使用的w为[3, 3, 1, 128] 使用的b是[128]

                                    第二层卷积, 使用的w为[3, 3, 128, 256], 使用的b是[256]

                                    第三层卷积,使用的w为[3, 3, 256, 512], 使用的b是[512]

                                    第四层全连接,使用的w为[4*4*512, 1] 使用的b是[1]

    代码说明:由于上述代码建立了多个函数,因此我们先进行主函数的说明

    建立函数train()进行代码的训练操作

     第一步:首先是定义参数, 包括input_size(输入图片的维度), noise_size(噪声图片的维度), output_dim(生成图片的维度),batch_size(一个batch的大小)

    第二步:使用get_inputs(input_size, noise_size) 获得生成的初始化的real_image 和 noise_image, 对生成的real_image进行维度的变化,将其变化为[-1, 28, 28, 1], 以用于判别网络进行判断

    第三步:将生成的real_image_reshape 和 noise_image 输入到get_loss里面 获得 d_loss 和 g_loss 

             get_loss函数说明:输入的数据为real_image_reshape, noise_image, output_dim

               第一步: 调用get_generator(noise_image, output_dim, True)生成g_outputs

               第二步:调用get_discrimator(real_image, reuse=False, ) 判别真实样本的输入

               第三步: 调用get_discrimator(g_outputs, reuse=True) 判别生成样本的输入

              第四步: 构造判别网络d_loss的损失值

                          第一步:构造判别网络的真实样本的损失值, tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=, label=tf.ones_like(real_logits)))

                          第二步:构造判别网络的生成样本的损失值

                          第三步:将两种损失值进行加和操作

              第五步:构造生成网络g_loss的损失值, tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=, label=tf.ones_like))

              第六步:返回d_loss 和 g_loss 

     第四步: 调用get_opt, 输入为d_loss, g_loss, learning_rate=0.001, 进行优化操作, 获得g_opt, 和d_opt 

               第一步:获得g_var 和 d_var 进行训练时生成网络的参数和判别网络的参数

                              第一步:使用varias = tf.train_variable() 获得训练时的参数

                              第二步:使用g_var = [v for v in varias if v.name.startswith('generator')] 来获得训练过程中的生成网络的参数

                              第三步:d_var = [v for v in varias if v.name.startswith('discrimator')] 来获得训练过程中的判别网络的参数

               第二步:构造优化的操作g_opt, d_opt 

                              第一步: 使用tf.train.Adaoptimer(learning_rate).minimize(d_loss, var_list=d_var), 构造d_opt 

                              第二步: 使用tf.train.Adaoptimer(learning_rate).minimize(g_loss, var_list=g_var)  构造g_opt 

    第五步:进入循环操作,迭代30次,进行训练操作,一个epoch迭代的次数为range(mnist.train.num_examples // batch_size)

                第一步:读取一个batch_size的数据image_batch,并将其转换为-1, 1的范围

                               第一步:使用mnist.train.next_batch(batch_size)获得一个batch的数据

                               第二步:使用batch_image = batch[0]获得其中的图片

                               第三步: batch_image = batch_image * 2 - 1将image的范围从0, 1变化为-1, 1

                 第二步:使用np.random.uniform(-1, 1, (batch_size, noise_size)) 生成一个batch的噪音数据,大小为batch_size, noise_size 

                 第三步:使用sess.run(g_opt, feed_dict) 和 d_opt更新参数

                 第四步:在一个epoch结束后,执行sess.run(d_loss) 和 sess,run(g_loss)

                 第五步:调用show_sample_image获得生成后的图片, 输入为sess, n_sample, input_image, output_dim, reuse , 这里的input_image表示real_image

                                  第一步:使用input_image.get_shape().as_list()[-1]获得noise的维度,这里是100

                                  第二步:使用np.random.uniform(-1, 1, (n_sample, input_shape)) 生成50,100的噪音数据

                                  第三步:使用sess.run(get_generator(input_image, output_dim, reuse), feed_dict={input_image, sample_noise})

                                  第四步:返回生成的图片sample

                  第六步:调用plot_show()进行图片的展示

                  第七步:打印结果

    import numpy as np
    import tensorflow as tf
    import pickle
    from tensorflow.examples.tutorials.mnist import input_data
    import matplotlib.pyplot as plt
    
    # 读入mnist输入
    mnist = input_data.read_data_sets('/data')
    
    # 构造输入样本的数据,real_size 和 noise_size, 生成初始化的real_image 和 noise_image
    def get_inputs(real_size, noise_size):
        # 真实图片的维度为[None, 784]
        real_img = tf.placeholder('float32', [None, real_size])
        # 噪音数据的维度为[None , 100]
        noise_img = tf.placeholder('float32', [None, noise_size])
    
        return real_img, noise_img
    
    # 构造generator网络,将[None, 100]的噪音数据, 生成[None, 28, 28, 1]的图片数据
    def get_generator(noise_img, output_dim, is_train, alpha=0.01):
    
        with tf.variable_scope('generator', reuse=not is_train):
    
            # 100 -> 4*4*512 - > 4, 4, 512
            # 进行全连接操作,将100的数据通过全连接,转换为[None ,4*4*512]
            layer1 = tf.layers.dense(noise_img, 4*4*512)
            # 进行维度变化,将其转换为[-1, 4, 4, 512]
            layer1 = tf.reshape(layer1, [-1, 4, 4, 512])
            # 使用tf.layers.batch_normalization进行归一化操作
            layer1 = tf.layers.batch_normalization(layer1, training=is_train)
            # 使用tf.maximum进行lrelu操作
            layer1 = tf.maximum(alpha*layer1, layer1)
            # 使用tf.nn.dropout进行dropout操作
            layer1 = tf.nn.dropout(layer1, keep_prob=0.8)
    
            # 4*4*512 -> 7*7*256
            # 进行反卷积操作,将4*4*256 -> 7*7*256
            layer2 = tf.layers.conv2d_transpose(layer1, 256, 4, 1, padding='valid')
            # 进行归一化操作
            layer2 = tf.layers.batch_normalization(layer2, training=is_train)
            # 进行lrelu操作
            layer2 = tf.maximum(alpha*layer2, layer2)
            # 进行dropout操作
            layer2 = tf.nn.dropout(layer2, keep_prob=0.8)
    
            #  7*7*256 - 14*14*128
            # 进行反卷积操作,stride=2,维度扩大为原来的2倍
            layer3 = tf.layers.conv2d_transpose(layer2, 128, 3, 2, padding='SAME')
            # 归一化操作
            layer3 = tf.layers.batch_normalization(layer3, training=is_train)
            # 进行lrelu操作
            layer3 = tf.maximum(alpha*layer3, layer3)
            # 进行dropout的操作
            layer3 = tf.nn.dropout(layer3, keep_prob=0.8)
            # 进行反卷积操作将 14*14*128 -> 28*28*1
            logits = tf.layers.conv2d_transpose(layer3, output_dim, 3, 2, padding='SAME')
            # 将输出结果转换为-1, 1之间
            outputs = tf.tanh(logits)
    
        return outputs
    
    
    # 生成判别网络,输入样本的大小为[28, 28, 1], reuse表示是否进行参数复用
    def get_discrimator(input_image, reuse, alpha=0.01):
        # 指定参数范围
        with tf.variable_scope('discrimator', reuse=reuse):
    
            # 28*28*1 -> 14*14*128
            # 进行卷积操作,将28*28*1变化为14*14*128,步长为2
            layer1 = tf.layers.conv2d(input_image, 128, 2, padding='SAME')
            # 进行lrelu操作
            layer1 = tf.maximum(layer1*alpha, layer1)
            # 进行dropout操作
            layer1 = tf.nn.dropout(layer1, keep_prob=0.8)
            # 14*14*128 -> 7*7*256
            # 进行卷积操作,将14*14*128变换为7*7*256, 步长为2
            layer2 = tf.layers.conv2d(layer1, 256, 2, padding='SAME')
            # 使用tf.layers.batch_normalization进行归一化操作
            layer2 = tf.layers.batch_normalization(layer2, training=True)
            # 进行lrelu操作
            layer2 = tf.maximum(layer2*alpha, layer2)
            # 进行dropout操作
            layer2 = tf.nn.dropout(layer2, keep_prob=0.8)
            # 7*7*64 -> 4*4*512
            # 进行卷积操作
            layer3 = tf.layers.conv2d(layer2, 512, 2, padding='SAME')
            # 进行归一化操作
            layer3 = tf.layers.batch_normalization(layer3, training=True)
            # 进行lrelu操作
            layer3 = tf.maximum(layer3*alpha, layer3)
            # 进行dropout操作
            layer3 = tf.nn.dropout(layer3, keep_prob=0.8)
            # 进行维度变换
            flatten_fc = tf.reshape(layer3, [-1, 4*4*512])
            # 进行全连接操作,将4*4*512 变为1
            logits = tf.layers.dense(flatten_fc, 1)
            # 将结果变化为0, 1之间,输出的是概率值
            outputs = tf.sigmoid(logits)
    
        return logits, outputs
    
    # 用于生成损失值,输入为真实图片,噪音图片, 生成图片的维度, smooth
    def get_loss(real_image, noise_image, output_dim, smooth=0.1):
    
        # 生成图片和判别网络
        # 使用生成网络,输入噪音图片,生成图片
        g_outputs = get_generator(noise_image, output_dim, True)
        # 使用判别网络,对真实图片进行判别,返回Logits和inputs
        d_real_logits, d_real_outputs = get_discrimator(real_image, False)
        # 使用判别网络,对生成图片进行判别,返回为logits和inputs
        d_fake_logits, d_real_outputs = get_discrimator(g_outputs, True)
    
        # 生成loss函数, 使用tf.reduce_mean构成d_loss
        d_loss_1 = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_real_logits, labels=tf.ones_like(d_real_logits) * (1-smooth)))
        d_loss_2 = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_fake_logits, labels=tf.zeros_like(d_fake_logits)))
        d_loss = d_loss_1 + d_loss_2
        # 使用tf.reduce_mean 构成g_loss, labels=tf.ones_like(d_fake_logits)
        g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_fake_logits, labels=tf.ones_like(d_fake_logits) * (1-smooth)))
    
        # 返回判别和生成的损失值
        return d_loss, g_loss
    
    # 获得用于降低损失的g_opt 和 d_opt
    def get_opt(d_loss, g_loss, learning_rate=0.001):
        # 获得训练过程中的所有训练参数
        varies = tf.trainable_variables()
        # 循环训练参数,根据参数名字的开头获得生成网络的参数
        g_var = [var for var in varies if var.name.startswith('generator')]
        # 根据参数名字的开头获得判别网络的参数
        d_var = [var for var in varies if var.name.startswith('discrimator')]
        # 对于d_loss的损失值,只训练d_var参数
        d_opt = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=d_var)
        # 对于g_loss的损失值,只训练g_var参数
        g_opt = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=g_var)
    
        return d_opt, g_opt
    # 调用get_generator生成图片
    def show_sample_image(sess, n_sample, input_noise, output_dim):
        # 获得输入图片的维度,这里值噪声图片,维度为100
        input_size = input_noise.get_shape().as_list()[-1]
        # 生成-1,1的[50, 100]的噪音数据
        noise_sample = np.random.uniform(-1, 1, (n_sample, input_size))
        # 执行生成函数,将噪音数据传入
        samples = sess.run(get_generator(input_noise, output_dim, False), feed_dict={input_noise:noise_sample})
    
        return samples
    # 进行画图操作
    def plot_samples(samples):
        # 表示图片以及图片的维度
        fig, axes = plt.subplots(nrows=1, ncols=25)
        # 循环每一个subplots进行画图操作
        for img, ax in zip(samples, axes):
            # 在每个subplot上进行画图
            ax.imshow(img, cmap='Greys_r')
            # 去除ax的边界
            ax.get_xaxis().set_visible(False)
            ax.get_yaxis().set_visible(False)
        # 图片没有边界    
        fig.tight_layer(pad=0)
        # 图片展示
        plt.show()
    
    # 主函数进行训练
    def train():
        # 第一步:设置基本的参数
        # 图片的大小,这里是784
        input_size = mnist.train.images[0].shape[0]
        # 噪声数据的大小,100
        noise_size = 100
        # 每一个batch值
        batch_size = 64
        # 生成图片的维度
        output_dim = 1
        # 迭代的epoch值
        epoch = 30
        # 用于展示的图片大小
        n_sample = 25
        # 第二步:调用get_inputs,生成初始化的输入数据,[None, 784], [None, 100]
        real_img, noise_img = get_inputs(input_size, noise_size)
        # 对输入数据的真实数据进行维度变化,用来输入到判别网络进行判别
        real_img_reshape = tf.reshape(real_img, [-1, 28, 28, 1])
        # 第三步: 将真实数据和噪音数据输入到loss函数中,生成判别损失值d_loss和生成损失值g_loss
        d_loss, g_loss = get_loss(real_img_reshape, noise_img, output_dim)
        # 第四步:嗲用get_op根据损失值获得操作步骤opt
        d_opt, g_opt = get_opt(d_loss, g_loss)
        # 第五步:实际传入数据,进行模型的训练
        with tf.Session() as sess:
            # 参数初始化
            sess.run(tf.global_variables_initializer())
            # 循环epoch
            for i in range(epoch):
                # 迭代每一个batch_size 
                for batch_i in range(mnist.train.num_examples // batch_size):
                    # 获得一个batch_size的数据
                    batch = mnist.train.next_batch(batch_size)
                    # 获得一个batch_size的图片
                    batch_img = batch[0]
                    # 将其范围变为-1, 1
                    batch_img = batch_img * 2 - 1
                    # 获得一个batch_size的噪音数据
                    batch_noise = np.random.uniform(-1, 1, (batch_size, noise_size))
                    # 实际传入参数,执行g_opt 和 d_opt
                    _ = sess.run(g_opt, feed_dict={real_img:batch_img, noise_img:batch_noise})
                    _ = sess.run(d_opt, feed_dict={real_img:batch_img, noise_img:batch_noise})
                # 一个epoch后获的损失值
                train_d_loss = sess.run(d_loss, feed_dict={real_img:batch_img, noise_img:batch_noise})
                train_g_loss = sess.run(g_loss, feed_dict={real_img: batch_img, noise_img: batch_noise})
                # 迭代10次以后
                if i % 10 == 0:
                    # 根据噪音数据生成samples数据
                    samples = show_sample_image(sess, n_sample, noise_img, output_dim)
                    # 对生成的samples数据进行图像展示
                    plot_samples(samples)
    
    
    
    
    train()

                          

                                             

                                                                                 

  • 相关阅读:
    vue3:jsbarcode生成条形码
    xml文件中<![CDATA[]]>和转义字符的使用
    VUE:计算属性
    BUG:JSONObject转实体类时空字符串变成19700101
    类与对象、封装、构造方法(成员变量与局部变量的区别)
    第四课rgb
    c++获取文件字符串
    cximage第一讲demo.cpp
    OPENGL第二课(正弦函数,点,线 圆,五角星)
    cv::flip
  • 原文地址:https://www.cnblogs.com/my-love-is-python/p/10697953.html
Copyright © 2020-2023  润新知