提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
总结
前言
本书已经接近尾声,大部分概念和定义也已经完成,学习深度学习和人工智能是一场漫长的旅途,这本书只是漫长旅途的小小开端,希望读者能够准备好独自迈向下一步。
提示:以下是本篇文章正文内容,下面案例可供参考
一、重点内容回顾
在开始我们回顾一下本书都介绍了什么,梳理一下用到的知识。
1.人工智能的各种方法
首先,深度学习不是人工智能的同义词,甚至也不是机器学习的同义词。人工智能(artificial
intelligence)是一个古老而宽泛的领域,通常可将其定义为“将认知过程自动化的所有尝试”,
换句话说,就是思想的自动化。它的范围非常广泛,既包括很基本的内容,比如Excel 电子表格,
也包括非常高级的内容,比如会走路和说话的人形机器人。
机器学习(machine learning)是人工智能的一个特殊子领域,其目标是仅靠观察训练数据
来自动开发程序[即模型(model)]。将数据转换为程序的这个过程叫作学习(learning)。虽然
机器学习已经存在了很长时间,但它在20 世纪90 年代才开始取得成功。
深度学习(deep learning)是机器学习的众多分支之一,它的模型是一长串几何函数,一个
接一个地作用在数据上。这些运算被组织成模块,叫作层(layer)。深度学习模型通常都是层的
堆叠,或者更通俗地说,是层组成的图。这些层由权重(weight)来参数化,权重是在训练过
程中需要学习的参数。模型的知识(knowledge)保存在它的权重中,学习的过程就是为这些权
重找到正确的值。
虽然深度学习只是机器学习的众多方法之一,但它与其他方法并不处于同等地位。深度学
习是突破性的成功。原因如下。
2.深度学习在机器学习领域中的特殊之处
在短短几年的时间里,深度学习在人们曾经认为对计算机来说极其困难的大量任务上取得
了巨大的突破,特别是在机器感知领域,这一领域需要从图像、视频、声音等输入中提取有用
的信息。给定足够多的训练数据(特别是由人类正确标记的训练数据),深度学习能够从感知数
据提取出人类能够提取出的几乎全部信息。因此,有时会听到这种说法——深度学习已经解决
了感知(solve perception),但这种说法只对感知的狭义定义而言才是正确的。
深度学习取得了前所未有的技术上的成功,以一己之力引发了第三次人工智能夏天(AI
summer),这也是迄今为止规模最大的一次,人们对人工智能领域表现出强烈的兴趣,投入大
量投资并大肆炒作。在本书的写作过程中,我们正处于这次人工智能夏天中。这一夏天是否会
在不远的将来结束,以及它结束后会发生什么,都是人们讨论的话题。有一件事是确定的:深
度学习已经为许多大型科技公司提供了巨大的商业价值,并且实现了人类水平的语音识别、智
能助理、人类水平的图像分类、极大改进的机器翻译,等等,这与之前的人工智能夏天形成了
鲜明对比。炒作很可能会烟消云散,但深度学习带来的持久经济影响和技术影响将会永远持续
下去。从这个意义上来讲,深度学习与互联网很类似:它可能在几年的时间里被夸大炒作,但
从长远来看,它仍然是一场改变我们经济和生活的重大革命。
我对深度学习特别乐观,因为即使未来十年没有进一步的技术进展,将现有算法部署到所
有适用的问题上,就能够带来大多数行业的变革。深度学习就是一场革命,目前正以惊人的速
度快速发展,这得益于在资源和人力上的指数式投资。从我的立场来看,未来很光明,尽管短
期期望有些过于乐观。将深度学习部署到可能应用的所有领域需要超过十年的时间。
3.如何看待深度学习
关于深度学习,最令人惊讶的是它非常简单。十年前没人能预料到,通过梯度下降来训练
简单的参数化模型,就能够在机器感知问题上取得如此惊人的结果。现在事实证明,你需要的
只是足够大的参数化模型,并且在足够多的样本上用梯度下降来训练。正如费曼曾经对宇宙的
描述:“它并不复杂,只是很多而已。”a
在深度学习中,一切都是向量,即一切都是几何空间(geometric space)中的点(point)。
首先将模型输入(文本、图像等)和目标向量化(vectorize),即将其转换为初始输入向量空
间和目标向量空间。深度学习模型的每一层都对通过它的数据做一个简单的几何变换。模型
中的层链共同形成了一个非常复杂的几何变换,它可以分解为一系列简单的几何变换。这个
复杂变换试图将输入空间映射到目标空间,每次映射一个点。这个变换由层的权重来参数化,
权重根据模型当前表现进行迭代更新。这种几何变换有一个关键性质,就是它必须是可微的
(differentiable),这样我们才能通过梯度下降来学习其参数。直观上来看,这意味着从输入到输
出的几何变形必须是平滑且连续的,这是一个很重要的约束条件。
将这个复杂的几何变换应用于输入数据的过程,可以用三维的形式可视化——你可以想象
一个人试图将一个纸球展平,这个皱巴巴的纸球就是模型初始输入数据的流形。这个人对纸球
做的每个动作都类似于某一层执行的简单几何变换。完整的展平动作系列就是整个模型所做的
复杂变换。深度学习模型就是用于解开高维数据复杂流形的数学机器。
这就是深度学习的神奇之处:将意义转换为向量,转换为几何空间,然后逐步学习将一个
空间映射到另一个空间的复杂几何变换。你需要的只是维度足够大的空间,以便捕捉到原始数
据中能够找到的所有关系。
整件事情完全取决于一个核心思想:意义来自于事物之间的成对关系(一门语言的单词之
间,一张图像的像素之间等),而这些关系可以用距离函数来表示。但请注意,大脑是否通过几
何空间来实现意义,这完全是另一个问题。从计算的角度来看,处理向量空间是很高效的,但
也很容易想到用于智能的其他数据结构,特别是图。神经网络最初来自于使用图对意义进行编
码这一思路,这也是它被命名为神经网络(neural network)的原因,相关的研究领域曾经被称
为联结主义(connectionism)。如今仍在使用神经网络这一名称,纯粹是出于历史原因,这是一
个极具误导性的名称,因为它与神经或网络都没有关系,尤其是和大脑几乎没有任何关系。更
合适的名称应该是分层表示学习(layered representations learning)或层级表示学习(hierarchical
representations learning),甚至还可以叫深度可微模型(deep differentiable model)或链式几何变
换(chained geometric transform),以强调其核心在于连续的几何空间操作。
4.关键的推动技术
目前正在展开的技术革命并非始于某个单项突破性发明。相反,与其他革命一样,它是大
量推动因素累积的结果——起初很慢,然后突然爆发。对于深度学习来说,我们可以找出下列
关键因素。
‰ 渐进式的算法创新,它们首先在 20 年内逐渐为人们所知(从反向传播算法开始),然后
在2012 年之后更多的科研力量涌入深度学习领域,这种创新的速度越来越快。
‰ 大量可用的感知数据,这对于实现在足够多的数据上训练足够大的模型是必要的。它是
消费者互联网的兴起与摩尔定律应用于存储介质上的副产物。
‰ 快速且高度并行的计算硬件,且价格很低,特别是 NVIDIA 公司生产的 GPU。NVIDIA
一开始生产的是游戏GPU,后来生产的是从头设计用于深度学习的芯片。NVIDIA 的
CEO 黄仁勋很早就注意到了深度学习的潜力,决定将公司的未来赌在这上面。
复杂的软件栈,使得人类能够利用这些计算能力。它包括 CUDA 语言、像 TensorFlow
这样能够做自动求微分的框架和Keras,Keras 让大多数人都可以使用深度学习。
未来,深度学习不仅会被专家(研究人员、研究生与具有学习背景的工程师)使用,而且
会成为所有开发人员工具箱中的工具,就像当今的Web 技术一样。所有人都需要构建智能应用
程序——正如当今每家企业都需要一个网站,每个产品都需要智能地理解用户生成的数据。实
现这个未来需要我们创造一些工具,它们可以让深度学习的使用更加容易,每个具有基本编程
能力的人都可以使用。Keras 是朝着这个方向迈出的第一大步。
本书写的时候,离现在已经有一段距离了,可以看到这段时间其实技术的进步很快的。
5.机器学习的通用工作流程
我们已经拥有非常强大的工具,能够创建将任何输入空间映射到任何目标空间的模型,这
非常好,但机器学习工作流程的难点通常是设计并训练这种模型之前的工作(对于生产模型而言,
也包括设计和训练这种模型之后的工作)。理解问题领域从而能够确定想要预测什么、需要哪些
数据以及如何衡量成功,这些都是所有成功的机器学习应用的前提,而Keras 和TensorFlow 等
高级工具是无法帮你解决这些问题的。提醒一下,第4 章介绍过典型的机器学习工作流程,下
面我们来快速回顾总结一下。
(1) 定义问题:有哪些数据可用?你想要预测什么?你是否需要收集更多数据或雇人为数据
集手动添加标签?
(2) 找到能够可靠评估目标成功的方法。对于简单任务,可以用预测精度,但很多情况都需
要与领域相关的复杂指标。
(3) 准备用于评估模型的验证过程。训练集、验证集和测试集是必须定义的。验证集和测试
集的标签不应该泄漏到训练数据中。举个例子,对于时序预测,验证数据和测试数据的
时间都应该在训练数据之后。
(4) 数据向量化。方法是将数据转换为向量并预处理,使其更容易被神经网络所处理(数据
标准化等)。
(5) 开发第一个模型,它要打败基于常识的简单基准方法,从而表明机器学习能够解决你的
问题。事实上并非总是如此!
(6) 通过调节超参数和添加正则化来逐步改进模型架构。仅根据模型在验证集(不是测试集
或训练集)上的性能来进行更改。请记住,你应该先让模型过拟合(从而找到比你的需
求更大的模型容量),然后才开始添加正则化或降低模型尺寸。
(7) 调节超参数时要小心验证集过拟合,即超参数可能会过于针对验证集而优化。我们保留
一个单独的测试集,正是为了避免这个问题!
6.关键网络架构
你应该熟悉以下三种网络架构:密集连接网络、卷积网络和循环网络。每种类型的网络都
针对于特定的输入模式,网络架构(密集网络、卷积网络、循环网络)中包含对数据结构的假设,
即搜索良好模型所在的假设空间。某种架构能否解决某个问题,这完全取决于数据结构与网络
架构的假设之间的匹配度。
这些不同的网络类型组合起来,很容易实现更大的多模式网络,就像组合乐高积木一样。
某种程度上来说,深度学习的层就是信息处理的乐高积木。我们来快速看一下输入模式与适当
的网络架构之间的对应关系。
‰ 向量数据:密集连接网络(Dense层)。
‰ 图像数据:二维卷积神经网络。
‰ 声音数据(比如波形):一维卷积神经网络(首选)或循环神经网络。
‰ 文本数据:一维卷积神经网络(首选)或循环神经网络。
‰ 时间序列数据:循环神经网络(首选)或一维卷积神经网络。
‰ 其他类型的序列数据:循环神经网络或一维卷积神经网络。如果数据顺序非常重要(比
如时间序列,但文本不是),那么首选循环神经网络。
‰ 视频数据:三维卷积神经网络(如果你需要捕捉运动效果),或者帧级的二维神经网络(用
于特征提取)+ 循环神经网络或一维卷积神经网络(用于处理得到的序列)。
‰ 立体数据:三维卷积神经网络。
下面快速回顾一下每种网络架构的特点。
- 密集连接网络
密集连接网络是Dense 层的堆叠,它用于处理向量数据(向量批量)。这种网络假设输入
特征中没有特定结构:之所以叫作密集连接,是因为Dense 层的每个单元都和其他所有单元相
连接。这种层试图映射任意两个输入特征之间的关系,它与二维卷积层不同,后者仅查看局部
关系。
密集连接网络最常用于分类数据(比如输入特征是属性的列表),比如第3 章的波士顿房价
数据集。它还用于大多数网络最终分类或回归的阶段。例如,第5 章介绍的卷积神经网络,最
后通常是一两个Dense 层,第6 章的循环神经网络也是如此。
请记住:对于二分类问题(binary classification),层堆叠的最后一层是使用sigmoid 激活
且只有一个单元的Dense 层,并使用binary_crossentropy 作为损失。目标应该是0 或1。
from keras import models
from keras import layers
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
对于单标签多分类问题(single-label categorical classification,每个样本只有一个类别,不
会超过一个),层堆叠的最后一层是一个Dense 层,它使用softmax 激活,其单元个数等于类
别个数。如果目标是one-hot 编码的,那么使用categorical_crossentropy 作为损失;如
果目标是整数,那么使用sparse_categorical_crossentropy 作为损失。
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
对于多标签多分类问题(multilabel categorical classification,每个样本可以有多个类别),
层堆叠的最后一层是一个Dense 层,它使用sigmoid 激活,其单元个数等于类别个数,并使
用binary_crossentropy 作为损失。目标应该是k-hot 编码的。
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
对于连续值向量的回归(regression)问题,层堆叠的最后一层是一个不带激活Dense 层,
其单元个数等于你要预测的值的个数(通常只有一个值,比如房价)。有几种损失可用于回归问
题,最常见的是mean_squared_error(均方误差,MSE)和mean_absolute_error(平均
绝对误差,MAE)。
model = models.Sequential()
model.add(layers.Dense(32, activation='relu', input_shape=(num_input_features,)))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_values))
model.compile(optimizer='rmsprop', loss='mse')
- 卷积神经网络
卷积层能够查看空间局部模式,其方法是对输入张量的不同空间位置(图块)应用相同的
几何变换。这样得到的表示具有平移不变性,这使得卷积层能够高效利用数据,并且能够高度
模块化。这个想法适用于任何维度的空间,包括一维(序列)、二维(图像)、三维(立体数据)等。
你可以使用Conv1D 层来处理序列(特别是文本,它对时间序列的效果并不好,因为时间序列
通常不满足平移不变的假设),使用Conv2D 层来处理图像,使用Conv3D 层来处理立体数据。
卷积神经网络或卷积网络是卷积层和最大池化层的堆叠。池化层可以对数据进行空间下采样,
这么做有两个目的:随着特征数量的增大,我们需要让特征图的尺寸保持在合理范围内;让后面
的卷积层能够“看到”输入中更大的空间范围。卷积神经网络的最后通常是一个Flatten 运算
或全局池化层,将空间特征图转换为向量,然后再是Dense 层,用于实现分类或回归。
注意,大部分(或者全部)普通卷积很可能不久后会被深度可分离卷积(depthwise separable
convolution,SeparableConv2D 层)所替代,后者与前者等效,但速度更快、表示效率更高。
对于三维、二维和一维的输入来说都是如此。如果你从头开始构建一个新网络,那么一定要使用
深度可分离卷积。SeparableConv2D 层可直接替代Conv2D 层,得到一个更小、更快的网络,
在任务上的表现也更好。
一个常见的图像分类网络如下所示(本例是多分类)。
model = models.Sequential()
model.add(layers.SeparableConv2D(32, 3, activation='relu',
input_shape=(height, width, channels)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
- 循环神经网络
循环神经网络(RNN,recurrent neural network)的工作原理是,对输入序列每次处理一个
时间步,并且自始至终保存一个状态(state,这个状态通常是一个向量或一组向量,即状态几
何空间中的点)。如果序列中的模式不具有时间平移不变性(比如时间序列数据,最近的过去比
遥远的过去更加重要),那么应该优先使用循环神经网络,而不是一维卷积神经网络。
Keras 中有三种RNN 层:SimpleRNN、GRU 和LSTM。对于大多数实际用途,你应该使用
GRU 或LSTM。两者中LSTM 更加强大,计算代价也更高。你可以将GRU 看作是一种更简单、计
算代价更小的替代方法。
想要将多个RNN 层逐个堆叠在一起,最后一层之前的每一层都应该返回输出的完整序列
(每个输入时间步都对应一个输出时间步)。如果你不再堆叠更多的RNN 层,那么通常只返回最
后一个输出,其中包含关于整个序列的信息。
下面是一个单层RNN 层,用于向量序列的二分类。
model = models.Sequential()
model.add(layers.LSTM(32, input_shape=(num_timesteps, num_features)))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
下面是RNN 层的堆叠,用于向量序列的二分类。
model = models.Sequential()
model.add(layers.LSTM(32, return_sequences=True,
input_shape=(num_timesteps, num_features)))
model.add(layers.LSTM(32, return_sequences=True))
model.add(layers.LSTM(32))
model.add(layers.Dense(num_classes, activation='sigmoid'))
model.compile(optimizer='rmsprop', loss='binary_crossentropy')
7.可能性空间
你想要用深度学习来做什么?请记住,构建深度学习模型就像是玩乐高积木:将许多层组
合在一起,基本上可以在任意数据之间建立映射,前提是拥有合适的训练数据,同时这种映射
可以通过具有合理复杂度的连续几何变换来实现。可能性空间是无限的。本节将会用几个例子
来激发你的思考,思考除基本的分类和回归任务之外的可能性,这二者一直是机器学习最基本
的任务。
下面是我提到的应用领域,我将其按输入模式和输出模式进行了分类。请注意,其中不少
应用扩展了可能性的范围。虽然在所有这些任务上都可以训练一个模型,但在某些情况下,这
样的模型可能无法泛化到训练数据之外的数据。9.2 节和9.3 节将会讨论未来可以如何突破这些
局限。
‰ 将向量数据映射到向量数据
ƒ 预测性医疗保健:将患者医疗记录映射到患者治疗效果的预测。
ƒ 行为定向:将一组网站属性映射到用户在网站上所花费的时间数据。
ƒ 产品质量控制:将与某件产品制成品相关的一组属性映射到产品明年会坏掉的概率。
‰ 将图像数据映射到向量数据
ƒ 医生助手:将医学影像幻灯片映射到是否存在肿瘤的预测。
ƒ 自动驾驶车辆:将车载摄像机的视频画面映射到方向盘的角度控制命令。
ƒ 棋盘游戏人工智能:将围棋和象棋棋盘映射到下一步走棋。
ƒ 饮食助手:将食物照片映射到食物的卡路里数量。
ƒ 年龄预测:将自拍照片映射到人的年龄。
‰ 将时间序列数据映射为向量数据
ƒ 天气预报:将多个地点天气数据的时间序列映射到某地下周的天气数据。
ƒ 脑机接口:将脑磁图(MEG)数据的时间序列映射到计算机命令。
ƒ 行为定向:将网站上用户交互的时间序列映射到用户购买某件商品的概率。
‰ 将文本映射到文本
ƒ 智能回复:将电子邮件映射到合理的单行回复。
ƒ 回答问题:将常识问题映射到答案。
ƒ 生成摘要:将一篇长文章映射到文章的简短摘要。
‰ 将图像映射到文本
ƒ 图像描述:将图像映射到描述图像内容的简短说明。
‰ 将文本映射到图像
ƒ 条件图像生成:将简短的文字描述映射到与这段描述相匹配的图像。
ƒ 标识生成 / 选择:将公司的名称和描述映射到公司标识。
‰ 将图像映射到图像
ƒ 超分辨率:将缩小的图像映射到相同图像的更高分辨率版本。
ƒ 视觉深度感知:将室内环境的图像映射到深度预测图。
‰ 将图像和文本映射到文本
ƒ 视觉问答:将图像和关于图像内容的自然语言问题映射到自然语言答案。
‰ 将视频和文本映射到文本
ƒ 视频问答:将短视频和关于视频内容的自然语言问题映射到自然语言答案。
几乎是一切皆有可能,但不完全是一切。下一节我们将会看到深度学习不能做什么。
二、深度学习的局限性
对于深度学习可以实现的应用,其可能性空间几乎是无限的。但是,对于当前的深度学习
技术,许多应用是完全无法实现的,即使拥有大量人工标注的数据也无法实现。比如说,你可
以收集一个数据集,其中包含数十万条(甚至上百万条)由产品经理编写的软件产品功能的英
文说明,还包含由一个工程师团队开发的满足这些要求的相应源代码。即使有了这些数据,你
也无法训练一个读取产品说明就能生成相应代码库的深度学习模型。这只是众多例子中的一个。
一般来说,任何需要推理(比如编程或科学方法的应用)、长期规划和算法数据处理的东西,无
论投入多少数据,深度学习模型都无法实现。即使是排序算法,用深度神经网络来学习也是非
常困难的。
这是因为深度学习模型只是将一个向量空间映射到另一个向量空间的简单而又连续的几何
变换链。它能做的只是将一个数据流形X 映射到另一个流形Y,前提是从X 到Y 存在可学习的
连续变换。深度学习模型可以被看作一种程序,但反过来说,大多数程序都不能被表示为深度
学习模型。对于大多数任务而言,要么不存在相应的深度神经网络能够解决任务,要么即使存
在这样的网络,它也可能是不可学习的(learnable)。后一种情况的原因可能是相应的几何变换
过于复杂,也可能是没有合适的数据用于学习。
通过堆叠更多的层并使用更多训练数据来扩展当前的深度学习技术,只能在表面上缓解一
些问题,无法解决更根本的问题,比如深度学习模型可以表示的内容非常有限,比如大多数你
想要学习的程序都不能被表示为数据流形的连续几何变形。
1.将机器学习模型拟人化的风险
当代人工智能有一个实实在在的风险,那就是人们误解了深度学习模型的作用,并高估了
它们的能力。人类的一个基本特征就是我们的心智理论:我们倾向于将意图、信念和知识投射
到身边的事物上。在石头上画一个笑脸,石头就突然变得“快乐”了——在我们的意识中。将
人类的这个特征应用于深度学习,举个例子,如果我们能够大致成功训练一个模型来生成描述
图像的说明文字,我们就会相信这个模型能够“理解”图像内容和它生成的说明文字。然后,
如果某张图像与训练数据中的那一类图像略有不同,并导致模型生成非常荒谬的说明文字,我
们就会感到很惊讶。
对抗样本尤其能够突出说明这一点。对抗样本是深度学习网络的输入样本,其目的在于欺
骗模型对它们进行错误归类。比如你已经知道,在输入空间中进行梯度上升,可以生成能够让
卷积神经网络某个过滤器激活最大化的输入,这正是第5 章介绍的过滤器可视化技术的基本原
理,也是第8 章DeepDream 算法的基本原理。与此类似,通过梯度上升,你也可以对图像稍做
修改,使其能够将某一类别的类别预测最大化。将长臂猿的梯度添加到一张熊猫照片中,我们
可以让神经网络将这个熊猫归类为长臂猿。这既表明了这些模型的脆弱性,也表明
这些模型从输入到输出的映射与人类感知之间的深刻差异。
简而言之,深度学习模型并不理解它们的输入,至少不是人类所说的理解。我们自己对图
像、声音和语言的理解是基于我们作为人类的感觉运动体验。机器学习模型无法获得这些体验,
因此也就无法用与人类相似的方式来理解它们的输入。通过对输入模型的大量训练样本进行标
记,我们可以让模型学会一个简单几何变换,这个变换在一组特定样本上将数据映射到人类概念,
但这种映射只是我们头脑中原始模型的简化。我们头脑中的原始模型是从我们作为具身主体的
体验发展而来的。机器学习模型就像是镜子中的模糊图像。
作为机器学习从业者,你一定要始终记住这一点,永远不要陷入这样一个陷阱,即相信神
经网络能够理解它们所执行的任务——它们并不理解,至少不是用我们可以理解的方式。我们
希望教神经网络学会某项任务,但它们是在一个不同的、更加狭窄的任务上进行训练,这个任
务就是将训练输入逐点映射到训练目标。如果向神经网络展示与训练数据不一样的数据,它们
可能会给出荒谬的结果。
2.局部泛化与极端泛化
深度学习模型从输入到输出的简单几何变形与人类思考和学习的方式之间存在根本性的区
别。区别不仅在于人类是从具身体验中自我学习,而不是通过观察显式的训练样例来学习。除
了学习过程不同,底层表示的性质也存在根本性的区别。
深度网络能够将即时刺激映射到即时反应(昆虫可能也是这样),但人类能做的比这远远
更多。对于现状、对于我们自己、对于其他人,我们都使用一个复杂的抽象模型,并可以利用
这些模型来预测各种可能的未来并执行长期规划。我们可以将已知的概念融合在一起,来表示
之前从未体验过的事物,比如绘制一匹穿着牛仔裤的马,或者想象我们如果中了彩票会做什么。
这种处理假想情况的能力,将我们的心智模型空间扩展到远远超出我们能够直接体验的范围,
让我们能够进行抽象和推理,这种能力可以说是人类认知的决定性特征。我将其称为极端泛化,
即只用很少的数据,甚至没有新数据,就可以适应从未体验过的新情况的能力。
这与深度网络的做法形成了鲜明对比,我将后者称为局部泛化。深度网络
执行从输入到输出的映射,如果新的输入与网络训练时所见到的输入稍有不同,这种映射就会
立刻变得没有意义。比如,思考这样一个问题,想要学习让火箭登陆月球的正确的发射参数。
如果使用深度网络来完成这个任务,并用监督学习或强化学习来训练网络,那么我们需要输入
上千次、甚至上百万次发射试验,也就是说,我们需要为它提供输入空间的密集采样,以便它
能够学到从输入空间到输出空间的可靠映射。相比之下,我们人类可以利用抽象能力提出物理
模型(火箭科学),并且只用一次或几次试验就能得到让火箭登陆月球的精确解决方案。同样,
如果你开发一个能够控制人体的深度网络,并且希望它学会在城市里安全行走,不会被汽车撞上,
那么这个网络不得不在各种场景中死亡数千次,才能推断出汽车是危险的,并做出适当的躲避
行为。将这个网络放到一个新城市,它将不得不重新学习已知的大部分知识。但人类不需要死
亡就可以学会安全行为,这也要归功于我们对假想情景进行抽象建模的能力。
总之,尽管我们在机器感知方面取得了进展,但离达到人类水平的人工智能仍然很遥远。
我们的模型只能进行局部泛化,只能适应与过去数据类似的新情况,而人类的认知能够进行极
端泛化,能够快速适应全新情况并为长期的未来情况做出规划。
3.总结
我们应该记住以下内容:到目前为止,深度学习唯一的真正成功之处就是,给定大量的人
工标注数据,它能够使用连续的几何变换将空间X 映射到空间Y。做好这一点已经可以引起基
本上所有行业的变革,但离达到人类水平的人工智能还有很长的路要走。
想要突破我们这里所讨论的一些局限性,并创造出能够与人类大脑匹敌的人工智能,我们
需要抛弃简单的从输入到输出的映射,转而研究推理和抽象。对各种情况和概念进行抽象建模,
一个合适的基础可能是计算机程序。我们之前说过,机器学习模型可以被定义为可学习的程序。
目前我们能学习的程序只是所有程序一个狭小的特定子集。但如果我们能够以一种模块化的、
可重复使用的方式来学习任何程序呢?下一节将会介绍深度学习的未来之路可能是什么样的。
三、深度学习的未来
本节的内容更加带有推测性,其目的在于为希望加入研究项目或开始独立研究的人开拓视
野。根据已知的深度网络的工作原理、局限性及其研究现状,我们能否预测未来一段时间内事
情的发展趋势?下面是一些纯个人想法。注意,我并没有水晶球,所以很多预测可能都无法实现。
之所以分享这些预测,并不是因为我希望它们在未来被证明是完全正确的,而是因为这些预测
很有趣,而且现在就可以付诸实践。
从较高层面来看,我认为下面这些重要方向很有前途。
‰ 与通用的计算机程序更加接近的模型,它建立在比当前可微层要更加丰富的原语之上。
这也是我们实现推理和抽象的方法,当前模型的致命弱点正是缺少推理和抽象。
‰ 使上一点成为可能的新学习形式,这种学习形式能够让模型抛弃可微变换。
‰ 需要更少人类工程师参与的模型。不停地调节模型不应该是我们的工作。
‰ 更好地、系统性地重复使用之前学到的特征和架构,比如使用可复用和模块化子程序的
元学习系统。
此外请注意,到目前为止,监督学习已成为深度学习的基本内容,这些思考并不仅针对于
监督学习,而是适用于任何形式的机器学习,包括无监督学习、自监督学习和强化学习。标签
来自哪里或训练循环是什么样子,这些都不重要,机器学习这些不同的分支是同一概念的不同
方面。我们来具体看一下。
1.模型即程序
正如上一节所述,我们可以预测机器学习领域的一个必要转型是,抛弃只能进行纯模式识
别并且只能实现局部泛化的模型,转而研究能够进行抽象和推理并且能够实现极端泛化的模型。
目前的人工智能程序能够进行基本形式的推理,它们都是由人类程序员硬编码的,如依赖于搜
索算法、图操作和形式逻辑的软件。比如DeepMind 的AlphaGo,它所展示的大部分智能都是由
专业程序员设计和硬编码的(如蒙特卡洛树搜索),从数据中进行学习只发生在专门的子模块中
(价值网络与策略网络)。但在未来,这样的人工智能系统可以完全通过学习得到,不需要人类
参与其中。
如何才能实现这一未来?我们来考虑一个众所周知的网络类型:循环神经网络(RNN)。
值得注意的是,RNN 的局限性比前馈网络要略小。这是因为RNN 不仅仅是几何变换,它是在
for 循环内不断重复的几何变换。时序for 循环本身就是由开发人员硬编码的,它是网络的内
置假设。当然,RNN 在能够表示的内容方面仍然非常有限,这主要是因为它执行的每一步都是
一个可微的几何变换,从一步到另一步都是通过连续几何空间中的点(状态向量)来携带信息。
现在想象一个神经网络,它用一种类似编程原语的方式得到了增强,但网络并不是单一硬编码
的for 循环,具有硬编码的几何记忆,而是包含大量的编程原语,模型可以自由地操作这些原
语来扩展其处理功能,比如if 分支、while 语句、变量创建、长期记忆的磁盘存储、排序运算符、
高级数据结构(如列表、图和散列表)等。这种网络能够表示的程序空间要远远大于当前深度
学习模型的表示范围,其中某些程序还可以实现优秀的泛化能力。
一方面,我们将不再使用硬编码的算法智能(手工软件),另一方面,我们也不再使用学到
的几何智能(深度学习)。相反,我们要将正式的算法模块和几何模块融合在一起,前者可以提
供推理和抽象能力,后者可以提供非正式的直觉与模式识别能力。整个系统的学习过程只需要
很少人参与,甚至不需要人参与。
我认为人工智能有一个与此相关的子领域即将迎来春天,它就是程序合成,特别是神经程
序合成。程序合成是指利用搜索算法(在遗传编程中也可能是遗传搜索)来探索可能程序的巨
大空间,从而自动生成简单的程序。如果找到了满足规格要求的程序(规格要求通常由一组输
入/ 输出对提供),那么搜索就会停止。这很容易让人联想到机器学习:给定输入/ 输出对作为
训练数据,我们找到一个程序,它能够将输入映射到输出,还能够泛化到新的输入。区别在于,
我们通过离散的搜索过程来生成源代码,而不是在硬编码的程序(神经网络)中学习参数值。
我非常期待未来几年人们对这个子领域重新燃起兴趣。我特别期待在深度学习和程序合成
之间出现一个交叉子领域,这一子领域不是用通用语言来生成程序,而是生成被大量丰富的算
法原语(如for 循环等)所增强的神经网络(几何数据处理流程)。与直接生成源代
码相比,这种方法应该更加容易处理,也更加有用,它将大大扩展机器学习所能解决问题的范
围(即给定适当的训练数据,我们能够自动生成的程序空间的范围)。当代RNN 可以看作这种
算法- 几何混合模型的鼻祖。
2.超越反向传播和可微层
如果机器学习模型变得更像程序,那么通常就不再是可微的了。这些程序仍然使用连续的
几何层作为子程序,这些子程序是可微的,但整个模型是不可微的。因此,使用反向传播在固
定的硬编码的网络中调节权重值,可能不是未来训练模型的首选方法,至少不会只用这种方法。
我们需要找到能够有效地训练不可微系统的方法。目前的方法包括遗传算法、进化策略、某些
强化学习方法和交替方向乘子法(ADMM)。当然,梯度下降也不会被淘汰,梯度信息对于可微
的参数化函数的最优化总是很有用的。但我们的模型会变得越来越不满足于可微的参数化函数,
因此模型的自动开发(即机器学习中的学习)需要的也不仅仅是反向传播。
此外,反向传播是端到端的,这对于学习良好的链式变换是很有用的,但它没有充分利用
深度网络的模块化,所以计算效率很低。为了提高效率,有一个通用的策略:引入模块化和层
次结构。因此,我们可以引入解耦的训练模块以及训练模块之间的同步机制,并用一种层次化
的方式来组织,从而使反向传播更加高效。DeepMind 最近关于合成梯度的工作就稍稍反映了
这种策略。我希望在不远的将来,人们在这一方向上能走得更远。我可以设想的一个未来就是,
模型在全局上是不可微的(但部分是可微的),我们使用一种有效的搜索过程(不使用梯度)来
训练(生长)模型,而可微的部分则利用更高效版本的反向传播得到的梯度进行训练,其训练
速度更快。
3.自动化机器学习
未来,模型架构将是通过学习得到的,而不是由工程师人为设计的。学习架构与使用更丰
富的原语、类似程序的机器学习模型是密切相关的。
目前,深度学习工程师的大部分工作都是用Python 脚本整理数据,然后花很长时间调节深
度网络的架构和超参数,以得到一个有效模型。如果这名工程师有野心,他可能还想得到一个
最先进的模型。毫无疑问,这种方法肯定不是最佳的,但人工智能可以提供帮助。只是数据整
理很难实现自动化,因为这一步通常需要领域知识,还需要对工程师想要实现的目标有一个清晰、
深刻的理解。但是,超参数调节是一个简单的搜索过程,我们也知道在这种情况下工程师想要
实现的目标,它由所调节网络的损失函数来定义。建立基本的自动化机器学习(AutoML)系统
已经是很常见的做法。多年前我甚至也建立过自己的AutoML 系统,用来赢得Kaggle 竞赛。
在最基本的层面上,这样的自动化机器学习系统可以调节堆叠的层数、层的顺序以及每一
层中单元或过滤器的个数。这通常使用Hyperopt 等库来实现,我们在第7 章介绍过。但我们还
可以更有野心,尝试从头开始学习合适的架构,让约束尽可能少,比如可以通过强化学习或遗
传算法来实现。
另一个重要的自动化机器学习方向是联合学习模型架构和模型权重。我们每次尝试一个略
有不同的架构,都要从头训练一个新模型,这种方法是极其低效的,因此,真正强大的自动化
机器学习系统,在训练数据上进行反向传播来调节模型特征的同时,还能够不断调节其模型架构。
在我写到本节内容时,这种方法已经开始出现了。
这种方法出现之后,机器学习工程师的工作并不会消失;相反,工程师会做更多具有创造
价值的工作。他们开始投入更多精力来设计可以真实反映业务目标的复杂的损失函数,还可以
深入理解模型如何影响它们所部署的数字生态系统(比如,消费模型预测并生成模型训练数据
的用户),目前只有那些最大的公司才有精力考虑这些问题。
4.终身学习与模块化子程序复用
如果模型变得更加复杂,并且构建于更加丰富的算法原语之上,对于这种增加的复杂度,
需要在不同的任务之间实现更多的复用,而不是每次面对一个新任务或新数据集时,都从头开
始训练一个新模型。许多数据集包含的信息都不足以让我们从头开发一个复杂的新模型,利用
以往数据集中包含的信息是很必要的(就像你每次打开一本新书时,也不会从头开始学习英语——
那是不可能的)。每开始一个新任务都从头训练模型也是非常低效的,因为当前任务与之前遇到
的任务有很多重复之处。
近年来有一个反复出现的观察结果值得注意:训练同一个模型同时完成几个几乎没有联系的
任务,这样得到的模型在每个任务上的效果都更好。例如,训练同一个神经机器翻译模型来实现
英语到德语的翻译和法语到意大利语的翻译,这样得到的模型在两组语言上的表现都变得更好。
同样,联合训练一个图像分类模型和一个图像分割模型,二者共享相同的卷积基,这样得到的模
型在两个任务上的表现都变得更好。这是很符合直觉的:看似无关的任务之间总是存在一些信息
重叠,与仅在特定任务上训练的模型相比,联合模型可以获取关于每项任务的更多信息。
目前,对于不同任务之间的模型复用,我们使用执行通用功能(比如视觉特征提取)的模
型的预训练权重。第5 章介绍过这种用法。未来我希望这种方法的更一般的版本能够更加常见:
我们不仅重复使用之前学到的特征(子模型权重),还会重复使用模型架构和训练过程。随着模
型变得越来越像程序,我们将开始重复使用程序的子程序(program subroutine),就像重复使用
人类编程语言中的函数和类那样。
想想如今的软件开发过程:每当工程师解决了一个具体问题(比如Python 中的HTTP 查询),
他们就会将其打包成一个抽象的、可复用的库。日后面临类似问题的工程师可以搜索现有的库,
然后下载,并在自己的项目中使用。同样,在未来,元学习系统能够在高级可复用模块的全局
库中筛选,从而组合成新程序。如果系统发现自己对几个不同的任务都开发出了类似的子程序,
那么它可以对这个子程序提出一个抽象的、可复用的版本,并将其存储在全局库中。
这一过程可以实现抽象,抽象是实现极端泛化的必要组件。如果一个子程序在不同任务和不同
领域中都很有用,我们可以说它对解决问题的某些方面进行了抽象化(abstract)。这个抽象的定
义与软件工程中的抽象概念类似。这些子程序可能是几何子程序(带有预训练表示的深度学习
模块),也可能是算法子程序(更接近于当代软件工程师所操作的库)。
5.长期愿景
简而言之,以下是我对机器学习的长期愿景。
‰ 模型将变得更像程序,其能力将远远超出我们目前对输入数据所做的连续几何变换。这
些程序可以说是更加接近于人类关于周围环境和自身的抽象心智模型。因为它们具有丰
富的算法特性,所以还具有更强的泛化能力。
‰ 具体而言,模型将会融合算法模块与几何模块,前者提供正式的推理、搜索和抽象能力,
后者提供非正式的直觉和模式识别能力。AlphaGo(这个系统需要大量的手动软件工程
和人为设计决策)就是这种符号人工智能和几何人工智能融合的一个早期例子。
‰ 通过使用存储在可复用子程序的全局库(这个库随着在数千个先前任务和数据集上学习
高性能模型而不断进化)中的模块化部件,这种模型可以自动成长(grow),而不需要
人类工程师对其硬编码。随着元学习系统识别出经常出现的问题解决模式,这些模式将
会被转化为可复用的子程序(正如软件工程中的函数和类),并被添加到全局库中。这
样就可以实现抽象。
‰ 这个全局库和相关的模型成长系统能够实现某种形式的与人类类似的极端泛化:给定一
个新任务或新情况,系统使用很少的数据就能组合出一个适用于该任务的新的有效模型,
这要归功于丰富的类似程序的原语,它具有很好的泛化能力,还要归功于在类似任务上
的大量经验。按照同样的方法,如果一个人具有很多以前的游戏经验,那么他可以很快
学会玩一个复杂的新视频游戏,因为从先前经验得到的模型是抽象的、类似程序的,而
不是刺激与行动之间的简单映射。
‰ 因此,这种永久学习的模型生长系统可以被看作一种通用人工智能(AGI,artificial general
intelligence)。但是,不要指望会出现奇点式的机器人灾难,那纯粹只是幻想,来自于人
们对智能和技术的一系列深刻误解。不过对这种观点的批判不属于本书的范畴。
四、了解一个快速发展领域的最新进展
作为最后的临别语,我希望给你一些建议,让你在翻完本书最后一页之后知道如何继续学
习并更新知识和技能。正如我们今天所知道的,现代深度学习领域只有几年的历史,尽管它有
一个很长、很缓慢的史前历史并长达数十年。自2013 年以来,随着资金来源和研究人数呈指数
式增长,整个领域目前正在以狂热的步伐前进。你在本书学到的知识不会永不过时,这些知识
也不是你职业生涯的剩余时间所需要掌握的全部内容。
幸运的是,网上有大量免费的在线资源,你可以用来了解最新进展,还可以拓展视野。下
面介绍其中一些资源。
1.使用Kaggle 练习解决现实世界的问题
想要获得现实世界的经验,一种有效的方法是参加Kaggle 上的机器学习竞赛。唯一的真正
学习方式就是通过实践与实际写代码来学习,这也是本书的哲学,而Kaggle 竞赛就是这一哲学
的自然延续。在Kaggle 上,你会发现一系列不断更新的数据科学竞赛,其中许多都涉及深度学习。
一些公司想要在最具挑战性的机器学习问题上获得新颖的解决方案,就举办了这些竞赛,还为
顶尖参赛者提供了相当丰厚的奖金。
大部分竞赛的获胜者都使用XGBoost 库(用于浅层机器学习)或Keras(用于深度学习)。
所以你非常适合参加这些竞赛!通过参加一些竞赛,也可能是作为团队的一员,你将会更加熟
悉本书所介绍的一些高级最佳实践的用法,特别是超参数优化、避免验证集过拟合与模型集成。
2.在arXiv 阅读最新进展
深度学习研究与某些其他科学领域不同,它是完全公开化的。论文一旦定稿,就会公开发布供
人们自由获取,而且许多相关软件也都是开源的。arXiv(读作archive,其中X 代表希腊字母χ)
是物理、数学和计算机科学研究论文的开放获取预印本服务器。arXiv 已经成为了解机器学习
和深度学习最新进展的重要方法。大多数深度学习研究人员在完成他们的论文后会立刻上传到
arXiv 上。这样他们可以插一面旗子,无需等待会议接收(这需要几个月)就可以宣称某项研究
成果的所有权,鉴于该领域研究速度很快、竞争很激烈,这种做法是很有必要的。它还可以让这
一领域快速向前发展,对于所有新的研究成果,所有人都可以立刻看到,并可以在其基础上扩展。
一个要命的缺点是,arXiv 上每天发布大量新论文,即使全部略读一遍也是不可能的。这些
论文没有经过同行评议,想要筛选出重要且质量很高的论文是很困难的。
在噪声中找到信号很困难,而且正在变得越来越难。目前,这个问题还没有好的解决方案。
但有一些工具可以提供帮助:一个名叫arXiv Sanity Preserver 的辅助网站可以作为新论文的推荐
引擎,还可以帮你在深度学习某个狭窄的垂直领域中跟踪最新进展。此外,你还可以使用谷歌
学术(Google Scholar)来跟踪你最喜欢的作者的出版物。
3.探索Keras 生态系统
截至2017 年11 月,Keras 约有20 万名用户,并且还在迅速增长。Keras 拥有大量教程、指
南和相关开源项目组成的大型生态系统。
‰ 使用 Keras 的主要参考资料就是 Keras 的在线文档(https://keras.io)。Keras 的源代码位
于GitHub 上。
‰ 你可以在Keras的Slack频道(https://kerasteam.slack.com)上寻求帮助并加入深度学习讨论。
‰ Keras 博客(https://blog.keras.io)提供了 Keras 教程以及其他与深度学习有关的文章。
‰ 你可以在推特上关注作者:@fchollet。
总结
本书到这里就结束了!我希望你掌握了关于机器学习、深度学习、Keras,甚至关于认知的
一般知识。学习是终生的旅程,特别是在人工智能领域,我们面对的未知远远多于已知。所以
请继续学习,继续提问,继续研究,永不止步。即使目前已经取得了一定进展,人工智能的大
多数基本问题也仍然没有答案,许多问题甚至还没有以正确方式提出来。