第 14 章:自编码器(Autoencoders)
自编码器(autoencoder)是一种神经网络,被训练来把输入复制到输出。在内部,它有一个隐藏层 \(h\),用来描述表示输入的 code。网络可以看作由两部分组成:编码器函数 \(h = f(x)\) 与生成重构的解码器 \(r = g(h)\)。如果自编码器仅仅是把 \(g(f(x)) = x\) 在整个空间上学会,那它就没什么用处。自编码器被设计成不能完美地学会复制:通常它们受到约束,只允许近似地复制,并且只复制那些与训练数据相似的输入。因为模型被迫去选择输入的哪些方面应该被复制,所以它常常能学到数据中有用的属性。
现代自编码器已经把编码器和解码器从确定性函数推广到随机映射 \(p_{\mathrm{encoder}}(h \mid x)\) 与 \(p_{\mathrm{decoder}}(x \mid h)\)。自编码器的想法在神经网络几十年的历史中一直存在(LeCun, 1987; Bourlard and Kamp, 1988; Hinton and Zemel, 1994)。传统上,自编码器用于降维或特征学习。最近,自编码器与潜变量模型之间的理论联系把它推到了生成模型的前沿,这一点将在第 20 章看到。自编码器可以视为前馈网络的特例,可以用所有相同的技术来训练,通常是用反向传播计算梯度的小批量梯度下降。与一般前馈网络不同,自编码器也可以用再循环(recirculation, Hinton and McClelland, 1988)来训练,这是一种基于比较网络在原始输入与重构输入上的激活的学习算法。再循环被视为比反向传播更符合生物学,但很少用于机器学习应用。
14.1 欠完备自编码器
把输入复制到输出听起来没什么用,但我们通常不关心解码器的输出;真正希望的是,把自编码器训练去完成输入复制任务,能让 \(h\) 呈现出有用的性质。从自编码器获得有用特征的一种方法是约束 \(h\) 的维度比 \(x\) 小。code 维度小于输入维度的自编码器称为欠完备(undercomplete)。学习欠完备表示迫使自编码器抓住训练数据最显著的特征。学习过程可以简单地描述为最小化一个损失函数
14.2 正则化自编码器
欠完备自编码器(code 维度小于输入维度)能学到数据分布最显著的特征;我们已经看到,如果编码器和解码器容量太大,它们就学不到任何有用的东西。一个类似的问题在隐藏 code 维度等于输入维度、以及过完备(code 维度大于输入维度)时也会出现。在这些情况下,即使编码器和解码器是线性的,也能在学不到数据分布任何有用信息的情况下把输入复制到输出。理想情况下,我们可以成功训练任何架构的自编码器,根据要建模分布的复杂度选择 code 维度以及编码器、解码器的容量。正则化自编码器(regularized autoencoder)允许这样做。它不靠让编码器和解码器很浅、code 维度很小来限制模型容量,而是使用一个损失函数,鼓励模型除"把输入复制到输出"之外还具有其他性质。这些性质包括表示的稀疏性、表示导数的大小,以及对噪声或缺失输入的鲁棒性。正则化自编码器可以是非线性的、过完备的,但即使模型容量足以学会平凡恒等函数,仍能学到数据分布有用的东西。除了这里介绍的方法之外,几乎任何有潜变量、并配有推理过程(给定输入计算潜表示)的生成模型,都可以视为自编码器的特定形式。强调与自编码器这种联系的两种生成建模方法是 Helmholtz machine 的后代(Hinton et al., 1995b),比如变分自编码器(第 20.10.3 节)和生成随机网络(第 20.12 节)。这些模型自然地学到输入的高容量、过完备编码,并且不需要对编码正则化就使其有用。它们的编码之所以自然有用,是因为模型被训练去近似最大化训练数据的概率,而不是把输入复制到输出。
14.2.1 稀疏自编码器
稀疏自编码器(sparse autoencoder)是训练准则中除了重构误差外、还在 code 层 \(h\) 上加了稀疏惩罚 \(\Omega(h)\) 的自编码器:
稀疏自编码器的早期工作(Ranzato et al., 2007a, 2008)探索了各种形式的稀疏性,并提出了稀疏惩罚与对无向概率模型 \(p(x) = \tilde{p}(x)/Z\) 做最大似然时出现的 \(\log Z\) 项之间的联系。其想法是,最小化 \(\log Z\) 防止概率模型到处都有高概率,对自编码器施加稀疏性防止自编码器到处都有低重构误差。在这个意义上,这种联系是直觉层面的普遍机制理解,而非数学上的严格对应。把稀疏惩罚解释为有向模型 \(p_{\mathrm{model}}(h) p_{\mathrm{model}}(x \mid h)\) 中的 \(\log p_{\mathrm{model}}(h)\),在数学上更为直接。
让稀疏(以及去噪)自编码器在 \(h\) 中获得真正零值的一种方法由 Glorot et al. (2011b) 引入。思路是用 ReLU 产生 code 层。配合一个真正把表示推向零的先验(如绝对值惩罚),就可以间接控制表示中零的平均数量。
14.2.2 去噪自编码器
与其给代价函数加一个惩罚 \(\Omega\),我们可以通过改变代价函数中的重构误差项来获得一个学到有用东西的自编码器。传统上,自编码器最小化某个函数
14.2.3 通过惩罚导数来正则化
正则化自编码器的另一种策略是像稀疏自编码器那样使用一个惩罚 \(\Omega\),
14.3 表示能力、层大小与深度
自编码器常常只用单层编码器和单层解码器来训练,但这并不是必须的。事实上,使用深度编码器和解码器带来很多好处。回想第 6.4.1 节,前馈网络中深度有很多好处。因为自编码器是前馈网络,这些好处同样适用于自编码器。此外,编码器本身就是一个前馈网络,解码器也是一个,因此自编码器的这两个组成部分都能各自从深度中获益。深度的一个主要好处是:万能逼近定理保证,至少有一个隐藏层的前馈神经网络能以任意精度(在广泛一类函数中)逼近任意函数,只要隐藏单元足够多。这意味着单隐藏层的自编码器能够在数据的定义域上任意好地表示恒等函数,但从输入到 code 的映射是浅的。这意味着我们没法强制任意约束,比如 code 应该是稀疏的。一个深度自编码器(编码器本身至少还有一个额外的隐藏层),只要隐藏单元足够多,就能以任意精度逼近任意输入到 code 的映射。深度可以指数级地降低表示某些函数的计算成本。深度也可以指数级地减少学习某些函数所需的训练数据量。深度在前馈网络中的好处在第 6.4.1 节有综述。实验上,深度自编码器比对应的浅层或线性自编码器产生好得多的压缩(Hinton and Salakhutdinov, 2006)。训练深度自编码器的一个常见策略是通过训练一组堆叠的浅层自编码器来贪心地预训练深度架构,所以即使最终目标是训练深度自编码器,我们也常常遇到浅层自编码器。
14.4 随机编码器与解码器
自编码器就是前馈网络。传统前馈网络能用的损失函数和输出单元类型,自编码器也能用。正如第 6.2.2.4 节所述,设计前馈网络的输出单元和损失函数的一个通用策略是定义一个输出分布 \(p(y \mid x)\) 并最小化负对数似然 \(-\log p(y \mid x)\)。那个场景下,\(y\) 是目标向量,比如类标签。在自编码器场景下,\(x\) 既是目标也是输入。然而我们仍然可以套用同样的机制。给定隐藏 code \(h\),我们可以把解码器视为提供一个条件分布 \(p_{\mathrm{decoder}}(x \mid h)\)。然后我们通过最小化 \(-\log p_{\mathrm{decoder}}(x \mid h)\) 来训练自编码器。这个损失函数的确切形式会随 \(p_{\mathrm{decoder}}\) 的形式而变。与传统前馈网络一样,如果 \(x\) 是实值的,我们通常用线性输出单元参数化 Gaussian 的均值;此时负对数似然给出均方误差准则。类似地,二值 \(x\) 对应一个 Bernoulli 分布,其参数由 sigmoid 输出单元给出;离散 \(x\) 对应 softmax 分布,等等。通常输出变量在给定 \(h\) 时被当作条件独立的,从而让这个概率分布的评估代价低,但像混合密度输出这类技术允许对有关联的输出做可处理的建模。为了比之前看到的前馈网络做出更根本的改变,我们也可以把编码函数 \(f(x)\) 的概念推广为编码分布 \(p_{\mathrm{encoder}}(h \mid x)\),如图 14.2 所示。任何潜变量模型 \(p_{\mathrm{model}}(h, x)\) 都定义一个随机编码器
14.5 去噪自编码器
去噪自编码器(DAE)接收一个被污染的数据点作为输入,并被训练去预测原始的、未被污染的数据点作为输出。DAE 的训练过程如图 14.3 所示。我们引入一个污染过程 \(C(\tilde{x} \mid x)\),它表示给定数据样本 \(x\) 时被污染样本 \(\tilde{x}\) 上的一个条件分布。然后自编码器从训练对 \((x, \tilde{x})\) 学习一个重构分布 \(p_{\mathrm{reconstruct}}(x \mid \tilde{x})\),方法如下:(1) 从训练数据中采样一个训练样本 \(x\);(2) 从 \(C(\tilde{x} \mid x = x)\) 中采样一个被污染版本 \(\tilde{x}\);(3) 用 \((x, \tilde{x})\) 作为训练样本来估计自编码器重构分布 \(p_{\mathrm{reconstruct}}(x \mid \tilde{x}) = p_{\mathrm{decoder}}(x \mid h)\),其中 \(h\) 是编码器 \(f(\tilde{x})\) 的输出,\(p_{\mathrm{decoder}}\) 通常由解码器 \(g(h)\) 定义。通常我们只需在负对数似然 \(-\log p_{\mathrm{decoder}}(x \mid h)\) 上做基于梯度的近似最小化(比如小批量梯度下降)。只要编码器是确定性的,去噪自编码器就是一个前馈网络,可以用与其他前馈网络完全一样的技术训练。因此我们可以把 DAE 视为在如下期望上做随机梯度下降:
DAE 的一个非常重要的性质是,它的训练准则(在 \(p(x \mid h)\) 是条件 Gaussian 的情况下)使自编码器学到向量场 \((g(f(\tilde{x})) - x)\),这个向量场估计数据分布的 score。这一点如图 14.4 所示。
一种特定自编码器(sigmoid 隐藏单元、线性重构单元)的去噪训练,使用 Gaussian 噪声和均方误差作为重构代价,等价于(Vincent, 2011)训练一种特定的无向概率模型,称为带 Gaussian 可见单元的 RBM。这种模型将在第 20.5.1 节详细介绍;对当前讨论而言,知道它是一个显式给出 \(p_{\mathrm{model}}(x; \theta)\) 的模型就够了。当 RBM 用去噪 score matching(Kingma and LeCun, 2010)训练时,其学习算法等价于对应自编码器中的去噪训练。在固定噪声水平下,正则化的 score matching 不是一个一致估计量;它恢复的是分布的一个模糊版本。然而,如果样本数趋于无穷时噪声水平趋于 0,一致性得以恢复。去噪 score matching 在第 18.5 节有更详细的讨论。自编码器和 RBM 之间还有其他联系。对 RBM 应用 score matching 得到的代价函数与重构误差加上一个类似于 CAE 收缩惩罚的正则项相同(Swersky et al., 2011)。Bengio and Delalleau (2009) 表明,自编码器梯度提供了 RBM 对比散度训练的近似。对于连续值 \(x\),带 Gaussian 污染和重构分布的去噪准则给出了适用于一般编码器和解码器参数化的 score 估计量(Alain and Bengio, 2013)。这意味着通过用平方误差准则 \(\|g(f(\tilde{x})) - x\|^2\) 和污染 \(C(\tilde{x} = \tilde{x} \mid x) = \mathcal{N}(\tilde{x}; \mu = x, \Sigma = \sigma^2 I)\) 训练,通用编码器-解码器架构可以被做成估计 score,其中 \(\sigma^2\) 是噪声方差。一般而言,重构 \(g(f(x))\) 减去输入 \(x\) 并不一定对应任何函数的梯度,更别说对应 score。这就是为什么早期结果(Vincent, 2011)专门针对那些 \(g(f(x)) - x\) 可以由另一个函数的导数得到的特定参数化。Kamyshanska and Memisevic (2015) 通过识别一族浅层自编码器推广了 Vincent (2011) 的结果:在这族所有成员上,\(g(f(x)) - x\) 都对应一个 score。到目前为止,我们只讨论了去噪自编码器如何学习表示一个概率分布。更一般地,我们可能希望把自编码器用作生成模型并从这个分布中采样。这一点将在第 20.11 节讨论。
从历史视角看:用 MLP 做去噪的想法可以追溯到 LeCun (1987) 和 Gallinari et al. (1987)。Behnke (2001) 也用循环网络对图像去噪。去噪自编码器在某种意义上就是被训练去做去噪的 MLP。然而,"去噪自编码器"这个名字指的是一个模型,其目的不仅是学会去噪输入,而是作为去噪的副作用学到一种好的内部表示。这个想法出现得更晚(Vincent et al., 2008, 2010)。学到的表示随后可以用于预训练更深的无监督网络或有监督网络。与稀疏自编码器、稀疏编码、收缩自编码器以及其他正则化自编码器一样,DAE 的动机都是允许学习一个非常高容量的编码器,同时防止编码器和解码器学到无用的恒等函数。在现代 DAE 出现之前,Inayoshi and Kurita (2005) 用一些类似的方法探索过类似的目标。他们的方法在有监督 MLP 的隐藏层注入噪声,最小化重构误差加上有监督目标,目的是通过引入重构误差和注入的噪声来改善泛化。然而,他们的方法基于线性编码器,不能学到像现代 DAE 那样强大的函数族。
14.6 用自编码器学习流形
与许多其他机器学习算法一样,自编码器利用数据集中于一个低维流形或一组低维流形附近的这一思想,如第 5.11.3 节所述。一些机器学习算法只是在这个意义上利用这个思想:它们学习一个在流形上行为正确、但在流形外被给到输入时可能表现奇怪的函数。自编码器把这个思想推得更远,目标是学习流形的结构。要理解自编码器如何做到这一点,我们必须先介绍流形的一些重要性质。流形的一个重要刻画是它的切平面(tangent plane)集合。在流形上一个 \(d\) 维点 \(x\) 处,切平面由 \(d\) 个基向量给出,它们张成流形上允许变化的局部方向。如图 14.6 所示,这些局部方向规定了在流形上如何对 \(x\) 做无穷小变化。所有自编码器训练过程都涉及两种力之间的权衡:(1) 学习训练样本 \(x\) 的一个表示 \(h\),使得 \(x\) 可以通过解码器从 \(h\) 中近似恢复。\(x\) 从训练数据中采出这一点至关重要,因为它意味着自编码器不需要成功重构那些在数据生成分布下不太可能出现的输入。(2) 满足约束或正则惩罚。这可以是一个限制自编码器容量的架构约束,也可以是一个加在重构代价上的正则项。这些技术通常偏好对输入不那么敏感的解。显然,单独任何一种力都没用——把输入复制到输出本身没有用,忽略输入也没有用。相反,这两种力合在一起有用,是因为它们迫使隐藏表示捕获数据生成分布的结构。重要的原则是,自编码器只需表示为了重构训练样本所需要的变化。如果数据生成分布集中于一个低维流形附近,这就隐式地产生该流形的局部坐标系:只需让沿流形在 \(x\) 附近的变化对应于 \(h = f(x)\) 的变化。因此编码器学习到从输入空间 \(x\) 到表示空间的映射,这个映射只对沿流形方向的变化敏感,而对垂直于流形方向的变化不敏感。一个一维的例子如图 14.7 所示,通过让重构函数对数据点附近输入的扰动不敏感,我们使自编码器恢复了流形结构。要理解自编码器为什么对流形学习有用,把它们与其他方法做比较是有启发性的。最常学到的用以刻画流形的是数据点在流形上(或附近)的表示。这种对特定样本的表示也叫做它的 embedding(嵌入)。它通常是一个低维向量,维度少于流形作为低维子集所处的那个"环境"空间。一些算法(非参数流形学习算法,下面会讨论)直接为每个训练样本学习一个 embedding;另一些则学习一个更通用的映射(有时叫做 encoder 或 representation function),把环境空间(输入空间)的任意点映射到它的 embedding。流形学习主要聚焦于无监督学习过程,试图捕获这些流形。早期关于非线性流形学习的机器学习研究大多聚焦于基于近邻图(nearest-neighbor graph)的非参数方法。这个图的每个训练样本是一个节点,节点之间通过近邻关系连边。这些方法(Schölkopf et al., 1998; Roweis and Saul, 2000; Tenenbaum et al., 2000; Brand, 2003; Belkin and Niyogi, 2003; Donoho and Grimes, 2003; Weinberger and Saul, 2004; Hinton and Roweis, 2003; van der Maaten and Hinton, 2008)把每个节点关联到一个切平面,这个切平面张成由样本与其近邻之间差向量所对应的变化方向,如图 14.8 所示。然后可以通过优化或解一个线性系统获得一个全局坐标系。图 14.9 展示了一个流形如何被大量局部线性的 Gaussian-like patch(或者叫"薄饼",因为这些 Gaussian 在切线方向上很扁)所铺成。然而,这种局部非参数流形学习方法存在一个根本性的困难,Bengio and Monperrus (2005) 提出过:如果流形不是很光滑(有很多峰、谷和扭转),那么可能需要非常多的训练样本来覆盖每一个这样的变化,而没有机会泛化到未见过的变化。事实上,这些方法只能通过在近邻样本之间插值来泛化流形的形状。不幸的是,AI 问题中涉及的流形可能具有非常复杂的结构,仅靠局部插值难以捕获。例如,考虑图 14.6 所示由平移产生的流形。如果我们观察输入向量内的一个坐标 \(x_i\),随着图像被平移,我们会看到这个坐标每遇到一次图像亮度中的峰或谷,它的值就出现一次峰或谷。换言之,底层图像模板中亮度模式的复杂度驱动了通过对图像做简单变换所产生的流形的复杂度。这激励我们使用分布式表示和深度学习来捕获流形结构。
14.7 收缩自编码器
收缩自编码器(CAE, Rifai et al., 2011a,b)在 code \(h = f(x)\) 上引入一个显式的正则项,鼓励 \(f\) 的导数尽可能小:
14.8 预测稀疏分解
预测稀疏分解(PSD)是稀疏编码与参数化自编码器的一种混合模型(Kavukcuoglu et al., 2008)。一个参数化编码器被训练去预测迭代推断的输出。PSD 已被应用于图像和视频中物体识别的无监督特征学习(Kavukcuoglu et al., 2009, 2010; Jarrett et al., 2009; Farabet et al., 2011),以及音频(Henaff et al., 2011)。模型由一个编码器 \(f(x)\) 和一个解码器 \(g(h)\) 组成,二者都是参数化的。在训练期间,\(h\) 由优化算法控制。训练通过最小化
14.9 自编码器的应用
自编码器已被成功地应用于降维和信息检索任务。降维是表示学习和深度学习的最初应用之一,也是早期研究自编码器的动机之一。例如 Hinton and Salakhutdinov (2006) 训练了一组堆叠的 RBM,然后用它们的权重初始化一个深度自编码器,隐藏层逐渐减小,最终在瓶颈处达到 30 个单元。得到的 code 比到 30 维的 PCA 产生更小的重构误差,学到的表示在定性上也更容易解释并与底层类别相关,这些类别表现为良好分离的聚类。低维表示可以提升许多任务(如分类)的性能。较小空间的模型消耗更少的内存和运行时间。许多形式的降维把语义相关的样本放在彼此附近,正如 Salakhutdinov and Hinton (2007b) 和 Torralba et al. (2008) 所观察到的。到低维空间的映射所提供的提示有助于泛化。比其他任务受益更多的一项任务是信息检索,即在数据库中找到与查询项相似的条目。这项任务除了享有降维的常规好处之外,还享有额外的便利:在某些特定类型的低维空间中,搜索可以变得极其高效。具体而言,如果我们训练降维算法产生的 code 是低维且二值的,那么我们可以把所有数据库条目存放在一个把二值 code 向量映射到条目的哈希表中。这个哈希表允许我们通过返回与查询具有相同二值 code 的所有数据库条目来做信息检索。我们也可以通过翻转查询编码中的单个 bit 来极其高效地搜索略微不太相似的条目。这种通过降维和二值化进行信息检索的方法称为语义哈希(semantic hashing, Salakhutdinov and Hinton, 2007b, 2009b),已被应用于文本输入(Salakhutdinov and Hinton, 2007b, 2009b)和图像(Torralba et al., 2008; Weiss et al., 2008; Krizhevsky and Hinton, 2011)。要为语义哈希生成二值 code,通常在最后一层使用带 sigmoid 的编码函数。sigmoid 单元必须被训练为对所有输入值都饱和到接近 0 或接近 1。一个能完成这件事的简单技巧是在训练中恰好在 sigmoid 非线性之前注入加性噪声。噪声的大小应该随时间增加。为了对抗这种噪声并保留尽可能多的信息,网络必须增大 sigmoid 输入的幅值,直到饱和发生。学习哈希函数的思想已在多个方向上被进一步探索,包括训练表示使其优化一个与在哈希表中查找近邻样本任务更直接相关的损失(Norouzi and Fleet, 2011)。
本章个人批注
读完这一章最让我停下来想的是第 14.6 节那段关于"流形局部插值无法泛化"的论证。它把第 5.11.3 节里那个"数据集中在低维流形附近"的设定从直觉推到了结构性的困难:近邻图方法受困于"只能插值,不能外推",而 AI 问题中简单的图像变换(如平移)就能产生极其复杂的流形——这条论证让我立刻想到它和我之前在流形学习综述里读过的内容形成了对照,也再次确认了第 6.4.1 节"深度带来指数级表示效率"在自编码器语境下并非泛泛之谈。第 14.5.1 节关于去噪 score 等价性的部分则是一个有趣的连接节点:把 RBM 用去噪 score matching 训练等价于自编码器做去噪训练——这条等价链把无向概率模型、有向潜变量模型、以及正则化自编码器这三类方法在同一根线上串了起来。CAE 的"局部收缩、全局可能扩张"这一性质(第 14.7 节)我之前没仔细想过,值得回头去看图 14.7 的玩具例子。第 14.8 节的 PSD 提醒我稀疏编码(第 13.4 节)和自编码器在"用参数化编码器近似迭代推断"这个抽象上其实是同一类思想的两个实例。
与上下章的衔接
承接第 13 章讨论的线性因子模型(概率 PCA、因子分析、ICA、稀疏编码等),第 14 章把"潜变量表示学习"从线性推广到非线性,并把生成式潜变量模型与前馈自监督学习这两条传统上分开的线索合到了一起:自编码器既可以视为一种特殊的前馈网络,也可以视为"任何带潜变量和推理过程的生成模型"的通用框架。这一章特别突出的连接是:第 14.2.1 节把稀疏自编码器重新解读为对带 Laplace 先验的生成模型的最大似然近似,从而把它从第 13.4 节的稀疏编码框架接回来;第 14.5 节把去噪自编码器与 score matching 串起来,并指出它可以解释为对数据分布的 score 估计。第 14.9 节把降维这一传统应用(包含第 13 章 PCA 的非线性版本)落实到语义哈希这一具体技术上,为后面第 20 章深入展开生成模型(包括第 20.10.3 节的变分自编码器、第 20.11 节的生成式去噪自编码器、以及第 20.12 节的生成随机网络)做了概念上的铺垫:所有这些后续模型都可以被视为这一章所建立的"自编码器=带潜变量和推理过程的生成模型"这一视角的具体实例。