GAN 的谱归一化(Spectral Norm)和矩阵的奇异值分解(Singular Value Decompostion)

WGAN 和 Wasserstein distance 在文献 [2] 中作者分析了 GAN [1] 难以训练的原因在于原生 GAN 的目标函数等价于优化生成数据的分布 $p_g$ 和真实数据的分布 $p_r$ 之间的 J-S 散度 (Jensen–Shannon Divergence)。 接着作者提出 WGAN [3],使用性质优良的 Wasserstein distance 代替原生 GAN 中的 J-S 散度。 然后利用KR对偶原理将 Wasserstein distance的求解问题转换为求解最优的利普希茨连续函数的问题。 为了使得判别器 D 满足利普希茨连续性,作者使用“梯度裁剪”将过大的参数直接裁剪到一个阈值以下。 本文要介绍的这篇文章 “Spectral normalization for generative adversarial network” (以下简称 Spectral Norm) 使用一种更优雅的方式使得判别器 D 满足 利普希茨连续性。 为了说明 Spectral Norm背后的动机,我们从 Wasserstein distance (以下简称 W distance)开始说起。 W distance的定义为: \begin{equation} \begin{split} \text{Was}(p_r, p_g) &= \inf_{\gamma \in \prod(p_r, p_g)} \int_{x, y} \gamma(x, y) \cdot \lVert x-y \rVert \\ &= \inf_{\gamma \in \prod(p_r, p_g)} \mathbb{E} [\lVert x - y\rVert] \end{split} \label{eq:wasserstein} \end{equation} $\ref{eq:wasserstein}$ 的定义看起来比较难懂。 其中 $\inf$ 可以简单地理解为 取最小值, $\gamma \in \prod_{p_r, p_g}$ 表示边缘分布分别为为 $p_r$ 和 $p_g$ 的一个联合分布。
Read more

PyTorch与caffe中SGD算法实现的一点小区别

最近在复现之前自己之前的一个paper的时候发现PyTorch与caffe在实现SGD优化算法时有一处不太引人注意的区别,导致原本复制caffe中的超参数在PyTorch中无法复现性能。 这个区别于momentum系数$\mu$有关。简单地说,文献[1]和caffe的实现中,学习率放到了参数更新量$v_t$内部; 而在PyTorch的实现里,参数更新量根据momentum和当前损失对参数的梯度$\Delta f(\theta)$,求得,而后在更新参数的时候再乘上学习率。 在学习率$\varepsilon$固定的情况下,这两种实现是等价的。 但通常我们会在训练过程中降低(有部分情况会提高)学习率,这样导致了训练的不稳定。 假设目标函数是 $f(\theta)$ ,目标函数的导数是$\Delta f(\theta_t)$,那么[1]和caffe根据以下公式更新参数 $\theta$ : $$ \begin{equation} v_{t+1} = \mu v_t - \varepsilon \Delta f(\theta_t) \end{equation} $$ $$ \begin{equation} \begin{split} \theta_{t+1} &= \theta_t + v_{t+1}\\ & = \theta_t + \mu \cdot v_t - \varepsilon \cdot \Delta f(\theta) \end{split} \end{equation} $$ (1)式中$\Delta f(\theta_t)$表示目标函数的导数,$\mu$表示momentum的系数(在[1]中被称为velocity),$\varepsilon$表示学习率。 我们先看caffe关于这部分的实现(代码在 https://github.com/BVLC/caffe/blob/99bd99795dcdf0b1d3086a8d67ab1782a8a08383/src/caffe/solvers/sgd_solver.cpp#L232-L234) template <typename Dtype> void SGDSolver<Dtype>::ComputeUpdateValue(int param_id, Dtype rate) { const vector<Blob<Dtype>*>& net_params = this->net_->learnable_params(); const vector<float>& net_params_lr = this->net_->params_lr(); Dtype momentum = this->param_.
Read more