会持续更新

文章阅读

详见[CVPR2022] CLIPstyler: Image Style Transfer with a Single Text Condition

问题梳理

这篇文章的方法存在一个比较明显的问题,就是对于一条文本,如果想获得其描述的风格的图像,需要使用这条文本训练一个新的模型,也就是说对于训练出的每一个模型,只能赋予图像一种风格,所以我们考虑能否只使用一个模型来达到该方法中多个模型的效果

我们最终想要实现的最完美的结果是,训练一个模型,输入一张图片和一条文本,模型就能给图片赋予对应文本的风格

研究过程

2022.07.12

初步思考的解决方法

看过StarGAN后,我想出了一个初步的pipeline,尝试解决这个问题

经过一些实验,我感觉目前主要存在两个问题

Loss问题

我认为CLIPStyle所使用的loss是有问题的,对此我进行了一些实验,文中使用的loss主要有两个,分别是整张图片编码到CLIP空间后,与文本编码计算余弦相似度,以及对图片先进行裁剪,再对patch分别编码到CLIP空间计算余弦相似度

我尝试去掉patch loss,发现效果确实不好,而且远不如从前,左边为有patch loss,右边为无

原图

观察发现风格几乎没有改变,这点很奇怪,因为不知道patch loss为什么会起作用,为什么整张图片的余弦相似度不起作用,换成每个patch却会有效果,因为余弦相似度只要求共线,而不要求长度

所以感觉他这个方法能起作用有很大的运气成分在里面,patch loss也不是一个很有效的loss,只是恰好能在他所使用的网络上有效,而且他的网络换成其他的网络,获得的结果效果也并不是很好

网络问题

他给出的代码有两种,一个是类似优化方法,网络ff只生成一张图片,然后通过loss逐渐将图片优化到指定的风格,另一种就是训练网络ff,让他具有转换风格的功能

这两种方法分别使用了不同的网络,第一种使用的是UNet,第二种用了预训练的VGG19,现在有个问题就是,如果想要达到我们的效果,我们需要在第二种的网络上进行修改,而在训练过程中,他定住了VGG19的encoder只优化decoder,而且预训练的网络很难进行输入上的修改

我尝试将StarGAN的生成器拿过来使用,但是并没有生成正常的图片,毕竟StarGAN是GAN,而我们这个方法里并没有判别器

我同样尝试使用UNet进行训练,并提高他的深度,但是效果也不是很好,如下图,而且结果类似于上述没有patch loss时的结果,目前还在尝试更长时间的训练是否会有效果

现在的想法是,将编码到CLIP空间的code cc,使用类似与StyleGAN的方法输入到VGG的decoder中,但是关于具体的细节还没有想好,而且也不知道是否会有效

2022.07.13

目前网络的问题比较难解决,所以对patch loss进行了一些实验

patch loss是合理的,整张图片的loss不行,去尝试切成patch的loss是值得去尝试的,但是仔细一想,发现patch loss并没有添加新的约束,不过是把整个图片的余弦相似度换成了一个个patch的余弦相似度

首先我尝试能否不用patch达到有patch时的效果,经过多次实验发现好像并不太可能。我首先猜测是否是因为余弦相似度只能保证共线,而不能保证长度,所以计算生成图片的编码和原图编码的距离并取负,添加到loss里让这个距离更长,但是并没有生成有意义的图片,然后我思考会不会图像的编码差和文本的编码差要一致,但是实验结果和之前一致。之后的基于这个观点的尝试基本都是生成意义不明的风格,或者就是和原图没太大区别

最终还是要将patch加进去,但是换了种形式,将每个patch的编码与整个图像的编码做差并减小

L=iNEI(I^csi)EI(f(Ic))1\mathcal L =\sum_{i}^{N}||E_I(\hat I_{cs}^i)-E_I(f(I_c))||_1

其中EIE_I是CLIP中的图像编码器,IcI_c是原始的图像,I^csi\hat I_{cs}^i是裁剪后的patch,ff是生成图像的网络

因为我猜测每个patch的编码可能分布在整张图编码的附近,而patch loss让他们合在一起,所以这么尝试一下。使用文本“Fire”进行训练,最终的结果如下,训练过程中patch loss也有所降低

而使用patch loss时的结果如下

但是后来我又进行了测试,使用patch loss训练,计算上面的距离loss,发现距离loss并不一定会下降,反而有可能会上升,所以两者应该不是等价的

总之loss的问题还要再考虑一下,接下来的任务是想想怎么改网络,跑一下试试先

2022.07.15

image_features 裁剪之后的图片编码后的结果,glob_features 未裁剪的图片编码后的结果,source_features 原图编码后的结果,text_features和text_source分别是目标文本和原始文本

使用PCA降维后画出的图像,训练过程中,红蓝连成的线和黑紫连成的线基本是共线的,但是代表patch的绿点基本分布在红蓝的点附近,而且绿蓝连成的线很少与黑紫共线。

训练过程中红蓝两点距离会逐渐接近,于是算了一下距离确实是逐渐减小的,而且这个减小是整张图片的clip loss造成的,去掉只留下patch loss距离就基本不会减小,而此时获得结果如下

文本为“Sketch with black pencil”,迭代200轮,左为正常loss训练,右为去掉全局clip loss后的结果

关于之前的网络修改的方法,应该都不太能实行,因为encoder是固定的,只训第一层应该没有效果,而且鉴于原方法没有训encoder,说明encoder并不控制风格的生成,在encoder前面接一个新网络的方法应该也不会很有效果。所以还是考虑如何将code输入到decoder里,我还是觉得按照类似stylegan的投入方法可能会有效,目前在研究stylegan的结构该怎么用在这上面

2022.07.17

实现了之前预想的code输入方法,因为有styleGAN的先例,我认为这个方法是有效的,而恰好之前看了一篇论文Pastiche Master: Exemplar-Based High-Resolution Portrait Style Transfer,这篇论文是使用参考图像进行style transfer,里面有个ModRes和我想得方法类似,所以直接搬运了过来

ModRes

该论文将参考图像的风格,通过StyleGAN转移给其他图像,结构如上图可以分为左右两部分,左边输入我们需要的图像II,右边输入提供风格的参考图像SSEE是pSp这些用于反演的encoder,然后将两边的latent code通过不同的方式输入到StyleGAN中以实现风格的转移

ModRes用于将右边风格图像的latent code输入进去,结构文中没画,根据代码看应该就是上面的结构,接在StyleGAN的卷积层下面,其中Conv层用的好像是StyleGAN的ConvLayer,AdaNorm的代码如下

class AdaptiveInstanceNorm(nn.Module):
    def __init__(self, fin, style_dim=512):
        super().__init__()

        self.norm = nn.InstanceNorm2d(fin, affine=False)
        self.style = nn.Linear(style_dim, fin * 2)

        self.style.bias.data[:fin] = 1
        self.style.bias.data[fin:] = 0

    def forward(self, input, style):
        style = self.style(style).unsqueeze(2).unsqueeze(3)
        gamma, beta = style.chunk(2, 1)
        out = self.norm(input)
        out = gamma * out + beta
        return out

将输入的style通过全连接层生成偏移和放缩参数,再转换到输入的特征中

然后我的拼接方式是直接接到了decoder中Conv层的后面,总共接了8个ModRes模块

实验

训练方法是,共NN条文本,在一次迭代中,将每条文本输入到网络中生成对应风格的图像xix_i,然后计算以下loss进行优化,只优化ModRes和decoder

最终结果如下,前五张是对于五条文本按照原方法单独训练的结果,后五张是使用更改过的方法由一个model输出出来的结果

五条文本一起生成的结果如下,此时迭代次数为1000次

可以看到如果是一起训练的话,各个风格会带有一些其他风格的特征,训练过程中也是一样,一开始其实每条文本生成的图片都是近似融合在一起的,然后才会逐渐分开

clip loss

其实为了解决这一点我想了个clip loss,就是将CLIP训练时的loss加进去,用交叉熵损失说不定可以将他们分开,流程如下

这是CLIP论文中提到的loss计算过程,我将生成的五条文本的图片通过image_encoder作为上面的I_f,将五条文本通过text_encoder作为上面的T_f,然后矩阵相乘,计算交叉熵损失,初衷是让图片与对应的文本相关性增大,与其他文本相关性减小,但是好像因为CLIP本来就是训练好的,所以效果与patch loss或者全局loss重叠了,感觉结果并没有很好的改善,但还是放在下面

结论

感觉问题出现的原因可能是code分辨能力不足,或者添加的网络规模不够大,接下来想从这两个方面入手,比如在code输入到ModRes之前加一个类似于StyleGAN中8层全连接层的网络,或者扩大一下ModRes的规模,不知道会不会有效

2022.09.22

经过了一段时间的积累,最近重新思考了这个问题,今天简单做一下总结

目标

首先是这个任务要完成的目标,经过这段时间的阅读,我作出以下总结

首先对照使用风格图片进行风格迁移的任务的目标,他们使用content images和style images两个数据集进行训练,训练出的模型可以输入任意内容图片和风格图片,以获得混合后的图片

转移到我们这个任务,目标就是使用content images和文本两个集合进行训练,可以实现任意内容图像和文本的风格转移

实现

目前的实现是使用CLIP编码之后的code,然后运用了一个类似stylegan里的模块将code输入进去,虽然能够达到指导风格的目的,但是最终图片的效果并不是很理想,接下来对这个问题进行讨论

问题定义

首先,我们需要具体描述出现的问题,然后才能寻找解决方法

按照本文之前展示的实验结果来看,对比使用原模型的实验结果,和添加ada后的实验结果来看,总共有以下几个问题

上面实验结果使用的文本分别是Fire,Oil painting of flowers,Sketch with black pencil,Pop art of night city,Van gogh

  1. Fire的结果差异最大,在原模型中火的纹理蔓延到了图片大部分位置,但是我们的结果只蔓延到了部分位置,而且分布也不均匀,这个问题在Oil painting of flowers的结果中也有所体现
  2. 我们的结果中色彩不如原模型丰富,从Oil painting of flowers和Pop art of night city可以比较明显地看出来
  3. 我们的结果多多少少带有其他文本结果的特征,从Sketch with black pencil可以看出并不是像原模型一样纯粹的灰白
  4. 不知道是不是迭代次数太多了,我们的结果和内容图片的内容相似度很高

问题研究

首先研究是不是添加的ada模块的问题,跑了五次实验,每次只用一个文本进行训练,同样迭代200次,结果确实还是不好,说明多多少少跟这个ada有些关联,而且我发现,随着迭代次数的增加,效果会时好时坏,并且慢慢变差。以最明显的Pop art of night city为例,每十次迭代保存一次结果,为下图中的第二行

同时为了观察ada对结果的影响,我同时输出了没有ada模块的结果,为下图中的第三行




















同时为了观察ada和decoder单独的作用,我分别定住decoder和ada做了实验,结果如下

定住ada迭代200次后的结果为

定住decoder迭代200次后的结果为

以上结果对比不难发现,ada的存在对于原模型并没有起到积极的作用,虽然定住ada也可以达到原模型的效果,但是如果对ada进行训练,就会拖decoder的后腿,影响最终的效果,而如果定住decoder的话,ada自己的能力也不足以达到原模型的效果

思考

ada模块存在问题是意料之中的事情,但还是没有一个明确的方向去改进,我目前能做的就是换换数量和排列方式,或者读些论文找找新的结构放上去

除此之外,我也在尝试新的loss去达到patch loss的结果,但是好像没什么效果,patch loss为什么有效果还是一个没法细想的问题,看起来很合理但其实没有什么理论或者公式支持。唯一有道理的解释就是把patch当作域中的元素,然后使用CLIP对齐图片与文本的域,但是公式推得不是很理想,不过至少能确定CLIP中确实蕴藏了文本对应的图片的域的信息

其实最主要的是,我认为想要达成前面所说的目标,目前的结构应该是做不到的,类比其他方法的模型,我们需要一个能代替style image的feature的东西,或许需要通过CLIP中文本encoder获得,或者通过其他的方式,先运用CLIP获得feature,然后再将其运用到style transfer中,不然即使目前的结果能解决效果不好的问题,能做到style transfer的文本也只能局限于参与训练的文本,无法做到真正的blind,我感觉这才是当前最重要的问题

2022.10.10

想了想还是先写一下吧,论文名字叫DF-GAN: A Simple and Effective Baseline for Text-to-Image Synthesis,是打算在组会讲的,所以就简单写一下总体思路,组会再细说

最近的改进方向主要有两个思路,一是改进之前的方法,二是前面说的运用其他方法获得style image的feature

首先第一个思路,算是研究第二个方向时顺带的吧,之前基本确定了问题就是出在网络结构上,于是在读论文时发现新的结构就放进去试试效果,因为上面那个模块感觉跟ada很像,就替换了一下,结果就是上周发的结果,原本是想的组会就讲了所以没写汇报,感觉效果是有提升的,但不知道足不足够,而且还是有越训效果越差的问题

对于第二个思路,我看text-to-image的论文也是基于这个思路,当时想的是,如果可以直接通过文本生成对应风格的图片,就可以输入到vgg获得该风格的feature,但是这个方法太笨了,于是想到了将vgg对应的decoder接到GAN中生成器的后面,然后进行训练,那么生成器就会自动生成feature。如果需要不同层的feature,那么就接不同层vgg对应的decoder。

这个思路的关键是,如何使用GAN生成不同风格的图片,目前的想法是,先训练一个其他数据集的GAN,然后再使用clip进行微调,但是代表风格的文本如何和之前训练GAN时的文本进行结合是个比较重要的问题,或者直接使用clip指导GAN的训练,但是怎么实现目前还没有好的想法。

原模型在训练到220epoch时的结果
接上decoder后训练到220epoch时的结果

目前经过努力已经成功把decoder接到了生成器的后面,经过训练看起来应该是可以生成图片,但是训起来比较慢,还不知道最终结果如何,不过目前看来应该时不如同epoch的原模型,算的fid下降也很慢,但是最起码还在下降,而且为了能接上decoder,对生成器的结构也进行了更改,所以还是等训完了再看看

之后的任务就是把clip的text encoder替换上去,因为他这个论文里的text encoder也是预训练好的,先看看换上去还能不能保证文本与图片的对应

2022.10.20

CLIPstyler可以做到的是,使用一个image to image的生成器,输入一张内容图片,输出一张新的图片,然后为了能达到用文本指导生成图片风格的目的,运用CLIP计算文本与图片之间的风格loss,并配合其他loss使最终生成的图片风格与给定的文本相对应,而内容与内容图片相对应。

但是他这个方法中,一个生成器只能对应一个文本,想要输入新的文本进行风格迁移,就必须重新训练,使得在应用时有很多不便,所以考虑是否可以解决这个问题,使用一个模型一次训练多个文本。终极目标肯定是一次训练后,可以使用任意文本进行编辑,但是可能难以实现,所以如果退而求其次,就训练集设置大量的文本,然后能实现这些文本的风格迁移

目前是先以退而求其次为目标,先实现多文本的训练,上图有三部分,第一部分是目前方法的流程图,E、Affs、D三个模块构成一个生成器,从原始的内容图片C生成新的图片X,然后使用CLIP的图片编码器EI分别生成编码并作差,同时将文本“A Photo”和目标风格文本T通过CLIP的文本编码器ET生成对应的编码并作差,然后两个差计算CLIPloss,再添加对应的patch loss和内容loss,对网络进行优化

Affs是与之前方法主要不同的地方,为了能实现生成器生成多种文本风格的目标,添加了这个模块,可以实现将T通过编码后的向量输入到网络中的目的,从而指导网络生成的风格。上图第二部分是以前使用的结构,不知道是Norm层还是网络太浅,结果并不理想,后来使用的是第三部分的结构,左侧模块堆叠了8次,右侧是左侧中Aff的结构,两个参数是分别由两个mlp网络预测出来的,更改之后的结果比之前要好,结果文件过大,就不放在这里了

在实验过程中,E是VGG并且是固定参数的,D是对应VGG的decoder,有分别尝试固定参数与不固定参数,同时Affs也不一定是位于E和D中间的,也有尝试穿插在D里面