GAN的代码结构

在GAN类外,是生成器类和判别器类的代码,而本篇中的GAN较为特殊,使用的是金字塔结构的判别器,有些地方需要额外注意。

初始化函数

参数解析器

首先是使用参数解析器(argparse),方便直接在控制台使用Python命令来控制训练的部分超参数

本篇代码中含有的超参数包含:

参数名类型默认值选择值帮助
descriptionstrnonenone对于本代码的描述
datasetstrCACD2000[‘CACD2000’,
‘UTKFace’,’FG_NET’,
‘wiki’,’MORPH’]
训练使用的数据集
epochint50训练的遍数
batch_sizeint8随显存提升而提高批量的大小
input_sizeint224输入图片大小
save_dirstr‘D:/GAN/Pyramid-GAN/Dict/‘模型保存目录
result_dirstr‘D:/GAN/Pyramid-GAN/results’结果保存目录
lrGfloat0.0001使用Adam时有人推荐3e-4生成器G的学习率
lrDfloat0.0001同上判别器D的学习率
beta1float0.5Adam中动量梯度下降超参数
beta2float0.999Adam中根均方传播超参数
gpu_modeboolTrueGPU模式
benchmark_modeboolTrue标准模式

数据加载器

4个数据加载器dataloader0,1,2,3分别对应30岁以下,30~40,40~50和50以上的年龄图片

网络模型

生成器G,判别器D,G的Adam优化器和D的Adam优化器

均方根误差

GPU模式使用CUDA训练G,D并且计算MSELoss(均方根误差)

噪声样本z

使用rand()生成batch_size个100*1*1的随机数,并且可以的话放入CUDA

训练函数

训练历史

使用train_hist元组,其中包含D_loss, G_loss, per_epoch_time和total_time

使用ones和zeros函数分别生成batch_size个真假标签,存入变量y_fake和y_real中

训练D_1

使用enumerate函数遍历dataloader1中的数据,用iter表示迭代次数,数据形式为(x, y)

当使用GPU模式时,将x放入cuda,清除D优化器重的梯度,并将X分别投入4个path中,这四个path代表的是从输入图片开始,经过VGG的部分然后经过扩展的部分再形成3*3*1表示的结果

然后将四个path的结果投入D中,形成判别器D真实的训练结果,并以真实标签计算均方根误差,这里计算的是最小二乘公式的前半段,即$(D_w(\phi_{age}(x))-1)^2$,完整公式如下:

\mathcal{L}_{GAN\_D} = {\frac{1}{2}\mathbb{E}_{x\sim P_{data}}(x)[(D_w(\phi_{age}(x)) -1)^2] +  \\ \frac{1}{2}\mathbb{E}_{x \sim P_{young}}(x)[D_w(\phi_{age}(G(x)))^2 + D_w(\phi_{age}(x))^2]}

这里计算了前半段的损失公式,并且进行反向传播。然后让D的优化器进行单次优化,即更新D的所有参数

训练D_2

使用enumerate函数遍历dataloader0中的数据,即年轻样本

开始前,先将x的前8张进行重复形成fixed_noise,修正噪声,然后声明一个全局变量fixed_img_v,即图像修正值,将fixed_noise转换成变量放入并保存

然后将D优化器中的梯度清零

将x重新放入更新过参数的D的Path中,并得出新的判别结果并让其与0标签计算均方根误差,用于计算损失公式的$D_w(\phi_{age}(x))^2$部分

再将x投入G中,并将结果放入D中,得到的真实结果与0计算均方根误差,得到公式的$D_w(\phi_{age}(G(x)))^2$部分,并将两者相加得到的损失放入train_hist[‘D_loss’]中,然后进行反向传播并更新参数

训练G

清除G优化器中的梯度,将x放入G中并将所得结果放入D,得到结果并计算均方根误差,得到:

\mathcal{L}_{GAN\_G} = \mathbb{E}_{x \sim P_{young}(x)}[(D_w(\phi_{age}(G(x))) - 1)^2]

并且将生成结果G(x)与x计算均方根误差,得到pixel-level-loss,即:

\mathcal{L}_{pixel} = \frac{1}{W\times H \times C}\lVert G(x)-x \rVert ^2_2

然后计算$L_G = 750 \times L_{GAN_G} + 0.2 \times L_{pixel}$

将其放入train_hist[‘G_loss’]中,并且进行反向传播并更新参数