1. Traing/Test Dataset
http://people.rennes.inria.fr/Aline.Roumy/results/SR_BMVC12.html
https://github.com/jbhuang0604/SelfExSR
http://vllab.ucmerced.edu/wlai24/LapSRN/
Taining data
91(ScSR)
General-100(FSRCNN)
BSD300(IDN)
DIV2K(NTIRE)
Test data
Set-5
Set-14
Urban-100(LapSRN)
BSD-100
Sun-Hays-80
Manga-109(LapSRN)
2. Benchmark使用的基本说明
IvoryCandy/super-resolution: collection of super-resolution models & algorithms
这个Github项目提供了一个很好的sr benchmark框架基于pytorch,我们要做的是两件事情
- 这个benchmark框架对每个网络规定了哪些不同的做法(model.py/solver.py), 就是除了网络结构不同还可以有哪些不同
- 新的网络加入到这个benchmark里需要注意哪些入参方便benchmark平台调用
Note
① How to add a new model
在benchmark中加入一个新网络主要是要添加属于这个网络的model.py和solver.py, 和caffe的两个protxt作用一样.
model.py用来定义模型结构, model.py主要就是一个从torch.nn.Module继承的类Net, 就是pytorch通常的做法, 包括一个_init_()函数(定义网络包含的模块)和一个forward()函数, 用来定义网络前向传播的路径, 可能会有weight_init()函数, 用来定义参数初始化方式的, 这个函数不一定要在这里定义, 在solver.py中定义也可以;
solver.py用来定义train和val过程, 基本上也是程式化的, 主要是用build_model()来建立模型, 规定optimizer, loss_function等, 然后在train()和test()函数中分别定义一个epoch的训练过程
也就是说不同网络可以定义不同的结构和不同的训练方法
② What is bench's work?
bench在更高一层要完成的主要是一下几件事情
* 处理数据, 得到training_data_loader和testing_data_loader(./dataset)
Todo
: dataset需要整理一下h5 in和folder in接口, 做成参数控制
* 统计参数量和计算量(./model_statistics)
Todo
: 这部分现在还是独立在整个框架之外的, 需要加入到框架里面去, 并且做成参数控制, 并且统计参数量和计算量目前没有把deconvolution结构计进去, 这部分随后要加上
* 测试集批处理(./test_bench.py), 这个主要是在训练结束后用来在特定测试集上比较模型performance的, 应该是将测试集同一放到./dataset/Test中, 然后分测试集放在不同的子文件夹中, 测试时直接读取文件夹信息, 然后分别来统计各子文件夹的performance的平均
Todo
: 和统计参数量和计算量一样, 这部分功能也要整理到主框架里去, 用参数-train和-test把训练和测试的流程分开, 并且最好可以指定输出结果的路径, 比如指定路径为./results/0822/, 那就会在这个路径下再分别生成对应着不同测试集的folder, 然后各测试集结果就存在对应folder里面
3. Data Preparing
构建数据集的过程是深度学习重要的一环, 因为神经网络本身是数据驱动模型, 数据集质量的高低很大程度上会影响最终的结果
SR的训练数据集图像大小是不同的(比如Yang91+BSD200这种混合数据集), 那就存在这如何把图像大小统一的问题, IDN_pytorch用的是统一resize的方法, IDN_caffe(source code of paper)用的是crop的方法, 还有如何crop, 做什么程度的data augmentation问题等等, 下面就从几个check点来比较一下如何获得更好的训练效果(以FSRCNN为例)
3.1 中心crop和随机crop
在IDN给的源码里, 数据处理的方式是从原图中crop出需要的input大小, 而且是能crop多少就crop多少出来, 但是matlab
代码中没有加越界保护, 很容易就跑崩了, 而且这样生成的数据也太多, 本身前面就加了data augmentation了, 所以我就想从一张图中crop一个input出来就可以了
center_crop: train_x4_center_32_a8.h5
rand_crop: train_x4_rand_32_a8.h5
Parameter list
Para | Value |
---|---|
Training set | BSD200+Yang90, flip+rotate(8x augmentation) |
How to get Training set | IDN matlab, crop input to 32x32 |
Validation set | BSD100 |
How to get Validation set | pytorch, resize input to 64x64 |
upscale factor | 4 |
Epochs | 400 |
batch size | 32 |
lr policy | MultiStepLR, milestones=[200, 500, 1000, 1500], gamma=0.5 |
Pytorch lr_scheduler
Training result
PSNR | Loss | |
---|---|---|
center crop, lr=1e-4(UL) | 24.1 | 4.0e-3 |
center crop, lr=1e-5(DL) | 24.0 | 4.0e-3 |
random crop, lr=1e-4(UR) | 18.85 | 3.4e-3 |
random crop, lr=1e-5(DR) | 18.9 | 3.4e-3 |
在这个check点里面, 我顺便夹带了一点私货, 把lr在这儿也比较了, 先说center crop和random crop
首先, random的crop的结果
从结果看, random crop最终的loss要低于center crop, 但是validation set的performance明显低很多, 而且从图上看, random crop出现了明显的overfitting, 在十几个epoch之后, validation set的PSNR就不升反降了, 这个现象和之前碰到的input和label没对齐的情况很类似, 需要check一下获取的inpu和label是否正确
然后, 再看一下初始learning rate的对比, 拿center crop来看, 1e-4的初始学习率有点稍大, 因为后期明显振荡比较严重, 但是validation set的PSNR却是1e-4稍大一点, 这样看, 初始学习率设到1e-5更合理一点, 让Epochs更多一点应该可以获得和1e-4初始学习率差不多的最终效果
3.2 40x augmentation vs. 8x augmentation
40x augmentation是IDN caffe(source code of paper)的做法, 就是4种rotation(0/90/180/280)+mirror+5种缩放(1.0/0.9/0.8/0.7/0.6), 一张图产生40张图(train_x4_center_32_a40.h5
).
8x augmentation是IDN pytorch的做法, 就是4种rotation(0/90/180/280)+mirror, 一张图产生8张图(train_x4_center_32_a8.h5
).
Parameter list
Para | Value |
---|---|
Training set | BSD200+Yang90 |
How to get Training set | IDN matlab, center crop input to 32x32 |
Validation set | BSD100 |
How to get Validation set | pytorch, resize input to 64x64 |
upscale factor | 4 |
Epochs | 400 |
batch size | 32 |
lr policy | MultiStepLR, milestones=[200, 500, 1000, 1500], gamma=0.5 |
initial learning rate | 1e-5 |
Training result
PSNR | Loss | |
---|---|---|
8x augmentation(Left) | 24.0 | 4.0e-3 |
40x augmentation(Right) | 24.2 | 3.9e-3 |
因为40x aug训练太慢, 就只跑了200 epochs, 40x aug明显好与8x aug, 200 epochs就已经达到validataion PSNR=24.2, 而8x aug到400 epochs validation PSNR=24.0, 但是40x aug一个batch的数据量是8x aug的5倍, 也就是说, 相同的epoch, 40x 训练看过的数据要比8x多, 我们看下到达饱和期的时间, 40x aug大概是在40 epochs, 8x aug是在200 epochs, 而且40x aug的训练cost太大, 23s/epoch, 而8x aug是2s, 这个差的太多了, 所以并没有看出40x aug明显的优势, 还是用8x aug
但是, 这也和所用的模型有关, FSRCNN可能模型结构太简单, 用更多的数据训练也体现不出优势, 复杂模型用40x aug可能会有更大的收益, 这个可以在周末跑试一下
3.3 64x64 in vs 32x32 in
32x32 in是送入训练的图像是32x32大小.
64x64 in是送入训练的图像是64x64大小
Parameter list
Para | Value |
---|---|
Training set | BSD200+Yang90, flip+rotate(8x augmentation) |
How to get Training set | IDN matlab, center crop input to ? |
Validation set | BSD100 |
How to get Validation set | pytorch, resize input to 64x64 |
upscale factor | 4 |
Epochs | 400 |
batch size | 32 |
lr policy | MultiStepLR, milestones=[200, 500, 1000, 1500], gamma=0.5 |
initial learning rate | 1e-5 |
Training result
PSNR | Loss | |
---|---|---|
64x64 in(Left) | 24.2 | 3.4e-3 |
32x32 in(Right) | 24.0 | 4.0e-3 |
64x64 input获得的收益和40x augmentation差不多, 但是速度更快, 用h5的方式读入training set, 速度和32x32差不多, 都是2s/epoch左右, 所以将input从32->64还是很划算的
3.4 h5(gen by Matlab) vs. folder(gen by pytorch)
h5是用IDN caffe(source code of paper)的代码产生的, 之前的实验证明, pytorch和matlab处理的resize和rgb->ycbcr转换的结果有不同, 可能对结果产生影响
Parameter list
Para | Value |
---|---|
Training set | BSD200+Yang90, flip+rotate(8x augmentation) |
How to get Training set | IDN matlab, center crop 64x64 pytorch, center crop 64x64 |
Validation set | BSD100 |
How to get Validation set | pytorch, resize input to 64x64 |
upscale factor | 4 |
Epochs | 400 |
batch size | 32 |
lr policy | MultiStepLR, milestones=[200, 500, 1000, 1500], gamma=0.5 |
initial learning rate | 1e-5 |
Training result
PSNR | Loss | |
---|---|---|
IDN matlab(UL) 64x64 | 24.2 | 3.4e-3 |
Pytorch 64x64(DR) | 24.26 | 4.4e-3 |
Pytorch 32x32(DL) | 24.28 | 5.1e-3 |
Pytorch 32x32 lr=1e-4(UR) | 24.55 | 4.8e-3 |
从400epochs训练的结果看, 用Matlab生成的h5和pytorch自己datasetfromFolder的差异不太大, pytorch 64x64 in 最终的loss在4.4e-3, PSNR和matlab的一样, 但是值得注意的是达到同样的PSNR pytorch的loss还没有降到和IDN一样的水准, 如果继续训练降低loss pytorch的方式应该可以比matlab in的方式有更大收益
还有一个问题, 就是在Pytorch的方式下, 32x32是否和64x64有在Matlab下一样的差异, 也就是说pytorch的这个收益, 是因为pytorch带来的, 还是64x64 input带来的. 从上面的图看得出来, 实际上收益是pytorch带来的, 因为用32x32 in得到的结果甚至比64x64的结果更好一些(loss 5.1e-3达到PSNR=24.28), 并且用32x32能够更快, 基本上是4.5s/epoch, 但是如何还原到08/19的表现, 就是在500epochs就能达到24.5的PSNR?
主要的差异在learning rate, 08/19那天learning rate: 1e-4, 并且在500 epochs之前, 没有降低过learning rate(图中的UR), 所以, 问题就是不能过早地降低学习率, 导致学不动, 就进入饱和区了
从以上的信息我们可以得到最佳的数据配置, 32x32+pytorch+1e-4 initial lr+8x augmentation+ center crop, 为了提高performance, 我们将Yang91数据集中大于128x128的数据也作为训练集加入
4. Training Log
Model | Params(K) | FLOPs(G) output_size=[224, 224] | running time(32x32, batch_size=32) | PSNR | Description |
---|---|---|---|---|---|
FSRCNN | 13 | 0.03 | 40ms | 24.74 | 原始FSRCNN架构, LR in |
C1SRCNN | 10 | 0.51(baseline) | 100ms | 24.64 | FSRCNN架构, MR(cheap upscale) in, no deconvolution |
C2SRCNN | 10 | 0.51(100%) | 100ms | 24.75 | C1SRCNN + Residual Learning |
C3SRCNN | 14 | 0.71(139%) | 246ms | 24.79 | C2SRCNN + Inverted Residual Block |
C4SRCNN | 6 | 0.35(68%) | 276ms | 24.80 | C3SRCNN + Group 1x1/ShuffleNetV1, 1x1 group=4 |
C5SRCNN | 6 | 0.33(64%) | 176ms | 24.84 | C3SRCNN + ShuffleNetV2 |
C6SRCNN | 5 | 0.29(56%) | 306ms | 24.78 | C4SRCNN, 1x1 group=8 |
C7SRCNN | 5 | 0.26(50%) | 322ms | 24.71 | C4SRCNN, 1x1 group=16 |
C8SRCNN | 4 | 0.24(47%) | 334ms | 24.70 | C7SRCNN, 将map中间两个block的3x3->1x3+3x1 |
C9SRCNN | 11 | 0.6(117%) | 220ms | 24.69 | 去掉C3SRCNN的shrink unit |
C10SRCNN | 5 | 0.29(56%) | 243ms | 24.69 | 去掉C4SRCNN的shrink unit |
C11SRCNN | 4 | 0.22(43%) | 147ms | 24.75 | 去掉C5SRCNN的shrink unit |
C12SRCNN | 13 | 0.70(137%) | 257ms | 24.83 | 将C3SRCNN map的中间两个block的3x3->1x3+3x1 |
C13SRCNN | 6 | 0.33(65%) | 285ms | 将C4SRCNN map的中间两个block的3x3->1x3+3x1 |
5. PQ Check
5.1 Database Set29(Y)
00_idx0
01_idx0
01_idx2
04_idx0
08_idx1
16_idx0
21_idx0
23_idx3
28_idx0
5.2 PQ check form
Issue | Description |
---|---|
看Stucture | |
jaggy | 锯齿, 如果是视频播放在边的地方会出现闪烁, 比如00_idx0中的"I"的边缘 |
overshoot | 过冲, 就是大的strcuture经过高通或者bicubic后旁边出现的伪影, 或者叫ghost |
ringing | 边缘旁边出现的重复并逐渐减弱的伪影 |
断线 | 有些大角度变化的结构上会出现线断开的情况, 比如00_idx0中的"S""M"的拐角 |
看Detail | |
overfitting | 过度拟合, 主要是看detail的时候, 感觉画面拟合过重, 缺少颗粒感, 过于平滑, 自然场景看起来假 |
crisp | 强边缘的地方要过渡够快, 就是线要细, 感觉边缘很脆 |
5.3 PQ check log(0905)
Issue | Description |
---|---|
00_idx0 | C1~C12/FSRCNN, C4整体更好, overshoot和ringing更轻, 整体看着更干净, 线也更细, 但是在"I"的边缘有jaggy, "M""S"的地方会有线断开, 1x1加组而言, C6和C3效果差不多, C4/C6/C7比, C6效果比较差 |
01_idx0 | golden看着更脏, 边角出现的白块叫什么? |
01_idx2 | C3SRCNN有轻微overfitting, 多看几张细节图, 比如16_idx悬崖, 其实C1~C12/FSRCNN确实在detail上差异不大, 不同的地方可以overfitting的情况不一样, 有些这个有有些另外的模型有 |
04_idx0 | overfitting和ringing大家的情况差不多 |
08_idx1 | 线的差别很明显, C4/C5最细, |
16_idx0 | detail的差异不太大, 基本上是各有好坏, 可能是在某个位置某个模型detail更好, 但是别的地方overfitting又比较重, 但是都不太明显, 基本上可以认为detail各模型的差异不大, 但是与golden比还是比较明显, golden感觉细节更丰富一些 |
21_idx0 | C4的线更细一些, 但是在detail的地方这种太sharp又会看着比较假 |
23_idx3 | detail上, 看不出太明显的差别 |
28_idx0 | 在小猫头上那个细线, 就是自然的线来说, golden明显更细, 其他模型看不出明显差别 |
整体上说, 论structure, C4在众多比较模型中是最好的, 线也细, artifact也少, 但是偶尔会有断线(00_idx, "S")或者jaggy(00_idx, "I"), 论detail, 说实话C1~C12包括FSRCNN都看不出太明显的差别, 基本算是属于同一个水平上, 和golden的差异在detail上明显