DCGAN模型讲解及避坑指南

最近在做科研上的项目,需要调各种GAN的模型,鉴于网上各种拿着标准数据集跑模型的流氓行为,本人决定推出一种对各种数据集都适用的模型训练教程。

话不多说,先上代码,大家看着我的代码,加上我的讲解,相信所有人都能无痛调节模型的参数。

我用的是github上PyTorch-GAN的代码,这个github实现了很多种类的GAN,并且写出来的模型也不复杂,很适合小白。然后我调的是DCGAN

DCGAN- 模型代码

class Generator(nn.Module):
   def __init__(self):
       super(Generator, self).__init__()

       self.init_size = opt.img_size // 4
       self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128*self.init_size**2))

       self.conv_blocks = nn.Sequential(
           nn.BatchNorm2d(128),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 128, 3, stride=1, padding=1),
           nn.BatchNorm2d(128, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 64, 3, stride=1, padding=1),
           nn.BatchNorm2d(64, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Conv2d(64, opt.channels, 3, stride=1, padding=1),
           nn.Tanh()
       )

   def forward(self, z):
       out = self.l1(z)
       out = out.view(out.shape[0], 128, self.init_size, self.init_size)
       img = self.conv_blocks(out)
       return img

class Discriminator(nn.Module):
   def __init__(self):
       super(Discriminator, self).__init__()

       def discriminator_block(in_filters, out_filters, bn=True):
           block = [   nn.Conv2d(in_filters, out_filters, 3, 2, 1),
                       nn.LeakyReLU(0.2, inplace=True),
                       nn.Dropout2d(0.25)]
           if bn:
               block.append(nn.BatchNorm2d(out_filters, 0.8))
           return block

       self.model = nn.Sequential(
           *discriminator_block(opt.channels, 16, bn=False),
           *discriminator_block(16, 32),
           *discriminator_block(32, 64),
           *discriminator_block(64, 128),
       )

       # The height and width of downsampled image
       ds_size = opt.img_size // 2**4
       self.adv_layer = nn.Sequential( nn.Linear(128*ds_size**2, 1),
                                       nn.Sigmoid())

   def forward(self, img):
       out = self.model(img)
       out = out.view(out.shape[0], -1)
       validity = self.adv_layer(out)

       return validity

上面的代码是DCGAN最核心的部分。是由两个网络组成:生成网络和判别网络。好了,接下来我一点点的解释这些代码。

Generator生成网络代码

class Generator(nn.Module):
   def __init__(self):
       super(Generator, self).__init__()

       self.init_size = opt.img_size // 4
       self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128*self.init_size**2))

       self.conv_blocks = nn.Sequential(
           nn.BatchNorm2d(128),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 128, 3, stride=1, padding=1),
           nn.BatchNorm2d(128, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 64, 3, stride=1, padding=1),
           nn.BatchNorm2d(64, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Conv2d(64, opt.channels, 3, stride=1, padding=1),
           nn.Tanh()
       )

   def forward(self, z):
       out = self.l1(z)
       out = out.view(out.shape[0], 128, self.init_size, self.init_size)
       img = self.conv_blocks(out)
       return img

看这个生成网络的代码,需要从def forward(self,z):看起。这个是数据真正被处理的流程。

这个处理的顺序是:

  1. out = self.l1(z)

  2. out = out.view(out.shape[0], 128, self.init_size, self.init_size)

  3. img = self.conv_blocks(out)

  4. return img

第一个语句执行的是l1函数,这个函数在上面的class里面定义好了:self.l1 = nn.Sequential(nn.Linear(opt.latent_dim, 128*self.init_size**2))这个语句的意思就是l1函数进行的是Linear变换。这个线性变换的两个参数是变换前的维度,和变换之后的维度。博主建议大家一个学习使用这些函数的方法:如果你使用的是pycharm 就可以选中你想了解的函数,然后按下ctrl + B 就可以跳转到该函数的定义处,一般在这个函数里都会有如何使用的介绍,以及example,非常好用。

那你会问了:这个Linear函数里面使用的参数是 self.init_size = opt.img_size // 4,为什么不是opt.img_size呢,这个就是接下来需要说的一个上采样.

第二个语句执行的是view()函数,这个函数很简单,是一个维度变换函数,我们可以看到out数据变成了四维数据,第一个是batch_size(通过整个的代码,你就可以明白了),第二个是channel,第三,四是单张图片的长宽。

第三个语句执行的是self.conv_blocks(out)函数,这个函数我们往上看,可以看到:

self.conv_blocks = nn.Sequential(
           nn.BatchNorm2d(128),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 128, 3, stride=1, padding=1),
           nn.BatchNorm2d(128, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Upsample(scale_factor=2),
           nn.Conv2d(128, 64, 3, stride=1, padding=1),
           nn.BatchNorm2d(64, 0.8),
           nn.LeakyReLU(0.2, inplace=True),
           nn.Conv2d(64, opt.channels, 3, stride=1, padding=1),
           nn.Tanh()
       )

nn.sequential{}是一个组成模型的壳子,用来容纳不同的操作。

我们大体可以看到这个壳子里面是由BatchNorm2dUpsampleConv2dLeakyReLU组成。

第一个是归一化函数对数据的形状没影响主要就是改变数据的量纲。

第二个函数是上采样函数,这个函数会将单张图片的尺寸进行放大(这就是为什么class最先开始将图片的长宽除了4,是因为壳子里面存在两个2倍的上采样函数)。

第三个函数是二维卷积函数,各个参数分别是输入数据的channel,输出数据的channel,剩下的三个参数是卷积的三个参数:卷积步长,卷积核大小,padding的大小。这个二维卷积函数会对channel的大小有影响,同时还会对单张图片的大小有影响。卷积的计算公式$H_{out} = (H_{in}-1)* S-2*P +K $

第四个函数是一个带有倾斜角度的激活函数,它是由ReLu函数改造而来的。

好了生成网络就讲完了。我们再来看判别网络:

Discriminator判别网络代码

class Discriminator(nn.Module):
   def __init__(self):
       super(Discriminator, self).__init__()

       def discriminator_block(in_filters, out_filters, bn=True):
           block = [   nn.Conv2d(in_filters, out_filters, 3, 2, 1),
                       nn.LeakyReLU(0.2, inplace=True),
                       nn.Dropout2d(0.25)]
           if bn:
               block.append(nn.BatchNorm2d(out_filters, 0.8))
           return block

       self.model = nn.Sequential(
           *discriminator_block(opt.channels, 16, bn=False),
           *discriminator_block(16, 32),
           *discriminator_block(32, 64),
           *discriminator_block(64, 128),
       )

       # The height and width of downsampled image
       ds_size = opt.img_size // 2**4
       self.adv_layer = nn.Sequential( nn.Linear(128*ds_size**2, 1),
                                       nn.Sigmoid())

   def forward(self, img):
       out = self.model(img)
       out = out.view(out.shape[0], -1)
       validity = self.adv_layer(out)

       return validity

同样地用生成网络看代码的顺序,看这段代码。数据处理的流程分四个步骤:

  1. out = self.model(img)
  2. out = out.view(out.shape[0], -1)
  3. validity = self.adv_layer(out)
  4. return validity

第一个语句执行的是model函数。好,我们来看model函数在class里面是如何定义的。

 def discriminator_block(in_filters, out_filters, bn=True):
           block = [   nn.Conv2d(in_filters, out_filters, 3, 2, 1),
                       nn.LeakyReLU(0.2, inplace=True),
                       nn.Dropout2d(0.25)]
           if bn:
               block.append(nn.BatchNorm2d(out_filters, 0.8))
           return block

       self.model = nn.Sequential(
           *discriminator_block(opt.channels, 16, bn=False),
           *discriminator_block(16, 32),
           *discriminator_block(32, 64),
           *discriminator_block(64, 128),
       )

model函数是由四个discriminator_block函数组成。然后我们再看discriminator_block函数的定义:

def discriminator_block(in_filters, out_filters, bn=True):
           block = [   nn.Conv2d(in_filters, out_filters, 3, 2, 1),
                       nn.LeakyReLU(0.2, inplace=True),
                       nn.Dropout2d(0.25)]
           if bn:
               block.append(nn.BatchNorm2d(out_filters, 0.8))
           return block

这个模块是由四部分组成:conv2dleakyReluDropoutBatchNorm2d

第一个语句:conv2d函数,是用来卷积的

第二个语句是:'leakyRelu’函数,用来做激活函数的

第三个语句:Dropout函数用来将部分神经元失活,进而防止过拟合

第四个语句:其实是一个判断语句,如果bn这个参数为True,那么就需要在block块里面添加上BatchNorm的归一化函数。

第二个语句执行的是view(out.shape[0],-1),这个语句是将处理之后的数据维度变成batch * N的维度形式,然后再放到最后一个语句里面执行。

第三个语句:self.adv_layer函数,这个函数是由:self.adv_layer = nn.Sequential( nn.Linear(128*ds_size**2, 1),nn.Sigmoid())就是先进行线性变换,再进行激活函数激活。其中第一个参数128*ds_size**2中128是指model模块中最后一个判别模块的最后一个参数决定的,ds_size是由model模块对单张图片的卷积效果决定的,而2次方的原因是,整个模型是选取的长宽一致的图片。

避坑指南

有时候我们在脑子里面想的很多设想其实和实际的情况不太一样,比如第一个坑。

  1. 在MATLAB和python里面经常遇到这样的情况,明明读取进去的图片是正常的,出来就是一个白板。这个问题在这个博客《python中opencv imshow函数显示一片白色原因》中解决的很好,会出现这个问题的原因是每个像素的数据类型出现了问题。

参考文献

Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks

DCGAN论文笔记+源码解析

python中opencv imshow函数显示一片白色原因

  • 22
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
1.版本:matlab2014/2019a,内含运行结果,不会运行可私信 2.领域:智能优化算法、神经网络预测、信号处理、元胞自动机、图像处理、路径规划、无人机等多种领域的Matlab仿真,更多内容可点击博主头像 3.内容:标题所示,对于介绍可点击主页搜索博客 4.适合人群:本科,硕士等教研学习使用 5.博客介绍:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可si信 ### 团队长期从事下列领域算法的研究和改进: ### 1 智能优化算法及应用 **1.1 改进智能优化算法方面(单目标和多目标)** **1.2 生产调度方面** 1.2.1 装配线调度研究 1.2.2 车间调度研究 1.2.3 生产线平衡研究 1.2.4 水库梯度调度研究 **1.3 路径规划方面** 1.3.1 旅行商问题研究(TSP、TSPTW) 1.3.2 各类车辆路径规划问题研究(vrp、VRPTW、CVRP) 1.3.3 机器人路径规划问题研究 1.3.4 无人机三维路径规划问题研究 1.3.5 多式联运问题研究 1.3.6 无人机结合车辆路径配送 **1.4 三维装箱求解** **1.5 物流选址研究** 1.5.1 背包问题 1.5.2 物流选址 1.5.4 货位优化 ##### 1.6 电力系统优化研究 1.6.1 微电网优化 1.6.2 配电网系统优化 1.6.3 配电网重构 1.6.4 有序充电 1.6.5 储能双层优化调度 1.6.6 储能优化配置 ### 2 神经网络回归预测、时序预测、分类清单 **2.1 bp预测和分类** **2.2 lssvm预测和分类** **2.3 svm预测和分类** **2.4 cnn预测和分类** ##### 2.5 ELM预测和分类 ##### 2.6 KELM预测和分类 **2.7 ELMAN预测和分类** ##### 2.8 LSTM预测和分类 **2.9 RBF预测和分类** ##### 2.10 DBN预测和分类 ##### 2.11 FNN预测 ##### 2.12 DELM预测和分类 ##### 2.13 BIlstm预测和分类 ##### 2.14 宽度学习预测和分类 ##### 2.15 模糊小波神经网络预测和分类 ##### 2.16 GRU预测和分类 ### 3 图像处理算法 **3.1 图像识别** 3.1.1 车牌、交通标志识别(新能源、国内外、复杂环境下车牌) 3.1.2 发票、身份证、银行卡识别 3.1.3 人脸类别和表情识别 3.1.4 打靶识别 3.1.5 字符识别(字母、数字、手写体、汉字、验证码) 3.1.6 病灶识别 3.1.7 花朵、药材、水果蔬菜识别 3.1.8 指纹、手势、虹膜识别 3.1.9 路面状态和裂缝识别 3.1.10 行为识别 3.1.11 万用表和表盘识别 3.1.12 人民币识别 3.1.13 答题卡识别 **3.2 图像分割** **3.3 图像检测** 3.3.1 显著性检测 3.3.2 缺陷检测 3.3.3 疲劳检测 3.3.4 病害检测 3.3.5 火灾检测 3.3.6 行人检测 3.3.7 水果分级 **3.4 图像隐藏** **3.5 图像去噪** **3.6 图像融合** **3.7 图像配准** **3.8 图像增强** **3.9 图像压缩** ##### 3.10 图像重建 ### 4 信号处理算法 **4.1 信号识别** **4.2 信号检测** **4.3 信号嵌入和提取** **4.4 信号去噪** ##### 4.5 故障诊断 ##### 4.6 脑电信号 ##### 4.7 心电信号 ##### 4.8 肌电信号 ### 5 元胞自动机仿真 **5.1 模拟交通流** **5.2 模拟人群疏散** **5.3 模拟病毒扩散** **5.4 模拟晶体生长** ### 6 无线传感器网络 ##### 6.1 无线传感器定位 ##### 6.2 无线传感器覆盖优化 ##### 6.3 室内定位 ##### 6.4 无线传感器通信及优化 ##### 6.5 无人机通信中继优化
抱歉,我作为AI语言模型不能够提供代码。但是,以下是DCGAN的Python代码示例,您可以根据自己的需要进行修改和优化: ``` import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from tensorflow.examples.tutorials.mnist import input_data # Load the MNIST dataset mnist = input_data.read_data_sets('MNIST_data') # Define the generator network def generator(z, reuse=None): with tf.variable_scope('gen', reuse=reuse): hidden1 = tf.layers.dense(inputs=z, units=128) # Leaky ReLU activation alpha = 0.01 hidden1 = tf.maximum(alpha * hidden1, hidden1) hidden2 = tf.layers.dense(inputs=hidden1, units=128) hidden2 = tf.maximum(alpha * hidden2, hidden2) output = tf.layers.dense(inputs=hidden2, units=784, activation=tf.nn.tanh) return output # Define the discriminator network def discriminator(X, reuse=None): with tf.variable_scope('dis', reuse=reuse): hidden1 = tf.layers.dense(inputs=X, units=128) alpha = 0.01 hidden1 = tf.maximum(alpha * hidden1, hidden1) hidden2 = tf.layers.dense(inputs=hidden1, units=128) hidden2 = tf.maximum(alpha * hidden2, hidden2) # Sigmoid activation function for binary classification logits = tf.layers.dense(hidden2, units=1) output = tf.sigmoid(logits) return output, logits # Define the placeholders for input and noise variables real_images = tf.placeholder(tf.float32, shape=[None, 784]) z = tf.placeholder(tf.float32, shape=[None, 100]) # Generate fake images from the generator network G = generator(z) # Calculate the discriminator output for real and fake images D_output_real, D_logits_real = discriminator(real_images) D_output_fake, D_logits_fake = discriminator(G, reuse=True) # Define the loss functions for generator and discriminator def loss_func(logits_in, labels_in): return tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits_in, labels=labels_in)) D_real_loss = loss_func(D_logits_real, tf.ones_like(D_logits_real) * 0.9) D_fake_loss = loss_func(D_logits_fake, tf.zeros_like(D_logits_real)) D_loss = D_real_loss + D_fake_loss G_loss = loss_func(D_logits_fake, tf.ones_like(D_logits_fake)) # Define the optimizer for generator and discriminator learning_rate = 0.001 tvars = tf.trainable_variables() d_vars = [var for var in tvars if 'dis' in var.name] g_vars = [var for var in tvars if 'gen' in var.name] D_trainer = tf.train.AdamOptimizer(learning_rate).minimize(D_loss, var_list=d_vars) G_trainer = tf.train.AdamOptimizer(learning_rate).minimize(G_loss, var_list=g_vars) # Define the batch size and number of epochs batch_size = 100 epochs = 100 samples = [] # Start the TensorFlow session with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # Train the DCGAN for epoch in range(epochs): for i in range(mnist.train.num_examples // batch_size): batch = mnist.train.next_batch(batch_size) # Generate random noise for the generator input batch_images = batch[0].reshape((batch_size, 784)) batch_images = batch_images * 2 - 1 batch_noise = np.random.uniform(-1, 1, size=(batch_size, 100)) # Train the discriminator on real and fake images _ = sess.run(D_trainer, feed_dict={real_images: batch_images, z: batch_noise}) # Train the generator by fooling the discriminator _ = sess.run(G_trainer, feed_dict={z: batch_noise}) # Print the loss function for discriminator and generator after each epoch print("Epoch {} completed. D Loss: {:.4f}, G Loss: {:.4f}".format(epoch+1, sess.run(D_loss, feed_dict={real_images: batch_images, z: batch_noise}), sess.run(G_loss, feed_dict={z: batch_noise}))) # Save generated images for testing sample_noise = np.random.uniform(-1, 1, size=(1, 100)) gen_sample = sess.run(generator(z, reuse=True), feed_dict={z: sample_noise}) samples.append(gen_sample) # Plot the generated images fig, axes = plt.subplots(nrows=1, ncols=10, sharex=True, sharey=True, figsize=(20, 2)) for img, ax in zip(samples[0], axes): ax.imshow(img.reshape((28, 28)), cmap='Greys_r') ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) plt.show() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值