【深度学习】图像风格混合——StyleGAN原理解析

1、前言

上一篇,我们讲了PGGAN的模型原理,本章我们就来讲解一下StyleGAN,这个模型能够自由控制图像的风格,细节变化等等,生成用户想要的图像,甚至从某种程度上说,其可以实现AI换脸。

PS:这篇文章其实我做了很多功课,本来不想写的。因为对于我这种水平的人来说,论文太难理解,不仅翻译过来语句不顺(本人英语不好,只能看机翻的版本),里面的原理部分也感觉相当抽象。本来想在网上搜一些文章来看一下,结果很多文章都是跟机器翻译直接复制过来的一样,完全不作解释,晦涩难懂。当燃了,也许是我资质驽钝,无法理解里面的那些浅显的概念。为了防止有人和我一样,看论文看的云里雾里,难以理解其中的意思,我还是下决心以通俗的语言去讲解其中的一些概念,不敢说一定正确理解了论文所讲,只希望能帮助到屏幕前对StyleGAN懵逼的你。

原论文:A Style-Based Generator Architecture for Generative Adversarial Networks

参考代码:Pytorch版本,非官方

视频:图像风格混合——StyleGAN原理解析-哔哩哔哩

效果图:

在这里插入图片描述

2、引入

首先,为什么要有StyleGAN。在上一篇的PGGAN中,我们已经能够生成高清大图了,并且质量相当不错。可是,我们仍有一个问题——当我们生成图像的时候,我们对这个图像的一些细节不满意,那能不能对这个图像进行一些修改,比如头型,头发等等进行一些变化。在传统的GAN模型系列中,几乎是做不到的。

为什么呢?因为你不知道那些数据代表头发,哪些数据代表头型。此时的你可能会想,那我们一点点的修改其中的量,看图像的变化,不就能试出来哪些变量代表什么了吗?

想法是美好的,但是现实是骨感的。你就是做不到,因为图像的特征之间存在极大的耦合(相关性),一个变量的修改会影响其他变量的更改。比如你修改了其中一个值,很有可能会让整张图像直接毁掉,因为在本来的框架中,那个值的变动要引起其他值的变动(相关性),才能形成图像。而你只修改了其中一个,很大可能会造成图像崩溃。

于是,人们就想,能不能充分的分离出这些特征,减小特征之间的耦合,让特征之间相互独立,互不影响。这样就可以单独修改图像的某一部分了。而StyleGAN正是解决了这个问题。

2、StyleGAN结构图

StyleGAN模型主要是通过修改生成网络,达到上面的目的

2.1、流程

生成网络的结构图是这篇论文最简单的部分了,我们来看这张图

在这里插入图片描述

其分为a,b两部分,左边是我们传统模型GAN的生成网络,而右边则是修改后的,StyleGAN的生成网络结构。

StyleGAN由两部分构成——Mapping network and Synthesis network ,其中Mapping network就是用来控制图像的风格信息的。Synthesis network用来生成图像。流程如下

首先,由Mapping network从标准正态分布中(也可以是其他简单概率分布)采样出一个z latent Code(512维的向量),然后归一化,依次经过8个全连接层映射,得到的值记作w latent Code(512维的向量)。我们把z latent Code的概率分布空间记作Z latent Space,w latent Code的概率分布空间记作W latent Space。如图

在这里插入图片描述

接着,我们初始化一个可学习的常数(Const),记为x,然后,x加上一个B(B是一个随机噪声经过了仿射变化后的值,也就是 B = w × n o i s e B=w\times noise B=w×noise,其中 w w w是一个可学习的参数,为了对噪声进行一些变化),再经过一个AdaIN(Adaptive Instance Normalization),这里的AdaIN实际上就是上一层的输出进行实例归一化,然后再加上缩放和偏置项,输出公式如下
o u t p u t = y s , i x i − μ ( x i ) σ ( x i ) + y b , i output = y_{s,i}\frac{x_i-\mu{(x_i)}}{\sigma(x_i)}+y_{b,i} output=ys,iσ(xi)xiμ(xi)+yb,i
x i − μ ( x i ) σ ( x i ) \frac{x_i-\mu{(x_i)}}{\sigma(x_i)} σ(xi)xiμ(xi)就是实例归一化了,然后通过 y s , i , y b , i y_{s,i},y_{b,i} ys,i,yb,i就是对其进行缩放和偏置项。这两个y哪来的呢,实际上就是左边的w latent Code 经过一个仿射变化(全连接层)转化为512x2的向量,记为A,然后A拆分为两个512向量,分别对应 y s , i , y b , i y_{s,i},y_{b,i} ys,i,yb,i

经过AdaIN后再经过一个卷积层Conv 3x3,然后再重复一个过程,接着上采样分辨率,又重复这个过程。

所以这就是StyleGAN的生成网络结构图了。

看起来没啥特殊的是不是?从哪里分离特征了?我们知道,synthesis network在生成图像的时候,在每个分辨率都是会将左边的w latent Code注入进去。作者经过实验,**发现在低分辨率注入w latent Code,能够控制图像的姿势、发型、脸型等,中分辨率注入w latent Code,则控制面部特征等,当高分辨率注入w latent Code,会带来颜色和微观结构的调整,比如说肤色。 **作者怎么做实验呢?当模型训练好了之后,作者生成两张图像A,B,他们对应的w latent Code为w0,w1,在低分辨率的时候,我们注入w0,在高分辨率的时候,我们注入w1,就可以观察到变化。如图所示

在这里插入图片描述

​ 这个实验的成功,已经充分说明了图片的特征之间已经充分解耦(线性无关)。

​ 除此之外,我们在结构图中,还看到了在不同分辨率中,都有随机噪声的注入。通过实验,作者发现这些噪声能够用来增加图像某些细节的随机性,比如头发、胡茬、雀斑或皮肤毛孔的准确位置。这个随机噪声的注入,在不同分辨率的影响也不同,具体我们来看这张图

在这里插入图片描述

(a)代表全局输入噪声的生成图。(b)代表无噪声的生成图。(c)代表在高分辨率使用噪声的生成图。

(d)代表在低分辨率使用噪声的生成图。

不难看到,当没有噪声的时候,图片几乎没啥细节、特色,其外观平平;而当加入噪声时,整张图像变得更加细腻。在高分辨率使用噪声时,生成图像的皮肤、头发卷曲、背景,都变得更加细致;在低分辨率使用噪声时,会让头发等变得卷曲或出现背景特征。

2.2、问题①:z latent Code 到 w latent Code

讲到这里,我不知道你是否会有疑惑,但是论文里面雀食讲到了,那就是为什么要多此一举把z latent Code 映射到w latent Code 才注入到synthesis network中,而不是直接把z注入到synthesis network中?

前面我们提到,在不同位置把w latent Code注入,会影响图像的风格(姿态、发型等等),说明w latent Code 是风格信息的代表。而如果我们直接用z latent Code去注入,那么z latent Code就是风格信息的代表。

可是,你想过没,z latent Code是从标准正态分布里面采样出来的,里面的值在一开始都是随机的,从某种意义上来说,这些数值还没有实质意义。什么意思呢?举个不太恰当的例子,假如你把从标准正太采样出来的值赋予意义,第一个值代表性别,第二个值代表头发长度,第三个值代表…,这些赋予的实际意义的值合理吗?

不合理!非常不合理!如果我们的数据集不存在男性且长发的数据,可这两个值是完全随机从标准正太分布中采样的,那么采样出男性且长发的概率就相当大。把这些信息注入到synthesis network中,如果这些信息仍然代表风格信息,那么判别网络肯定会判别为假图像,因为真图像根本没有这种图像。

而对于生成网络而言,既然它避免不了随机采样出代表男性且长发的值,那唯一的办法就是,在后面的数值传播中,将这个组合信息抹去。这种操作会造成什么呢?论文里面的意思会造成特征的扭曲(可简单理解为特征耦合)。

以下为个人看法

换句话说,此时的z latent Code代表的不再是真正意义上的风格信息,因为真正的风格信息不会有男性且长发的组合。如果我们把此时的z latent Code仍然当作是风格信息,那么在后续的前向传播中削去这个组合之后,图像的性别和头发信息又该从哪来?这些都不得而知

在后面的数值传播中,比如在模型图中,经过一个Conv 3x3 的卷积层的变化后,或许就消去了那个组合。那么此时我是否可以认为,此时得到的值,才是真正代表风格信息的呢?但是,你如何确保在经过一个3x3之后就会消除这个组合呢?万一它到了后面输出图像的前一刻才消除呢?那个时刻的信息才真正代表风格信息呢?那个时候的信息已经充分耦合了,你怎么办?这些你是没办法控制的**(也许此时你会疑惑为什么w latent Code就一定能充分解耦,后面会讲到,别急)**

以上为个人看法

而如果先把z latent Code映射到w latent Code,就可以在映射的过程中,直接消去男性且长发的组合。并且,由于经过的是非线性变化,此时的概率分布,理论上可以接近风格信息所对应的概率分布。(当燃了,前提假设是生成网络对于充分解耦的特征能够生成更好的图像,而耦合的则更难)

论文里面用了一张非常形象的图来表示

在这里插入图片描述

(a)是数据集特征空间,左上角缺失的那一部分代表男性且长发的数据。

(b)代表从Z latent Space映射到图像的特征空间,可以看到空间扭曲。这张图的意思更像是Z latent Space本身包含了数据男性且长发的组合,所以其形状是一个圆,如果不扭曲空间,就会包含有那个组合,后续的数值传播中,神经网络不得不扭曲空间,而从达到消去该组合的目的。

(c)代表从W latent Space映射到图像的特征空间,其和数据集的特征空间形状很接近,可以看到特征之间相当平整,有序,更加线性。

作者还进行了消融实验,发现w雀食能够充分解耦,而z却不行。

2.3、 Style mixing(风格混合)

之所以在w latent Code这个位置注入到synthesis network 能够充分解耦,我个人认为很大原因就是因为Style mixing。

风格混合其实就是在训练的时候,我们随机采样出两个z latent Code——z0,z1,然后经过全连接层变成w0,w1。接着,就到了风格的混合。选定一个分辨率位置,低于这个分辨率的层把w0注入进去,高于这个分辨率的层,把w1注入进去。从而达到风格混合。

想法也很简单,如果w代表的是风格信息且没有充分解耦,那么我们随意的对两个w latent Code进行混合,必然会造成文章前面所说到的图像崩溃,从而判别器会一眼判断出真假。而生成网络为了避免这种情况,会让w所代表的风格信息充分解耦起来。

2.4、问题②:W latent Space or Noise ?

前面实验的结果已经很明显了,w latent Code 代表风格信息,控制着图像的全局信息。而噪声则代表一些局部的随机变化。

你是否会有一个疑问,为什么风格是由w latent Code来控制的?就是因为它在不同分辨率注入进去了?噪声也在不同分辨率都注入进去了呀。 凭什么就是你w latent Code代表全局?噪声代表局部?

论文里面提到的如果噪声尝试控制全局信息,会导致空间不一致的情况,从而被判别网络惩罚。

空间不一致?什么意思呢?假如,我们要生成的是一张复古风格的图像,那么在低分辨率的姿态,面部等会带有一些复古的元素;在高分辨率的时候,人面部的肤色以及背景,肯定也是服从复古风格。而这些风格的来源,皆来自同一个w latent Code。

可如果是要噪声来控制,每次都会随机采样一个噪声注入进去,也许在低分辨率的时候,采样出来的风格是复古风格,但是在高分辨率,由于随机性,可能会生成一张清新风格的背景和肤色。这会造成在不同分斌率的风格不一样,这就是空间不一致性。这种不一致性大大提高了判别器判别假图片的成功率。所以,生成网络必然会学习使用w latent Code来代表风格信息,噪声代表局部随机变化。

2.5、 Truncation trick in W(截断技巧)

这个小技巧并不是这篇论文提出来的,其方法是对W latent Code 进行一些约束。首先,计算w latent Code的数学期望
w ˉ = E z ∼ P ( z ) [ f ( z ) ] \bar w = \mathbb{E}_{z \sim P(z)}[f(z)] wˉ=EzP(z)[f(z)]
然后新的w latent Code就等于
w ′ = w ˉ + ϕ ( w − w ˉ ) w^{'}=\bar w + \phi(w-\bar w) w=wˉ+ϕ(wwˉ)
w ′ w^{'} w代表输出的新的w latent Code , ϕ \phi ϕ是我们设定的超参数,其中 ϕ < 1 \phi<1 ϕ<1

这个公式怎么理解呢?在我们进行训练的时候,或许我们存在某种类型的数据较为稀少(低密度区域),那么这种数据肯定没有得到很好的学习。为了提高后面图像的生成质量,采用截断技巧收缩风格空间,减少生成低密度区域图像的可能。

所以我们先对风格信息求出数学期望,得到平均风格,然后用 d = w − w ˉ d =w-\bar w d=wwˉ代表每张图片的风格信息与平均风格的距离。再乘以一个 ϕ \phi ϕ,就代表对这个距离进行缩放。比如 ϕ = 0.5 , d = 0.1 \phi = 0.5,d=0.1 ϕ=0.5d=0.1,那么最终得到0.05,可如果 d = 100 d = 100 d=100,那么最终得到50。不难看到,当这个距离很小的时候,对其进行缩放的程度就越小。而当距离很大时(低密度区域),其缩放程度就越大。

3、Perceptual path length(感知路径长度)

前面我们只是感性地认识了W latent Space可以充分解耦,那么我们如何去衡量解耦的程度呢?

那就通过感知路径长度,首先,我们随机从标准正态中采用出 z 1 , z 2 z_1,z_2 z1,z2,然后利用生成网络,生成左上角和右下角的图像。当特征充分解耦,那么从 z 1 z_1 z1图像的狗变到 z 2 z_2 z2图像的狗的过程中,理应就是改变一些肤色等等。比如我们在点t的位置,仍然是只狗,然后再往前走一步 t + ϵ 1 t+\epsilon_1 t+ϵ1改变一些值,如果充分解耦,那么理应得到的也是一只狗。但是,当特征耦合程度很高的时候,你随意改变其中一个值而其他值没有得到修改,会让图像崩掉,也许就变成了左下角那张床的图像。对于这种情况,你所要修改的值会更多,路径也会更加长(对应图中绿色的线)

图像来自参考【1】

Ps:图像来自参考【1】

所以,当把z latent Code直接注入到synthesis network,我们使用下面的公式求出他的感知路径长度
L Z = E [ 1 ϵ 2 d ( G ( s l e r p ( z 1 , z 2 ; t ) ) , G ( s l e r p ( z 1 , z 2 : t + ϵ ) ) ) ] \mathbb{L}_Z = \mathbb{E}\left[\frac{1}{\epsilon^2}d\left(G(slerp(z_1,z_2;t)),G(slerp(z_1,z_2:t+\epsilon))\right)\right] LZ=E[ϵ21d(G(slerp(z1,z2;t)),G(slerp(z1,z2:t+ϵ)))]
其中 z 1 , z 2 ∼ P ( z ) z_1,z_2 \sim P(z) z1,z2P(z) t ∼ U ( 0 , 1 ) t ∼ U(0,1) tU(0,1), G是生成器,d代表的是感知距离, ϵ = 10 −4,slerp表示球面插值,插值其实就是求出两点之间某个点的所对应的值,比如图中, z 1 , z 2 z_1,z_2 z1,z2之中t所对应的值,不懂的话参考线性插值

而对于将z latent Code映射为w latent Code再注入,其感知距离为
L W = E [ 1 ϵ 2 d ( G ( l e r p ( f ( z 1 ) , f ( z 2 ) ; t ) ) , G ( l e r p ( f ( z 1 ) , f ( z 2 ) : t + ϵ ) ) ) ] \mathbb{L}_W = \mathbb{E}\left[\frac{1}{\epsilon^2}d\left(G(lerp(f(z_1),f(z_2);t)),G(lerp(f(z_1),f(z_2):t+\epsilon))\right)\right] LW=E[ϵ21d(G(lerp(f(z1),f(z2);t)),G(lerp(f(z1),f(z2):t+ϵ)))]
其中lerp表示线性插值

下面我们来看一下流程w latent Code计算感知路径长度的流程

①随机从标准正太采样出 z 1 , z 2 z_1,z_2 z1,z2,映射成 w 1 , w 2 w_1,w_2 w1,w2

②从0~1分布中随机采样一个t,计算 w 1 , w 2 w_1,w_2 w1,w2在t这个位置的线性插值,得到的值记作wt0。再计算t+ ϵ \epsilon ϵ时刻的线性插值,得到的值记作wt1。然后把wt0,wt1注入给synthesis network生成图像 i m g 1 , i m g 2 img_1,img_2 img1img2,对这两张图片进行剪裁,只留下人脸的部分(消去背景)。

③用原始训练数据训练好一个VGG16模型。

④将 i m g 1 , i m g 2 img_1,img_2 img1img2喂给VGG16,VGG16输出他们的特征向量分别记为feature1,feature2

⑤求平方,然后在通道维度求和 d = ∑ c h a n n e l ( f e a t u r e 1 − f e a t u r e 2 ) 2 d = \sum\limits_{channel}(feature1-feature2)^2 d=channel(feature1feature2)2

L w = 1 ϵ 2 d \mathbb{L}_w=\frac{1}{\epsilon^2}d Lw=ϵ21d

最后实验发现,z latent Code的路径长度远远高于w latent Code,这说明w latent Code的解耦程度比z高很多。

4、结束

以上,就是StyleGAN的全部内容了,其中还有一些细节,比如线性可分性我没讲到,因为我觉得无关紧要。如有问题,还望指出,阿里嘎多

在这里插入图片描述

5、参考

【1】图像生成典中典:StyleGAN & StyleGAN2 论文&代码精读 - 知乎 (zhihu.com)

【2】StyleGAN 架构解读(重读StyleGAN)精【1】-CSDN博客

【3】Python PyTorch lerp用法及代码示例 - 纯净天空 (vimsky.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/601875.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【跟我每天学习1个QT类】QLibrary类 — 加载管理动态链接库的类

一、QLibrary类简介 由于项目原因&#xff0c;QT软件经常会调用各种各类的库函数&#xff0c;Qt框架中提供的一个类&#xff0c;用于在运行时动态加载和访问共享库&#xff08;也称作动态链接库&#xff0c;DLLs&#xff09;&#xff0c;实现对库中函数、变量等符号的透明调用…

市场复盘总结 20240408

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率 33% 最常用的…

【CTF】rip--堆栈的简单认识

前言 最近在学二进制&#xff0c;准备拿BUUCTF的pwn试试手&#xff0c;还在摸索的阶段&#xff0c;有什么思路出错的地方还请指出。 解题思路 下载文件到kali&#xff0c;查看文件为 64-bit的ELF&#xff08;ELF为Linux下的可执行文件&#xff0c;相当于Windows的exe&#xff0…

Verilog语法——按位取反“~“和位宽扩展的优先级

前言 先说结论&#xff0c;如下图所示&#xff0c;在Verilog中“~ ”按位取反的优先级是最高的&#xff0c;但是在等式计算时&#xff0c;有时候会遇到位宽扩展&#xff0c;此时需要注意的是位宽扩展的优先级高于“~”。 验证 仿真代码&#xff0c;下面代码验证的是“~”按位取…

合并两个有序数组——每日一题

题目&#xff1a; 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&…

CLIPSeg如果报“目标计算机积极拒绝,无法连接。”怎么办?

CLIPSeg这个插件在使用的时候&#xff0c;偶尔会遇到以下报错&#xff1a; Error occurred when executing CLIPSeg: (MaxRetryError("HTTPSConnectionPool(hosthuggingface.co, port443): Max retries exceeded with url: /CIDAS/clipseg-rd64-refined/resolve/main/toke…

登录信息失效后多次请求提示合并成一次

在通常的业务场景中经常会出现进入页面之后一次性发送好多个请求,如果登录信息失效,那就会出现很多提示 类似这种多个提示的,看起来不美观,希望改成可以把在短时间内出现相同的错误信息,只提示一次,其他的就不提示了 实现思路 通常业务中每一个请求的code都是有具体的意思,可以…

【Leetcode每日一题】 递归 - 验证二叉搜索树(难度⭐⭐)(53)

1. 题目解析 题目链接&#xff1a;98. 验证二叉搜索树 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 中序遍历是二叉树遍历中的一种重要方式&#xff0c;它按照左子树、根节点、右子树的顺序访问每个节点。这种方式…

Linux从入门到精通 --- 4(下).网络请求和下载、端口、进程管理、主机状态监控、环境变量、文件的上传和下载、压缩和解压

文章目录 第四章(下)&#xff1a;4.8 网络请求和下载4.8.1 ping4.8.2 wget4.8.3 curl 4.9 端口4.9.1 查看端口占用 4.10 进程管理4.10.1 查看进程4.10.2 查看指定进程4.10.3 关闭进程 4.11 主机状态监控4.11.1 查看系统资源占用4.11.2 top交互式选项4.11.3 磁盘信息监控4.11.4 …

【简单讲解下Lisp的学习历程】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

【优选算法专栏】专题十六:BFS解决最短路问题(二)

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

7.1.4 Selenium 爬取京东商品信息实战

目录 1、实战内容 2、思路 3、分析 url 4、开始操作 1、得到 Cookies 2、访问页面&#xff0c;得到 response 3、解析页面 4、存入 MySQL 5、1-3步总代码 1、实战内容 爬取京东笔记本电脑商品的信息(如&#xff1a;价格、商品名、评论数量)&#xff0c;存入 MySQL 中…