DL中常用的三种K-Lipschitz技术

文章目录

  • Lipschitz continuity
  • Weight clipping
  • Gradient penalty
  • Spectral Normalization
    • 理论推导
    • Power iteration
    • Tensorflow 实现

在进入到正题前,首先来了解下什么是 K-Lipschitz 以及它在 DL 中能起到什么作用

Lipschitz continuity

利普希茨连续。满足如下性质的任意连续函数 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)Kx1x2, x1,x2domf
这里的 ∥ ⋅ ∥ \|\cdot\| 常用2-范。直观上看,Lipschitz 条件限制了函数变化的剧烈程度。在DL中,由于 Lipschitz continous 的函数的梯度上界被限制,因此函数会更平滑。因此利用梯度下降进行参数更新时,参数的变化不会太大/剧烈从而降低梯度爆炸的发生概率,使模型的更新更稳定。 K K K 称为 Lipschitz constant。

那么在 DL 中,有哪些方法可用于将 f f f 限制在 K-Lipschitz 空间中?这里介绍三种:weight clipping、gradient penality、spectral normalization,一般而言,第三种的效果最佳

Weight clipping

由 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具体无法确定)

Gradient penalty

由 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 f1-Lipschitzxf(x)1,xdomf
在具体实现时,即在 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 会偏向具有该属性

Spectral Normalization

谱归一化,由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} fgLipfLipgLip
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} fgLipfLipgLip=gLip,故要使得复合函数 f ∘ g f \circ g fg 为 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} xRf×f 为 local receptive field, M ∈ R f × f M \in R^{f×f} MRf×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} AK-Lipschitz,A:RnRm/ARm×nAx Kx ,x RnAx ,Ax K2x ,x x T(ATAK2I)x 0(ATAK2I)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} ATARn×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 v i 两两互相正交(不严谨,因为不一定有 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 xRn,则续 (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} (ATAK2I)x ,x 0(ATAK2I)i=1nxivi ,i=1nxivi 0i=1nj=1nxixj(ATAK2I)vi ,vj 0i=1nj=1nxixj[(ATAK2I)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} [(ATAK2I)vi ]Tvj =vi T(ATAK2I)vj =vi TATAvj K2vi Tvj ={0,(λiK2)vi ,vi =λiK2,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=1nj=1nxixj[(ATAK2I)vi ]Tvj 0i=1nxi2(λiK2)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} AK-Lipschitz,A:RnRm/ARm×ni=1nxi2(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=1nxi2(K2λi)0AK-Lipschitz,A:RnRm/ARm×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 normA2=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 是用于近似计算方阵最大特征值和其对应特征向量的常用方法,其具体步骤如下:

  1. B = A T A ∈ R n × n \color{#F00}{B = A^TA \in R^{n×n}} B=ATARn×n ,假设 B B B 是一个 n × n n×n n×n 的满秩方阵,其单位特征向量为 v 1 → , v 2 → , ⋯   , v n → ∈ R n \overrightarrow{v_1},\overrightarrow{v_2},\cdots,\overrightarrow{v_n} \in R^n v1 ,v2 ,,vn Rn,对应特征值为 λ 1 → , λ 2 → , ⋯   , λ n → \overrightarrow{\lambda_1},\overrightarrow{\lambda_2},\cdots,\overrightarrow{\lambda_n} λ1 ,λ2 ,,λn (因 B B B 实对称,故 v 1 → , ⋯   , v n → \overrightarrow{v_1},\cdots,\overrightarrow{v_n} v1 ,,vn 相互正交)。那么对任意向量 x → ∈ R n \overrightarrow{x} \in R^n x Rn 均可写成 x → = ∑ i = 1 n x i v i → \overrightarrow{x} = \sum_{i=1}^n x_i \overrightarrow{v_i} x =i=1nxivi ,有:
    B x → = B ∑ i = 1 n x i v i → = ∑ i = 1 n x i λ i v i → \begin{array}{lll} B \overrightarrow{x} &=& B \sum_{i=1}^n x_i \overrightarrow{v_i} \\[.4em] &=& \sum_{i=1}^n x_i \lambda_i \overrightarrow{v_i} \end{array} Bx ==Bi=1nxivi i=1nxiλivi
    经过 k k k 次迭代后:
    (5) B k x → = ∑ i = 1 n x i λ i k v i → = λ 1 k x 1 v 1 → + ∑ i = 2 n x i ( λ i λ 1 ) k v i → B^k\overrightarrow{x} = \sum_{i=1}^n x_i \lambda_i^k \overrightarrow{v_i} = \lambda_1^k x_1 \overrightarrow{v_1} + \sum_{i=2}^n x_i \left(\frac{\lambda_i}{\lambda_1}\right)^k \overrightarrow{v_i} \tag{5} Bkx =i=1nxiλikvi =λ1kx1v1 +i=2nxi(λ1λi)kvi (5)
    不妨假定 λ 1 > λ 2 > ⋯ > λ n \lambda_1 > \lambda_2 > \cdots > \lambda_n λ1>λ2>>λn(不考虑特征值相等的情况,因为这在实际中很少见),因此, lim ⁡ k → ∞ ( λ i λ 1 ) k = 0 \displaystyle\lim_{k \to \infty} \left(\frac{\lambda_i}{\lambda_1}\right)^k = 0 klim(λ1λi)k=0,故式 (5) 可进一步化为:
    (6) B k x → ≈ λ 1 k x 1 v 1 → B^k\overrightarrow{x} \approx \lambda_1^k x_1 \overrightarrow{v_1} \tag{6} Bkx λ1kx1v1 (6)
    即经过 k k k 次迭代后,我们将得到特征向量 v 1 → \overrightarrow{v_1} v1 的线性缩放,只要将 B k x → B^k \overrightarrow{x} Bkx 归一化就可得到主特征向量 v 1 → \overrightarrow{v_1} v1 ,进而再利用 B v 1 → = λ 1 v 1 → B \overrightarrow{v_1} = \lambda_1 \overrightarrow{v_1} Bv1 =λ1v1 解得 λ 1 \lambda_1 λ1

上述为 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:RnRm/ARm×n v ∈ R n , u ∈ R m v \in R^n, u \in R^m vRn,uRm,其中 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 =ATAv 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 ,v2=1v TATAv =λ1v Tv =λ1λ1 =Av 2u =Av 2Av u Tu =Av 2u TAv 1=Av 2u TAv λ1 =u TAv

Tensorflow 实现

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

你可能感兴趣的:(DL中常用的三种K-Lipschitz技术)