zoukankan      html  css  js  c++  java
  • [Paddle学习笔记][05][对抗生成网络]

    说明:

    生成对抗网络(Generative Adversarial Network [1],简称GAN)是非监督式学习的一种方法,通过让两个神经网络相互博弈的方式进行学习。本例程使用DCGAN网络和MNIST数据集生成数字字符。


    实验代码:

    import paddle
    import paddle.fluid as fluid
    import numpy as np
    
    import math
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    # 全局变量
    use_cuda = 1 # 是否使用GPU
    batch_size = 128 # 每批读取数据
    epoch_num = 20 # 训练迭代周期
    noise_size = 100 # 噪声维度
    
    # 判别网络
    def D(image):
        # 输入图像: N*C*H*W=N*1*28*28, H/W=(H/W-F+2*P)/S+1, 网络层数: 4
        image = fluid.layers.reshape(x=image, shape=[-1, 1, 28, 28])
        
        conv_pool_1 = fluid.nets.simple_img_conv_pool( # 输出: N*64*12*12
            input=image, num_filters=64, filter_size=5, act='leaky_relu',
            pool_size=2, pool_stride=2, param_attr='conv_pool_1_w', bias_attr='conv_pool_1_b')
        conv_pool_2 = fluid.nets.simple_img_conv_pool( # 输出: N*128*4*4
            input=conv_pool_1, num_filters=128, filter_size=5, act='leaky_relu',
            pool_size=2, pool_stride=2, param_attr='conv_pool_2_w', bias_attr='conv_pool_2_b')
        bn1 = fluid.layers.batch_norm(
            input=conv_pool_2, act='leaky_relu', name='bn1',
            param_attr='bn1_w', bias_attr='bn1_b', moving_mean_name='bn1_m', moving_variance_name='bn1_v')
        fc1 = fluid.layers.fc(                         # 输出: N*1024
            input=bn1, size=1024, act=None,
            param_attr='fc1_w', bias_attr='fc1_b')
        bn2 = fluid.layers.batch_norm(
            input=fc1, act='leaky_relu', name='bn2',
            param_attr='bn2_w', bias_attr='bn2_b', moving_mean_name='bn2_m', moving_variance_name='bn2_v')
        
        # 输出标签: 1为真实图像,0为虚假图像
        logit = fluid.layers.fc(                       # 输出: N*1
            input=bn2, size=1, act='sigmoid',
            param_attr='fc2_w', bias_attr='fc2_b')
        
        return logit
    
    # 生成网络
    def G(noise):
        # 输入噪声: N*100, 网络层数: 4
        fc3 = fluid.layers.fc(                     # 输出: N*2048
            input=noise, size=2048, act=None,
            param_attr='fc3_w', bias_attr='fc3_b')
        bn3 = fluid.layers.batch_norm(
            input=fc3, act='relu', name='bn3',
            param_attr='bn3_w', bias_attr='bn3_b', moving_mean_name='bn3_m', moving_variance_name='bn3_v')
        fc4 = fluid.layers.fc(                     # 输出: N*6272
            input=bn3, size=6272, act=None,
            param_attr='fc4_w', bias_attr='fc4_b')
        bn5 = fluid.layers.batch_norm(
            input=fc4, act='relu', name='bn5',
            param_attr='bn5_w', bias_attr='bn5_b', moving_mean_name='bn5_m', moving_variance_name='bn5_v')
        
        reshape = fluid.layers.reshape(x=bn5, shape=[-1, 128, 7, 7])
        
        deconv1 = fluid.layers.conv2d_transpose(   # 输出: N*128*14*14
            input=reshape, output_size=[14, 14], 
            num_filters=128, filter_size=5, stride=2, padding=2, dilation=1, act='relu',
            param_attr='deconv1_w', bias_attr='deconv1_b')
        deconv2 = fluid.layers.conv2d_transpose(   # 输出: N*1*28*28
            input=deconv1, output_size=[28, 28], 
            num_filters=1, filter_size=5, stride=2, padding=2, dilation=1, act='tanh',
            param_attr='deconv2_w', bias_attr='deconv2_b')
        
        # 输出图像
        image = fluid.layers.reshape(x=deconv2, shape=[-1, 784])
        
        return image
    
    # 显示图像
    def show_image(total_image):
        n = int(math.ceil(math.sqrt(total_image.shape[0])))
        total_image = total_image.reshape((n, n, 28, 28)).transpose((0, 2, 1, 3)).reshape((n*28, n*28))
        fig= plt.figure(figsize=(8, 8))
        plt.axis('off')
        plt.imshow(total_image, cmap='Greys_r', vmin=-1, vmax=1)
        plt.show(fig)
    
    # 训练模型
    def train():
        # 读取数据
        train_reader = paddle.batch(
            paddle.reader.shuffle(paddle.dataset.mnist.train(), buf_size=60000),
            batch_size=batch_size)
        
        # 配置训练判别网络
        d_program = fluid.Program() # 获取判别网络
        with fluid.program_guard(d_program):
            # 输入图像
            d_image = fluid.data(name='image', shape=[None, 784], dtype='float32') # 输入图像: N*1*28*28
            d_label = fluid.data(name='label', shape=[None, 1], dtype='float32')   # 图像标签: N*1
            
            # 判别图像
            d_logit = D(d_image)
            
            # 计算损失
            d_loss = fluid.layers.sigmoid_cross_entropy_with_logits(x=d_logit, label=d_label)
            d_avg_loss = fluid.layers.mean(d_loss)
            
        # 配置训练生成网络
        dg_program = fluid.Program() # 获取判别生成网络
        with fluid.program_guard(dg_program):
            # 输入噪声
            g_noise = fluid.data(name='noise', shape=[None, noise_size], dtype='float32')               # 输入噪声: N*100
            noise_shape = fluid.layers.shape(g_noise)
            g_label = fluid.layers.fill_constant(value=1.0, shape=[noise_shape[0], 1], dtype='float32') # 图像标签: N*1
            
            # 生成图像
            g_image = G(g_noise)
            
            # 克隆生成网络
            g_program = dg_program.clone()
            g_program_test = dg_program.clone(for_test=True)
            
            # 判别图像
            dg_logit = D(g_image)
            
            # 计算损失
            dg_loss = fluid.layers.sigmoid_cross_entropy_with_logits(x=dg_logit, label=g_label)
            dg_avg_loss = fluid.layers.mean(dg_loss)
        
        # 配置优化方法
        optimizer = fluid.optimizer.Adam(learning_rate=0.0002) #Adam算法
        
        d_parameters = [p.name for p in d_program.global_block().all_parameters()]
        optimizer.minimize(loss=d_avg_loss, parameter_list=d_parameters) # 最小化判别网络平均损失值
        
        g_parameters = [p.name for p in g_program.global_block().all_parameters()]
        optimizer.minimize(loss=dg_avg_loss, parameter_list=g_parameters) # 最小化生成网络平均损失值
    
        # 启动程序
        place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() # 获取执行设备
        exe = fluid.Executor(place) # 获取执行程序
        exe.run(fluid.default_startup_program()) # 运行启动程序
        
        # 训练模型
        for epoch in range(epoch_num):
            for batch, train_data in enumerate(train_reader()):
                # 准备训练数据
                if len(train_data) != batch_size:
                    continue
                
                real_images = np.array(list(map(lambda x: x[0], train_data))).reshape(-1, 784).astype('float32')
                real_labels = np.ones(shape=[real_images.shape[0], 1], dtype='float32')
                
                fake_noises = np.random.uniform(low=-1.0, high=1.0, size=[batch_size, noise_size]).astype('float32')
                fake_labels = np.zeros(shape=[real_images.shape[0], 1], dtype='float32')
    
                # 生成虚假图像
                fake_images = exe.run(
                    program=g_program, 
                    feed={'noise': fake_noises}, 
                    fetch_list=[g_image])[0]
         
                # 训练判别模型:判断虚假图片为假的损失
                d_avg_loss_fake = exe.run(
                    program=d_program,
                    feed={'image': fake_images, 'label': fake_labels},
                    fetch_list=[d_avg_loss])[0][0]
                
                # 训练判别模型:判断真实图片为真的损失
                d_avg_loss_real = exe.run(
                    program=d_program,
                    feed={'image': real_images, 'label': real_labels},
                    fetch_list=[d_avg_loss])[0][0]
                
                # 计算判别损失
                d_avg_loss_n = d_avg_loss_fake + d_avg_loss_real
         
                # 训练生成模型
                for i in range(2):
                    noise = np.random.uniform(low=-1.0, high=1.0, size=[batch_size, noise_size]).astype('float32')
                    dg_avg_loss_n = exe.run(
                        program=dg_program,
                        feed={'noise': noise},
                        fetch_list=[dg_avg_loss])[0][0]
    
                # 显示生成图像
                if batch % 10 == 0:
                    # 获取生成图像
                    noise = np.random.uniform(low=-1.0, high=1.0, size=[batch_size, noise_size]).astype('float32')
                    generate_images = exe.run(
                        program=g_program_test,
                        feed={'noise': noise},
                        fetch_list=[g_image])[0]
                    
                    total_image = np.concatenate([real_images, generate_images])
                    
                    # 显示生成图像 
                    print("Epoch: {0}, Batch: {1}, D AVG Loss: {2}, DG AVG Loss: {3}".format(epoch, batch, d_avg_loss_n, dg_avg_loss_n))
                    show_image(total_image)
    
    # 主函数
    if __name__ == "__main__":
        train()


     

    实验结果:

    8行为训练集字符,后8行为生成字符

    Epoch: 19, Batch: 460, D AVG Loss: 1.1578519344329834, DG AVG Loss: 0.6636089086532593

    参考资料:

    https://www.paddlepaddle.org.cn/documentation/docs/zh/user_guides/cv_case/gan/README.cn.html

     

  • 相关阅读:
    HTTP深入浅出 http请求
    javascript 新兴的API
    javascript 高级技巧详解
    javascript AJAX与Comet详解
    php文件扩展名判断
    php创建新用户注册界面布局实例
    php使用递归创建多级目录
    php对文本文件进行分页功能简单实现
    php上传功能集后缀名判断和随机命名
    php判断数据库是否连接成功的测试例子
  • 原文地址:https://www.cnblogs.com/d442130165/p/13178929.html
Copyright © 2011-2022 走看看