GAN中的Spectral Normalization

2024-01-20 17:58
文章标签 gan normalization spectral

本文主要是介绍GAN中的Spectral Normalization,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GAN中的Spectral Normalization

  Spectral Normalization 出自 《Spectral Norm Regularization for Improving the Generalizability of Deep Learning》《Spectral Normalization for Generative Adversarial Networks》,是为了解决GAN训练不稳定的问题,从“层参数”的角度用spectral normalization的方式施加regularization,从而使判别器D具备Lipschitz连续条件


为什么要让D具备Lipschitz连续

为了防止判别器“放飞自我”

根据Wikipedia的定义,Lipschitz连续条件 如下。其意义在于使得 f 足够稳定,在输入发生少量变化时,输出不会有太巨大的变化。如果有图像A,修改少量像素得到图像B,输入判别器D后得到相差非常巨大的判别效果,那么判别器就是不稳定的,它对输入过于敏感。
∣ ∣ f ( x 1 ) − f ( x 2 ) ∣ ∣ ∣ ∣ x 1 − x 2 ∣ ∣ ≤ K , ∀ x 1 , x 2 \frac{||f(x_1)-f(x_2)||}{||x_1-x_2||}\leq K, \forall x_1,x_2 x1x2f(x1)f(x2)K,x1,x2
这里的 K 被称为 f ( x ) f(x) f(x)Lipschitz constantK的最小值(上确界)被称为 ∣ ∣ f ∣ ∣ L i p ||f||_{Lip} fLip ,称 f ( x ) f(x) f(x) 满足 Lipschitz连续条件

《Wasserstein GAN》 给出了衡量真实分布 P r P_r Pr和生成分布 P g P_g PgEarth-Mover(EM) 距离:

W ( P r , P g ) = inf ⁡ γ ∈ ( P r , P g ) E ( x , y ) ∼ γ [ ∣ ∣ x − y ∣ ∣ ] W(P_r, P_g)=\inf_{\gamma \in (P_r, P_g)}E_{(x,y)\sim \gamma}[||x-y||] W(Pr,Pg)=γ(Pr,Pg)infE(x,y)γ[xy]

Kantorovich-Rubinstein duality 可得EM距离的另一个形式,这里有用到 ∣ ∣ f ∣ ∣ L i p ||f||_{Lip} fLip

W ( P r , P g ) = 1 K sup ⁡ ∣ ∣ f ∣ ∣ L i p ≤ K E x ∼ P r [ f ( x ) ] − E x ∼ P g [ f ( x ) ] W(P_r, P_g)=\frac{1}{K} \sup_{||f||_{Lip}\leq K}E_{x\sim P_r}[f(x)]-E_{x\sim P_g}[f(x)] W(Pr,Pg)=K1fLipKsupExPr[f(x)]ExPg[f(x)]

∣ ∣ f ∣ ∣ L i p ≤ 1 ||f||_{Lip}\leq 1 fLip1的条件下,求两个期望之差的上确界,就是EM距离,推导过程可参考这里。


矩阵范数

根据Wikipedia,矩阵的范数如下,它是右边的分式的上确界。

∣ ∣ A ∣ ∣ p = sup ⁡ x ≠ 0 ∣ ∣ A x ∣ ∣ p ∣ ∣ x ∣ ∣ p ||A||_p=\sup_{x\neq 0}\frac{||Ax||_p}{||x||_p} Ap=x̸=0supxpAxp

其中, p = 2 p=2 p=2时被称为 Euclidean NormL2-NormSpectral Norm,它是矩阵的最大奇异值(或者最大特征值的开方),下面 A T A^T AT 表示共轭转置。

σ ( A ) = ∣ ∣ A ∣ ∣ 2 = λ m a x ( A T A ) \sigma (A)=||A||_2=\sqrt{\lambda_{max}(A^TA)} σ(A)=A2=λmax(ATA)

矩阵范数的性质:

∣ ∣ A B ∣ ∣ p ≤ ∣ ∣ A ∣ ∣ p ∣ ∣ B ∣ ∣ p ||AB||_p\leq ||A||_p||B||_p ABpApBp
σ ( A B ) ≤ σ ( A ) σ ( B ) \sigma (AB)\leq \sigma (A)\sigma (B) σ(AB)σ(A)σ(B)


Spectral Normalization

考虑采用了非线性激活函数的MLP网络构成的判别器D, x l = a l ( W l x l − 1 + b l ) x^l=a^l(W^lx^{l-1}+b^l) xl=al(Wlxl1+bl),把它的参数写成 θ = { W l , b l } l = 1 L \theta=\{W^l, b^l\}_{l=1}^{L} θ={Wl,bl}l=1L,使的判别器可以写成 f θ ( x 0 ) = x L f_{\theta}(x^0)=x^L fθ(x0)=xL。只考虑 x x x的一个很小的邻域,可以将判别器看作一个线性函数, f θ ( x ) = W θ , x x + b θ , x f_{\theta}(x)=W_{\theta,x}x+b_{\theta,x} fθ(x)=Wθ,xx+bθ,x

∣ ∣ f θ ( x + δ ) − f θ ( x ) ∣ ∣ 2 ∣ ∣ δ ∣ ∣ 2 = ∣ ∣ W θ , x δ ∣ ∣ 2 ∣ ∣ δ ∣ ∣ 2 ≤ σ ( W θ , x ) = sup ⁡ δ ≠ 0 ∣ ∣ W θ , x δ ∣ ∣ 2 ∣ ∣ δ ∣ ∣ 2 \frac{||f_{\theta}(x+\delta)-f_{\theta}(x)||_2}{||\delta||_2}=\frac{||W_{\theta,x}\delta||_2}{||\delta||_2}\leq \sigma(W_{\theta,x})=\sup_{\delta\neq 0}\frac{||W_{\theta,x}\delta||_2}{||\delta||_2} δ2fθ(x+δ)fθ(x)2=δ2Wθ,xδ2σ(Wθ,x)=δ̸=0supδ2Wθ,xδ2

若激活函数使用 ReLU,可以把 a l ( x l − 1 ) a^l(x^{l-1}) al(xl1) 看作 D θ , x l x D^l_{\theta, x}x Dθ,xlx,对角阵 D θ , x l D^l_{\theta, x} Dθ,xl x l − 1 x^{l-1} xl1 非负的对应位置上为1,其他地方是0,这样 σ ( D θ , x l ) = ∣ ∣ D θ , x l ∣ ∣ 2 ≤ 1 \sigma(D^l_{\theta, x})=||D^l_{\theta, x}||_2\leq 1 σ(Dθ,xl)=Dθ,xl21

W θ , x = D θ , x L W θ , x L ⋯ D θ , x 1 W 1 W_{\theta,x}=D^L_{\theta,x}W^{L}_{\theta,x}\cdots D^1_{\theta,x}W^1 Wθ,x=Dθ,xLWθ,xLDθ,x1W1

σ ( W θ , x ) ≤ σ ( D θ , x L ) σ ( W L ) ⋯ σ ( D θ , x 1 ) σ ( W 1 ) ≤ ∏ l = 1 L σ ( W l ) \sigma(W_{\theta,x})\leq \sigma(D^L_{\theta,x})\sigma(W^{L})\cdots\sigma(D^1_{\theta,x})\sigma(W^1)\leq\prod_{l=1}^L\sigma(W^l) σ(Wθ,x)σ(Dθ,xL)σ(WL)σ(Dθ,x1)σ(W1)l=1Lσ(Wl)

若对判别器D的每一层都做 Spectral Normalization:

W ^ S N l = W l σ ( W l ) \hat W^l_{SN}=\frac{W^l}{\sigma(W^l)} W^SNl=σ(Wl)Wl

σ ( W ^ S N l ) = σ ( W ) σ ( W ) = 1 \sigma(\hat W^l_{SN})=\frac{\sigma(W)}{\sigma(W)}=1 σ(W^SNl)=σ(W)σ(W)=1

∣ ∣ f θ ( x + δ ) − f θ ( x ) ∣ ∣ 2 ∣ ∣ δ ∣ ∣ 2 ≤ σ ( W θ , x ) ≤ 1 \frac{||f_{\theta}(x+\delta)-f_{\theta}(x)||_2}{||\delta||_2}\leq\sigma(W_{\theta,x})\leq1 δ2fθ(x+δ)fθ(x)2σ(Wθ,x)1


Spectral Normalization 实现

Spectral Normalization实际上在做的事情,是将每层的参数矩阵除以自身的最大奇异值,本质上是一个逐层SVD的过程,但是真的去做SVD就太耗时了,所以采用幂迭代的方法求(参见Wikipedia)。

def spectral_norm(w, iteration=10, name="sn"):'''Ref: https://github.com/taki0112/Spectral_Normalization-Tensorflow/blob/65218e8cc6916d24b49504c337981548685e1be1/spectral_norm.py'''w_shape = w.shape.as_list() # [KH, KW, Cin, Cout] or [H, W]w = tf.reshape(w, [-1, w_shape[-1]]) # [KH*KW*Cin, Cout] or [H, W]u = tf.get_variable(name+"_u", [1, w_shape[-1]], initializer=tf.random_normal_initializer(), trainable=False)s = tf.get_variable(name+"_sigma", [1, ], initializer=tf.random_normal_initializer(), trainable=False)u_hat = u # [1, Cout] or [1, W]v_hat = None for _ in range(iteration):v_hat = tf.nn.l2_normalize(tf.matmul(u_hat, tf.transpose(w))) # [1, KH*KW*Cin] or [1, H]u_hat = tf.nn.l2_normalize(tf.matmul(v_hat, w)) # [1, Cout] or [1, W]u_hat = tf.stop_gradient(u_hat)v_hat = tf.stop_gradient(v_hat)sigma = tf.matmul(tf.matmul(v_hat, w), tf.transpose(u_hat)) # [1,1]sigma = tf.reshape(sigma, (1,))with tf.control_dependencies([u.assign(u_hat), s.assign(sigma)]):# ops here run after u.assign(u_hat)w_norm = w / sigma w_norm = tf.reshape(w_norm, w_shape)return w_norm

若输入矩阵是全连接层的参数,尺寸为 [ H , W ] [H,W] [H,W],则spectral_norm在效果上会直接对该二维矩阵求最大奇异值,但如果输入矩阵为卷积层的卷积核,其尺寸应该是 [ K H , K W , C i n , C o u t ] [K_H, K_W, C_{in}, C_{out}] [KH,KW,Cin,Cout]spectral_norm会先将该矩阵reshape成一个大小为 [ K H K W C i n , C o u t ] [K_HK_W C_{in}, C_{out}] [KHKWCin,Cout]的矩阵,再用迭代法对该二维矩阵求最大奇异值。不论哪种情况,求得的奇异值都是一个单值scalar


带SN的卷积层

def conv2d(x, channel, k_h=5, k_w=5, d_h=2, d_w=2, stddev=0.02, name='conv2d'):with tf.variable_scope(name):w = tf.get_variable('w', [k_h, k_w, x.get_shape()[-1], channel], initializer=tf.truncated_normal_initializer(stddev=stddev))w_sn = spectral_norm(w, iteration=3)conv = tf.nn.conv2d(x, filter=w_sn, strides=[1, d_h, d_w, 1], padding='VALID')biases = tf.get_variable('biases', [channel], initializer=tf.constant_initializer(0.0))conv = tf.reshape(tf.nn.bias_add(conv, biases), conv.get_shape())return conv

带SN的FC层

def dense(x, output_size, stddev=0.02, bias_start=0.0, activation=None, sn=False, reuse=False, name='dense'):shape = x.get_shape().as_list()with tf.variable_scope(name, reuse=reuse):W = tf.get_variable('weights', [shape[1], output_size], tf.float32, tf.random_normal_initializer(stddev=stddev))bias = tf.get_variable('biases', [output_size], initializer=tf.constant_initializer(bias_start))if sn:W = spectral_norm(W, 20, name="sn")out = tf.matmul(x, W) + bias if activation is not None:out = activation(out)return out

检验SpectralNorm

  用dense层检验,首先将W的初始值改为tf.ones_initializer()变成全1矩阵,然后用大小(3,3)的全1输入,在sn=Truesn=False的条件下分别输出结果。

x = tf.ones(shape=(3,3), dtype=tf.float32)
y1 = dense_ones(x, output_size=4, sn=False)
y2 = dense_ones(x, output_size=4, sn=True)
with tf.Session() as sess:sess.run(tf.global_variables_initializer())print sess.run(y1)print sess.run(y2)

  dense层的W是一个大小为(3,4)的全1矩阵,用matlabnp.linalg.svd可以算出它的最大奇异值为3.464,而3.0/3.464=0.8660,从下面的结果可见,在sn=True时,FC层输出的结果等于在sn=False时的结果除以FC层权值矩阵W的最大奇异值,该结果本质上是由于权值矩阵W自己除以最大奇异值导致的。
  因此,Spectral Norm的实现是正确的。

# y1
[[3. 3. 3. 3.][3. 3. 3. 3.][3. 3. 3. 3.]]
# y2
[[0.86602545 0.86602545 0.86602545 0.86602545][0.86602545 0.86602545 0.86602545 0.86602545][0.86602545 0.86602545 0.86602545 0.86602545]]

如何查看sigma的值

  有时候希望查看迭代法求得的最大奇异值是否正确,或者用它作为某种指示指标(比如用作GAN里判别器是否放飞自我的标准),希望以Tensor的形式获取它。只需在spectral_norm中专门声明一个variable用于存储它的值,在迭代法计算完之后把sigma赋给它即可。

def spectral_norm(...):...s = tf.get_variable("sn_sigma", [1, 1], initializer=tf.random_normal_initializer(), trainable=False)...with tf.control_dependencies([u.assign(u_hat), s.assign(sigma)]):...

  为了用sess.run获取它实时的值,需要先得到这个Tensor,一种简单暴力的方法是首先用tf.global_variables()查看所有variable的名字,找到该Tensor的名字,用tf.get_collection获取。要注意Tensor的名字往往前面带有很多variable_scope,就像文件路径一样,需要完整地传入tf.get_collection

with tf.Session() as sess:sess.run(tf.global_variables_initializer())v = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, '你的前缀/sn_sigma:0')[0]sigma = sess.run(v, feed_dict={...})print sigma[0, 0]

control_dependencies的作用

  在我找到的所有Spectral Normalization的实现代码中,都有control_dependencies存在,其作用在于每次调用spectral_norm时用上一次调用中进行迭代得到的u来初始化本次调用的u,暂时不明白其必要性,如果为了更加精确而多次调用输入同一个权值矩阵,倒不如将iteration设的大一点(20以上就已经非常精确了),如果是不同的输入,则这样初始化没有意义,并不会变得更精确。
  这里演示一下control_dependencies、assign和identity的配合使用。
  在下面的代码中,control_dependencies保证了在每次out=tf.identity(u)前都会先将u_var更新为u的值,只有在最开始u_var的初始值为1.0。

u_var = tf.Variable(1.0)
u = u_var u = u * 3with tf.control_dependencies([tf.assign(u_var, u, name='update_u')]):out = tf.identity(u)with tf.Session() as sess:sess.run(tf.global_variables_initializer())for _ in range(3):print out.eval()
'''
3.0
9.0
27.0
'''

关于迭代次数

  迭代法计算最大奇异值,迭代次数达到25即可非常精确,但为了节省时间,一般不需要这么多。


Reference

Spectral Norm Regularization for Improving the Generalizability of Deep Learning
Spectral Normalization for Generative Adversarial Networks
BatchNormalization LSTMCell Tensorflow
spectral normalization Tensorflow
compare_gan spectral normalization Tensorflow
Wikipedia Matrix norm

这篇关于GAN中的Spectral Normalization的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/626837

相关文章

生成对抗网络(GAN网络)

Generative Adversarial Nets 生成对抗网络GAN交互式可视化网站 1、GAN 基本结构 GAN 模型其实是两个网络的组合: 生成器(Generator) 负责生成模拟数据; 判别器(Discriminator) 负责判断输入的数据是真实的还是生成的。 生成器要不断优化自己生成的数据让判别网络判断不出来,判别器也要优化自己让自己判断得更准确。 二者关系形成

深度学习--对抗生成网络(GAN, Generative Adversarial Network)

对抗生成网络(GAN, Generative Adversarial Network)是一种深度学习模型,由Ian Goodfellow等人在2014年提出。GAN主要用于生成数据,通过两个神经网络相互对抗,来生成以假乱真的新数据。以下是对GAN的详细阐述,包括其概念、作用、核心要点、实现过程、代码实现和适用场景。 1. 概念 GAN由两个神经网络组成:生成器(Generator)和判别器(D

基于 AC 驱动的电容结构 GaN LED 模型开发和应用

随着芯片尺寸减小,微小尺寸GaN 基 Micro LED 显示面临着显示与驱动高密度集成的难题,传统直流(DC)驱动技术会导致结温上升,降低器件寿命。南京大学团队创新提出交流(AC)驱动的单电极 LED(SC-LED)结构【见图1】,利用隧穿结(TJ)降低器件的交流工作电压。为了深入理解该器件的工作原理,我司技术团队开发了基于 AC 驱动的物理解析模型,揭示了隧穿结降低器件工作电压的

深入理解GAN网络

Generative Adversarial Networks创造性地提出了对抗训练来代替人工指定的loss。之前的文章初步理解了一下,感觉还是不到位,在这里再稍微深入一点。 交叉熵cross entropy 鉴别器是GAN中重要的一部分,鉴别器和生成器交替训练的过程就是adversarial training的过程。而鉴别器的本质是一个二分类网络,所以要理解gan loss,就首先要熟悉二分

Layer Normalization论文解读

基本信息 作者JL Badoi发表时间2016期刊NIPS网址https://arxiv.org/abs/1607.06450v1 研究背景 1. What’s known 既往研究已证实 batch Normalization对属于同一个Batch中的数据长度要求是相同的,不适合处理序列型的数据。因此它在NLP领域的RNN上效果并不显著,但在CV领域的CNN上效果显著。 2. What’s

深度学习实战4--GAN进阶与优化

GAN  的问题主要有两点:Loss 等于0的梯度消失问题和梯度不稳定以及多样性受损。 前者是因为选择的分布函数使用JS 距离,这个距离不能衡量两个不相交的分布的距离;后者是因为Loss  函数要求KL 距离最小,JS 距离最大,所以梯度不稳定,而且 Loss 函数对正确率要求太大,多样性要求小,所以会造成模型选择大量生成“安全”的“数字1”来降低Loss函数。

神经网络训练不起来怎么办(五)| Batch Normalization

Ⅰ,领域背景 训练困境:当 input feature 在不同 dimension 上差距很大的时候,会产生一个非常崎岖的 error surface(误差平面)。这种崎岖多变的误差平面容易导致训练陷入以下的几个困境。 收敛困难:在崎岖的误差表面上,梯度下降等优化算法很容易陷入局部最小值或者鞍点,并且很难继续优化。这会导致模型无法收敛到全局最优解,训练过程变得非常困难。训练速度变慢:由于优化算

深度学习-生成模型:Generation(Tranform Vector To Object with RNN)【PixelRNN、VAE(变分自编码器)、GAN(生成对抗网络)】

深度学习-生成模型:Generation(Tranform Vector To Object with RNN)【PixelRNN、VAE(变分自编码器)、GAN(生成对抗网络)】 一、Generator的分类二、Native Generator (AutoEncoder's Decoder)三、PixelRNN1、生成句子序列2、生成图片3、生成音频:WaveNet4、生成视频:Video

GNN-频域-2014:Spectral Networks and Locally Connected Networks on Graphs(频谱图卷积神经网络)【第一篇从频域角度分析】

《原始论文:Spectral Networks and Locally Connected Networks on Graphs》 空域卷积非常直观地借鉴了图像里的卷积操作,但缺乏一定的理论基础。 而频域卷积则不同,相比于空域卷积而言,它主要利用的是**图傅里叶变换(Graph Fourier Transform)**实现卷积。 简单来讲,它利用图的**拉普拉斯矩阵(Laplacian ma

Attentation-GAN for super-resolution(ASRGAN )

Attenatation-GAN for super-resolution(ASRGAN) 1 简单介绍:       目前的SR方法解决的都是小尺寸的数据小于500px,本文提出的是针对大尺寸的数据比如大于2000px的商业数据。本文的创新之处: 提出一种新奇的使用注意力机制的SRGAN方法,叫做A-SRGAN,他是吸收了SAGAN的思想,然后哩由于处理的是大尺度的数据,所以