这是一篇被CVPR2019收录的论文,论文名称:《Deep Network Interpolation for Continuous Imagery Effect Transition》
作者:由xintao大佬一作,Yu Ke, Dong Chao, XIaoou Tang(汤老师), Chen Change Loy(吕老师)
商汤出品,必属精品。
项目主页: https://github.com/xinntao/DNI
文章主旨
深度卷积网络在学习一个特定的映射上表现出了很强的能力,然而由于用户群和目标的变化,会想要得到一些连续的输出变化。跟现存的方法只能一对一映射不同(比如风格迁移),本文提出了一种有效且通用的方法来获取对目标图像的效果控制。本文将将该方法称之为Deep Network Interpolation, 一种通过对网络参数的插值来控制输出的连续性变化的方法。
Deep Network Interpolation (DNI)参数插值
很多low-level的视觉任务都是一种图像到另一种图像之间的迁移,比如说图像修复, 图像风格迁移。深度卷积网络可以很好的直接学习源图像 x x x到目标图像 y y y的映射, y = G θ ( x ) y=G_{\theta}(x) y=Gθ(x)。
那么考虑两个完全相同的网络 G A G^A GA和 G B G^B GB, 分别实现了两种不同映射效果A和B效果。在这里,作者进行假设两个网络的参数 θ A \theta_A θA和 θ B \theta_B θB存在着强相关的关系,这就意味这网络A的卷积层所学习到的filters与网络B的卷积层所学习到的filters存在相同的pattern。只有在这个前提下,DNI方法才会起作用。
这里注意:两个网络在插值的过程中,对应卷积层所学习到的filters必须是强相关的,如果是非相关的化,DNI将不适用。那么如何使得卷积层的卷积核是强相关的,这可以通过finetune来实现。
上图
在满足上述前提下,我们已经有了两个相同网络结果的网络A和网络B,分别实现了效果A和效果B。那么我们可以采取本文的方法,在网络A和网络B之间进行参数插值,对于我们想要得到的在效果A和效果B之间连续变化的网络,其参数可以由下式获得:
θ
i
n
t
e
r
p
=
α
θ
A
+
(
1
−
α
)
θ
B
\theta_{interp} = \alpha \theta_{A} + (1 - \alpha) \theta_{B}
θinterp=αθA+(1−α)θB
其中
α
\alpha
α 在0-1之间。通过平滑的调整参数alpha,我们可以获得非常连续的变化。
一般的,对于N个模型来说,
G
1
G^1
G1,
G
2
G^2
G2,
G
3
G^3
G3,…
G
N
G^N
GN,那么对于一个插值模型可以由以下获得
θ
i
n
t
e
r
p
=
α
1
θ
A
+
α
2
θ
A
+
.
.
.
+
α
N
θ
N
\theta_{interp} = \alpha_{1} \theta_{A} + \alpha_{2} \theta_{A} +...+ \alpha_{N} \theta_{N}
θinterp=α1θA+α2θA+...+αNθN
参数插值是需要执行在所以卷积层上的所有参数上,包括卷积层和normalization layer
关于实现代码
pytorch
作者提供了一种pytorch的实现方式:
alpha = 0.3 # interpolation coefficient
net_A = torch.load('path_to_net_A.pth')
net_B = torch.load('path_to_net_B.pth')
net_interp = OrderedDict()
for k, v_A in net_A.items():
v_B = net_B[k]
net_interp[k] = alpha * v_A + (1 - alpha) * v_B
tensorflow
我在这里实现了一种tensorflow的实现方式,由于tensorflow的checkpoint不像pytorch那样灵活,因此可以将模型用npz文件进行存储。
modelA = "xxxxA.npz"
modelB = "xxxxB.npz" # GAN model
paramsA = np.load(modelA)['params']
paramsB = np.load(modelB)['params']
alpha = 0.7
saveModel = 'xxxxInterp.npz'
net_interp = []
for idx, varA in enumerate(paramsA):
varB = paramsB[idx]
net_interp.append(alpha*varA + (1-alpha)*varB)
np.savez(saveModel, params=net_interp)
这里提供将模型存储成npz的tensorflow实现:
def save_tfmodel_npy(save_list=None, name='model.npz', sess=None):
print("Saving TF params into numpy format...")
if save_list is None:
save_list = []
save_list_var = []
if sess:
save_list_var = sess.run(save_list)
else:
try:
save_list_var.extend([v.eval() for v in save_list])
except Exception:
print("Save Error!!!")
np.savez(name, params=save_list_var)
save_list_var = None
del save_list_var
将npz模型load到tensorflow的实现:
def load_tfmodel_npy(sess, modelpath, varlist):
d = np.load(modelpath)
params = d['params']
ops = []
for idx, param in enumerate(params):
ops.append(varlist[idx].assign(param))
if sess is not None:
sess.run(ops)
return ops