第 12 章:应用(Applications)
12.1 大规模深度学习
本章开篇定调:深度学习在连接主义哲学下成立——单个生物神经元或单个机器学习特征并不智能,但由大量神经元或特征协同作用后能展现智能行为。作者强调,神经网络的"规模"是 1980 年代以来精度提升与可解任务复杂化的关键因素。1.2.3 节已经指出,过去三十年网络规模呈指数增长,但人工神经网络的规模仍仅与昆虫神经系统相当。规模既然如此重要,深度学习就必须依托高性能的硬件与软件基础设施。这一节以这一论点为引子展开 12.1.1–12.1.6 的六个子节,分别讨论快速 CPU 实现、GPU 实现、大规模分布式实现、模型压缩、动态结构以及专用硬件实现。
12.1.1 快速 CPU 实现
作者回顾,神经网络训练最初是基于单机 CPU 的,如今这种做法普遍被认为不够用,当前主流是 GPU 计算或多机联网 CPU。即便如此,研究者仍花过大量精力证明 CPU 不能胜任神经网络的高强度工作负载。本书不展开高效 CPU 数值代码的实现细节,但强调针对特定 CPU 家族做精细化实现能带来巨大收益。2011 年的实验显示,当时最好的 CPU 在跑神经网络负载时使用定点算术比浮点算术更快。Vanhoucke 等人(2011)通过精心调优的定点实现,在强浮点系统上取得三倍加速。每一代 CPU 的性能特征不同,有时浮点实现也会更快。关键原则是:数值计算例程的精细专业化能带来高回报。除了定点/浮点的选择外,还包括优化数据结构以避免缓存未命中,以及使用向量指令。许多机器学习研究者忽视这些实现细节,但当实现性能限制了模型规模时,模型精度会随之受损。
12.1.2 GPU 实现
现代神经网络实现大多基于 GPU。GPU 是最初为图形应用开发的专用硬件,消费级视频游戏市场推动了图形硬件的发展,而好游戏所需的性能特征恰好对神经网络也有利。视频游戏渲染需要快速并行执行大量操作:3D 角色和环境模型由顶点 3D 坐标列表指定,显卡必须对大量顶点并行做矩阵乘除,把 3D 坐标变换成 2D 屏幕坐标;随后还要在每个像素上并行计算颜色。这两类计算都比较简单、分支很少:例如,同一刚体中的每个顶点都会乘以相同的矩阵,不需要为每个顶点判断用哪个矩阵;计算相互完全独立,易于并行;同时需要处理包含纹理位图的大块内存。这些特性使得 GPU 相对 CPU 拥有更高的并行度和内存带宽,代价是时钟频率较低、分支能力较弱。神经网络算法正需要上述性能特征:参数、激活值、梯度值都需要在每一步训练中完全更新的大块缓冲区,这些缓冲区大到会落到传统桌面计算机缓存之外,因此内存带宽往往成为瓶颈。GPU 相对 CPU 的核心优势正在于其高内存带宽。神经网络训练通常没有复杂的分支和控制流,非常适合 GPU 硬件;同一层内的"神经元"相互独立,可以独立处理,自然能利用 GPU 的并行性。早期 GPU 高度专用化,只能用于图形任务;后来随着可对顶点坐标或像素颜色编写自定义子例程的灵活性增加,原则上输出像素值不必来自渲染任务。Steinkrau 等人(2005)在 GPU 上实现了一个两层全连接神经网络,相对 CPU 基线获得三倍加速;Chellapilla 等人(2006)随后展示了同一技术可加速有监督卷积网络。通用 GPU(GP-GPUs)能执行任意代码而非仅渲染子例程,这一变革使图形卡在神经网络训练中爆发:NVIDIA 的 CUDA 编程语言提供了类 C 的任意代码编写能力,加上便捷的编程模型、海量并行与高带宽,GP-GPU 成为神经网络编程的理想平台,并在面世后被深度学习研究者迅速采用(Raina 等人 2009;Ciresan 等人 2010)。然而,编写高效 GP-GPU 代码仍然困难,最好留给专家。GPU 的高性能技术与 CPU 截然不同:好的 CPU 代码通常尽量从缓存读数据,而 GPU 上大多数可写内存位置不被缓存,同一值算两遍反而比算一遍再从内存读回来更快。GPU 代码本质上是多线程的,线程之间需要仔细协调——例如,内存操作在能合并时更快,所谓合并读/写是指多个线程能在同一次内存事务中各自读/写所需值;不同 GPU 型号能合并的读写模式不同,通常在线程 \(i\) 访问字节 \(i+j\)(\(j\) 是 2 的幂次倍数)时较易合并,具体规格因 GPU 型号而异。另一个常见考量是确保一个线程组内的线程同时执行同一条指令,这意味着分支在 GPU 上处理起来较困难。线程被划分成若干小 warp,同一 warp 内的线程在每个周期执行同一条指令,因此当同一 warp 内不同线程要走不同代码路径时,这些路径必须串行执行。由于编写高性能 GPU 代码困难,研究者应规划好工作流,避免为了测试新模型或新算法而反复写新的 GPU 代码。常见做法是构建一个由卷积、矩阵乘法等高性能运算组成的软件库,再以调用该库运算的方式描述模型。例如,机器学习库 Pylearn2(Goodfellow 等人 2013c)将所有机器学习算法都表示为对 Theano(Bergstra 等人 2010;Bastien 等人 2012)和 cuda-convnet(Krizhevsky 2010)的调用,后者提供这些高性能运算。这种分解方式也便于支持多种硬件,例如同一份 Theano 程序无需修改 Theano 调用就能在 CPU 或 GPU 上运行。TensorFlow(Abadi 等人 2015)、Torch(Collobert 等人 2011b)等库也提供类似特性。
12.1.3 大规模分布式实现
许多情况下,单机可用的计算资源不够用,因此需要把训练与推理的工作负载分布到多台机器上。推理的分布很简单:每个待处理的输入样本可以由一台独立机器运行,这叫数据并行(data parallelism)。也可以做模型并行(model parallelism),即多台机器协作处理同一个数据点,每台机器负责模型的不同部分;模型并行对推理和训练都可行。训练时的数据并行则相对更难。可以扩大单次 SGD 步骤所用的 minibatch 规模,但优化性能往往呈次线性收益;更好的做法是让多台机器并行地计算多个梯度下降步骤。然而,梯度下降的标准定义是一个完全顺序的算法:第 \(t\) 步的梯度是第 \(t-1\) 步参数的函数。这一问题可以用异步随机梯度下降(Bengio 等人 2001;Recht 等人 2011)解决:在该方法下,多个处理器核共享代表参数的内存,每个核无锁地读取参数、计算梯度、再无锁地累加参数。由于核之间会互相覆盖进度,单步梯度下降的"平均改进量"会下降,但单位时间产生的步数增多,整体学习过程反而更快。Dean 等人(2012)率先实现了多机版的这种无锁梯度下降方法,其中参数由参数服务器(parameter server)管理而非存储在共享内存中。分布式异步梯度下降至今仍是训练大型深度网络的主要策略,被工业界大多数主要深度学习团队所采用(Chilimbi 等人 2014;Wu 等人 2015)。学术界的深度学习研究者通常负担不起同等规模的分布式学习系统,但也有研究聚焦于在大学环境中用相对廉价的硬件搭建分布式网络(Coates 等人 2013)。
12.1.4 模型压缩
在许多商业应用中,推理阶段的时间和内存成本比训练阶段的成本更重要。对于不需要个性化的应用,可以一次训练模型后部署给数十亿用户使用;在很多情况下,终端用户比开发者更受资源约束。例如,可以在一台强大的计算集群上训练语音识别网络,然后部署到移动手机上运行。降低推理成本的关键策略是模型压缩(Bucilǎ 等人 2006)。其基本思想是用一个更小的模型替代原始的昂贵模型,从而减少存储与运行时的内存与时间开销。模型压缩的适用条件是:原始模型的规模主要源于防止过拟合的需要。在大多数情况下,泛化误差最低的模型是由若干独立训练模型组成的集成;评估集成中所有 \(n\) 个成员的代价是昂贵的;有时即便是单一模型,规模更大时泛化也会更好(例如用 dropout 正则化时)。这些大模型学习某个函数 \(f(x)\),但使用的参数远超任务所需;其规模之所以必要,仅仅是由于训练样本数量有限。一旦拟合出 \(f(x)\),就可以通过在随机采样的 \(x\) 点上应用 \(f\) 生成包含无穷多样本的训练集,然后用更小的模型在这些点上学习逼近 \(f(x)\)。为最有效利用小模型的容量,最好从一个与未来实际测试输入分布相似的分布中采样新 \(x\) 点,这可以通过对训练样本做扰动或从一个基于原训练集训练的生成模型中采样来实现。另一种做法是只让小模型在原始训练点上训练,但训练它去复制大模型的其他特征,例如对错误类别的后验分布(Hinton 等人 2014、2015)。
12.1.5 动态结构
加速数据处理系统的一般性策略之一,是在描述计算图中构建动态结构。数据处理系统可以动态地决定在给定输入上运行众多神经网络的哪一个子集。单个神经网络也可以在内部展现动态结构,根据输入信息决定要计算哪些特征(隐藏单元)子集。这种神经网络内部的动态结构有时称为条件计算(Bengio 2013;Bengio 等人 2013b)。由于架构中许多组件可能只对少数输入相关,系统可以通过按需计算这些特征而跑得更快。计算的动态结构是计算机科学中的一个基本原则,在软件工程学科中广泛适用。神经网络动态结构的最简单形式是:决定哪一组神经网络(或其他机器学习模型)中的哪一子集应用于某一特定输入。一种在分类器中加速推理的成熟策略是分类器级联(cascade)。级联适用于目标是检测稀有对象(或事件)是否存在的场景:要确认对象确实存在,必须使用高容量但运行昂贵的复杂分类器;然而由于对象稀有,可以用少得多的计算把不含对象的输入排除掉。这时可以训练一系列分类器:序列中前几个分类器容量低,但被训练为高召回,确保不会在对象存在时错误地拒绝输入;最终的分类器被训练为高精度。测试时,按顺序运行这些分类器,只要任何一级拒绝某样本就立即停止。整体上,这套机制既能用高容量模型高置信度地确认对象存在,又不必为每个样本都付出完整推理的代价。级联的高容量可以有两种实现方式:一是让序列末端的成员各自具有高容量,则系统整体显然具有高容量,因为其部分成员本身具有高容量;二是让每个成员都低容量,但通过大量小模型的组合使系统整体具有高容量。Viola 和 Jones(2001)使用一组级联的提升决策树,实现了一个适合手持数码相机使用的快速且鲁棒的人脸检测器。他们的分类器本质上用滑动窗口策略定位人脸,检查大量窗口并拒绝不含人脸的窗口。另一种级联形式是:先前的模型实现一种硬注意机制,前级成员定位对象,后级成员在已知位置的前提下做进一步处理。例如 Google 用一个两步级联从街景图像中转录门牌号:先用一个机器学习模型定位门牌号,再用另一个模型转录(Goodfellow 等人 2014d)。决策树本身就是动态结构的一个例子:树中每个节点对每个输入决定要评估其哪个子树。深度学习与动态结构结合的一个简单办法是训练一棵决策树,其中每个节点用一个神经网络做分裂决策(Guo 和 Gelfand 1992),不过这通常并非以加速推理计算为主要目标。同理,可以用一个称为"门控器"(gater)的神经网络,根据当前输入在多个专家网络中挑选一个来计算输出。这一思路的第一个版本称为专家混合(mixture of experts,Nowlan 1990;Jacobs 等人 1991),其中门控器输出一组概率或权重(通过 softmax 非线性得到),每个专家一个权重,最终输出由专家输出的加权和得到。这种门控用法并不能减少计算量,但如果对每个样本由门控器挑出单一专家,就得到硬专家混合(Collobert 等人 2001、2002),可以显著加速训练与推理。该策略在门控决策数量较小(非组合性)时效果较好;但当要选择不同单元或参数子集时,不能用"软开关",因为那需要枚举并计算所有门控器配置下的输出。为此,研究者探索了多种训练组合门控器的方法:Bengio 等人(2013b)试验了多种门控概率上梯度估计器;Bacon 等人(2015)和 Bengio 等人(2015a)使用强化学习技术(策略梯度)学习一种对隐藏单元块的条件 dropout,从而在不损近似质量的前提下实际降低计算成本。另一种动态结构是开关(switch):一个隐藏单元可以根据上下文从不同单元接收输入。这种动态路由方法可解释为注意机制(Olshausen 等人 1993)。到目前为止,硬开关在大规模应用上尚未证明有效。当代方法改为对许多可能输入做加权平均,因此并未获得动态结构全部潜在计算收益。当代的注意机制将在 12.4.5.1 节介绍。使用动态结构系统的一个主要障碍是其并行度会下降:系统对不同输入走不同代码分支,网络中很少操作可以描述成对 minibatch 样本的矩阵乘法或批量卷积。可以编写更专门化的子例程,对每个样本用不同卷积核做卷积,或用权重矩阵的不同列子集乘设计矩阵的每一行;然而这些更专门化的子例程实现起来很困难——CPU 实现会因缺乏缓存一致性而变慢,GPU 实现会因缺乏合并内存事务、且 warp 内成员走不同分支时需串行化而变慢。某些情况下,可以把所有走同一分支的样本分到一组,再成组地同时处理,这是在离线设定下处理固定数量样本时可接受的策略。在实时设定中,样本连续到来,分组会带来负载均衡问题:例如若把一台机器分配处理级联的第一步、另一台处理最后一步,则前者通常过载、后者通常欠载;类似问题也出现在把不同机器分配到神经决策树不同节点时。
12.1.6 深度网络的专用硬件实现
自神经网络研究早期起,硬件设计者就致力于开发能加速神经网络训练和/或推理的专用硬件实现(Lindsey 和 Lindblad 1994;Beiu 等人 2003;Misra 和 Saha 2010)。过去几十年间出现了多种形式的专用硬件(Graf 和 Jackel 1989;Mead 和 Ismail 2012;Kim 等人 2009;Pham 等人 2012;Chen 等人 2014a,b),实现方式有 ASIC(专用集成电路)、数字式(基于数字表示)、模拟式(Graf 和 Jackel 1989;Mead 和 Ismail 2012,基于用电压或电流物理实现连续值)以及数模混合(结合数字与模拟元件)。近年来更灵活的 FPGA(现场可编程门阵列)实现也被开发出来,电路细节可以在芯片造出后再写入。尽管在通用处理单元(CPU 和 GPU)上的软件实现通常用 32 或 64 位浮点数表示,但早就知道至少在推理时可以使用更低的精度(Holt 和 Baker 1991;Holi 和 Hwang 1993;Presley 和 Haggard 1994;Simard 和 Graf 1994;Wawrzynek 等人 1996;Savich 等人 2007)。随着深度学习在工业产品中的普及以及 GPU 所展示的硬件速度的显著影响,这一议题变得更加紧迫。推动当前深度网络专用硬件研究的另一个因素是单个 CPU 或 GPU 核心的进步速率已经放缓,最近的计算速度提升大多来自核心并行化(CPU 或 GPU 内核并行)。这与 1990 年代(上一轮神经网络热潮)的情况截然不同:当时的神经网络专用硬件(从设计到芯片可用可能需要两年)无法跟上通用 CPU 的快速进步与低价格。当前是面向手机等低功耗设备设计新硬件的时期,目标是大规模公众应用(如语音、计算机视觉、自然语言处理)的深度学习,因此构建专用硬件是把性能边界再往前推的一条路。最近关于基于反向传播的神经网络低精度实现的工作(Vanhoucke 等人 2011;Courbariaux 等人 2015;Gupta 等人 2015)表明,使用 8 到 16 位精度即可用反向传播训练或使用深度神经网络。可以确定的是,训练比推理需要更高的精度,并且某些动态定点表示可以减少每个数所需的位数。传统定点数被限制在一个固定范围(对应浮点表示中的某个指数),动态定点表示把这一范围在一组数(例如同一层所有权重)之间共享。用定点替代浮点、用更少位数,能降低执行乘法所需的硬件面积、功耗与计算时间,而乘法是反向传播训练与使用现代深度网络时最耗费的操作。
12.2 计算机视觉
计算机视觉历来是深度学习应用最活跃的研究领域之一,因为视觉对人类和许多动物毫不费力、但对计算机却充满挑战(Ballard 等人 1983)。许多最流行的深度学习标准基准任务都是某种形式的目标识别或光学字符识别。计算机视觉是一个非常广阔的领域,涵盖各种图像处理方式与应用,应用范围从复现人类视觉能力(如人脸识别)到创造全新的视觉能力类别。后者的一个近期例子是:从视频中物体可见的振动反推出声波(Davis 等人 2014)。但大多数深度学习在计算机视觉上的研究并未聚焦于这种扩展图像学边界的奇特应用,而是聚焦于一小撮复制人类能力的 AI 目标。深度学习在计算机视觉上主要用于某种形式的目标识别或检测,无论这意味着报告图像中存在哪种目标、用包围框标注目标、从图像转录符号序列,还是为图像中每个像素标注其所属目标身份。由于生成建模一直是深度学习研究的指导原则,也存在大量用深度模型做图像合成的工作。完全从无到有的图像合成通常不被视作计算机视觉任务,但具备图像合成能力的模型通常对图像修复这类计算机视觉任务有用——修复图像中的瑕疵或从图像中移除物体。
12.2.1 预处理
许多应用领域需要精细的预处理,因为原始输入以难以被许多深度学习架构表达的形式给出。计算机视觉通常所需的这类预处理较少:图像应被标准化到同一合理范围,如 \([0,1]\) 或 \([-1,1]\);把 \([0,1]\) 的图像和 \([0,255]\) 的图像混在一起几乎一定会失败。把图像格式化到同一尺度是唯一严格必要的预处理。许多计算机视觉架构要求图像为统一大小,所以必须裁剪或缩放到该大小;即便这种重缩放也并非总是必需的。一些卷积模型接受可变大小输入,并动态调整其池化区域大小以保持输出大小恒定(Waibel 等人 1989);另一些卷积模型的输出大小可变,会随输入自动缩放,例如对图像去噪或对每个像素做标注的模型(Hadsell 等人 2007)。数据集增强可以视作仅对训练集做的一种预处理。数据集增强是减少大多数计算机视觉模型泛化误差的极佳方法。测试时一种相关思路是给模型展示同一输入的多种版本(例如同一图像在不同位置裁剪),让模型的不同实例投票决定输出。这一思路可被解释为一种集成方法,也有助于降低泛化误差。其他种类的预处理同时作用于训练集和测试集,目标是把每个样本放入更规范的形式,以减少模型需要应对的变化量。减少数据中的变化量既能降低泛化误差,也能缩小拟合训练集所需的模型规模。更简单的任务可以由更小的模型解决,更简单的方案更可能泛化良好。这类预处理通常被设计为去除某种变化:这种变化易于人类设计者描述、且设计者确信其与任务无关。当使用大数据集和大模型训练时,这类预处理往往没有必要,最好让模型自己学习应对哪些变化。例如,AlexNet 在 ImageNet 分类上仅做一步预处理:减去训练集每个像素上的均值(Krizhevsky 等人 2012)。
12.2.1.1 对比度归一化
对许多任务而言,最明显可以安全去除的变化来源之一是图像的对比度。对比度即图像中明像素与暗像素之间差异的大小。对比度的量化方式多种多样。在深度学习语境下,对比度通常指图像或图像局部区域中像素的标准差。设有图像 \(X \in \mathbb{R}^{r \times c \times 3}\),其中 \(X_{i,j,1}\) 为第 \(i\) 行第 \(j\) 列的红色强度,\(X_{i,j,2}\) 为绿色,\(X_{i,j,3}\) 为蓝色。整张图像的对比度由下式给出:
其中 \(\bar{X}\) 是整张图像的均值强度:
全局对比度归一化(GCN)的目标是防止不同图像具有不同的对比度,做法是从每张图像中减去均值,然后重新缩放使像素的标准差等于某个常数 \(s\)。"零对比度"图像(所有像素强度相等)让这件事变得复杂:任何缩放因子都不能改变其对比度。极低但非零对比度的图像往往信息量也很小,此时除以真实的标准差往往只是把传感器噪声或压缩伪影放大。为此需要引入一个小的正常化参数 \(\lambda\) 来对标准差估计做偏置;或把分母约束到至少为 \(\epsilon\)。给定输入图像 \(X\),GCN 产生输出图像 \(X'\),其定义为:
由大图像裁剪到感兴趣对象所组成的数据集几乎不包含接近恒定强度的图像,此时可放心地基本忽略小分母问题:设 \(\lambda = 0\),把 \(\epsilon\) 设为极小值(如 \(10^{-8}\))以防极少数情况下除零,这就是 Goodfellow 等人(2013a)在 CIFAR-10 数据集上采用的做法。随机裁剪出的小图像更可能接近恒定强度,因而更需要激进的正常化。Coates 等人(2011)在从 CIFAR-10 随机选出的小块上使用 \(\epsilon = 0\)、\(\lambda = 10\)。尺度参数 \(s\) 通常可设为 1(Coates 等人 2011 即如此),也可以选为使每个像素在样本间的标准差接近 1(Goodfellow 等人 2013a 即如此)。公式 12.3 中的标准差只是图像 \(L_2\) 范数的一个重缩放(假设已减去均值)。基于标准差而非 \(L_2\) 范数定义 GCN 更可取,因为标准差含除以像素数项,所以基于标准差的 GCN 允许同一 \(s\) 在不同图像大小下通用;不过 \(L_2\) 范数与标准差成正比这一观察有助于建立直观理解:可以把 GCN 理解为把样本映射到一个球壳(见 figure 12.1)。这是一个有用的性质,因为神经网络通常更善于响应空间中的方向而非精确位置。响应同一方向上的多个距离需要带共线权重向量、不同偏置的隐藏单元,这种协调对学习算法而言较难发现;此外,许多浅层图模型难以表示同一直线上的多个分离模式。GCN 把每个样本约简为方向而非"方向 + 距离",避开了上述问题。与直觉相反的是,存在一种称为"球化"(sphering)的预处理操作,它与 GCN 并非同一种操作。球化并非让数据分布在球壳上,而是对主成分做重缩放,使 PCA 中使用的多元正态分布具有球形等高线;球化更常被称作白化(whitening)。GCN 往往无法突出我们希望凸显的图像特征,例如边缘和角点。如果场景中存在大面积暗区和大面积亮区(如城市广场中一半图像被建筑物阴影遮挡),GCN 会保证暗区与亮区亮度之间存在大差异,但不会保证暗区内部的边缘被凸显出来。这促使研究者提出局部对比度归一化:局部对比度归一化在每个小窗口上做归一化,而非对整张图像做(见 figure 12.2)。局部对比度归一化有多种定义:所有做法都是先减去邻近像素的均值,再除以邻近像素的标准差。在一些定义中,"邻近像素"就是以待修改像素为中心的矩形窗口内所有像素的均值与标准差(Pinto 等人 2008);在另一些定义中,使用以该像素为中心的高斯权重做加权均值和加权标准差。对彩色图像,有些策略分别处理不同颜色通道,有些则跨通道结合信息再对每个像素做归一化(Sermanet 等人 2012)。局部对比度归一化通常可以用可分离卷积(第 9.8 节)高效实现:先计算局部均值和局部标准差的特征图,再对不同特征图做逐元素减法和除法。局部对比度归一化是一个可微操作,既可以作为网络隐藏层的非线性,也可以作为输入的预处理操作。和 GCN 一样,局部对比度归一化通常也需要正常化以避免除零。事实上,由于局部对比度归一化作用在更小的窗口上,值更可能彼此接近,标准差更可能为零,正常化甚至更为重要。
12.2.1.2 数据集增强
如第 7.4 节所述,通过把训练样本复制为经过不改变类别的变换的额外版本来扩充训练集,是提升分类器泛化性能的简单办法。目标识别是一类特别适合这种数据集增强的分类任务,因为类别对很多变换具有不变性,且输入可以方便地通过许多几何操作进行变换。前文已经提到,分类器可受益于对输入做随机平移、旋转,以及在某些情况下的翻转,来增强数据集。在专门的计算机视觉应用中,更复杂的变换常被用于数据集增强,包括对图像中颜色的随机扰动(Krizhevsky 等人 2012)和对输入的非线性几何畸变(LeCun 等人 1998b)。
12.3 语音识别
语音识别的任务是把一段含口语自然语言语句的声学信号映射到说话者意图对应的词序列。设 \(X = (x^{(1)}, x^{(2)}, \ldots, x^{(T)})\) 表示声学输入向量序列(传统上由把音频切成 20ms 帧得到)。多数语音识别系统会使用专门手工设计的特征对输入做预处理,但也有一些深度学习系统直接从原始输入学习特征(Jaitly 和 Hinton 2011)。设 \(y = (y_1, y_2, \ldots, y_N)\) 表示目标输出序列(通常是一个词或字符序列)。自动语音识别(ASR)任务在于构造一个函数 \(f^*_{\text{ASR}}\),给定声学序列 \(X\) 计算最可能的语言序列 \(y\):
其中 \(P^*\) 是联系输入 \(X\) 与目标 \(y\) 的真实条件分布。从 1980 年代到 2009–2012 年左右,最先进的语音识别系统主要结合了隐马尔可夫模型(HMM)与高斯混合模型(GMM)。GMM 建模声学特征与音素之间的关联(Bahl 等人 1987),HMM 建模音素序列。GMM-HMM 家族把声学波形视为按以下过程生成:首先一个 HMM 生成音素及音素内离散子状态序列(如音素的开始、中间、结束),然后一个 GMM 把每个离散符号转换为一小段音频波形。尽管 GMM-HMM 系统直到最近才主导 ASR,语音识别实际上是最早应用神经网络的领域之一,1980 年代末到 1990 年代初的许多 ASR 系统就使用了神经网络(Bourlard 和 Wellekens 1989;Waibel 等人 1989;Robinson 和 Fallside 1991;Bengio 等人 1991、1992;Konig 等人 1996)。当时基于神经网络的 ASR 性能与 GMM-HMM 系统大致相当;例如 Robinson 和 Fallside(1991)在 TIMIT(Garofolo 等人 1993)语料库上达到 26% 的音素错误率(需区分 39 个音素),优于或相当于基于 HMM 的系统。此后 TIMIT 一直是音素识别的基准,扮演着类似于 MNIST 在目标识别中的角色。然而,由于语音识别软件系统工程复杂、工业界在 GMM-HMM 基础上已投入巨大建设努力,没有看到改用神经网络的强有力论据;因此直到 2000 年代末,学术界和工业界在使用神经网络做语音识别上的研究大多聚焦于用神经网络为 GMM-HMM 系统学习额外特征。后来,随着模型更大更深、数据集更大,使用神经网络替代 GMM 来完成声学特征到音素(或子音素状态)的关联任务,使识别准确率大幅提升。2009 年起,语音研究者将一种基于无监督学习的深度学习形式用于语音识别。这种深度学习基于训练无向概率模型(受限玻尔兹曼机 RBM)来建模输入数据;RBM 将在第三部分描述。为解决语音识别任务,无监督预训练被用来构建深度前馈网络,其每层由一个 RBM 训练做初始化;这些网络以固定大小输入窗口(围绕中心帧)内的频谱声学表示为输入,预测该中心帧对应 HMM 状态的条件概率。训练这种深度网络显著改善了 TIMIT 上的识别率(Mohamed 等人 2009、2012a),把音素错误率从约 26% 降至 20.7%。对这一成功原因的分析见 Mohamed 等人(2012b)。基础音素识别流水线的扩展包括加入说话人自适应特征(Mohamed 等人 2011),进一步降低了错误率。随后工作将架构从音素识别(TIMIT 的关注点)扩展到大词汇量语音识别(Dahl 等人 2012),不仅要识别音素,还要从大词汇量中识别词序列。语音识别深度网络最终从基于预训练和玻尔兹曼机的方法转向基于修正线性单元和 dropout 等技术(Zeiler 等人 2013;Dahl 等人 2013)。那时,几家主要的工业界语音研究组已开始与学术研究者合作探索深度学习。Hinton 等人(2012a)描述了这些合作者取得的突破,这些成果现已部署在手机等产品中。后来,随着研究组探索更大规模的有标注数据集并引入若干深度网络初始化、训练和架构搭建的方法,他们意识到无监督预训练阶段要么不必要,要么没有带来显著改善。这些语音识别词错误率上约 30% 的提升是前所未有的,紧随之前 GMM-HMM 时代约十年间错误率几乎没有改善的停滞期——尽管训练集规模持续增长(Deng 和 Yu 2014 的 figure 2.4)。这在语音识别社区引发了向深度学习的快速转向:在大约两年时间里,工业界大多数语音识别产品都引入了深度神经网络,这次成功又激起了一波对 ASR 深度学习算法和架构的研究热潮,至今仍在持续。其中一项创新是使用卷积网络(Sainath 等人 2013),沿时间和频率两个方向共享权重,超越早期仅沿时间共享权重的时延神经网络。新的二维卷积模型把输入频谱图视为图像:一个轴对应时间,另一个对应频谱成分的频率。另一项重要推进(仍在进行)是端到端深度学习语音识别系统,完全去掉 HMM。该方向的第一个重大突破来自 Graves 等人(2013):他们训练了一个深度 LSTM RNN(第 10.10 节),使用 LeCun 等人(1998b)以及 CTC 框架(Graves 等人 2006;Graves 2012)中的帧到音素对齐 MAP 推理。深度 RNN(Graves 等人 2013)在每个时间步都具有来自多个层的状态变量,展开后的图具有两种深度:层堆叠带来的常规深度与时间展开带来的深度。这项工作把 TIMIT 上的音素错误率降至 17.7% 的新低。其他深度 RNN 变体见 Pascanu 等人(2014a)和 Chung 等人(2014),应用于其他场景。端到端深度学习 ASR 的另一个当下步骤是让系统学习如何把声学层信息"对齐"到音素层信息(Chorowski 等人 2014;Lu 等人 2015)。
12.4 自然语言处理
自然语言处理(NLP)是指计算机使用人类语言(如英语或法语)。计算机程序通常读入并输出专门设计的语言,使其能被简单程序高效且无歧义地解析;自然发生的语言往往有歧义,难以形式化描述。NLP 的应用包括机器翻译:学习者必须读入一种人类语言的句子并输出另一种人类语言中等价的句子。许多 NLP 应用基于语言模型——对自然语言中词、字符或字节序列定义概率分布。与本章讨论的其他应用一样,非常通用的神经网络技术可以成功用于 NLP。然而要获得出色性能并良好扩展到大规模应用,某些领域专用策略变得重要。要构建高效的自然语言模型,通常必须使用专门处理序列数据的技术。在很多情况下,我们把自然语言视作词序列而非单个字符或字节的序列。由于可能的词总数巨大,基于词的语言模型必须运行在极高维且稀疏的离散空间上。研究者已开发出多种策略,使这种空间上的模型在计算和统计上都高效。
12.4.1 n 元文法
语言模型对自然语言中 token 序列定义概率分布。依模型设计,token 可以是词、字符,甚至字节。token 总是离散实体。最早成功的语言模型基于固定长度 token 序列的模型,称为 n 元文法(n-grams)。n 元文法是 \(n\) 个 token 的序列。基于 n 元文法的模型定义第 \(n\) 个 token 在前 \(n-1\) 个 token 条件下的条件概率,再用这些条件概率的乘积定义更长序列上的概率分布:
该分解由概率的链式法则保证。初始序列上的概率 \(P(x_1, \ldots, x_{n-1})\) 可用更小 \(n\) 值的不同模型建模。训练 n 元文法模型是直接的:最大似然估计可通过对训练集中每个可能 n 元文法出现次数做简单计数得到。基于 n 元文法的模型几十年来一直是统计语言建模的核心构件(Jelinek 和 Mercer 1980;Katz 1987;Chen 和 Goodman 1999)。在小 \(n\) 值下,模型有专门名字:unigram 表示 \(n=1\),bigram 表示 \(n=2\),trigram 表示 \(n=3\),这些名字来自对应的拉丁语数字前缀与表示"被书写之物"的希腊语后缀 "-gram"。通常同时训练一个 n 元文法模型和一个 n-1 元文法模型,便于按下式计算:
只需查两个存储的概率即可。要使这严格复现 \(P_n\) 的推理,训练 \(P_{n-1}\) 时必须从每个序列中去掉最后一个字符。举 trigram 模型为例,说明它如何计算句子"THE DOG RAN AWAY"的概率:句首的词无法用基于条件概率的默认公式处理(句首没有上下文),必须使用句首词的边际概率,因此先计算 \(P_3(\text{THE DOG RAN})\);最后一个词用常规条件分布 \(P(\text{AWAY} \mid \text{DOG RAN})\) 预测;与公式 12.6 一起得到:
最大似然用于 n 元文法模型的一个根本局限是:从训练集计数估计出的 \(P_n\) 在许多情况下极可能为零,即便元组 \((x_{t-n+1}, \ldots, x_t)\) 出现在测试集中。这可能造成两种灾难性后果:当 \(P_{n-1}\) 为零时,比值未定义,模型甚至不能给出合理输出;当 \(P_{n-1}\) 非零而 \(P_n\) 为零时,测试对数似然为 \(-\infty\)。为避免这些灾难性结果,大多数 n 元文法模型采用某种形式的平滑技术,将概率质量从观测到的元组转移到与之相似的未观测元组上。Chen 和 Goodman(1999)给出了综述和实证比较。一种基本技巧是给所有可能的下一个符号值都加上非零概率质量,这可以解释为对计数参数取均匀或 Dirichlet 先验的贝叶斯推理。另一种非常流行的思路是构造一个混合模型,把高阶与低阶 n 元文法模型放在一起:高阶模型提供更强容量,低阶模型更可能避免零计数。回退(back-off)方法在上下文 \(x_{t-1}, \ldots, x_{t-n+1}\) 频率过小而无法使用高阶模型时,去查低阶 n 元文法。更形式化地说,它们通过依次使用上下文 \(x_{t-n+k}, \ldots, x_{t-1}\)(\(k\) 递增),直到找到足够可靠的估计来估计 \(x_t\) 上的分布。经典 n 元文法模型特别易受维度灾难的困扰:共有 \(|V|^n\) 种可能 n 元文法,\(|V|\) 通常非常大。即使训练集庞大、\(n\) 较小,多数 n 元文法也不会出现在训练集中。一种看待经典 n 元文法模型的方式是:它在执行最近邻查找——也即它可以视作一种局部非参预测器,类似于 \(k\) 近邻。这些极局部预测器面临的统计问题已在第 5.11.2 节描述。语言模型面临的问题比一般情况更严重,因为在 one-hot 向量空间中任何两个不同词之间的距离相同,从而很难从任何"邻居"那里借力——只有字面重复同一上下文的训练样本才对局部泛化有用。要克服这些问题,语言模型必须能在一个词和其他语义相似的词之间共享知识。为提升 n 元文法模型的统计效率,基于类别的语言模型(Brown 等人 1992;Ney 和 Kneser 1993;Niesler 等人 1998)引入词类别的概念,从而在同一类内的词之间共享统计强度。思路是用聚类算法根据词与其他词的共现频率把词集划分成簇或类。模型随后可以用词类 ID 而非单独的词 ID 表示条件右侧的上下文。也可以通过混合或回退把基于词和基于类的模型组合成复合模型。虽然词类提供了一种在"将某词替换为同类的另一个词"时能泛化的手段,但这种表示会丢失大量信息。
12.4.2 神经语言模型
神经语言模型(NLM)是一类语言模型,旨在通过使用词的分布式表示(Bengio 等人 2001)来克服自然语言序列建模中的维度灾难问题。与基于类的 n 元文法模型不同,神经语言模型能够识别两个词相似而仍保留把每个词编码为彼此不同的能力。神经语言模型在某个词(及其上下文)与其他相似词和上下文之间共享统计强度。模型为每个词学到的分布式表示使这种共享成为可能:模型可以对具有共同特征的词做相似处理。例如,如果词 dog 和词 cat 被映射到共享许多属性的表示,那么包含 cat 的句子就能影响模型对包含 dog 的句子所做的预测,反之亦然。由于存在许多这样的属性,泛化可以以多种方式发生,把每条训练句子的信息转移到数量指数级增长的语义相关句子。维度灾难要求模型泛化到长度上指数增长的句子数;模型通过把每条训练句子关联到指数级数量的相似句子来应对这一诅咒。这些词表示有时被称为词嵌入(word embeddings)。在这种解读下,原始符号被视作维度等于词表大小的空间中的点;词嵌入把这些点嵌入到更低维的特征空间中。在原始空间中,每个词由 one-hot 向量表示,任意两个词之间的欧氏距离都是 \(\sqrt{2}\)。在嵌入空间中,频繁出现在相似上下文中的词(或任何共享某些模型所学"特征"的词对)彼此接近。这通常导致语义相似的词成为近邻。figure 12.3 放大显示了学习到的词嵌入空间中的特定区域,以展示语义相似的词的嵌入向量彼此接近。其他领域的神经网络也定义嵌入。例如,卷积网络的隐藏层提供一种"图像嵌入"。NLP 从业者通常对这一思想更感兴趣,因为自然语言原本并不位于实值向量空间中。隐藏层带来了表示数据方式的质变。使用分布式表示来改进自然语言处理模型的基本思想并不局限于神经网络,也可用于具有分布式表示(图形式为多个潜变量)的图模型(Mnih 和 Hinton 2007)。
12.4.3 高维输出
在许多 NLP 应用中,模型希望以词(而非字符)作为输出的基本单位。对于大词表,要表示词选择上的输出分布,计算代价可能非常高昂,因为词表规模庞大。在许多应用中,\(V\) 包含数十万词。表示这种分布的朴素做法是:先对隐藏表示做一次仿射变换到输出空间,再应用 softmax。设词表 \(V\) 大小为 \(|V|\)。该仿射变换的线性部分对应的权重矩阵非常大,因为其输出维度为 \(|V|\)。这导致表示该矩阵的内存代价高、与之相乘的计算代价高。由于 softmax 需对所有 \(|V|\) 个输出做归一化,训练和测试时都必须做完整的矩阵乘法——不能只计算与正确输出权重向量的点积。输出层的高计算代价因此同时出现在训练时(计算似然和梯度)和测试时(计算所有或所选词的概率)。对特定损失函数,梯度可以被高效计算(Vincent 等人 2015),但用于传统 softmax 输出层的标准交叉熵损失带来许多困难。设 \(h\) 是用于预测输出概率 \(\hat{y}\) 的最顶层隐藏层。若用学习到的权重 \(W\) 和偏置 \(b\) 参数化从 \(h\) 到 \(\hat{y}\) 的变换,则仿射-softmax 输出层执行如下计算:
若 \(h\) 含 \(n_h\) 个元素,则上述操作的复杂度为 \(O(|V| n_h)\)。当 \(n_h\) 在千级、\(|V|\) 在数十万级时,该操作主导了多数神经语言模型的计算。
12.4.3.1 使用短列表
最早的神经语言模型(Bengio 等人 2001、2003)通过把词表大小限制在 1 万或 2 万词来应对大输出词表 softmax 的高代价。Schwenk 和 Gauvain(2002)以及 Schwenk(2007)在此基础上扩展,把词表 \(V\) 分成由神经网络处理的最频繁词的短列表 \(L\),以及由 n 元文法模型处理的稀有词的尾部 \(T = V \setminus L\)。为组合两种预测,神经网络还需预测在上下文 \(C\) 后出现的词属于尾列表的概率。这可以通过增加一个额外的 sigmoid 输出单元来估计 \(P(i \in T \mid C)\);该额外输出可用于对 \(V\) 中所有词的概率分布做如下估计:
其中 \(P(y = i \mid C, i \in L)\) 由神经语言模型给出,\(P(y = i \mid C, i \in T)\) 由 n 元文法模型给出。稍作修改,这种方法也可以在神经语言模型的 softmax 层中通过增加一个额外输出值实现,而非单独的 sigmoid 单元。短列表方法的一个明显缺点是神经语言模型的潜在泛化优势仅限于最频繁的词——而恰恰是这些最频繁词处,泛化优势最不重要。这一缺点推动了下面要描述的应对高维输出的替代方法的研究。
12.4.3.2 分层 Softmax
一种降低大词表 \(V\) 上高维输出层计算负担的经典方法(Goodman 2001)是分层分解概率。无需计算量与 \(|V|\)(以及隐藏单元数 \(n_h\))成正比,可以把 \(|V|\) 因子降至低至 \(\log |V|\)。Bengio(2002)和 Morin 与 Bengio(2005)将这种分解方法引入神经语言模型语境。可以把这种层次结构视作:先建词的类别,再建词类别的类别,再建类别的类别的类别,等等。这些嵌套类别形成一棵树,词位于叶节点。在一棵平衡树中,树的深度为 \(O(\log |V|)\)。选择一个词的概率等于从树根到该词所在叶节点的路径上每个节点处选择通向该词分支的概率之积。figure 12.4 给出了一个简单示例。Mnih 和 Hinton(2009)也描述了如何用多条路径识别同一个词,以更好地建模一词多义的情况。这种情况下,计算一个词的概率需对该词对应的所有路径求和。为预测树的每个节点所需的这些条件概率,通常在每个节点使用一个 logistic 回归模型,并把同一上下文 \(C\) 作为输入提供给所有这些模型。由于训练集中已编码正确输出,可以用监督学习训练这些 logistic 回归模型,常用标准交叉熵损失,对应最大化正确决策序列的对数似然。由于输出对数似然可被高效计算(低至 \(\log |V|\) 而非 \(|V|\)),其梯度也可被高效计算,这包括对输出参数的梯度,也包括对隐藏层激活的梯度。优化树结构以最小化期望计算量是可能的但通常不实际。信息论工具指定了在已知词相对频率时如何选择最优二进制码:可以构造树,使每个词关联的位数大致等于其频率的对数。然而实践中,输出概率的计算只是神经语言模型总计算的一部分,节省的计算通常不值得费这个劲。设有 \(l\) 个宽度为 \(n_h\) 的全连接隐藏层;令 \(n_b\) 为识别一个词所需位数的加权平均,权重由这些词的频率给出。在这个例子中,计算隐藏激活所需操作数随 \(l n_h^2\) 增长,而输出计算随 \(n_h n_b\) 增长。只要 \(n_b \leq l n_h\),缩减 \(n_h\) 带来的计算节省大于缩减 \(n_b\)。事实上 \(n_b\) 通常很小。词表规模很少超过一百万词,\(\log_2(10^6) \approx 20\),因此 \(n_b\) 可降至约 20,但 \(n_h\) 通常远大于此,约为 \(10^3\) 甚至更大。与其精心优化一棵分支因子为 2 的树,不如定义一棵深度为二、分支因子为 \(\sqrt{|V|}\) 的树。这样的树等价于简单地定义一组互斥的词类。基于深度为二的树的简单方法能捕获分层策略的大部分计算收益。一个仍有待解决的问题是如何最佳地定义这些词类,或更一般地定义词的层次结构。早期工作使用现成的层次结构(Morin 和 Bengio 2005),但层次结构也可以学习,理想情况下与神经语言模型联合学习。学习层次结构很困难。精确优化对数似然似乎不可行,因为词层次结构的选择是离散的,不适合基于梯度的优化。不过可以使用离散优化来近似优化词到词类的划分。分层 softmax 的一个重要优点是:只要在测试时需要计算特定词的概率,训练和测试都能获得计算收益。当然,即便使用分层 softmax,计算所有 \(|V|\) 个词的概率仍然昂贵。另一项重要操作是在给定上下文下选最可能的词;不幸的是,树结构并未提供该问题的高效精确解。一个缺点是实践中分层 softmax 的测试结果往往差于下文要介绍的基于采样的方法,这可能源于词类选择不佳。
12.4.3.3 重要性采样
加速神经语言模型训练的一种方法是避免显式计算未出现在下一位置的所有词对梯度的贡献。每个错误词在模型下的概率应该都很低;枚举这些词计算成本高,因此可以只对词的子集采样。使用公式 12.8 中引入的记号,梯度可写为:
其中 \(a\) 是 softmax 前的激活(或分数)向量,每个词一个元素。第一项是正相项(把 \(a_y\) 推高),第二项是负相项(以权重 \(P(i \mid C)\) 把所有 \(a_i\) 推低)。由于负相项是一个期望,可以用蒙特卡洛样本估计。然而这需要从模型自身采样;从模型采样需要计算词表中所有 \(i\) 的 \(P(i \mid C)\),而这恰恰是我们想避免的。可以不从模型采样,而从另一个分布采样,称为提议分布(记作 \(q\)),并通过适当的权重修正从错误分布采样引入的偏倚(Bengio 和 Sénécal 2003;Bengio 和 Sénécal 2008)。这正是更一般技术"重要性采样"的一个应用,第 17.2 节将详细描述。不幸的是,即便精确重要性采样也不高效,因为它需要计算权重 \(p_i / q_i\),其中 \(p_i = P(i \mid C)\),而这只有在所有分数 \(a_i\) 都算出来时才能得到。该应用中的解决方案称为有偏重要性采样,其中重要性权重被归一化到总和为 1。当负词 \(n_i\) 被采样时,其关联的梯度按如下权重加权:
这些权重用于对来自 \(q\) 的 \(m\) 个负样本赋予适当的重要性,从而形成对负相贡献的估计:
unigram 或 bigram 分布作为提议分布 \(q\) 效果不错;这种分布的参数易于从数据中估计;参数估计后从中采样也非常高效。重要性采样不仅对加速具有大 softmax 输出的模型有用,更一般地,对加速具有大稀疏输出层的训练也有用——其输出是稀疏向量而非 1-of-n 选择。一个例子是词袋(bag of words)。词袋是一个稀疏向量 \(v\),其中 \(v_i\) 指示词表中词 \(i\) 是否出现在文档中;或 \(v_i\) 表示词 \(i\) 出现的次数。产生这种稀疏向量的机器学习模型可能因多种原因训练昂贵。学习早期,模型可能并不真让输出变得稀疏;此外用于训练的目标损失函数最自然的描述方式是对输出的每个元素与目标的每个元素做比较。这意味着稀疏输出并不总是带来计算收益,因为模型可能选择让多数输出非零,而这些非零值都需要与训练目标中的相应值做比较,即便训练目标为零。Dauphin 等人(2011)证明这种模型可以使用重要性采样加速。该高效算法对"正词"(目标中非零的词)和同样数量的"负词"最小化损失重构;负词随机选取,使用启发式倾向于采样更可能被误识别的词;该启发式过采样引入的偏倚随后用重要性权重修正。在所有这些情况下,输出层梯度估计的计算复杂度被降低到与负样本数成正比,而非与输出向量大小成正比。
12.4.3.4 噪声对比估计与排序损失
其他基于采样的方法也被提出以降低大词表神经语言模型训练的计算成本。一个早期例子是 Collobert 和 Weston(2008a)提出的排序损失,它把神经语言模型对每个词的输出视为一个分数,并试图使正确词 \(a_y\) 的分数在与其他词分数 \(a_i\) 的比较中排名靠前。所提出的排序损失为:
若观测词的分数 \(a_y\) 比负词分数 \(a_i\) 高出至少 1 的间隔,则第 \(i\) 项的梯度为零。该准则的一个问题是它不提供估计的条件概率,而条件概率在某些应用(包括语音识别与文本生成、翻译等条件文本生成任务)中是有用的。神经语言模型一种更新近使用的训练目标是噪声对比估计,介绍见第 18.6 节;该方法已成功应用于神经语言模型(Mnih 和 Teh 2012;Mnih 和 Kavukcuoglu 2013)。
12.4.4 神经语言模型与 n 元文法的组合
n 元文法模型相对神经网络的一大优势是:通过存储非常多元组的频率获得高模型容量,而处理一个样本所需的计算又极少(只需查找匹配当前上下文的少数几个元组)。如果用哈希表或树来访问计数,n 元文法的计算几乎与容量无关。相比之下,把神经网络的参数数量翻倍通常也会使计算时间大致翻倍;存在一些例外,例如避免在每次前向都使用所有参数的模型——嵌入层每次只索引一个嵌入,所以增大词表不会增加每个样本的计算时间;还有一些模型如平铺卷积网络能在维持相同计算量的同时通过减少参数共享来增加参数。然而典型的基于矩阵乘法的神经网络层使用的计算量与参数数量成正比。因此一个简单的提升容量的方法是组合两种方法,构造一个由神经语言模型和 n 元文法语言模型组成的集成(Bengio 等人 2001、2003)。和任何集成一样,只要各成员犯的错误相互独立,该技术就能降低测试误差。集成学习领域提供了多种组合集成成员预测的方法,包括均匀加权和在验证集上选权重。Mikolov 等人(2011a)将集成扩展到包含两个模型,而是大量模型。也可以把神经网络与最大熵模型配对并联合训练(Mikolov 等人 2011b)。这可以视作训练一个神经网络,附带一组直接连到输出、而不连到模型其他部分的额外输入。这些额外输入是指示输入上下文中是否出现特定 n 元文法的指示变量,因此维度极高且极稀疏。新增部分的容量很大——架构这一部分包含多达 \(|sV|^n\) 个参数——但处理一个输入所需额外计算量极小,因为额外输入极稀疏。
12.4.5 神经机器翻译
机器翻译任务是读入一种自然语言的句子,并输出另一种语言中等价的句子。机器翻译系统通常包含多个组件。较粗略地看,往往有一个组件提出许多候选翻译;由于语言间的差异,许多翻译并不合语法,例如许多语言把形容词放在名词之后,直接翻译成英文就得到"apple red"这样的短语;提议机制会给出建议翻译的多种变体,理想情况下包括"red apple"。翻译系统的第二个组件是语言模型,评估提出的翻译,可以把"red apple"打分高于"apple red"。神经网络在机器翻译中的最早应用是使用神经语言模型来升级翻译系统的语言模型组件(Schwenk 等人 2006;Schwenk 2010)。此前大多数机器翻译系统对该组件使用 n 元文法模型。用于机器翻译的 n 元文法模型不仅包括传统回退 n 元文法模型(Jelinek 和 Mercer 1980;Katz 1987;Chen 和 Goodman 1999),还包括最大熵语言模型(Berger 等人 1996),后者用仿射-softmax 层在上下文中出现频繁 n 元文法时预测下一个词。传统语言模型只是报告自然语言句子的概率。由于机器翻译涉及在给定输入句子的情况下产生输出句子,因此把自然语言模型扩展为条件化的有意义。如 6.2.1.1 节所述,把一个定义某变量边际分布的模型扩展为在给定上下文 \(C\)(可以是单变量或变量列表)下定义该变量的条件分布是直接的。Devlin 等人(2014)通过用一个 MLP 给定源语言短语 \(s_1, s_2, \ldots, s_n\) 对目标语言短语 \(t_1, t_2, \ldots, t_k\) 打分,在一些统计机器翻译基准上达到了当时最先进水平。该 MLP 估计 \(P(t_1, t_2, \ldots, t_k \mid s_1, s_2, \ldots, s_n)\),用此估计替代条件 n 元文法模型提供的估计。MLP 方法的一个缺点是它要求把序列预处理为固定长度。为使翻译更灵活,希望使用能适应可变长输入和可变长输出的模型。RNN 提供了这种能力。第 10.2.4 节描述了几种构造表示"给定某输入的序列条件分布"的 RNN 的方法,第 10.4 节描述了当输入是序列时如何实现这种条件化。在所有情况下,一个模型先读入输入序列并发出一个总结输入序列的数据结构,称之为"上下文" \(C\)。\(C\) 可以是向量列表,也可以是向量或张量。读入输入产生 \(C\) 的模型可以是 RNN(Cho 等人 2014a;Sutskever 等人 2014;Jean 等人 2014),也可以是卷积网络(Kalchbrenner 和 Blunsom 2013)。第二个模型(通常是 RNN)然后读入上下文 \(C\) 并生成目标语言的句子。机器翻译的 encoder-decoder 框架这一总体思路如 figure 12.5 所示。为了在给定源句的情况下生成完整句子,模型必须能表示整个源句。早期模型只能表示单个词或短语。从表示学习的角度看,学习一种"无论用源语言还是目标语言书写,相同含义的句子都有相似表示"的表示是有用的。这一策略最早在卷积和 RNN 的组合中被探索(Kalchbrenner 和 Blunsom 2013)。后续工作引入了用 RNN 对提议翻译打分(Cho 等人 2014a)以及生成翻译句子(Sutskever 等人 2014)。Jean 等人(2014)把这些模型扩展到更大词表。
12.4.5.1 使用注意机制与对齐数据片段
Bahdanau 等人(2015)首次提出注意机制:翻译时一次生成一个词,每一步聚焦于输入句子的不同部分以收集产生下一个输出词所需的语义细节。本质上,注意机制是一种加权平均:上下文向量 \(c\) 由特征向量 \(h^{(t)}\) 以权重 \(\alpha^{(t)}\) 加权平均得到;在某些应用中,特征向量 \(h\) 是神经网络的隐藏单元,也可以是模型的原始输入。权重 \(\alpha^{(t)}\) 由模型自身产生,通常取值在 \([0, 1]\),意在集中在一个 \(h^{(t)}\) 附近,使加权平均近似精确读入那一个特定时间步。\(\alpha^{(t)}\) 通常通过对模型另一部分输出的相关性分数施加 softmax 得到。注意机制在计算上比直接索引期望的 \(h^{(t)}\) 更贵,但直接索引不能用梯度下降训练;基于加权平均的注意机制是平滑、可微的近似,可以用现成优化算法训练。使用固定大小表示来捕获非常长的句子(假设 60 词)的全部语义细节非常困难。Cho 等人(2014a)和 Sutskever 等人(2014)证明,只要把 RNN 训练得足够大、足够久、足够好,这是可以做到的。然而更高效的做法是:先读入整个句子或段落(获得上下文和表达要旨),然后一次生成一个翻译词,每一步聚焦于输入句子不同部分以收集所需语义细节。这正是 Bahdanau 等人(2015)首次提出的思想。基于注意的系统可视为有三个组件:(1) 一个"读"原始数据(例如源句中的源词)并将其转换为分布式表示的过程,每个词位置对应一个特征向量;(2) 一个存储读入器输出的特征向量列表,可理解为"记忆",其中包含一个事实序列,可被后续检索,不必按同一顺序,不必访问全部;(3) 一个"利用"记忆内容依次执行任务的过程,每一步能把注意放在一个(或几个不同权重的)记忆元素的内容上。第三个组件生成翻译句子。当一种语言中句子的词与另一种语言中翻译句子的对应词对齐时,就可以把对应的词嵌入关联起来。早期工作表明可以学习一种"翻译矩阵",把一种语言的词嵌入与另一种语言的词嵌入关联起来(Kočiský 等人 2014),比对齐错误率低于基于短语表中频次计数的传统方法。学习跨语言词向量的更早期工作也存在(Klementiev 等人 2012)。这一思路有许多可能扩展,例如更高效的跨语言对齐(Gouws 等人 2014)允许在更大数据集上训练。
12.4.6 历史回顾
符号分布式表示的思想由 Rumelhart 等人(1986a)在早期反向传播的探索之一中引入:符号对应家庭成员身份,神经网络捕获家庭成员之间的关系,训练样本形成形如 (Colin, Mother, Victoria) 的三元组。神经网络第一层学习每个家庭成员的表示,例如 Colin 的特征可能代表他属于哪个家谱、该家谱的哪个分支、属于哪一代。可以把神经网络视作计算把这些属性关联起来以得到期望预测的学习到的规则,模型进而可以做出如推断谁是 Colin 的母亲这样的预测。符号嵌入的思想被 Deerwester 等人(1990)扩展到词的嵌入,这些嵌入用 SVD 学习。后续嵌入由神经网络学习。NLP 的历史以输入表示方式流行的更迭为标志。在这些早期关于符号或词的工作之后,一些最早将神经网络用于 NLP 的研究(Miikkulainen 和 Dyer 1991;Schmidhuber 1996)把输入表示为字符序列。Bengio 等人(2001)把关注点拉回到词的建模上,引入神经语言模型,产生可解释的词嵌入。这些神经模型从 1980 年代定义小规模符号的表示,扩展到现代应用中数百万词(包括专有名词和拼写错误)的表示。这一计算规模的扩展促成了 12.4.3 节描述的各项技术。最初,把词作为语言模型基本单位带来了语言建模性能提升(Bengio 等人 2001)。至今新技术持续推进基于字符的模型(Sutskever 等人 2011)和基于词的模型,近期工作(Gillick 等人 2015)甚至建模 Unicode 字符的各个字节。神经语言模型背后的思想已被扩展到多个 NLP 应用,如句法分析(Henderson 2003、2004;Collobert 2011)、词性标注、语义角色标注、组块分析等,有时使用单一多任务学习架构(Collobert 和 Weston 2008a;Collobert 等人 2011a),其中词嵌入在各任务间共享。t-SNE 降维算法(van der Maaten 和 Hinton 2008)的提出以及 Joseph Turian 2009 年将其高调应用于可视化词嵌入,使得嵌入的二维可视化成为分析语言模型的流行工具。
12.5 其他应用
本节覆盖一些与上文目标识别、语音识别、自然语言处理标准任务不同的深度学习应用。第三部分将进一步扩展范围,涵盖仍主要处于研究阶段的那些任务。
12.5.1 推荐系统
信息技术领域机器学习的主要应用族系之一是向潜在用户或客户推荐项目的能力。可区分两大类应用:在线广告和项目推荐(这些推荐往往仍以售卖产品为目的)。两者都依赖于预测用户和项目之间的关联——要么预测某个动作(用户购买产品,或该动作的某种代理指标)的概率,要么预测若向该用户展示广告或推荐该项目时所能获得的期望收益(可能依赖于产品价值)。互联网目前在很大程度上由各种形式的在线广告支撑。经济中有许多重要部分依赖在线购物。Amazon 和 eBay 等公司使用包括深度学习在内的机器学习做产品推荐。有时推荐的项目并非实际待售产品,例如选择社交网络信息流上要展示的帖子、推荐观看的电影、推荐笑话、推荐专家建议、为电子游戏匹配玩家,或在婚恋服务中匹配人。通常这种关联问题被当作监督学习问题处理:给定关于项目和用户的一些信息,预测兴趣代理(用户点击广告、用户输入评分、用户点击"赞"按钮、用户购买产品、用户在产品上花费的金额、用户访问产品页面的时间,等等)。这往往最终变成一个回归问题(预测某个条件期望值)或一个概率分类问题(预测某个离散事件的条件概率)。早期推荐系统的工作用极少的输入信息做这些预测:用户 ID 和项目 ID。在这种上下文下,泛化的唯一办法是依赖不同用户或不同项目目标变量取值模式的相似性。假设用户 1 和用户 2 都喜欢项目 A、B、C;由此可推断用户 1 和用户 2 口味相似。若用户 1 喜欢项目 D,这就是用户 2 也喜欢 D 的强信号。基于这一原则的算法属于协同过滤(collaborative filtering)。既可以使用非参数方法(如基于偏好模式估计相似度的最近邻方法),也可以使用参数方法。参数方法通常依赖于为每个用户和每个项目学习一个分布式表示(也称嵌入)。双线性预测(bilinear prediction)目标变量(如评分)是一种简单但非常成功且常作为最先进系统组件出现的参数方法。预测由用户嵌入与项目嵌入的点积得到(可能由仅依赖于用户 ID 或项目 ID 的常数修正)。设 \(\hat{R}\) 为包含预测的矩阵,\(A\) 为行中含用户嵌入的矩阵,\(B\) 为列中含项目嵌入的矩阵。设 \(b\) 和 \(c\) 分别为包含每个用户的某种偏置(表示该用户总体上是挑剔还是积极)和每个项目的某种偏置(表示其总体流行度)的向量。双线性预测如下:
通常希望最小化预测评分 \(\hat{R}_{u,i}\) 与实际评分 \(R_{u,i}\) 之间的平方误差。用户嵌入和项目嵌入可以方便地先降维到低维(两维或三维)后可视化,也可以像词嵌入一样用来在用户或项目之间做比较。获得这些嵌入的一种方式是对实际目标(如评分)的矩阵 \(R\) 做奇异值分解。这相当于将 \(R = UDV^\top\)(或其归一化变体)分解为两个低秩矩阵的乘积 \(A = UD\) 和 \(B = V^\top\)。SVD 的一个问题是它以任意方式处理缺失项,仿佛它们对应的目标值为 0。但我们希望对在缺失项上的预测不付出任何代价。幸运的是,观测评分上的平方误差和也可以用基于梯度的优化轻松最小化。SVD 和公式 12.20 的双线性预测在 Netflix 大赛(Bennett 和 Lanning 2007)中都表现非常好,该比赛旨在仅基于大量匿名用户先前的评分预测电影评分。比赛在 2006 到 2009 年间举行,吸引了许多机器学习专家参与,提升了推荐系统先进机器学习研究的水平并带来改进。尽管单独的简单双线性预测或 SVD 自身并未获胜,但它们是大多数参赛者(包括获胜者,Töscher 等人 2009;Koren 2009)所提交的集成模型的组件。在这些使用分布式表示的双线性模型之外,神经网络在协同过滤中的一种早期使用基于 RBM 无向概率模型(Salakhutdinov 等人 2007)。RBM 是赢得 Netflix 比赛的集成方法的重要元素(Töscher 等人 2009;Koren 2009)。评分矩阵分解思路的更高级变体也在神经网络社区被探索(Salakhutdinov 和 Mnih 2008)。然而协同过滤系统存在一个基本局限:当新项目或新用户被引入时,由于没有评分历史,无法评估其与已有项目或用户的相似度(相应地),也无法评估新用户与已有项目之间的关联程度。这被称为冷启动推荐问题。解决冷启动推荐问题的一般方法是引入关于个体用户和项目的额外信息,例如用户档案信息或每个项目的特征。使用这些信息的系统称为基于内容的推荐系统。从丰富的用户特征或项目特征到嵌入的映射可以通过深度学习架构学习(Huang 等人 2013;Elkahky 等人 2015)。专门的深度学习架构如卷积网络也被用于从丰富内容(如音乐音轨)中学习特征以做音乐推荐(van den Oörd 等人 2013)。在那项工作中,卷积网络以声学特征为输入,计算关联歌曲的嵌入;歌曲嵌入与用户嵌入的点积被用于预测用户是否会听这首歌。
12.5.1.1 探索与利用
向用户做推荐时,会出现一个超出普通监督学习、进入强化学习范畴的问题。许多推荐问题理论上最准确的描述是情境赌博机(contextual bandits,Langford 和 Zhang 2008;Lu 等人 2010)。其问题在于:用推荐系统收集数据时,我们对用户偏好得到的是有偏且不完整的视角:我们只看到用户对被推荐项目的反应,而看不到对其他项目的反应。此外在某些情况下,对未被推荐的用户,我们可能完全得不到信息(例如广告拍卖中,提出的价格可能低于最低门槛或未赢得拍卖,广告根本不展示)。更重要的是,我们无从得知若推荐其他项目会出现什么结果。这就像训练分类器时,对每个训练样本 \(x\) 选一个类 \(\hat{y}\)(通常按模型概率最高的类),然后只得到该选择是否正确的反馈。显然每条样本传递的信息比监督情形(直接得到真实标签 \(y\))少,因此需要更多样本。更糟的是,若不谨慎,可能出现一个在数据不断累积时仍持续做出错误决策的系统,因为正确决策最初概率很低:学习器在挑选到正确决策前无法学到关于该正确决策的任何信息。这与强化学习中只观察到所选动作奖励的情形类似。一般而言强化学习可能涉及多步动作与多个奖励的序列。赌博机情形是强化学习的特例:学习器只做一个动作、收一个奖励。赌博机问题的简单之处在于学习器知道哪个奖励对应哪个动作。在一般强化学习情形下,高或低奖励可能由最近动作引起,也可能由很久以前的动作引起。情境赌博机指动作在某种能辅助决策的输入变量上下文中做出的情形。例如,我们至少知道用户身份,并要挑选一个项目。从上下文到动作的映射也称为策略。学习器与数据分布(现在依赖于学习器的动作)之间的反馈环是强化学习和赌博机文献中的一个核心研究问题。强化学习需要在探索(exploration)和利用(exploitation)之间做权衡。利用指采取来自当前最佳已学策略的动作——我们已知这些动作能获得高奖励;探索指特意采取动作以获得更多训练数据。若知道给定上下文 \(x\) 动作 \(a\) 给我们的奖励为 1,并不知道这是否是最好的可能奖励。我们可能想利用当前策略继续采取动作 \(a\) 以较确定地获得 1 的奖励;但也可能想通过尝试 \(a'\) 来探索;尝试 \(a'\) 的结果未知,希望得到 2 的奖励,但有得到 0 奖励的风险。无论如何,我们至少获得了一些知识。探索可以以多种方式实现:从偶尔采取覆盖整个可能动作空间的随机动作,到基于模型的方法(基于期望奖励和模型对该奖励的不确定性来计算动作选择)。有许多因素决定我们偏好探索还是利用的程度,其中最显著的因素之一是我们感兴趣的时间尺度。若智能体只有很短时间累积奖励,我们更偏好利用;若智能体有很长时间累积奖励,一开始就做更多探索是有意义的,以便未来动作能基于更多知识被更有效地规划。随着时间推移、所学策略改进,我们向更多利用的方向移动。监督学习不存在探索-利用权衡,因为监督信号总是为每个输入指明哪个输出正确,没有必要尝试不同输出来确定是否更好——我们始终知道标签是最佳输出。强化学习情境下的另一难点(除探索-利用权衡外)是评估与比较不同策略的困难。强化学习涉及学习器与环境的交互;这种反馈环意味着用固定测试集输入评估学习器性能并不直接——策略本身决定会看到哪些输入。Dudik 等人(2011)提出了评估情境赌博机的技术。
12.5.2 知识表示、推理与问答
深度学习方法在语言建模、机器翻译和 NLP 上大获成功,原因之一是对符号(Rumelhart 等人 1986a)和词(Deerwester 等人 1990;Bengio 等人 2001)使用嵌入。这些嵌入表示关于单个词和概念的语义知识。一个研究前沿是为短语以及词与事实之间的关系开发嵌入。搜索引擎已为这一目的使用机器学习,但要改进这些更高级的表示仍有许多工作要做。一个有趣的研究方向是确定如何训练分布式表示以捕获两个实体之间的关系。这些关系允许我们形式化关于对象以及对象之间如何交互的事实。数学上,二元关系是对象有序对的集合。在集合中的对被认为具有该关系,不在集合中的对则没有。例如,可以用有序对集合 \(S = \{(1, 2), (1, 3), (2, 3)\}\) 在实体集 \(\{1, 2, 3\}\) 上定义"小于"关系。关系一旦定义,就可以像动词一样使用。因为 \((1, 2) \in S\),我们说 1 小于 2;因为 \((2, 1) \notin S\),我们不能说 2 小于 1。当然,相互关联的实体不必是数字,可以定义 is_a_type_of 关系包含如 (dog, mammal) 的元组。在 AI 语境下,我们把关系视为用句法简单、高度结构化的语言写出的一句话。关系扮演动词角色,关系的两个参数扮演主语和宾语角色。这些句子形如一个 token 三元组:
取值形式为:
也可以定义属性(attribute),一个类似关系但只取一个参数的概念:
例如可以定义 has_fur 属性,并把它应用于 dog 这样的实体。许多应用需要表示关系并对其推理。在神经网络语境下,应如何最佳地做到这一点?机器学习模型当然需要训练数据。可以从由非结构化自然语言组成的训练数据集中推断实体间关系;也存在显式识别关系的结构化数据库。这些数据库的常见结构是关系数据库,存储同一类信息,虽然并非以三 token 句子的形式格式化。当一个数据库旨在把关于日常生活的常识或关于某个应用领域的专家知识传递给 AI 系统时,我们称该数据库为知识库(knowledge base)。知识库范围从像 Freebase、OpenCyc、WordNet 或 Wikibase 等通用知识库,到更专门的知识库如 GeneOntology。通过把知识库中每个三元组视作一个训练样本,并最大化一个捕获其联合分布的训练目标,可以学习实体和关系的表示(Bordes 等人 2013a)。除训练数据外,我们还需要定义要训练的模型族。一种常见方法是把神经语言模型扩展为对实体和关系建模。神经语言模型学习一个向量,提供每个词的分布式表示;它们也通过学习这些向量的函数学习词之间的交互,如哪个词可能跟随一个词序列出现。我们可以通过为每个关系学习一个嵌入向量把这一方法扩展到实体和关系。事实上,建模语言和建模以关系编码的知识之间的平行性如此紧密,以至于研究者已经通过同时使用知识库和自然语言句子(Bordes 等人 2011、2012;Wang 等人 2014a)或组合多个关系数据库的数据(Bordes 等人 2013b)训练此类实体的表示。对于与这种模型相关的具体参数化,存在许多可能。早期关于学习实体间关系的工作(Paccanaro 和 Hinton 2000)假设强约束的参数形式("线性关系嵌入"),通常对关系和实体使用不同形式的表示:例如 Paccanaro 和 Hinton(2000)和 Bordes 等人(2011)对实体用向量、对关系用矩阵,思路是关系像算子一样作用于实体。另一种方式是把关系视为与其他实体一样的实体(Bordes 等人 2012),允许对关系本身做陈述,但需要把更多灵活性放在组合它们的机制中以建模其联合分布。此类模型的一个实际短期应用是链接预测(link prediction):预测知识图谱中缺失的弧。这是一种基于旧事实泛化到新事实的形式。当前大多数知识库都是通过人工构建的,这倾向于让许多——可能是大多数——真实关系从知识库中缺失。此类应用的例子见 Wang 等人(2014b)、Lin 等人(2015)和 Garcia-Duran 等人(2015)。在链接预测任务上评估模型性能是困难的,因为我们只有正例数据集(已知为真的事实)。若模型提出一个不在数据集中的事实,我们无法确定模型是犯了错还是发现了一个新的、此前未知的事实。因此评估指标不那么精确,基于的是:模型把一组留出的已知真正事实的排名,相对于其他不太可能为真的事实的排名如何。构造"可能为负"(大概率为假)事实的一种常见方式是从一个真事实出发,生成该事实的损坏版本,例如把关系中的某个实体随机替换为另一个实体。流行的 precision at 10% 指标统计模型把"正确"事实排在所有该事实的损坏版本的前 10% 之中的次数。知识库及其分布式表示的另一应用是词义消歧(word-sense disambiguation,Navigli 和 Velardi 2005;Bordes 等人 2012),即在某种上下文中决定应使用词的哪个义项。关系知识与推理过程及对自然语言理解的结合最终将允许我们构建通用问答系统。通用问答系统必须能处理输入信息、记住重要事实,并以能在事后检索和推理的方式组织它们。这仍是一个困难的开放问题,只能在受限的"玩具"环境中解决。目前,记忆与检索具体陈述性事实的最佳方法是使用显式记忆机制,第 10.12 节描述。记忆网络(memory networks)最早被提出用于解决玩具问答任务(Weston 等人 2014)。Kumar 等人(2015)提出了一个扩展,用 GRU 循环网络把输入读入记忆并根据记忆内容产生答案。深度学习已被应用于除上述之外的许多应用,并且无疑将在本书写作之后被应用于更多应用。要给出任何接近这种主题的全面覆盖都是不可能的;本节提供了写作时可能的代表性样本。第二部分(描述涉及深度网络的现代实践,包含所有最成功的方法)在此告一段落。一般而言,这些方法使用代价函数的梯度来找到逼近某期望函数的模型参数。只要有足够多的训练数据,这种方法就非常强大。下一部分进入研究领域——为在更少训练数据下工作或执行更多种类任务而设计的方法;这些任务更具挑战性,远未像前文描述的那样接近解决。
本章个人批注
第十二章是 Goodfellow《Deep Learning》"现代实践"部分的收尾,它把前面章节里所有"如何训练一个网络"的知识落实到"现在都用这些网络做什么"。读下来最强烈的感受是,这一章几乎没有"新理论",它本质上是一份应用地图:12.1 节讲基础设施(CPU/GPU/分布式/压缩/动态结构/专用硬件),12.2–12.5 节讲四大应用领域(视觉、语音、NLP、推荐+知识)。作为读者,本章给我留下的最具体的问题不是"哪个方法最厉害",而是"为什么需要这么多工程化技巧"。比如 12.1.4 提到的模型压缩——"原始模型规模主要源于防止过拟合的需要"——这句话直白地揭示了一个反直觉事实:在很多场景下,"大"不是必要的,而是被数据稀缺逼出来的。这种观察在 12.5.1 的双线性推荐中再次出现,"用 SVD 把 \(R = UDV^\top\) 分解"和"用梯度下降直接优化平方误差"并列为两种主流路径,让我联想到科研里经常被并列提及的"线性方法"与"非线性方法"——它们很多时候只是在同一目标下的两条优化路径。另一个让我反复回看的部分是 12.4.3.2 的分层 softmax。Goodfellow 写得很克制:"实践中节省的计算通常不值得费这个劲",并给出 \(n_b \leq l n_h\) 的判据。这一句的诚实让我觉得比任何"分层 softmax 加速了 N 倍"的宣传都更有指导意义。类似地,12.4.3.3 关于噪声对比估计的讨论提醒我:在一个 1-of-\(|V|\) 的 softmax 上做"看起来自然的"梯度,会自然而然地把负相项展开成对所有词求和——这其实是一个隐含的"全词表枚举",而重要性采样只是换一种方式在不展开全词表的前提下估计同一个量。读完 12.4.5 的神经机器翻译小节,我意识到 attention 机制之所以在 2015 年被提出,本质上是在打破"用一个固定大小向量表示整句"这一瓶颈;Bahdanau 等人的方案里 \(c\) 仍然是 \(h^{(t)}\) 的加权和,区别在于 \(h\) 序列已经存在,\(c\) 是按需组合出来的,而不是把所有信息压缩到一个向量再压回去。这一点在科研写作上对我是个具体的方法论提示。12.5 节里"探索与利用"和"链接预测评估"两节不是深度学习核心内容,但作者把它们放进应用章,提示我:评估和应用层引入的反馈环(强化学习、bias 收集)会反过来影响模型设计。章节结尾处提到本书第二部分结束、第三部分转向"研究前沿"——这种结构安排暗示:前 11 章写的都是"已经管用的东西",12 章则把这些管用的东西和现实约束(硬件、数据、评估、用户行为)连起来,让读者明白"为什么这些方法在工业界能跑起来"。
与上下章的衔接(一段话)
第十二章上承第 11 章"实践方法论"——第 11 章讨论的是"如何系统地设计、调试、评估一个深度学习项目",本质上是面向研究者的方法论;第十二章则把这些方法论应用到具体的工业级问题中。具体的承接点至少有两处:一是 12.1 节的硬件与基础设施讨论,呼应了第 11 章关于"计算资源约束下选择模型规模"的内容;二是 12.2–12.5 节对各应用领域的覆盖,对应第 11 章"选择性能度量指标"和"决定基准模型"两步——读者在第 11 章学到"如何选择度量",在第 12 章则看到"在实际应用中具体度量是什么"。下启第三部分(深度学习研究):第 12 章结尾的"第二部分告一段落"段落明确预告,第三部分将进入"用更少训练数据、更多任务类型"的研究方法。12.4.2 与 12.4.6 把"词嵌入"和"分布式表示"的历史脉络铺到 Rumelhart 1986a、Deerwester 1990、Bengio 2001,并指出"学习更高级表示(短语、关系)"是开放问题,这为第三部分关于无监督学习、生成模型的研究方向做了铺垫;而 12.5.2 末尾对"通用问答系统"在玩具环境之外的开放状态描述,也直接对应第三部分将要讨论的记忆网络与推理方法。整章在结构上承担"应用 → 评估 → 开放问题"的桥梁作用,既是第二部分的具体落地,也是第三部分研究议程的现实驱动力。