利普希茨连续。满足如下性质的任意连续函数 f f f 称为 K-Lipschitz:
∥ f ( x 1 ) − f ( x 2 ) ∥ ≤ K ∥ x 1 − x 2 ∥ , ∀ x 1 , x 2 ∈ dom f \| f(x_1) - f(x_2) \| \leq K \| x_1 - x_2 \|,\ \forall x_1,x_2 \in \text{dom}f ∥f(x1)−f(x2)∥≤K∥x1−x2∥, ∀x1,x2∈domf
这里的 ∥ ⋅ ∥ \|\cdot\| ∥⋅∥ 常用2-范。直观上看,Lipschitz 条件限制了函数变化的剧烈程度。在DL中,由于 Lipschitz continous 的函数的梯度上界被限制,因此函数会更平滑。因此利用梯度下降进行参数更新时,参数的变化不会太大/剧烈从而降低梯度爆炸的发生概率,使模型的更新更稳定。 K K K 称为 Lipschitz constant。
那么在 DL 中,有哪些方法可用于将 f f f 限制在 K-Lipschitz 空间中?这里介绍三种:weight clipping、gradient penality、spectral normalization,一般而言,第三种的效果最佳
由 Wasserstein GAN 提出。
在利用 gradient descent 进行参数更新后,在对所有参数进行如下操作:
w = { c , if w > c − c , if w < − c w , otherwise w=\begin{cases} c, & \text{if } w > c \\ -c, & \text{if } w < -c \\ w, & \text{otherwise} \end{cases} w=⎩⎪⎨⎪⎧c,−c,w,if w>cif w<−cotherwise
其中 c c c 是人为设定的阈值。注意,Weight cplipping 并无法保证 f f f 位于 1-Lipschitz,而只能保证其是 K-Lipschitz的(K具体无法确定)
由 Improved Training of Wasserstein GANs 提出。
理论支持:一个可微函数 f f f 是 1-Lipschitz 当且仅当它对所有的输入 x x x 均满足 ∥ ∇ x f ( x ) ∥ ≤ 1 \| \nabla_x f(x) \| \leq 1 ∥∇xf(x)∥≤1,即,
f ∈ 1-Lipschitz    ⟺    ∥ ∇ x f ( x ) ∥ ≤ 1 , ∀ x ∈ dom f f \in \text{1-Lipschitz} \iff \| \nabla_x f(x) \| \leq 1, \forall x \in \text{dom}f f∈1-Lipschitz⟺∥∇xf(x)∥≤1,∀x∈domf
在具体实现时,即在 Objective function 中添加如下正则项:
min θ { L ( x , θ ) + λ max ( 0 , ∥ ∇ x f ( x ) − 1 ) ∥ } \min_{\theta} \{ \mathcal{L}(x, \theta) + \lambda \color{#F00}{\max(0, \| \nabla_x f(x) - 1) \| } \} θmin{L(x,θ)+λmax(0,∥∇xf(x)−1)∥}
公式中的 L \mathcal L L 即为 Loss/Objective function,而 f f f 为 Score function。注意,优化该目标函数后,所解出的 f f f 并无法保证一定满足 ∥ ∇ x f ( x ) ∥ ≤ 1 \| \nabla_x f(x) \| \leq 1 ∥∇xf(x)∥≤1,但 f f f 会偏向具有该属性
谱归一化,由SN-GAN提出,是目前三种方法中效果最优的方法。
下面简要介绍其非严格的理论推导,主要来自知乎,再添加上自己的一些理解
对于复合函数,存在如下定理:
∥ f ∘ g ∥ L i p ≤ ∥ f ∥ L i p ⋅ ∥ g ∥ L i p \|f \circ g\|_{Lip} \leq \| f \|_{Lip} \cdot \| g \|_{Lip} ∥f∘g∥Lip≤∥f∥Lip⋅∥g∥Lip
neutral network 正是由多个复合函数嵌套而成,最常见的嵌套方式如下: f ( g ( f ( g ( ⋯   ) ) ) ) f(g(f(g(\cdots)))) f(g(f(g(⋯)))),其中 f 表示激活函数, g g g 表示卷积操作(以CNN为例)。而 f f f 常选取 LeakyRelu,Relu,Sigmoid,Tanh,而它们均为 1-Lipschitz。因此 ∥ f ∘ g ∥ L i p ≤ ∥ f ∥ L i p ⋅ ∥ g ∥ L i p = ∥ g ∥ L i p \|f \circ g\|_{Lip} \leq \| f \|_{Lip} \cdot \| g \|_{Lip}=\| g \|_{Lip} ∥f∘g∥Lip≤∥f∥Lip⋅∥g∥Lip=∥g∥Lip,故要使得复合函数 f ∘ g f \circ g f∘g 为 1-Lipschitz,即需保证卷积操作 g g g 是 1-Lipschitz,就可以保证整个网络都是 1-Lipschitz continous 的。
在图像上每个位置的卷积操作,正好就是做如下“局部区域“的变换:
∥ unfold r a w ( M ) ⋅ unfold c o l ( x ) ∥ = y \| \text{unfold}_{raw}(M) \cdot \text{unfold}_{col}(x) \| = y ∥unfoldraw(M)⋅unfoldcol(x)∥=y
其中 x ∈ R f × f x \in R^{f×f} x∈Rf×f 为 local receptive field, M ∈ R f × f M \in R^{f×f} M∈Rf×f 为卷积核, y y y 为对应位置的卷积输出, unfold r a w ( ⋅ ) \text{unfold}_{raw}(\cdot) unfoldraw(⋅) 将 ⋅ \cdot ⋅ 按行展开成行向量, unfold c o l ( ⋅ ) \text{unfold}_{col}(\cdot) unfoldcol(⋅) 将 ⋅ \cdot ⋅ 按列展开成列向量。因此,只需保证 unfold r a w ( M ) \text{unfold}_{raw}(M) unfoldraw(M) 是 1-Lipschitz,就可以使得整个 network 是 1-Lipschitz。
对任意矩阵 A A A ( unfold r a w ( M ) \text{unfold}_{raw}(M) unfoldraw(M) 是 A A A 的一个具例),存在如下定理:
(1) A ∈ K-Lipschitz , ∀ A : R n → R m / ∀ A ∈ R m × n    ⟺    ∥ A x → ∥ ≤ K ∥ x → ∥ , ∀ x → ∈ R n    ⟺    ⟨ A x → , A x → ⟩ ≤ K 2 ⟨ x → , x → ⟩    ⟺    x → T ( A T A − K 2 I ) x → ≤ 0    ⟺    ⟨ ( A T A − K 2 I ) x → , x → ⟩ ≤ 0 \begin{array}{ll} & A \in \text{K-Lipschitz}, \forall A: R^n \to R^m / \forall A \in R^{m×n} \\[.4em] \iff& \| A \overrightarrow{x} \| \leq K \| \overrightarrow{x} \|, \forall \overrightarrow{x} \in R^n \\[.4em] \iff& \langle A \overrightarrow{x}, A \overrightarrow{x} \rangle \leq K^2 \langle \overrightarrow{x}, \overrightarrow{x} \rangle \\[.4em] \iff& \overrightarrow{x}^T (A^TA - K^2I)\overrightarrow{x} \leq 0 \\[.4em] \iff& \langle (A^TA - K^2I) \overrightarrow{x}, \overrightarrow{x} \rangle \leq 0 \end{array} \tag{1} ⟺⟺⟺⟺A∈K-Lipschitz,∀A:Rn→Rm/∀A∈Rm×n∥Ax∥≤K∥x∥,∀x∈Rn⟨Ax,Ax⟩≤K2⟨x,x⟩xT(ATA−K2I)x≤0⟨(ATA−K2I)x,x⟩≤0(1)
因 A T A A^TA ATA 为实对称矩阵,故不同特征值对应的特征向量两两正交,又因 A T A A^TA ATA 为半正定阵,故其所有特征值非负。不妨假设 A T A ∈ R n × n A^TA \in R^{n×n} ATA∈Rn×n 的特征向量为 v i → for i = 1 , 2 , ⋯   , n \overrightarrow{v_i}\ \text{for}\ i=1,2,\cdots,n vi for i=1,2,⋯,n,各自对应的特征值为 λ i for i = 1 , 2 , ⋯   , n \lambda_i\ \text{for}\ i=1,2,\cdots,n λi for i=1,2,⋯,n。因为 v → i \overrightarrow{v}_i vi 两两互相正交(不严谨,因为不一定有 n n n 个),不妨令 v i → \overrightarrow{v_i} vi 已经单位化,则它们构成 R n R^n Rn 空间的一组单位正交基。因此 x → = ∑ i = 1 n x i v i → , for ∀ x ∈ R n \overrightarrow{x} = \sum_{i=1}^n x_i \overrightarrow{v_i}, \text{ for } \forall x \in R^n x=∑i=1nxivi, for ∀x∈Rn,则续 (1):
(2) ⟨ ( A T A − K 2 I ) x → , x → ⟩ ≤ 0    ⟺    ⟨ ( A T A − K 2 I ) ∑ i = 1 n x i v i → , ∑ i = 1 n x i v i → ⟩ ≤ 0    ⟺    ∑ i = 1 n ∑ j = 1 n x i x j ⟨ ( A T A − K 2 I ) v i → , v j → ⟩ ≤ 0    ⟺    ∑ i = 1 n ∑ j = 1 n x i x j [ ( A T A − K 2 I ) v i → ] T v j → ≤ 0 \begin{array}{ll} & \langle (A^TA - K^2I) \overrightarrow{x}, \overrightarrow{x} \rangle \leq 0 \\[.4em] \iff& \langle (A^TA - K^2I) \sum_{i=1}^n x_i \overrightarrow{v_i}, \sum_{i=1}^n x_i \overrightarrow{v_i} \rangle \leq 0 \\[.4em] \iff& \sum_{i=1}^n\sum_{j=1}^n x_i x_j \langle (A^TA - K^2I) \overrightarrow{v_i}, \overrightarrow{v_j} \rangle \leq 0 \\[.4em] \iff& \sum_{i=1}^n\sum_{j=1}^n x_i x_j \left[(A^TA-K^2I) \overrightarrow{v_i}\right]^T \overrightarrow{v_j} \leq 0 \end{array} \tag{2} ⟺⟺⟺⟨(ATA−K2I)x,x⟩≤0⟨(ATA−K2I)∑i=1nxivi,∑i=1nxivi⟩≤0∑i=1n∑j=1nxixj⟨(ATA−K2I)vi,vj⟩≤0∑i=1n∑j=1nxixj[(ATA−K2I)vi]Tvj≤0(2)
又
[ ( A T A − K 2 I ) v i → ] T v j → = v i → T ( A T A − K 2 I ) v j → = v i → T A T A v j → − K 2 v i → T v j → = { 0 , if i = ̸ j ( λ i − K 2 ) ⟨ v i → , v i → ⟩ = λ i − K 2 , if i = j \begin{array}{l} \left[(A^TA-K^2I) \overrightarrow{v_i}\right]^T \overrightarrow{v_j} = \overrightarrow{v_i}^T (A^TA-K^2I)\overrightarrow{v_j} = \overrightarrow{v_i}^T A^TA \overrightarrow{v_j} - K^2 \overrightarrow{v_i}^T \overrightarrow{v_j} \\[.4em] =\begin{cases} 0, &\text{if } i =\not j \\ (\lambda_i - K^2) \langle \overrightarrow{v_i}, \overrightarrow{v_i} \rangle = \lambda_i - K^2, &\text{if } i = j \end{cases} \end{array} [(ATA−K2I)vi]Tvj=viT(ATA−K2I)vj=viTATAvj−K2viTvj={0,(λi−K2)⟨vi,vi⟩=λi−K2,if i≠jif i=j
故续 (2)
∑ i = 1 n ∑ j = 1 n x i x j [ ( A T A − K 2 I ) v i → ] T v j → ≤ 0    ⟺    ∑ i = 1 n x i 2 ( λ i − K 2 ) ≤ 0 \sum_{i=1}^n\sum_{j=1}^n x_i x_j \left[(A^TA-K^2I) \overrightarrow{v_i}\right]^T \overrightarrow{v_j} \leq 0 \iff \sum_{i=1}^n x_i^2 (\lambda_i - K^2) \leq 0 i=1∑nj=1∑nxixj[(ATA−K2I)vi]Tvj≤0⟺i=1∑nxi2(λi−K2)≤0
即
(3) A ∈ K-Lipschitz , ∀ A : R n → R m / ∀ A ∈ R m × n    ⟺    ∑ i = 1 n x i 2 ( K 2 − λ i ) ≥ 0 A \in \text{K-Lipschitz}, \forall A: R^n \to R^m / \forall A \in R^{m×n} \iff \sum_{i=1}^n x_i^2 (K^2 - \lambda_i) \geq 0 \tag{3} A∈K-Lipschitz,∀A:Rn→Rm/∀A∈Rm×n⟺i=1∑nxi2(K2−λi)≥0(3)
其中 λ i \lambda_i λi 为 A T A A^TA ATA 的第 i i i 个特征值。
不妨令 K 2 = max i ( λ i ) \color{#F00}{K^2 = \max_i(\lambda_i)} K2=maxi(λi),则必有 ∑ i = 1 n x i 2 ( K 2 − λ i ) ≥ 0 \sum_{i=1}^n x_i^2 (K^2 - \lambda_i) \geq 0 ∑i=1nxi2(K2−λi)≥0 成立,因此:
(4) K 2 = max i ( λ i ) ⇒ ( ∑ i = 1 n x i 2 ( K 2 − λ i ) ≥ 0    ⟺    A ∈ K-Lipschitz , ∀ A : R n → R m / ∀ A ∈ R m × n ) \color{#F00}{K^2 = \max_i(\lambda_i) \Rightarrow \left( \sum_{i=1}^n x_i^2 (K^2 - \lambda_i) \geq 0 \iff A \in \text{K-Lipschitz}, \forall A: R^n \to R^m / \forall A \in R^{m×n} \right)} \tag{4} K2=imax(λi)⇒(i=1∑nxi2(K2−λi)≥0⟺A∈K-Lipschitz,∀A:Rn→Rm/∀A∈Rm×n)(4)
而要令 A A A 从 K-Lipschitz 变为 1-Lipschitz,仅需对 A A A 作如下缩放即可: A : = A K A := \displaystyle\frac{A}{K} A:=KA。即, 矩阵 A 除以它的 spectral norm ( ∥ A ∥ 2 = A T A 的 最 大 特 征 值 ) 可以使其具有1-Lipschitz continuity \color{#F00}{\text{矩阵 A 除以它的 spectral norm}(\|A\|_2 = \sqrt{A^TA的最大特征值})\text{可以使其具有1-Lipschitz continuity}} 矩阵 A 除以它的 spectral norm(∥A∥2=ATA的最大特征值)可以使其具有1-Lipschitz continuity。
于是问题的关键就转变成如何求解 A T A A^TA ATA 的最大特征值 λ 1 \lambda_1 λ1 了(不妨令 λ 1 ≥ λ 2 ≥ ⋯ ≥ λ n \lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_n λ1≥λ2≥⋯≥λn),最经典的算法为 Power iteration
Power iteration 是用于近似计算方阵最大特征值和其对应特征向量的常用方法,其具体步骤如下:
上述为 Power iteration 的理论部分,而伪代码如下:
u, v = 随机初始化, None
for k iteration:
v = A^T u / |A^T u|_2 # (1)
u = A v / |A v|_2 # (2)
sqrt_lambda_1 = u^T A v # (3)
其中 A : R n → R m / A ∈ R m × n A: R^n \to R^m / A \in R^{m×n} A:Rn→Rm/A∈Rm×n, v ∈ R n , u ∈ R m v \in R^n, u \in R^m v∈Rn,u∈Rm,其中 n , m n,m n,m 分别属于输入,输出空间的维度
伪代码中的 (1) 等价于公式 (6) 的原因:
v → = A T u → ∥ A T u → ∥ 2 = A T A v → ∥ A v → ∥ 2 / ∥ A T u → ∥ 2 = α i ( A T A ) v → = α i B v → \displaystyle\overrightarrow{v} = \frac{A^T \overrightarrow{u}}{\|A^T \overrightarrow{u}\|_2} = A^T \frac{A\overrightarrow{v}}{\| A\overrightarrow{v} \|_2} /\left\| A^T \overrightarrow{u} \right\|_2 = \alpha_i (A^TA)\overrightarrow{v} = \alpha_i B \overrightarrow{v} v=∥ATu∥2ATu=AT∥Av∥2Av/∥∥∥ATu∥∥∥2=αi(ATA)v=αiBv,该公式在迭代了 k k k 次后,与上面的式 (6) 仅多乘了一个常数系数 α = ∏ i = 1 k α i \alpha=\prod_{i=1}^k \alpha_i α=∏i=1kαi,这并不影响主特征向量 v 1 → \overrightarrow{v_1} v1 的方向,因此对 v → \overrightarrow{v} v 归一化后即可得到 v 1 → \overrightarrow{v_1} v1。而在实际上,在每步迭代后,都会对 v → \overrightarrow{v} v 进行归一化,因此 v 1 → = v → \overrightarrow{v_1}=\overrightarrow{v} v1=v
伪代码中的 (3) 可求解 λ 1 \lambda_1 λ1 的原因:
∵ A T A v → = λ 1 v → , 且 ∥ v ∥ 2 = 1 ∴ v → T A T A v → = λ 1 v → T v → = λ 1 即 λ 1 = ∥ A v → ∥ 2 又 u → = A v → ∥ A v → ∥ 2 → u → T u → = u → T A v → ∥ A v → ∥ 2 → 1 = u → T A v → ∥ A v → ∥ 2 ∴ λ 1 = u → T A v → \begin{array}{ll} \because & A^TA \overrightarrow{v} = \lambda_1 \overrightarrow{v}, 且 \|v\|_2 = 1 \\[.4em] \therefore & \overrightarrow{v}^TA^TA\overrightarrow{v} = \lambda_1\overrightarrow{v}^T\overrightarrow{v} = \lambda_1 \\[.4em] 即 & \sqrt{\lambda_1} = \| A \overrightarrow{v} \|_2 \\[.4em] 又 & \displaystyle\overrightarrow{u} = \frac{A \overrightarrow{v}}{\| A \overrightarrow{v} \|_2} \to \overrightarrow{u}^T \overrightarrow{u} = \frac{\overrightarrow{u}^T A \overrightarrow{v}}{\| A \overrightarrow{v} \|_2} \to 1 = \frac{\overrightarrow{u}^T A \overrightarrow{v}}{\| A \overrightarrow{v} \|_2} \\[.4em] \therefore & \sqrt{\lambda_1} = \overrightarrow{u}^T A \overrightarrow{v} \end{array} ∵∴即又∴ATAv=λ1v,且∥v∥2=1vTATAv=λ1vTv=λ1λ1=∥Av∥2u=∥Av∥2Av→uTu=∥Av∥2uTAv→1=∥Av∥2uTAvλ1=uTAv
def spectral_norm(W, is_training, iteration=1):
'''
W: [f, f, in_c, out_c]
'''
shape = W.get_shape().as_list() # [f, f, in_c, out_c]
W = tf.reshape(W, [-1, shape[-1]]) # [N, out_c], 其中 N=f*f*in_c
# reshape,即理论推导里所说的展开操作——以通道为单位将 M 展开
u = tf.get_variable(shape=[1, shape[-1]],
trainable=False,
initializer=...)
# power iteration
u_norm, v_norm = u, None
for k in range(iteration):
v_norm = tf.matmul(u_norm, W, transpose_b=True) # [1, N]
v_norm = tf.math.l2_normalize(v_norm)
u_norm = tf.matmul(v_norm, W) # [1, out_c]
u_norm = tf.math.l1_normalize(u_norm)
lambda_sqrt = tf.matmul(v_norm, W)
lambda_sqrt = tf.matmul(u_norm, lambda_sqrt, transpose_b=True)
# spectral norm
W_sn = W / lambda_sqrt
# update estimated 1st singular vector while training
with tf.control_dependencies([tf.cond(is_training,
lambda: u.assign(u_norm),
lambda: u.assign(u))]):
W_norm = tf.reshape(W_norm, shape)
return W_norm