
論文復現:Progressive Growing of GANs for Improved Quality, Stability, and Variation
一、簡介
本文提出了一種新的訓練 GAN 的方法——在訓練程序中逐步增加生成器和鑒別器的卷積層:從低解析度開始,隨著訓練的進行,添加更高解析度的卷積層,對更加精細的細節進行建模,生成更高解析度和質量的影像,

這個方法既加快了 GAN 的訓練速度,又增加了訓練的穩定性,因為預先訓練的低解析度層能給更難收斂的高解析度層帶來更有利于訓練的隱藏編碼,
本文還提出了一種新的評估 GAN 生成影像的指標——Sliced Wasserstein Distance(SWD),來評估源圖和生成影像的質量和變化,
論文鏈接:Progressive Growing of GANs for Improved Quality, Stability, and Variation
賽場:
- 飛槳論文復現挑戰賽(第四期)
- 【飛槳論文復現挑戰賽(第四期)】榜單
二、復現精度
參考官方開源的 pytorch 版本代碼 https://github.com/facebookresearch/pytorch_GAN_zoo,基于 paddlepaddle 深度學習框架,對文獻演算法進行復現后,本專案達到的測驗精度,如下表所示, 參考文獻的最高精度為 CelebA MS-SSIM=0.2838, SWD=2.64(64)
| 指標 | SWD × 1 0 3 10^3 103 | MS-SSIM |
|---|---|---|
| 解析度 | 128、64、32、16 | 128 |
| paddle 版本精度 | 4.46、2.61、4.98、11.41 | 0.2719 |
| 參考文獻精度 | 4.62、2.64、3.78、6.06 | 0.2838 |
超引數配置如下:
詳見
PGAN-Paddle/models/trainer/standard_configurations/pgan_config.py
| 超引數名 | 設定值 | 說明 |
|---|---|---|
| miniBatchSize | 32 | Mini batch size |
| initBiasToZero | True | 是否把網路的 bias 初始化為 0? |
| perChannelNormalization | True | Per channel normalization |
| lossMode | WGANGP | loss mode,默認 |
| lambdaGP | 10.0 | Gradient penalty coefficient (WGANGP) |
| leakyness | 0.2 | Leakyness of the leakyRelU activation function |
| epsilonD | 0.001 | Weight penalty on D ( x ) 2 D(x)^2 D(x)2 |
| baseLearningRate | 0.001 | Base learning rate |
| GDPP | False | 是否使用 GDPP loss 加入訓練? |
Paddle 版原始碼:https://github.com/GXU-GMU-MICCAI/PGAN-Paddle
三、資料集
本專案使用的是 celeba 資料集,(CelebA)是一個大規模人臉屬性資料集,擁有超過 20 萬張名人頭像,該資料集中的影像包含大量姿勢變化和背景噪音以及模糊,
-
資料集概述:
- 影像數量:202599 張人臉影像
- 影像大小:178 × 218 解析度
- 資料集名稱:
img_align_celeba
-
資料集鏈接:CELEBA
四、環境依賴
- 硬體:
- x86 cpu(RAM >= 16 GB)
- NVIDIA GPU(VRAM >= 32 GB)
- CUDA + cuDNN
- 框架:
- paddlepaddle-gpu==0.0.0(nightly build 版本)
- 其它依賴項:
- numpy >= 1.19.2
- scipy = 1.6.2
- h5py = 3.2.1
- imageio = 2.9.0
五、快速開始
1. 訓練
-
資料預處理
在開始訓練之前先解壓下載的
img_align_celeba.zip資料集,然后使用datasets.py腳本對解壓后的資料集進行預處理:每個影像會被 cropped 到 128×128 解析度
python datasets.py celeba_cropped $PATH_TO_CELEBA/img_align_celeba/ -o $OUTPUT_DATASET處理完成后,會在專案根目錄下生成組態檔
config_celeba_cropped.json并自動寫入了以下內容,指定了預處理資料集路徑以及逐層訓練的相應迭代次數:{ "pathDB": "img_dataset/celeba_cropped", "config": { "maxIterAtScale": [ 48000, 96000, 96000, 96000, 96000, 96000 ] } }可以在 config 中修改訓練配置,比如調整 batch_size,它會覆寫
standard configuration中的默認配置,以下是我的訓練配置:{ "pathDB": "work/img_dataset/celeba_cropped", "config": { "miniBatchScheduler": {"1": 64, "2": 64, "3": 64, "4": 32, "5": 22}, "configScheduler": { "3": {"baseLearningRate": 0.003}, "4": {"baseLearningRate": 0.003}, "5": {"baseLearningRate": 0.003} }, "maxIterAtScale": [ 48000, 96000, 96000, 96000, 96000, 160000 ] } }miniBatchScheduler中可以針對不同的 scale 設定不同的 batch_size,因為隨著 scale 的增加,需要減小 batch_size 來防止爆顯存,configScheduler中可以針對不同的 scale 設定不同的 learning_rate,在代碼PGAN-Paddle/models/progressive_gan.py中我還加入了自適應學習率衰減策略(lr.ReduceOnPlateau), -
運行訓練
接著運行以下命令從零開始訓練 PGAN:
python train.py PGAN -c config_celeba_cropped.json --restart -n celeba_cropped --np_vis然后等幾天(我用 T4 和百度 AI studio 的 V100,前后跑了 6 天,所以它到底加速了什么呢 😝 ),,,各個階段訓練好的模型會被轉儲到
output_networks/celeba_cropped中,訓練完成后應該得到 128 x 128 解析度的生成影像,如果訓練中斷,重啟訓練時可以把
--restart去掉,訓練會從output_networks/celeba_cropped中保存的最新模型開始,如果想使用 GDPP loss,可以加入--GDPP True,output_networks/celeba_cropped中會保存每個階段訓練完成的:- 模型:
celeba_cropped_s$scale_i$iters.pdparams - 組態檔:
celeba_cropped_s$scale_i$iters_tmp_config.json - refVectors:
celeba_cropped_refVectors.pdparams - losses:
celeba_cropped_losses.pkl - 生成的影像:
celeba_cropped_s$scale_i$iters_avg.jpg、celeba_cropped_s$scale_i$iters.jpg,_avg.jpg影像效果更好,預測時默認使用其來計算指標,

- 模型:
2. 預測
訓練好的最終模型可到百度網盤自取:celeba_cropped_s5_i96000,提取碼:6nv9,將其中的檔案放到專案的 output_networks/celeba_cropped 中,在 .json 檔案中指定 refVectors.pdparams 的路徑,losses.pkl 可以沒有,
如需要運行 i80000.pdparams 模型,可以把
.json檔案的檔案名改成對應的 i80000,因為需要通過這個檔案找到refVectors.pdparams的路徑,
-
影像生成
通過以下命令使用
output_networks/celeba_cropped中保存的最新模型來生成影像:python eval.py visualization -n celeba_cropped -m PGAN --np_vis如果你想指定某個階段的模型,加入
-s $scale和-i $iter:python eval.py visualization -n celeba_cropped -m PGAN -s $SCALE -i $ITER --np_vis以上兩個命令生成的影像保存在
output_networks/celeba_cropped中,名為:celeba_cropped_s$scale_i$iter_fullavg.jpg隨機生成一些影像:
python eval.py visualization -n celeba_cropped -m PGAN --save_dataset $PATH_TO_THE_OUTPUT_DATASET --size_dataset $SIZE_OF_THE_OUTPUT --np_vis其中,
$SIZE_OF_THE_OUTPUT表示要生成多少張影像, -
評估指標
SWD & MS-SSIM metric
運行:
python eval.py laplacian_SWD -c config_celeba_cropped.json -n celeba_cropped -m PGAN -s 5 -i 64000 --np_vis它會在
config_celeba_cropped.json里指定的資料路徑中隨機遍歷 16000 張源影像及其生成影像來計算 SWD 指標,Merging the results 的程序會占用不少 CPU 記憶體(18 GB 左右)和時間,運行后會輸出:Running laplacian_SWD Checkpoint found at scale 5, iter 64000 Average network found ! 202599 images found Generating the fake dataset... |####################################################################################################| 100.0% |####################################################################################################| 100.0% Merging the results, please wait it can take some time... |####################################################################################################| 100.0% resolution 128 64 32 16 (background) score 0.006042 0.002615 0.004997 0.011406 ms-ssim score 0.2719 ...OK其中相應的指標數值會保存在
output_networks/celeba_cropped/celeba_cropped_swd.json中,
六、代碼結構與詳細說明
6.1 代碼結構
├── logs # 訓練日志檔案
├── models # 包含模型定義、損失函式、資料集讀取、訓練測驗方法
│ ├── datasets # 讀取資料集
│ ├── eval # 使用預訓練模型進行預測、指標評估
│ ├── loss_criterions # 損失函式定義
│ ├── metrics # 評估指標
│ ├── networks # 網路模型定義
│ ├── trainer # 訓練策略封裝
│ ├── utils # 工具包
│ ├── UTs # 未使用
│ ├── base_GAN.py # GAN父類
│ ├── gan_visualizer.py # GAN 訓練中間影像保存
│ ├── progressive_gan.py # PGAN
│ ├── README.md # models' readme
├── output_networks # 保存訓練和預測結果
├── visualization # 可視化、影像保存
├── CODE_OF_CONDUCT.md
├── config_celeba_cropped.json # 資料預處理后生成的組態檔
├── CONTRIBUTING.md
├── datasets.py # 資料預處理腳本
├── eval.py # 預測、生成影像腳本
├── hubconf.py # 用于加載預訓練的參考代碼,未使用
├── LICENSE # 開源協議
├── README.md # 主頁 readme
├── requirements.txt # 專案的其它依賴
├── save_feature_extractor.py # 未使用
├── train.py # 訓練腳本
6.2 引數說明
見 二、復現精度
6.3 訓練流程
見 五、快速開始
執行訓練開始后,將得到類似如下的輸出,每 100 個迭代會列印當前 [scale: iters] 以及生成器損失、辨別器損失,
一個 scale 代表添加了一層,scale = len(maxIterAtScale),maxIterAtScale 指定了逐層訓練的每層相應迭代次數,
config_celeba_cropped.json:
{
"pathDB": "img_dataset/celeba_cropped",
"config": {
"maxIterAtScale": [
48000,
96000,
96000,
96000,
96000,
96000
]
}
}
開頭的 loss 會比較大,大小與設定的 batch_size 成正比,到 3000 個迭代后 loss 趨于穩定,穩下來的時間或許也跟設定的 batch_size 大小有關,
Running PGAN
size 10
202599 images found
202599 images detected
size (4, 4)
202599 images found
Changing alpha to 0.000
[0 : 100] loss G : 614.970 loss D : 750532.237
[0 : 200] loss G : 1535.155 loss D : 322471.667
[0 : 300] loss G : 1557.878 loss D : 211534.072
[0 : 400] loss G : 1459.596 loss D : 155299.552
[0 : 500] loss G : 1289.707 loss D : 108436.870
[0 : 600] loss G : 926.709 loss D : 85481.609
[0 : 700] loss G : 616.158 loss D : 55485.711
[0 : 800] loss G : 521.535 loss D : 37811.031
[0 : 900] loss G : 426.269 loss D : 31965.410
[0 : 1000] loss G : 330.425 loss D : 24301.256
[0 : 1100] loss G : 183.268 loss D : 19704.261
[0 : 1200] loss G : 53.901 loss D : 16482.146
[0 : 1300] loss G : -63.348 loss D : 11397.357
[0 : 1400] loss G : 22.371 loss D : 8459.339
[0 : 1500] loss G : -13.653 loss D : 6577.623
[0 : 1600] loss G : 8.768 loss D : 6329.811
[0 : 1700] loss G : -2.990 loss D : 4607.002
[0 : 1800] loss G : 29.571 loss D : 3684.394
[0 : 1900] loss G : 27.713 loss D : 3607.460
[0 : 2000] loss G : -43.031 loss D : 2106.303
[0 : 2100] loss G : -95.974 loss D : 1928.345
[0 : 2200] loss G : -74.860 loss D : 2405.030
[0 : 2300] loss G : -65.015 loss D : 1664.527
[0 : 2400] loss G : -62.593 loss D : 1063.161
[0 : 2500] loss G : -12.376 loss D : 1379.406
[0 : 2600] loss G : 36.092 loss D : 549.926
[0 : 2700] loss G : 49.579 loss D : 691.503
[0 : 2800] loss G : 49.356 loss D : 52.687
[0 : 2900] loss G : 31.852 loss D : 570.363
[0 : 3000] loss G : 54.769 loss D : 382.479
[0 : 3100] loss G : 62.957 loss D : 491.729
[0 : 3200] loss G : 39.215 loss D : 37.412
[0 : 3300] loss G : 29.801 loss D : 215.652
[0 : 3400] loss G : 20.525 loss D : 27.800
[0 : 3500] loss G : 18.882 loss D : 338.726
[0 : 3600] loss G : 39.331 loss D : 128.357
[0 : 3700] loss G : -11.004 loss D : 93.745
[0 : 3800] loss G : 4.962 loss D : 205.661
[0 : 3900] loss G : 10.032 loss D : 187.112
[0 : 4000] loss G : 15.935 loss D : 11.016
[0 : 4100] loss G : 43.358 loss D : 183.713
[0 : 4200] loss G : 5.674 loss D : 5.614
[0 : 4300] loss G : -21.695 loss D : 285.515
[0 : 4400] loss G : 5.493 loss D : 9.029
6.4 測驗流程
見 五、快速開始
使用最終的預訓練模型 celeba_cropped_s5_i96000.pdparams 生成的影像如下:

七、實驗資料比較及復現心得

miniBatchSize
原文的實驗中,PGAN 的 batch_size 配置是 64,不是原始碼中默認設定的 16,batch_size = 16 的配置在論文中是在添加高解析度層之后才下調的(也起到降低顯存的效果),如果從頭到尾都使用 batch_size=16 會導致影像生成的效果不好,
但是我復現時沒有注意到此處,復現的 paddle 版本直接使用原始碼默認的 batch_size=16 進行訓練,發現顯存還剩余很多,于是改成 batch_size=32,發現開頭的 loss 變得很大,但是也很快收斂到穩定的 20 以內,訓練到 scale=5 時,PGAN 增加的高解析度層會導致 32 GB 的顯存爆滿,需要將 batch_size 下調至 16 或更小,
SWD metric
預測程序會在整個 celeba_cropped 資料集中隨機采樣 16000 張影像來預測并計算一個模型的不同 scale 下每對影像(輸入影像和對應的生成影像)的 SWD 指標,用同樣的模型每次計算得到的指標結果有所不同,如果把采樣數改成幾千或更少,SWD 的值會很大,但是采樣數在 16000 左右,SWD 就基本不變了,既然都是在訓練集中采樣的,模型應該是擬合了所有 20 多萬張頭像的資訊,為何采樣數量少的情況下 SWD 指標會變大,我暫時不明白,
MS-SSIM metric
由于源代碼沒有提供 MS-SSIM 的實作,我參考 GitHub 的開源 pytorch 版本 https://github.com/VainF/pytorch-msssim/blob/master/pytorch_msssim/ssim.py 來計算 MS-SSIM 指標,得到的結果跟論文中在 celeba 資料集上的測驗結果差不多,論文中說 SWD 指標能更好反映影像質量以及結構的差異和變化,而 MS-SSIM 只測量輸出之間的變化,不會反映生成影像和訓練集的差異,所以在生成影像發生了明顯改善后,MS-SSIM 指標也幾乎沒有變化,SWD 指標的結果變好了一點,
生成效果
論文中說明在規定的迭代次數內網路并沒有完全收斂,而是達到指定迭代次數后就停止訓練,所以生成的影像還不夠完美,如果想要生成更完美的影像,那得再等上好幾天?
API 轉換
將 pytorch 版本代碼轉為 paddle 有些 API 在 paddle 中是沒有的,但是 numpy 里是肯定都有的 😄,找不到的 API 用 numpy 來搭個橋,這是很不錯的復現辦法,
八、模型資訊
| 資訊 | 說明 |
|---|---|
| 發布者 | 絕絕子 |
| 時間 | 2021.09 |
| 框架版本 | paddlepaddle 0.0.0 (develop 版本) |
| 應用場景 | GAN 影像生成 |
| 支持硬體 | GPU、CPU(RAM >= 16 GB) |
| CELEBA資料集下載 | CELEBA |
| AI Studio 地址 | https://aistudio.baidu.com/aistudio/projectdetail/2351963 |
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301624.html
標籤:其他
上一篇:OpenCV-美食—鮮美濾鏡
下一篇:OpenCV-影像色溫
