tensorflow实现谱归一化(Lipschitz stability constraint)
前言
根据(wgan的推导过程)在生成对抗网络的训练中,由于卷积神经网络的权重矩阵应该满足Lipschitz stability constraint,具体的详细了解,因此采用谱归一化,将权重限制在(0,1)之间以代替传统的超过1部分截断等,一般用在生成对抗网络的鉴别器中,这样带来的好处是减少了函数振荡和加速了模型收敛,推导部分可以参照下面这一篇博客,个人觉得这篇博客写的很好,就是最后的谱归一化实现不太清楚,可以参照我写的过程,也可以阅读论文wgan和wgan-gp以及spectral normalization。
对于谱归一化部分的推导和lipschitz稳定性限制可以参照这篇博客
一、实现谱归一化推导过程?
在实际进行谱归一化的过程中会产生大量的计算量,因此采用奇异值分解的方式,用幂迭代法实现卷积神经网络中权重矩阵的谱归一化,W为卷积神经网络的卷积核(权重矩阵)。
个人认为想要实现谱归一化(可能理解有一些错误,欢迎指正,目前正常学习中)
W
=
W
∥
W
∥
2
W=\frac {W}{\left\|W\right\|_2}
W=∥W∥2W
首先要先进行求得W的谱范数,即||W||,而求二范数通常使用如下两个方式:
1
)
∥
W
∥
2
=
∑
i
=
1
M
∑
j
=
1
N
W
i
,
j
2
1)\left\|W\right\|_2 = \sqrt{\sum_{i=1}^M \sum_{j=1}^N W_i,_j^{2}}
1)∥W∥2=i=1∑Mj=1∑NWi,j2
2
)
∥
W
∥
2
′
=
sup
x
∈
R
n
(
∣
A
x
∣
∣
x
∣
)
,
其
中
∣
x
∣
=
(
x
,
x
)
2)\left\|W\right\|_{2^{'}} = \mathop{\sup}\limits_{x\in\R^n}(\frac{|Ax|}{|x|}),其中|x|=\sqrt{(x,x)}
2)∥W∥2′=x∈Rnsup(∣x∣∣Ax∣),其中∣x∣=(x,x)
这两种方式都有较大的计算量,并且对于卷积神经网络中通常有多个卷积核,因此采用幂迭代法先求奇异值,对于奇异值有如下理论,若矩阵A的n个奇异值为
σ
1
,
σ
2
,
σ
3
,
σ
4
,
σ
5
.
.
.
.
.
σ
n
\sigma_1,\sigma_2,\sigma_3,\sigma_4,\sigma_5.....\sigma_n
σ1,σ2,σ3,σ4,σ5.....σn
则
1
)
∥
W
∥
2
=
σ
1
2
,
σ
2
2
,
σ
3
2
,
σ
4
2
,
σ
5
2
.
.
.
.
.
σ
n
2
1)\left\|W\right\|_2 = \sqrt{\sigma_1^2,\sigma_2^2,\sigma_3^2,\sigma_4^2,\sigma_5^2.....\sigma_n^2}
1)∥W∥2=σ12,σ22,σ32,σ42,σ52.....σn2
2
)
∥
W
∥
2
′
=
m
a
x
(
σ
1
,
σ
2
,
σ
3
,
σ
4
,
σ
5
.
.
.
.
.
σ
n
)
2)\left\|W\right\|_{2^{'}}= max(\sigma_1,\sigma_2,\sigma_3,\sigma_4,\sigma_5.....\sigma_n)
2)∥W∥2′=max(σ1,σ2,σ3,σ4,σ5.....σn)
二、tensorflow实现
1.采用幂迭代法进行谱归一化的过程如下(示例):
import tensorflow as tf
def l2_norm(v, eps=1e-12):
return v / (tf.reduce_sum(v ** 2) ** 0.5 + eps)
def spectral_norm(w, iteration=1):
w_shape = w.shape.as_list()
w = tf.reshape(w, [-1, w_shape[-1]])
# print("w:",w.shape)#w: (48, 64) #w: (1024, 128) w: (2048, 256)
u = tf.get_variable("u", [1, w_shape[-1]], initializer=tf.truncated_normal_initializer(), trainable=False)
u_hat = u
v_hat = None
for i in range(iteration):
"""
power iteration
Usually iteration = 1 will be enough
"""
# print("u_hat:",i,u_hat.shape)#u_hat: 0 (1, 64) u_hat: 0 (1, 128) u_hat: 0 (1, 256)
v_ = tf.matmul(u_hat, tf.transpose(w))
# print("v_",v_.shape)#v_ (1, 48) #v_ (1, 1024) v_ (1, 2048)
v_hat = l2_norm(v_)
# print("v_hat:",v_hat.shape)#v_hat: (1, 48) v_hat: (1, 1024) v_hat: (1, 2048)
u_ = tf.matmul(v_hat, w)
u_hat = l2_norm(u_)
sigma = tf.matmul(tf.matmul(v_hat, w), tf.transpose(u_hat))
# print("sigma",sigma.shape)#sigma (1, 1)
w_norm = w / sigma
with tf.control_dependencies([u.assign(u_hat)]):
w_norm = tf.reshape(w_norm, w_shape)
return w_norm
2.如何使用
对于tensorflow实现的卷积神经网络,只需要对参数中的卷积核调用spectral_norm函数即可代码如下(示例):
tf.nn.conv2d(input_, spectral_norm(kernel), [1, stride, stride, 1], padding=padding
3.在自己的一个模型中的实际使用效果
使用spectral_norm前
使用spectral_norm后
总结
在生成对抗网络中,spectral_norm通常使用在鉴别器中,能够带来比较好的效果,觉得用得上的不要忘记点个赞啊。