超越fast style transfer----任意风格图和内容图0.1秒出结果

如果不知道风格转换的,移步 http://blog.csdn.net/hungryof/article/details/53981959 ,瞄上一眼再回来。

1. 以前风格转换速度之尴尬

如果从得到效果图速度来分的话,可以分为三个阶段。

阶段一

最初的用神经网络实现的风格转换是需要不断迭代的,不仅速度慢,而且我要在A图加上B图的风格,就需要分别根据这两幅图进行不断前反向传播,更新输入,效率实在太低。称之为style transfer

阶段二

后来人们就想能不能直接一个前向传播搞定啊~,然后他们想出了,先训练一个 G , 这个 G 可以让输入 I 通过 G 后得到的 G(I) 是A图加上B图的风格。这个方法还是有很大的问题,那就是我训练的G必须是同一种风格,一般就用一幅风格图B,然后用很多的内容图,不断优化训练G, 最终G有啥用啊,只是“B风格的滤镜”罢了。那我要很多种风格呢?我就要训练很多很多的G,那挺尴尬的。. 代表论文是是 http://blog.csdn.net/hungryof/article/details/53981959 中提到的 Texture Networks: Feed-forward Synthesis of Textures and Stylized Images 和 Perceptual Losses for Real-Time Style Transfer and Super-Resolution . 这也就是网上经常说的 fast style transfer.

阶段三

大家就想,我怎么直接输入任意A和B,一次前向出来呢?如果能成功,那么速度就不需要考虑了,因为已经到达顶峰了。
style-swap 就是第三阶段的开始。
0.1秒出结果。
这里写图片描述

2. Style-swap的魅力

超越fast style transfer----任意风格图和内容图0.1秒出结果_第1张图片
超越fast style transfer----任意风格图和内容图0.1秒出结果_第2张图片

效果还是挺不错的嘛~~再放几张。。

超越fast style transfer----任意风格图和内容图0.1秒出结果_第3张图片

超越fast style transfer----任意风格图和内容图0.1秒出结果_第4张图片

用上面素描画形成的效果:

超越fast style transfer----任意风格图和内容图0.1秒出结果_第5张图片

超越fast style transfer----任意风格图和内容图0.1秒出结果_第6张图片
别问这人是谁,一个好友的qq头像,有较多的纹理,就直接拿过来试了试效果。。

3. style-swap浅谈

论文分为2个部分,第一部分就是常规的迭代方式,第二个是将常规的改成一次前向的方法。

3.1 style-swap的新方法

以前不都是认为Gram操作就是相当于“风格”的一种表示嘛,他们认为,如果我要得到C图的内容加上S图的风格,那么我希望我的网络输入 I 在高维度特征 ϕ(I) (一般用VGG19的某一层的相应的输出,作为 I 的高维特征)与C图的高维特征 ϕ(C) 尽量一样,同时希望 ϕ(I) 进行Gram计算后得到的 G(ϕ(I)) G(ϕ(S)) 尽量一样。为什么要用Gram矩阵呢?是否有必要?这些都不知道。
后来Chuan Li的 Combining Markov Random Fields and Convolutional Neural Networks for
Image Synthesis将Style loss改成了MRFs Loss Function,依旧保留content loss。这篇论文第一部分工作其实就单纯用第一种loss了,舍弃了content loss。 这篇论文的详细讲了计算这种Loss的高效方法。这篇论文的主要贡献还是第二部分工作,引入了Inverse Net,这使得一次前向传播得到的特征图成为可能。

3.2 实现方法

C S 分别代表内容图和风格图, ϕ() 代表预训练网络(一般VGG19)的前部分网络。 ϕ(C) 就是 C 传入网络中在某一层出来的特征。

  1. 先提取一系列块 ϕi(C) ϕj(S) 。其中 inc , jns ,其中 nc ns 分别是能从 ϕi(C) ϕj(S) 抽取的块数。
  2. 对于每块 ϕi(C) ,我们希望选择其最近的style 块 ϕj(S) , 称之为 ϕssi(C,S) .
    ϕssi(C,S):=ARGMAXϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕi(C)||||ϕj(S)||
  3. 这步称之为重建 Φss(C,S) 。这时候我们只需要平均一下那些重叠区域的值就行了。这样就可以得到 Φss(C,S) ,称之为 Φss(C,S) 的重建。

因此总的优化目标是:

Istylized(C,S)=ARGMINIRh×w×d||Φ(I)Φss(C,S)||2F+λTV(I)

3.3 高效方法

这里可能会写的比较啰嗦。。因为要讲的很明白,确实需要啰嗦点。。为了简便,提取的块spatial size就3x3吧, relu3_1层是256个通道。下面的三步统称为style-swap.

3.3.1 实现方法的第一二步解释

先看看3.2节实现方法的第一二步干啥:

ϕssi(C,S):=ARGMAXϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕi(C)||||ϕj(S)||

对于每一块 ϕi(C) ,从 ns ϕj(S) 中找到与其最匹配的块,称之为 ϕssi(C,S) 。最终我们可以找到 nc ϕssi(C,S)
可以发现 <ϕi(C),ϕj(S)> 是相关操作,也是卷积网络中说的卷积,对于某一块 ϕi(C) ,其和 ns 块分别进行相关,不就是将这 ns 块看成 ns 个卷积核,每个卷积核就是 ϕj(S) (大小是 256×3×3 )。输入是 ϕi(C) , 最终输出是 ϕi(C) ns 个卷积核卷积后的输出,大小为 ns×1×1 。总共有 nc ϕi(C) ,恰恰对应这卷积核在 Φ(C) 上的位置的所有情况,就是卷积核在 Φ(C) 上的卷积操作的移动恰恰就能满足这样。

3.3.2 高效方法的第一步

结论: Φ(C) 作为输入, ns ϕj(S)ϕj(S) 作为卷积核( ns×256×3×3 )。得到的输出就是所有的 i=1,,nc ϕi(C) 所对应的

ϕj(S),j=1,,ns<ϕi(C),ϕj(S)>||ϕj(S)||

论文的写法更为简便:
Ka,b,j=ϕa,b(C),ϕj(S)ϕi(S)

输出的大小为: ns×w×h , 显然 w×h 等于 nc 。为了计算速度,省略了 ϕi(C) , 因为这不会影响取哪一个最近style块。
该步称之为 swap_enc

3.3.3 高效方法的第二步

第一步得到的输出 O 到底是什么?记 Oa,b O 中以 (a,b) 为中心点的 ns *1*1大小的输出张量,那么 Oa,b,j ϕa,b(C) ϕj(S) 的卷积的值。因此我们对于每个位置 (a,b) 如果第 j 个通道的值是 ns 个值中最大的,将该位置记为1,其他 ns1 个通道记为0. 这样就选出了块 ϕi(C) 对应的最匹配的块 ϕj(S) j 值!

K¯¯¯a,b,j={1,0,if j=argmaxjKa,b,j otherwise

没错,第二步就是 通道最大值记录为1,其余为0
实现结束高效方法的第一第二步,我们要的就是 K¯¯¯
该步称之为 Maxcoord

3.3.4 高效方法的第三步

K¯¯¯ 作为输入,将 ϕj(S) 作为反卷积核。显然反卷积核与刚才的一样,也是 ns×256×3×3
对于每个位置 (a,b) , 只有最匹配的style块才会输出,其他的块都被乘上了0!此时就可以得到 ϕssa,b(C,S) ,比如与 ϕ10,10(C) 相关程度最大的块是第200块,即 max{O10,10,j} 的值为 O10,10,200 ,得到 K¯¯¯10,10,200=1 , 同时 K¯¯¯10,10,j=0,j200 K¯¯¯10,10,j ϕ(S) 反卷积,此时可以提取出 ϕssa,b(C,S) ,就是 ϕ200(S) 。直到这里我们才弄好了所有的 ϕssa,b(C,S) , 反卷积后这些 ϕssa,b(C,S) 是重叠的,重叠部分取平均即可。
此时才真正得到 Φss(C,S)
这一步称之为swap_dec

4. 训练Inverse网络

这是第二部分内容,是核心部分。回忆第一部分的优化目标:

Istylized(C,S)=ARGMINIRh×w×d||Φ(I)Φss(C,S)||2F+λTV(I)

我们希望该Inverse网络 f 无论对于任何输入 H (这些输入包括 Φ(C) 或是 Φ(S) 或是 Φss(C,S) ), 我们都能使得f(H)能得到 Istylized(C,S) 。 即 Φ(f(H)) H 尽量一样。因此有:
arginff=EH[Φ(f(H))H2F+λ(f(H))]

值得注意的是,如果我们训练好Inverse网络,称之为decoder, 然后进行前向传播是,首先是 Φ(C) 经过style-swap结构后得到 Φss(C,S) ,再输入到decoder中,即可得到 Iˆstylized(C,S)

至此, 彻底完成一次前向传播出结果的目标!!!!!

4.1 训练时代码的细节

在训练时,

Enc(4,256,64,64)latent_beforeswapLoss(8,256,64,64)latent_after(8,256,64,64)recons_latentdec(8,3,256,256)recons_inputEnc

比如我一下子输入2个content图和2个style图,然后latent_before是(4, 256, 64, 64),经过swap结构,得到latent_after是(8,256,64,64)。注意的是latent_after的前4个仍旧是latent_before, 而后4个是 Φss(C,S) 。更加准确的说:
latent_before[1]和latent_before[2]是 Φ(C1)Φ(C2) ,而latent_before[3]和latent_before[4]是 Φ(S1)Φ(S2) 。 然后传入swap中,得到latent_after,latent_after[1:4]与latent-before一致,latent_after[5:8]分别为 Φ(C1,S1),Φ(C1,S2),Φ(C2,S1),Φ(C2,S2) 。得到的Loss是MSE(latent_after, recons_latent)。具体的含义见下图

Enc[Φ(C),Φ(S)]swapLoss[Φ(C),Φ(S),Φss(C,S)][Φ(f(Φ(C))),Φ(f(Φ(S))),Φ(f(Φss(C,S)))]Dec[f(Φ(C)),f(Φ(S)),f(Φss(C,S))]Enc

因此我们当然是希望 Φ(f(Φ(C))) Φ(C) 尽量接近, Φ(f(Φ(S))) Φ(S) 尽量接近, Φ(f(Φss(C,S)) Φss(C,S) 尽量接近,这样才能实现对于 Φ 的反转!

为什么是用 [Φ(C),Φ(S),Φ(C,S)] [Φ(f(Φ(C))),Φ(f(Φ(S))),Φ(f(Φss(C,S)))] 进行求Loss,再反向传播呢?

为了方便,直接说为什么是用 Φ(C,S) Φ(f(Φss(C,S))) 。其实我们希望优化Dec,那么最好是希望 f(Φ(C,S)) C 在高层语义上尽量一样。高层语义自然要将 f(Φ(C,S)) C 进行升维,所以把 f(Φ(C,S)) 再次输入到 Φ 中,与 Φ(C) 相比,用MSE就行了。
其实这种思想和fast neural style是类似的,或是可以看成是fast neural style的升级版本。fast neural style使用 G 网络生成 G(x) ,使用 D 网络提供Loss形式。希望在高层语义特征上 D(G(x)) D(C) 尽量接近,同时希望在高层语义上 Gram(D(G(x))) Gram(D(S)) 尽量接近。那么style-swap也是如此。Enc就是D,而Dec就是G。不过更加准确的说Dec不仅仅是G,而是G的升级版,因为以前的G只是针对一种style进行训练,而这里的Dec是针对大量的style一起训练。

附录:
Fast Patch-based Style Transfer of Arbitrary Style

你可能感兴趣的:(Paper,Reading,深度学习论文阅读)