MindSpore实现DCGAN网络

本文介绍了如何使用MindSpore框架构建和训练DCGAN模型。DCGAN是一种无监督学习方法,由生成器和判别器组成。生成器从噪声中生成图像,而判别器则试图区分真实图像和生成的图像。模型的训练涉及生成器和判别器的交替优化,目标是使生成器能产生逼真的图像,同时判别器能准确区分真实和虚假图像。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MindSpore实现DCGAN网络

本文源自MindSpore教程

DCGAN(深度卷积对抗生成网络)是一种经典的无监督学习。

  • 参数
batch_size = 128          # 批量大小
image_size = 64           # 训练图像空间大小
nc = 3                    # 图像彩色通道数
nz = 100                  # 隐向量的长度
ngf = 64                  # 特征图在生成器中的大小
ndf = 64                  # 特征图在判别器中的大小
num_epochs = 10           # 训练周期数
lr = 0.0002               # 学习率
beta1 = 0.5               # Adam优化器的beta1超参数

DCGAN的网络结构主要由生成器和判别器构成。

  • 生成器输入一个噪声(100维),输出一个生成的图像。网络结构主要有反卷积Batch norm,激活函数使用ReLU。
# 按照DCGAN论文中的描述,所有模型权重均应从mean为0,sigma为0.02的正态分布中随机初始化。
weight_init = Normal(mean=0, sigma=0.02)
gamma_init = Normal(mean=1, sigma=0.02)

class Generator(nn.Cell):
    """DCGAN网络生成器"""

    def __init__(self):
        super(Generator, self).__init__()
        self.generator = nn.SequentialCell(
            nn.Conv2dTranspose(nz, ngf * 8, 4, 1, 'valid', weight_init=weight_init), # 反卷积
            nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),
            nn.ReLU(),
            nn.Conv2dTranspose(ngf * 8, ngf * 4, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),
            nn.ReLU(),
            nn.Conv2dTranspose(ngf * 4, ngf * 2, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),
            nn.ReLU(),
            nn.Conv2dTranspose(ngf * 2, ngf, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf, gamma_init=gamma_init),
            nn.ReLU(),
            nn.Conv2dTranspose(ngf, nc, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.Tanh()
            )

    def construct(self, x):
        return self.generator(x)

generator = Generator()
  • 生成器生成图片后,会与数据集中的图片一起给判别器进行预测。判别器的网络结构相当于将生成器反过来,输入一个图像,输出是一个值,0代表生成图,1代表数据集中图片。在DCGAN论文中提到,判别器中,出了输出层的激活函数是tanh 之外,其他的激活函数都是LeakyReLU

class Discriminator(nn.Cell):
    """DCGAN网络判别器"""

    def __init__(self):
        super(Discriminator, self).__init__()
        self.discriminator = nn.SequentialCell(
            nn.Conv2d(nc, ndf, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.LeakyReLU(0.2),
            nn.Conv2d(ndf, ndf * 2, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf * 2, gamma_init=gamma_init),
            nn.LeakyReLU(0.2),
            nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf * 4, gamma_init=gamma_init),
            nn.LeakyReLU(0.2),
            nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 'pad', 1, weight_init=weight_init),
            nn.BatchNorm2d(ngf * 8, gamma_init=gamma_init),
            nn.LeakyReLU(0.2),
            nn.Conv2d(ndf * 8, 1, 4, 1, 'valid', weight_init=weight_init),
            )
        self.adv_layer = nn.Sigmoid()

    def construct(self, x):
        out = self.discriminator(x)
        out = out.reshape(out.shape[0], -1)
        return self.adv_layer(out)

discriminator = Discriminator()

  • 判别器的输出可以看成是一个二分类输出,因此损失函数可以选择二分类交叉熵损失函数,即BCELoss。损失函数为:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r6bcMPrN-1678379690441)(:/8df9e46a74f9481a86574a59a072183a)]
    这里,D(x)表示图像x是真实图像的概率,G(z)是生成器函数,D(G(z))表示生成的图像是真实图像的概率。判别器的任务是最大程度的分辨出真实图像(D(x)),以及预测生成图像的概率更小(1-D(G(z)))。
  • 优化器部分,DCGAN使用的是学习率为0.0002和beta1为0.5的Adam优化器。
# 定义损失函数
adversarial_loss = nn.BCELoss(reduction='mean')

# 为生成器和判别器设置优化器
optimizer_D = nn.Adam(discriminator.trainable_params(), learning_rate=lr, beta1=beta1)
optimizer_G = nn.Adam(generator.trainable_params(), learning_rate=lr, beta1=beta1)
optimizer_D.update_parameters_name('optim_d.')
optimizer_G.update_parameters_name('optim_g.')
  • 下面是对训练过程的定义。训练过程主要有两部分,一个是由生成器生成图像,一个是判别器预测生成器生成的图像和数据集中图像为真实图像的概率。
def generator_forward(real_imgs, valid):
    # 将噪声采样为发生器的输入
    z = ops.standard_normal((real_imgs.shape[0], nz, 1, 1))

    # 生成一批图像
    gen_imgs = generator(z)

    # 损失衡量发生器绕过判别器的能力
    g_loss = adversarial_loss(discriminator(gen_imgs), valid)

    return g_loss, gen_imgs

def discriminator_forward(real_imgs, gen_imgs, valid, fake):
    # 衡量鉴别器从生成的样本中对真实样本进行分类的能力
    real_loss = adversarial_loss(discriminator(real_imgs), valid)
    fake_loss = adversarial_loss(discriminator(gen_imgs), fake)
    d_loss = (real_loss + fake_loss) / 2
    return d_loss

grad_generator_fn = ms.value_and_grad(generator_forward, None,
                                      optimizer_G.parameters,
                                      has_aux=True)
grad_discriminator_fn = ms.value_and_grad(discriminator_forward, None,
                                          optimizer_D.parameters)

@ms.jit
def train_step(imgs):
    valid = ops.ones((imgs.shape[0], 1), mindspore.float32)
    fake = ops.zeros((imgs.shape[0], 1), mindspore.float32)

    (g_loss, gen_imgs), g_grads = grad_generator_fn(imgs, valid)
    g_loss = ops.depend(g_loss, optimizer_G(g_grads))
    d_loss, d_grads = grad_discriminator_fn(imgs, gen_imgs, valid, fake)
    d_loss = ops.depend(d_loss, optimizer_D(d_grads))

    return g_loss, d_loss, gen_imgs

  • 将训练的一个步骤定义完成后,就可以开始训练了。
import mindspore

G_losses = []
D_losses = []
image_list = []

total = dataset.get_dataset_size()
for epoch in range(num_epochs):
    generator.set_train()
    discriminator.set_train()
    # 为每轮训练读入数据
    for i, (imgs, ) in enumerate(dataset.create_tuple_iterator()):
        g_loss, d_loss, gen_imgs = train_step(imgs)
        if i % 100 == 0 or i == total - 1:
            # 输出训练记录
            print('[%2d/%d][%3d/%d]   Loss_D:%7.4f  Loss_G:%7.4f' % (
                epoch + 1, num_epochs, i + 1, total, d_loss.asnumpy(), g_loss.asnumpy()))
        D_losses.append(d_loss.asnumpy())
        G_losses.append(g_loss.asnumpy())

    # 每个epoch结束后,使用生成器生成一组图片
    generator.set_train(False)
    fixed_noise = ops.standard_normal((batch_size, nz, 1, 1))
    img = generator(fixed_noise)
    image_list.append(img.transpose(0, 2, 3, 1).asnumpy())

    # 保存网络模型参数为ckpt文件
    mindspore.save_checkpoint(generator, "./ckpt/generator.ckpt")
    mindspore.save_checkpoint(discriminator, "./ckpt/discriminator.ckpt")
  • 训练完成后,就可以尝试使用网络生成图片了:
# 从文件中获取模型参数并加载到网络中
mindspore.load_checkpoint("./ckpt/generator.ckpt", generator)

fixed_noise = ops.standard_normal((batch_size, nz, 1, 1)) # 生成batch_size个随机数
img64 = generator(fixed_noise).transpose(0, 2, 3, 1).asnumpy()

fig = plt.figure(figsize=(8, 3), dpi=120)
images = []
for i in range(3):
    images.append(np.concatenate((img64[i * 8:(i + 1) * 8]), axis=1))
img = np.clip(np.concatenate((images[:]), axis=0), 0, 1)
plt.axis("off")
plt.imshow(img)
plt.show()

@article{Radford2015UnsupervisedRL,
title={Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks},
author={Alec Radford and Luke Metz and Soumith Chintala},
journal={CoRR},
year={2015},
volume={abs/1511.06434}
}
@article{goodfellow2020generative,
title={Generative adversarial networks},
author={Goodfellow, Ian and Pouget-Abadie, Jean and Mirza, Mehdi and Xu, Bing and Warde-Farley, David and Ozair, Sherjil and Courville, Aaron and Bengio, Yoshua},
journal={Communications of the ACM},
volume={63},
number={11},
pages={139–144},
year={2020},
publisher={ACM New York, NY, USA}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值