GAN的代码结构
在GAN类外,是生成器类和判别器类的代码,而本篇中的GAN较为特殊,使用的是金字塔结构的判别器,有些地方需要额外注意。
初始化函数
参数解析器
首先是使用参数解析器(argparse),方便直接在控制台使用Python命令来控制训练的部分超参数
本篇代码中含有的超参数包含:
| 参数名 | 类型 | 默认值 | 选择值 | 帮助 |
|---|---|---|---|---|
| description | str | none | none | 对于本代码的描述 |
| dataset | str | CACD2000 | [‘CACD2000’, ‘UTKFace’,’FG_NET’, ‘wiki’,’MORPH’] | 训练使用的数据集 |
| epoch | int | 50 | 训练的遍数 | |
| batch_size | int | 8 | 随显存提升而提高 | 批量的大小 |
| input_size | int | 224 | 输入图片大小 | |
| save_dir | str | ‘D:/GAN/Pyramid-GAN/Dict/‘ | 模型保存目录 | |
| result_dir | str | ‘D:/GAN/Pyramid-GAN/results’ | 结果保存目录 | |
| lrG | float | 0.0001 | 使用Adam时有人推荐3e-4 | 生成器G的学习率 |
| lrD | float | 0.0001 | 同上 | 判别器D的学习率 |
| beta1 | float | 0.5 | Adam中动量梯度下降超参数 | |
| beta2 | float | 0.999 | Adam中根均方传播超参数 | |
| gpu_mode | bool | True | GPU模式 | |
| benchmark_mode | bool | True | 标准模式 |
数据加载器
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’]中,并且进行反向传播并更新参数