原文地址:Accelerating the Super-Resolution Convolutional Neural Network
SRCNN:超分辨网络SRCNN的Pytorch实现
概述
FSRCNN,即Fast SRCNN,可见这个算法和SRCNN相比应该是在速度上做了优化。
在训练模型的过程中,SRCNN需要先将LR(低分辨率)图片通过双三次插值,变成HR(高分辨率)图片,这个过程随着放大倍数变大而变得十分耗时。
FSRCNN正是着眼于此,取消了双三次插值,代之以
5
×
5
5\times5
5×5的卷积层。剩下的都是常规的加速操作,比如压缩特征层维度、用多层
3
×
3
3\times3
3×3卷积核代替单层
9
×
9
9\times9
9×9卷积。
其激活函数为PReLU,其表达式为
f
(
x
)
=
max
?
(
0
,
x
)
+
a
?
min
?
(
0
,
x
)
f(x)=\max(0,x)+a*\min(0,x)
f(x)=max(0,x)+a?min(0,x)
当
a
=
0
a=0
a=0时,PReLU就退化为ReLU。
代价函数和SRCNN相同,皆为均方误差。设
X
X
X为原图,
Y
Y
Y为LR图像,
F
(
Y
)
F(Y)
F(Y)为模型输出的图像,则其损失为
L
(
θ
)
=
1
n
∑
i
=
1
n
∥
F
(
Y
i
;
θ
)
?
X
i
∥
2
L(\theta)=\frac{1}{n}\sum^n_{i=1}\Vert F(Y_i;\theta)-X_i\Vert^2
L(θ)=n1?i=1∑n?∥F(Yi?;θ)?Xi?∥2
网络模型
由于没有了插值过程,所以FSRCNN要比SRCNN更加存粹,只需一个神经网络就可以跑完流程,其模型分为5步:
- 特征提取:通过
5
×
5
5\times5
5×5的卷积核,将1层数据转为
d
d
d层。
- 降维(shrinking):将
d
d
d层数据,通过
1
×
1
1\times1
1×1的卷积核降为
s
s
s层,
s
?
d
s\leqslant d
s?d。
- 匹配(Mapping):用
3
×
3
3\times3
3×3的卷积核,将
s
s
s层数据再卷成
s
s
s层。
- 放大(Expanding):用
1
×
1
1\times1
1×1的卷积核,将
s
s
s层数据在展回
d
d
d层。
- 反卷积:通过
9
×
9
9\times9
9×9的卷积核,将
s
s
s层数据卷回1层。
所以,第一步是
5
×
5
5\times5
5×5卷积核,以及卷积之后的PReLU计算,
import math
from torch import nn
def normNN(N, d, k, p=0):
NN = nn.Conv2d(N, d, kernel_size=k, padding=p)
std = math.sqrt(2/d/NN.weight.data[0][0].numel())
nn.init.normal_(NN.weight.data, mean=0.0, std=std)
nn.init.zeros_(NN.bias.data)
return NN
class FSRCNN(nn.Module):
def __init__(self, scale_factor,
N=1, d=56, s=12, m=4):
super(FSRCNN, self).__init__()
nns = [normNN(N, d, 5, 5//2), nn.PReLU(d)]
nns += [normNN(d, s, 1), nn.PReLU(s)]
for _ in range(m):
nns += [normNN(s, s, 3, 3//2), nn.PReLU(s)]
nns += [nn.Conv2d(s, d, 1), nn.PReLU(d)]
self.NN1 = nn.Sequential(*nns)
self.NN2 = nn.ConvTranspose2d(d, N, 9, scale_factor,
9//2, output_padding=scale_factor-1)
nn.init.normal_(self.NN2.weight.data,
mean=0.0, std=0.001)
nn.init.zeros_(self.NN2.bias.data)
def forward(self, x):
x = self.NN1(x)
x = self.NN2(x)
return x
其中,nn.init.normal_ 可通过给定均值和标准差,生成正态分布,填充输入的变量。
最终效果为
|