ACGAN

转处:https://zhuanlan.zhihu.com/p/64034844

前言

ODOG,顾名思义就我我希望能每天抽出一个小时的时间来讲讲到目前为止,GAN的前沿发展和研究,笔者观察了很多深度学习的应用,特别是在图像这一方面,GAN已经在扮演着越来越重要的角色,我们经常可以看到老黄的NVIDIA做了各种各样的application,而且其中涉及到了大量GAN的理论及其实现,再者笔者个人也觉得目前国内缺少GAN在pytorch,keras,tensorflow等主流的框架下的实现教学.

我的老师曾经对我说过:"深度学习是一块未知的新大陆,它是一个大的黑箱系统,而GAN则是黑箱中的黑箱,谁要是能打开这个盒子,将会引领一个新的时代"

ACGAN

ACGAN的全称叫Auxiliary Classifier Generative Adversarial Network,翻译成汉语的意思就是带辅助分类器的GAN,其实他的思想和昨天说到的CGAN很想,也是利用label的信息作为噪声的输入的条件概率,但是相比较于CGAN,ACGAN在设计上更为巧妙,他很好地利用了判别器使得不但可以判别真假,也可以判别类别,通过对生成图像类别的判断,判别器可以更好地传递loss函数使得生成器能够更加准确地找到label对应的噪声分布,通过下图告诉了我们ACGAN与CGAN的异同之处.

 

 

为此,我们先回顾一下我们昨天讲的CGAN的loss函数:

 

 

那么在对比一下我们ACGAN他的loss函数:

 

 

Ls表示的是真实样本对应ground truth,假的样本对应fake.

Lc表示的是真实样本对应他真实的类别信息,假的样本对应的也是真实样本的类别信息

在训练判别器的时候,我们希望$L_S+L_C$最大化

在训练生成器的时候,我们希望$L_C-L_S$最大化

当然了,也有人是从JS散度优化的角度来看待这个问题的,我不想把问题将得太复杂,有兴趣的同学可以瞄一瞄:

 

 

代码实现

其实和之前的CGAN,只是做了很微小的改变,生成器和CGAN相比,就是加入了卷积层,相当于把原来CGAN里面的多层感知机换成了DCGAN里面一样的深度卷积神经网络,那么判别器同理.

生成器

def build_generator(self):

    model = Sequential()

    model.add(Dense(128 * 7 * 7, activation="relu", input_dim=self.latent_dim))
    model.add(Reshape((7, 7, 128)))
    model.add(BatchNormalization(momentum=0.8))
    model.add(UpSampling2D())
    model.add(Conv2D(128, kernel_size=3, padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(UpSampling2D())
    model.add(Conv2D(64, kernel_size=3, padding="same"))
    model.add(Activation("relu"))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Conv2D(self.channels, kernel_size=3, padding='same'))
    model.add(Activation("tanh"))

    model.summary()

    noise = Input(shape=(self.latent_dim,))
    label = Input(shape=(1,), dtype='int32')
    label_embedding = Flatten()(Embedding(self.num_classes, 100)(label))

    model_input = multiply([noise, label_embedding])
    img = model(model_input)

    return Model([noise, label], img)

判别器

判别器倒是有些有趣,他在卷积层的末尾相当于做了一个分叉,一边是判断真假,一边是还得判断类别.

def build_discriminator(self):

    model = Sequential()

    model.add(Conv2D(16, kernel_size=3, strides=2, input_shape=self.img_shape, padding="same"))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(Conv2D(32, kernel_size=3, strides=2, padding="same"))
    model.add(ZeroPadding2D(padding=((0,1),(0,1))))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Conv2D(64, kernel_size=3, strides=2, padding="same"))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))
    model.add(BatchNormalization(momentum=0.8))
    model.add(Conv2D(128, kernel_size=3, strides=1, padding="same"))
    model.add(LeakyReLU(alpha=0.2))
    model.add(Dropout(0.25))

    model.add(Flatten())
    model.summary()

    img = Input(shape=self.img_shape)

    # Extract feature representation
    features = model(img)

    # Determine validity and label of the image
    validity = Dense(1, activation="sigmoid")(features)
    label = Dense(self.num_classes+1, activation="softmax")(features)

    return Model(img, [validity, label])
#所以判别器的输出有两个,一个是判断真假的validity,一个图片对应的label信息


# 对应的,他的loss函数定义也挺有意思的,不得不说keras是真的方便? 
losses = ['binary_crossentropy', 'sparse_categorical_crossentropy']
self.discriminator = self.build_discriminator()
self.discriminator.compile(loss=losses,
    optimizer=optimizer,
    metrics=['accuracy'])

self.combined = Model([noise, label], [valid, target_label])
self.combined.compile(loss=losses,
    optimizer=optimizer)

训练细节

# ---------------------
#  训练判别器
# ---------------------

# 随机选择batch个图片
idx = np.random.randint(0, X_train.shape[0], batch_size)
imgs = X_train[idx]

# 生成高斯噪声noise
noise = np.random.normal(0, 1, (batch_size, 100))

# 生成随机标签
# image representation of
sampled_labels = np.random.randint(0, 10, (batch_size, 1))

# 应用随机标签和noise生成图片
gen_imgs = self.generator.predict([noise, sampled_labels])

# 判别器要判别10(0~9)+1(fake)=11种类别
img_labels = y_train[idx]
fake_labels = 10 * np.ones(img_labels.shape)

# 训练判别器
d_loss_real = self.discriminator.train_on_batch(imgs, [valid, img_labels])
d_loss_fake = self.discriminator.train_on_batch(gen_imgs, [fake, fake_labels])
d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

# ---------------------
#  训练生成器
# ---------------------

# 训练生成器
g_loss = self.combined.train_on_batch([noise, sampled_labels], [valid, sampled_labels])

实验结果

 

 

作者从1000类的imageNet数据集上挑选了10种类别的图像,并在不同的尺度上做了实验,我们看得出来,在彩色图像上的生成结果还是马马虎虎不错的,不过看起来还是显得图像没什么协调感,在之后的GAN中,我们会讲到如何利用GAN生成高质量的图像.看到这里了要是看官老爷觉得interesting,不如麻烦关注转发好看三连一波,你的每一点小小的鼓励都是对作者莫大的鼓舞鸭?.

参考

https://zhuanlan.zhihu.com/p/44177576

http://ruishu.io/2017/12/26/acgan/

https://www.cnblogs.com/punkcure/p/7873566.html

https://github.com/eriklindernoren/Keras-GAN/blob/master/acgan/acgan.py

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值