读书导读 · CC BY-SA 4.0
《动手学深度学习》全书摘要与逐章导读
引文按 CC BY-SA 4.0 使用;本页文字也按同一协议授权,引文译文属于改编作品。免费阅读原书。
《动手学深度学习》讲了什么AI 辅助
每一台新的学习机器,都补上前一台没做完的事
整体来看,这是一本关于深度学习究竟是怎样被学习和实践的书,它的回答,是把概念、数学和可运行的代码交织在同一种载体里——每个示例一本自成一体的 notebook,一个共享的 d2l 包,每个组件先从零构建、再用简洁的框架 API 实现——因为应用深度学习,同时需要问题的界定、模型的数学、优化、统计和工程。它的主线是:抗拒手工编码规则的任务,应该通过四个组成部分(数据、模型、目标、优化)从数据中学习,从这个起点出发,每一件新机制的引入,都只是作为对前一件的某个局限的修补:线性回归已经提供了带参数的模型、极大似然损失和小批量 SGD;softmax 分类把预测改写为从分布中抽取一个样本;带非线性激活的隐藏层,化解了复合仿射映射的坍缩;卷积利用了对顺序不敏感的稠密层所忽略的像素相邻性;循环、门控、双向性和编码器—解码器对,吸纳了变长序列;而注意力去掉了定长上下文的瓶颈,Transformer 则完全丢掉了循环,使预训练的基础模型成为可能。然后,本书把这一切奠基在优化理论上——训练误差不是泛化误差,高维空间中鞍点比局部极小值占优,凸性提供了海森矩阵检验、拉格朗日函数、惩罚和投影,使梯度下降虽然面对非凸也仍然站得住——之后才转向让这些方法派上用场:编译与硬件感知的执行,数据并行对模型并行,计算机视觉从数据增广和微调,到基于锚框、用 IoU 打标签并用非极大值抑制的检测,自然语言处理从 word2vec 及其采样近似,到 BERT 及其序列级和词元级的微调,以及强化学习中用值迭代和 Q 学习求解的马尔可夫决策过程。它的收尾部分让实践有原则而不是临时凑合:高斯过程在函数上放置可解释的先验,超参数优化被改写为有噪声、无梯度的搜索,由逐次减半和 ASHA 这类多保真度方案加速,GAN 把双样本检验变成极小极大信号,推荐系统从显式评分走向基于隐式反馈的个性化排序,附录则把线性代数、微积分和概率呈现为一条几何的链,其中矩阵只会倾斜、旋转和缩放空间。最后的结论是,这里的胜任与基础设施和工作流密不可分——notebook 在 Jupyter 里被阅读、运行和编辑,可审阅的 markdown 源文件通过派生—编辑—提交—拉取请求回流,GPU 依据算力、显存大小和带宽来选,低精度是提高每美元吞吐的杠杆,云实例通过 SSH 端口转发来访问并在不用时停掉以控制成本——因此,理解、代码和运行它们的机器,构成了同一种实践。
一则讲透全书的寓言AI 辅助
用一个故事装下全书最核心的想法,并老实交代故事在哪里失真。
规则说不出口,学徒就从数据里学会了定价
从前有个村子,村里的面包师出了名:陌生人拿来任何一个面包,她都能猜出价钱。她的学徒央求她把规则说出来。她试了:“先称一称,然后……嗯,要是外皮深、内瓤松,除非是黑麦的……”规则总从她嘴边溜走,因为她的手知道,她的嘴却说不出;再说行情每个季节都在变。于是学徒不再追问,转而做了别的事。他把卖出的每个面包都记进一本账:重量、发酵了几天、卖了多少钱。他在石板上画了一台带两个旋钮的猜价机——每盎司多少钱,每发酵一天多少钱,再加一笔固定的钱——还定了一条给自己打分的规矩:对每个面包,取他的猜测和真实价格之间的差,平方,再减半,最后取平均。然后每天早上,他不拿整本账,只拿几行,看看每个旋钮往哪个方向拧一点能让差距变小,就拧一下。头一个星期,他把夏天的面包拟合过头了,得罪了一位冬天的顾客,于是他留出一页封好的账,里面的面包他从不拿来练手,只有这页封好的账也认可的时候,他才信得过自己。一位长辈训斥他:“真正的匠人是推导出规则的。”学徒回答:“面包师说不出来的东西,我推导不了。但我能拧旋钮,看着差距缩小,也能把账本拿给你看。”多年以后,他的石板上有了许多旋钮,也有了许多层叠起来的石板,可它仍然是那同样的四样东西:账本、旋钮、差距,以及拧动。那块旧的两旋钮石板挂在炉子上方,因为每个新来的人都能一眼看清它的全部。
故事里的每样东西代表什么
| 故事里 | 书里 |
|---|---|
| 说不出自己的定价规则、却定得很准的面包师 | 规则无法手工编写的任务——模式在变,或者映射超出了有意识的理解——而这恰恰是机器学习该出场的地方 |
| 学徒记下重量、发酵天数和价格的账本 | 数据:带标签的样本,以及把杂乱记录变成学习算法可以消化的张量的预处理和加载 |
| 带两个旋钮和一笔固定金额的石板 | 模型和模型族:线性回归是特征的加权和再加一个偏置;所有可以达到的旋钮设置构成被搜索的空间 |
| 把差距平方、减半,再取平均 | 平方误差损失作为目标函数——以及它在加性高斯噪声下的极大似然依据,而不是随手拿来的便利 |
| 每天早上取几行账,拧一下旋钮 | 小批量随机梯度下降作为默认的学习算法,而不是闭式解 |
| 从不用来练手的那页封好的面包账 | 泛化与超参数:训练误差不等于泛化误差,所以判断要依据留出的验证集 |
| 要求推导规则的长辈,对比“拧旋钮,看着差距缩小” | 本书的立场:形式化理论落后的地方,直觉靠调整可运行的代码并观察结果来建立 |
| 许多旋钮和层叠的石板,仍然是同样的四样东西 | 四部分分解——数据、模型、目标、优化——作为一个框架,之后的每种方法都读作对其中某一部分的替换 |
寓言在哪里失真
这则寓言的扭曲在于,它把旋钮变得一目了然:学徒能读懂“每盎司多少钱”并加以解释,所以这个故事偷偷把面包师所缺乏的那种可解释性又带了回来。书里的这个概念包含寓言承载不了的东西——层叠的石板并不是更多的旋钮,而是复合起来的非线性层,而仅仅复合仿射映射只会坍缩回一个仿射映射;拧动要依赖前向和反向传播、梯度缩放和打破对称性的初始化,没有一样像是手拨旋钮;在高维空间里,地形由鞍点主宰,而不是“缩小差距”所暗示的那个单一山谷;数据中的结构(像素的相邻、变长的序列)要求改变模型的形状,而不是旋钮的数量;以及工程底座——向量化、避免内存分配、GPU、共享的 d2l 包和可复现的环境——是训练得以进行的前提,而石板只需要粉笔。这则寓言也掩盖了书本身尚未解决的张力:学徒的两个特征被假定能解释全部变化,以及先从零实现、再把它丢掉换成框架 API,让他到底该在哪一层抽象上思考这个问题悬而未决。
《动手学深度学习》的核心论点
全书捍卫的 10 个论点,按论证需要的顺序排列。
- 深度学习不能单靠文字、数学或代码来讲授,因为应用它同时需要问题的界定、模型的数学、优化、统计泛化和工程;三者必须交织在同一种载体里。
“检验深度学习的潜力面临独特的挑战,因为任何一个应用都汇集了多个学科。”
“Testing the potential of deep learning presents unique challenges because any single application brings together various disciplines.”
Preface查看原文 → - 因为形式化的理论往往无法解释为什么这些技术管用,直觉应该靠调整可运行的代码并观察结果来建立,而不是靠等待证明。
- 当一项任务的规则说不出来——因为模式在变,或者映射超出了有意识的理解——正确的做法是写一个从带标签的样本中学习映射的程序,而不是手工设计识别器。
- 每个机器学习问题都可以分解为同样的四个组成部分——数据、模型、目标函数和优化算法——所以新方法应该读作这个框架内的替换。
- 线性回归理应最先讲授,因为它虽然很浅,却已经包含了深度学习几乎所有的组成部分,而且足够直观,两个账单的例子就能还原出它的参数。
- 解析的闭式解只是一个走运的特例,而不是学习的样板,所以应该把基于梯度的小批量优化当作默认的方法。
- 损失函数不是随意的便利:最小化平方误差,恰好就是加性高斯噪声下的极大似然。
- 工程上的细节——向量化计算、避免内存分配,以及用 pandas 预处理杂乱的数据——不是边角料,而是模型能训练起来的必要条件。
- 数学对象应该读作变换,而不只是记账:乘以一个矩阵,就是在空间之间映射向量,而这正是神经网络的一层所做的事。
- 只有 CPU 的机器就足以开始,所以没有 GPU 不应该阻止读者起步。
逐章导读
每一章都在本页:论证怎样展开、关键论点、常见误读和核心概念。从目录里选一章。
第 1 章:引言
把数据分成训练集和测试集,如何暴露出过拟合?
第 1 章是怎样展开的AI 辅助
本章如何开篇。 本章不是从机器学习的定义开始,而是从一个旨在划出它的必要性的对比开始。当一个问题可以被一一列举时,普通编程就好用得很:把一件商品加进购物车的逻辑,可以逐种情形地写出来,在第一位顾客到来之前就放心地发布。作者随后在它旁边放了第二类任务——预测天气、识别物体、听到一个口头的触发短语就唤醒设备——对这类任务,从输入到答案的逐步路径根本无法被有意识地检视,而输入本身也多得压倒一切:一支麦克风每秒递给你大约 44,000 个振幅数字,而你写不出任何规则把它们变成是或否。所以开篇的这一招是一种诊断,而不是一个证明,作者也坦率地说,唤醒词只是列举法失灵之处的一个示例,而不是证明它总是必定失灵。从这个诊断,替代方案直接顺势而出:如果你说不出规则,就收集任务被正确执行的样本,让一个优化算法去调整一个灵活程序的参数,直到它复现这些样本。这就搭起了四部分的脚手架——数据、模型、目标、优化——本章其余部分的分类法都挂在它上面。
本章如何展开。 确立了参数应该被拟合而不是被手写之后,作者的下一步是安抚:基本情形是读者本来就凭直觉在做的事。一位承包商,三小时收 350 美元,两小时收 250 美元,邀请任何人算出每小时 100 美元,外加 50 美元的上门费——这恰恰是一个拟合出来的线性模型,而作者点明了附带的条件:只有当假定的那两个特征真的解释了账单的全部变化时,这个推断才成立。回归由其目标的数值形态来定义,并以房价和这张账单来说明,之后的展开靠变换目标,而不是变换方法:分类回答的是哪一个?,从这里开始,综述通过层级的类别结构、标注(标签不互斥)、搜索、推荐系统和序列学习而扩展。关键的警示落在分类的讨论里:最可能的标签并不自动就是正确的行动。一个被判断有 20% 可能是毒鹅膏的蘑菇,吃下去的期望伤害是 0.2 乘以无穷大,而丢掉的损失只是 0.8 顿饭——所以理性的决策与排名第一的预测相矛盾。决策需要按后果给结果加权,而不只是给概率排名,本章就是这样在概念上把损失函数和决策规则分开的。
转折在哪里。 转折出现在作者从整个监督学习的综述中退后一步,点名它共同的局限的时候。到这一点为止的每一项任务,都是从预先收集好的一堆固定数据中学习的,而论证是,这种离线的设定本身无法支撑一个智能的智能体。一旦某个东西行动,它的行动就会塑造它随后观察到的东西——环境是否记得它、是否与它合作或与它竞争,以及环境的动态是否随时间漂移。其后果是训练与部署之间的分布偏移,所以假定数据集一成不变的方法,与问题是不匹配的。这就是接下来强化学习框架的动机:一个与环境交互的智能体,收到的是奖励而不是正确答案。作者小心地解释了为什么这真的更难。学习者从不会被告知哪个动作是最优的;在下棋或职业生涯中,奖励在产生它的那些动作之后很久才到来,所以学习者必须推断,先前许多没有标签的动作中,哪一个该得到功劳或该受责备。再加上部分可观测性,以及探索与利用的取舍,稀疏而延迟的反馈就作为与带标签监督性质不同的一种困难浮现出来——老虎机和马尔可夫决策过程则被定位为可处理的特例。
如何收尾。 结尾一节做了两件事。首先,它给 AI 焦虑的科幻腔调泄了气,并把真正的风险重新安置到:日常劳动的自动化,以及草率的统计偏见。作为例证的是农业机器人,它将为有机农户降低成本,同时又让收割自动化,消除目前雇用着极其大量人口的单调工作——这是一个看得见的、已经在展开的效应,作者认为它比推测中的恶意超级智能更紧迫。然后是本章对其主题的真正定义,被有意地放在结尾而不是开头。深度学习的特征不在于深度本身,而在于对多层表示的联合学习。作者预见了这里显而易见的误读:几乎所有早先的机器学习都已经涉及多层计算,早先的那些层是人设计的特征提取,只有最后那个浅层模型是用数据拟合的。变化在于,现在每一步变换都是与预测器一起学出来的,所以数百万个候选滤波器可以被自动评估,而不是由人手工发明——学出来的滤波器就是这样在计算机视觉中取代了设计出来的,并提高了准确率。因为这样的层可以直接消化原始音频、原始像素和变长文本,许多特定领域的预处理就消散了,各应用领域之间的边界变得模糊。本章最后把这放在更广的方法论转变之内——朝向形式由数据决定的模型,朝向经验主义,朝向代码和权重的开放共享——同时给其中的第一项附上了一个老实的条件:假设少的模型在数据充足时才合理,数据稀缺时仍然需要简化的假设,而准确率的提升通常以可解释性为代价。所提供的类比是物理学从手算近似转向数值模拟,是作为类比而不是证明提出的。
关键论点,以及支撑它们的原文
手写的规则对有些问题足够了,对另一些则无望,因为模式在漂移,或者输入到输出的关系超出了我们能够表达的范围。
作者对比了两种情形:像把商品加进购物车这样的电商逻辑可以逐种情形地列举,在任何顾客到来之前就放心地发布,而唤醒词检测器面对的是每秒大约 44,000 个麦克风样本,没有任何可写的规则把它们变成是或否。第二种情形只是一个说明性的任务,不是证明,但它表明了列举法在哪里失灵。
“以图像识别为例,完成这项任务所需的精确步骤超出了我们有意识的理解,尽管我们的潜意识认知过程毫不费力地完成了这项任务。”
“In the case of image recognition, the precise steps required to perform the task lie beyond our conscious understanding, even though our subconscious cognitive processes execute the task effortlessly.”
Chapter 1. Introduction查看原文 →
确立了参数应该从数据中拟合之后,作者论证基本情形其实已经很熟悉:线性回归是读者凭直觉就会做的事。
一位承包商三小时收 350 美元,两小时收 250 美元,任何人都能算出每小时 100 美元,外加 50 美元的上门费——恰恰是一个拟合出来的线性模型。作者点明了条件:只有当假定的那两个特征真的解释了账单的全部变化时,这才行得通。
“如果你跟上了这些,那你已经理解了线性回归背后的高层思想。”
“If you followed that much, then you already understand the high-level idea behind linear regression.”
Chapter 1. Introduction查看原文 →
从回归转向分类,作者警告说,概率最高的类别并不自动就是该采取的行动。
一个被判断有 20% 可能是毒鹅膏的蘑菇,吃下去的期望伤害是 0.2 乘以无穷大,而丢掉的损失只是 0.8 顿饭,所以理性的选择与最可能的标签相矛盾。因此,决策需要按后果给结果加权,而不只是给概率排名。
“注意,最可能的类别不一定是你要用来做决策的那个。”
“Note that the most likely class is not necessarily the one that you are going to use for your decision.”
Chapter 1. Introduction查看原文 →
另外 3 个论点
综述完从固定数据堆中学习的任务之后,作者论证这种离线的设定无法支撑一个智能的智能体。
一旦智能体行动,它的行动就塑造了它之后观察到的东西:环境是否记得它、是否与它合作或竞争,以及它的动态是否随时间而变。这些可能性造成了训练与部署之间的分布偏移,所以假定数据集一成不变的学习,与问题是不匹配的——这就是接下来强化学习框架的动机。
“如果我们想训练一个智能的智能体,就必须考虑它的行动可能怎样影响它未来的观测,所以离线学习是不合适的。”
“If we want to train an intelligent agent, we must account for the way its actions might impact the future observations of the agent, and so offline learning is inappropriate.”
Chapter 1. Introduction查看原文 →
在综述的结尾,作者认为,紧迫的风险是日常劳动的自动化和草率的统计偏见,而不是一个恶意的超级智能。
农业机器人将为有机农户降低成本,同时也让收割自动化,消除雇用着大量人口的单调工作——这是一个具体的、已经看得见的效应,作者认为它比推测的情景更紧迫。
“就我们今天所知,这在我们看来,是比恶意超级智能毁灭人类的可能性更紧迫的担忧。”
“With what we know today, this strikes us as a much more pressing concern than the potential of malevolent superintelligence for destroying humanity.”
Chapter 1. Introduction查看原文 →
深度学习的独特之处在于,所有的表示层都是一起学出来的,这消解了领域预处理与建模之间旧有的分野。
作者指向计算机视觉:那里的流水线曾经把手工设计的特征提取器与一个浅层模型分开,直到学出来的滤波器以更高的准确率取代了那些提取器。因为学出来的层可以消化原始音频、原始像素和用于翻译的变长文本——这些是早先的工具无法处理的低层感知数据——许多特定领域的预处理就消失了,各应用领域之间的边界也变得模糊。
“可以说,所有的机器学习都有许多层计算,其中第一层由特征处理步骤构成。”
“Arguably, all machine learning has many layers of computation, the first consisting of feature processing steps.”
Chapter 1. Introduction查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么规则失效,拟合有效
对于感知任务,从输入到答案的逐步映射无法被有意识地检视,而且原始输入极其庞大——仅一支麦克风每秒就送来大约 44,000 个振幅数字。既然写不出规则,人们就收集任务被正确执行的样本,让一个优化算法调整一个灵活程序的参数,直到它与这些样本相符。
机制 2
延迟的奖励模糊了责任
强化学习者从不会被告知哪个动作是最优的;它只收到奖励,而在下棋或职业生涯中,奖励在造成它的动作之后很久才到来。因此学习者必须推断,先前许多没有标签的动作中,哪一个该得到功劳或该受责备,这就是稀疏而延迟的反馈比带标签的监督难得多的原因。
机制 3
联合学习的层胜过手工构建的特征
经典的流水线也有层,但特征提取器是人设计的,只有最后那个浅层模型是用数据拟合的。深度学习是从数据中把每一步变换和预测器一起学出来的,所以数百万个候选滤波器可以被自动评估,而不是由人手工发明——学出来的滤波器就是这样取代了设计出来的,并提高了准确率。
常见误读
深度学习不过是老一套的机器学习,只是在上面堆了更多的层,所以深度就是全部的诀窍。
作者指出,几乎所有的机器学习本来就有多层计算——早先的那些层是人设计的特征提取。真正的转变在于,每一层都是从数据中联合学出来的,而不是手工设计的,这就是为什么自动学出来的滤波器胜过了设计出来的。
“可以说,所有的机器学习都有许多层计算,其中第一层由特征处理步骤构成。”
“Arguably, all machine learning has many layers of computation, the first consisting of feature processing steps.”
Chapter 1. Introduction查看原文 →
既然让数据来决定模型的形式胜过强加假设,那就应该总是偏爱灵活的、假设少的模型。
作者把这一转变呈现为有条件的:让数据来决定形式的模型,只有在数据充足时才合理,数据稀缺时仍然需要简化的假设,而准确率的提升通常以可解释性为代价——这与物理学从手算近似转向数值模拟时接受的取舍是一样的,书把它作为类比提出,而不是证明。
“当数据充足时,这些可以被更贴合数据的非参数模型取代。”
“When data is abundant, these can be replaced by nonparametric models that better fit the data.”
Chapter 1. Introduction查看原文 →
第 1 章的核心概念
- 机器学习
- 性能随着数据或交互的积累而提高的算法。
- 适用处: 当基于规则的解法能 100% 管用时,就不需要。
- 模型与模型族
- 参数设置固定的程序是一个模型;所有可以达到的设置构成它的族。
- 适用处: 本质上不同的输入/输出类型,可能需要一个不同的族。
- 学习算法
- 利用数据集来挑选参数值的元程序。
- 适用处: 需要先定义好问题的输入、输出和模型族。
- 监督学习
- 利用带标签的样本,基于已知的输入去预测一个指定的未知标签。
- 适用处: 只是若干种机器学习问题中的一种。
- 回归
- 预测一个可以取任意数值的标签。
- 适用处: 适用于标签是数值而不是离散类别的情形。
- 分类
- 预测一个样本属于一组离散类别中的哪一个。
- 适用处: 需要一个已知的、离散的类别集;用交叉熵而不是平方误差。
另外 10 个概念
- 多标签分类
- 一次预测多个标签,因为类别可以同时出现。
- 适用处: 用于类别不互斥的情形,比如一张有四种动物的图像。
- 序列学习
- 输入或输出是变长序列、需要上下文的任务。
- 适用处: 当相继的观测彼此依赖时需要,不同于固定输入的任务。
- 离线学习
- 在算法与环境断开之后,利用一堆固定的数据进行的学习。
- 适用处: 当智能体的行动会改变它未来的观测时,并不合适。
- 策略
- 一条把智能体所观察到的东西变成它所采取的动作的规则。
- 适用处: 只在“观测—动作—奖励”的循环内部才有定义。
- 功劳归属问题
- 弄清楚先前的哪些动作,该为晚得多的一个结果受到表扬或责备。
- 适用处: 当奖励稀疏而延迟时出现,比如下棋或晋升。
- 探索与利用
- 在使用已知的最佳策略和尝试未知的策略以求可能的收益之间做选择。
- 适用处: 用短期的奖励换取知识。
- 深度学习
- 使用多层神经网络的机器学习,其各层变换是从数据中一起学出来的。
- 适用处: 重点不在深度本身;传统的流水线也有层,但它们的层是手工设计的,而不是联合学习的。
- 端到端训练
- 先搭建起整个系统,再联合调整它的各个部分,而不是把分别调好的组件拼装起来。
- 适用处: 并非总是默认做法;有些场合仍然偏爱分别设计的组件。
- 特征工程
- 手工发明一些变换,把原始数据变成浅层模型能用的向量。
- 适用处: 人的巧思比不上对数百万种选择的自动评估,所以学出来的滤波器取代了它。
- 非参数模型
- 让充足的数据而不是简化的假设来决定其形式的模型。
- 适用处: 只有数据充足时才合理;数据稀缺时仍需要简化的假设,而且准确率可能以可解释性为代价。
第 1 章划线与批注AI 陪读
“而当你能设计出 $100\%$ 的时候都管用的解决方案时,你通常不应该去操心机器学习。”
“And when you are able to devise solutions that work \(100\%\) of the time, you typically should not be worrying about machine learning.”
查看原文 →对一本即将向你兜售一千页机器学习的教科书来说,这是一个令人耳目一新的老实边界标记。这个领域由它的补集来定义:规则够不着的地方。
“完成这项任务所需的精确步骤超出了我们有意识的理解,尽管我们的潜意识认知过程毫不费力地完成了这项任务”
“the precise steps required to perform the task lie beyond our conscious understanding, even though our subconscious cognitive processes execute the task effortlessly”
查看原文 →这才是本章真正的论点——不是任务很难,而是我们对自己是不透明的。机器学习是从“做到”和“解释”之间的缺口进来的。
“虽然这个故事是为了教学上的方便而编的”
“While this story was fabricated for pedagogical convenience”
查看原文 →括号里那一下眨眼在起作用:承认这个轶事是编排出来的,让作者保持老实,同时仍能用上它的温度。漂亮的修辞卫生。
另外 17 条批注
“麦克风每秒大约会收集 44,000 个样本。”
“Every second, the microphone will collect roughly 44,000 samples.”
查看原文 →这里最有说服力的一句。一个具体的数字,做到了三段“这很难”都做不到的事。
“你可以把参数想象成我们可以拧动的旋钮”
“You can think of the parameters as knobs that we can turn”
查看原文 →旋钮的比喻是整本书的承重梁。不过值得留意它藏了什么:旋钮暗示的是少数几个可解释的刻度盘,而不是十亿个纠缠的。
“注意,这一切都可以在数据科学家没有主动共谋、甚至没有意识到的情况下发生。”
“Note that this can all happen without the data scientist actively conspiring, or even being aware.”
查看原文 →这一节里最尖锐的一句话。伤害不需要恶棍——只需要一条流水线。把这句话放在一篇谈“关键组成部分”的章节里,悄悄地让伦理成了结构性的,而不是可选的。
“学生可能开始死记练习题,看似掌握了这个主题,一遇到以前没见过的题目就露怯”
“the student might begin to memorize the practice questions, appearing to master the topic but faltering when faced with previously unseen questions”
查看原文 →这个类比之所以落地,是因为每个读者都当过那个学生。不过请注意它也夹带了一个价值判断:死记就是失败。对人来说,大概也是如此。
“每小时 100 美元,外加 50 美元上门费。如果你跟上了这些,那你已经理解了线性回归背后的高层思想。”
“100 dollars per hour plus 50 dollars to show up at your house. If you followed that much, then you already understand the high-level idea behind linear regression.”
查看原文 →两个数据点,两个参数,精确求解——然后他们立刻就把这份精确收了回去。老实的地方在于承认接下来是噪声。
“一顿美味晚餐的确定好处,不值得为它冒 20% 的丧命风险”
“the certain benefit of a delicious dinner is not worth a 20% risk of dying from it”
查看原文 →蘑菇是本章悄悄地不再讲预测、转而讲决策的地方。准确率不是目标函数;后果才是。大多数已部署的机器学习都忘了这一点。
“0.2 \times \infty + 0.8 \times 0 = \infty”
查看原文 →把无穷大写进期望是一种修辞手法,而不是数学——任何非零的死亡概率都会让这个积分爆炸,这也意味着这个框架分不清 20% 的风险和 0.0001% 的风险。死亡其实并不是无穷坏,否则就没人开车了。
“把响尾蛇错认成束带蛇,可能会造成致命的后果”
“mistaking a rattler for a garter could have fatal consequences”
查看原文 →漂亮地拆了他们自己例子的台:层级不在自然界里,而在你的使用场景里。系统发生和后果是两棵不同的树,模型应该用那棵能伤到你的树来训练。
“通常在存档和标注之间有一年的滞后”
“typically there is a one-year lag between archiving and tagging”
查看原文 →MeSH 的细节是这一节里最有说服力的论证——不是基准测试的荣耀,而是医学文献中一年的延迟。具体的机构痛点胜过任何准确率表格。
“奇怪的是,PageRank 提供的评分并不依赖于实际的查询”
“Weirdly, the scoring provided by PageRank did not depend on the actual query”
查看原文 →“奇怪”这个词承担了很多。与查询无关不是疏忽,而是它让整个网络能够只离线计算一次的原因。这种奇怪是事后才有的。
“我们只观察到被审查的反馈:用户倾向于给他们感触强烈的电影打分”
“we only observe censored feedback: users preferentially rate movies that they feel strongly about”
查看原文 →缺失的三星评分是每个推荐系统里的幽灵。数据不是有噪声,而是系统性地缺席——而且缺席的方式与你要预测的东西相关。
“反馈循环的形成,是因为推荐系统偏向于推某个物品,而这个物品随后被认为更好”
“feedback loops to form where a recommender system preferentially pushes an item that is then taken to be better”
查看原文 →书在这里承认,模型是它所度量的系统的一部分。此前的一切都假定数据来自世界;在这里,数据来自上一个模型。这一段就是整个现代危机。
“一份极其专业化的工作,和一位极其独裁的老板”
“an extremely specialized job and an extremely dictatorial boss”
查看原文 →老板的类比讨好了监督学习,把它的弱点说成了舒适。真正的代价不是乏味——而是独裁者的标签编码着他的偏见,而模仿会继承它们。
“我们能问的问题的种类和数量,只受限于我们的创造力”
“the type and number of questions we can ask is limited only by our creativity”
查看原文 →老实的翻译:无监督学习没有真值,所以没有办法区分发现与人造产物。“只受限于创造力”也就是“构造上不可证伪”。
“参加由讲师出的考试,而作业却是由他们的助教布置的”
“taking exams written by a lecturer, while the homework was composed by their teaching assistants”
查看原文 →本章最好的类比——分布偏移是学生们普遍的怨言。它之所以落地,是因为每个人都感受过这种损失,而不只是读到过。
“监督学习可以被重新表述为强化学习”
“supervised learning can be recast as reinforcement learning”
查看原文 →是真的,也几乎没用。如果特例有闭式解,而一般情形需要几百万回合,通用性就什么也买不到。框架的宽度不是框架的威力。
“那次晋升很可能反映了上一年里一系列选得好的行动”
“That promotion likely reflects a number of well-chosen actions over the previous year”
查看原文 →功劳归属通过办公室政治偷偷带了进来——这个类比比本意更尖锐,因为晋升也有一部分是噪声和裙带。从一个你无法完全掌控的稀疏奖励中学习,恰恰是最难的情形。
读后感AI 陪读
旋钮的比喻优雅得把十亿个纠缠的参数都藏了起来
这一章的弧线比看上去要安静:它一开头就给自己划了一条界——如果你能用规则 100% 地解决它,那就去做那个——然后用本章余下的篇幅去描绘这条线之外的疆域。真正的论点不是被排除在外的任务很难;而是我们对自己是不透明的。我们认出一张脸,听到一个唤醒词,捕捉到一种语气,却说不出怎么做到的。机器学习是从“做到”和“解释”之间的缺口进来的,而本章最有说服力的招数是具体的而不是概念性的:每秒 44,000 个样本,做到了好几段“这很困难”都做不到的事。从这里开始,旋钮的比喻承载了一切——一个带参数的程序,其旋钮由数据来拧——它作为全书的承重梁,当之无愧,同时也恰好藏起了之后将要紧的东西,因为旋钮意味着少数几个可读的刻度盘,而不是十亿个纠缠在一起的。然后是分类法:回归由其目标的数值形态来定义,分类则对应“是哪一个”的问题,还有那个小时工资的例子,用两个数据点就把线性回归讲清楚了,随后又老实地收回了那份精确。蘑菇是整章的枢纽。在这之前,主题是预测;在这之后,主题是决策。准确率不再是目标,后果接管了一切,而大多数已部署的系统都忘了这一点。写进那个期望里的无穷大是修辞而不是数学——任何非零的死亡概率都会让它爆炸,所以这个框架分不清 20% 和 0.0001%,而我们事实上是会开车的——但它所戏剧化的要点,经受得住糟糕的算术。同样的洞察在层级结构出现时再次出现:响尾蛇对比束带蛇的旁白,拆了作者自己例子的台,因为要紧的那棵树不是系统发生树,而是“什么会伤到你”的那棵树。
标注、搜索、推荐系统和序列学习随后把讨论从玩具场景带到了机构,质地越往后越好:存档与 MeSH 标注之间一年的滞后,比任何基准表格都更有说服力地论证了自动化;PageRank 与查询无关,被称为“奇怪”,恰恰是那个让整个网络得以离线计算的设计选择;被审查的反馈意味着缺失的三星评分,是系统性地缺席的,而且缺席的方式与你想预测的东西相关。反馈循环那一段是本章反过来审视自己前提的地方——此前的一切都假定数据来自世界,而在这里,数据来自上一个模型。这一段话里包含了现代的危机。学习体制那一节,是我最想反驳这个框定过于舒适的地方。监督学习那位“独裁的老板”被说得只是乏味,而真正的代价是独裁者的标签带着他的偏见,模仿会继承它们。无监督学习的问题“只受限于我们的创造力”,这是对“没有真值,因此无法区分发现与人造产物”的一种慷慨说法——构造上就不可证伪。监督学习可以被重新表述为强化学习,这个说法是真的,也几乎没用:当特例有闭式解,而一般情形需要几百万回合时,通用性什么也买不到。框架的宽度不是框架的威力。真正落地的,是“考试由讲师出、作业由助教布置”的类比——分布偏移是学生们普遍的怨言,是感受到的而不是读到的——还有通过办公室政治到来的功劳归属,比本意更尖锐,因为晋升也有一部分是噪声和裙带。本章的伦理线索是它最被低估的特色,因为它是结构性的,而不是后来硬加上去的。关于伤害可以在数据科学家没有共谋、甚至没有意识到的情况下发生的那句话,位于“关键组成部分”一节里,而不在一篇关于责任的附录中,这悄悄地让它成为机制的一部分。
继续阅读
结尾的综述保持了这种姿态:真实的风险——自动化、被编码的偏见、反馈——而不是电影式的风险,然后给出深度学习的定义:联合学习的多层表示,端到端训练吞并了特征工程,同时还有朝向非参数模型、经验重于理论和开放共享的转变。我会这样告诉读者:把这一章读成一篇关于局限而不是能力的论证。它告诉你规则在哪里止步,准确率在哪里不再是目标,你的数据在哪里不再是世界的样本、而成了你上一个模型的回声,以及框架的通用性在哪里不再有用。教学的语气很温暖,类比出奇地好——好到你应该留意每一个类比偷偷带进了什么。这里的每一次比较,都在讨好它所说明的方法,而如果你是带着这个目的去读,这一章老实到把接缝留在了那里,看得见。
在 FeedLitra 里读第 1 章,每段旁边都有这些卡片。
开始读书第 2 章:预备知识
自动微分究竟是如何利用张量所存储的历史的?
第 2 章是怎样展开的AI 辅助
开篇:被框成生存技能的工具箱。 本章不是从论点开始,而是从一份清单开始——在任何模型能够被搭建之前读者需要的七项技能。其中的第一项,数据操作,为之后的一切定下了模式:张量,一个 n 维数组,被引入为数据进出深度学习系统的唯一接口。本章马上为这个选择提供了理由,而不是假定它,点出一个普通数值数组库所缺少的两项具体能力——自动微分和 GPU 执行——并论证这两者合起来,恰恰让神经网络既容易写又运行得快。这里顺带塞进了一个机制上的小要点,日后会有回报:普通的算术每次都会新建一个对象(Y = Y + X 会改变 Y 的身份,而 Z[:] = X + Y 不会),而由于模型带着几百兆字节的参数、每秒要更新多次,原地写入是一种内存纪律,而不是风格偏好。开篇随后绕道 pandas,因为真实的数据到来时是杂乱的:一张小小的房价表,有缺失的条目,它的类别型屋顶类型列被展开为指示列(“缺失”被提升为自己的一个类别),数值型的房间数用均值填充,然后才有东西变成张量。本章明确说,这只是速成课,不能代替好好学这个库。
展开:从头搭建的线性代数,然后重新框定。 从标量出发,本章依次爬升到向量、矩阵、转置和对称性、高阶张量,然后是运算的词汇——按元素的算术、降维、点积、矩阵—向量积和矩阵—矩阵积,以及范数。使它不至于成为一份运算清单的,是一条始终如一的解读指示:矩阵乘积应当被读作对向量的变换,而不是记账。本章通过指出这样的乘积把向量从一个空间带到另一个可能维度不同的空间来支持这一点,提出用方阵旋转作为熟悉的情形,并观察到矩阵—向量积字面上就是神经网络一层计算其输出的方式。这一节真正的转折出现在范数,它们不是作为收尾的技术细节,而是作为写学习目标所用的语言呈现的:让观测数据的概率尽可能大,把预测拉向真实值,把不同人的表示推开、同时把同一个人的表示拉近——这些每一条都是关于距离的主张,而实践中的距离就是范数。确立了目标就是关于距离的陈述之后,本章把自己交给了使它们最小化的微积分。
第一个转折:微分变成了机械的。 微积分通过导数的极限定义和可微性的定义进入,经过记法、基本规则和一些 matplotlib 绘图工具,再推广到偏导数和梯度。本章的支点出现在链式法则。对于嵌套的函数,导数相乘;写成多元形式,这就变成一个偏导数矩阵乘以一个梯度向量。随之而来的有两个后果,本章把它们都点了出来。第一,每一次梯度计算都是一个向量—矩阵乘积,这追溯性地解释了为什么线性代数那一节不是预备知识的预备知识,而是引擎本身。第二——这是概念上的回报——这个过程机械到可以自动化:沿依赖图向前走来求值,向后走来求导。与此同时,还有一个清醒的限定,关于梯度能作用于什么。准确率和曲线下面积是我们真正在乎的目标,而两者都不可微,所以没有任何基于导数的优化器能碰它们。因此训练最小化的是一个平滑的替身,其梯度指示参数该往哪个方向走,而被优化的量从来不完全是想要的量。
第二个转折:从存在的量到我们估计的量。 概率以自己是不确定性下的形式推理开篇,区分了频率派与贝叶斯派的读法,而统计则是从数据反过来做推断的学科。本章的组织性区分是用一枚公平的硬币铺陈开的:那个二分之一是硬币的属性,靠对称性来论证——正反面有给定分布的每个结果都与它的镜像相配。然而,如果正面的概率未知,就没有对称性论证可用;你必须收集抛掷的结果并设计一个估计量,比如正面次数与抛掷次数之比,然后追问它是否一致。演示有意设计得不够痛快:从明确公平的一对概率中模拟抽取,仍然返回不相等的计数,只有当抛掷次数爬升到一万次左右时,滚动的估计才落定到真值,大数定律缓慢而明显地发挥作用。教训是,理论上的概率和由数据算出的统计量是不同的对象,由估计量连接起来,而不是同义词。
收尾:条件化、汇总,以及更多数据的极限。 本章被引用最多的例证接着到来。两次 HIV 检测呈阳性,把作者的概率从 13.06% 提高到 83.07%——但本章小心地说明,算术并不是重点。第二次测量只有在给定真实状态时、它的误差与第一次检测无关的情况下才是有信息的;在这个假设下,即使第二次检测明显更不准确,这一跃升也成立,而反例让边界一目了然:把同一个检测再做一遍,它只会复现它自己的结果,什么也没增加。买来信心的是条件独立,而不是重复。其余的机制——期望、方差、协方差、读作似然乘以先验的贝叶斯公式、切比雪夫不等式——随之而来,本章在离场时用它们戳破了两个直觉。期望不是决策规则:一笔期望回报是本金 1.8 倍的投资,可以带着 0.7 的期望效用,即 30% 的期望损失,所以在那个效用函数下,把钱留着更划算;而平均值对分散程度或风险什么也没说。不确定性也不仅仅是数据短缺。估计误差只以大约样本量平方根分之一的速度下降,所以收益集中在前面,然后停滞——从 10 个观测到 1000 个,使不确定性大约降为十分之一,再来的 1000 个只换来大约 1.41 倍——而且无论如何,有些不确定性是偶然的,是现象本身固有的,再多的观测也毫无帮助。本章就这样结束在它的工具箱开始的地方,只是读者的期望已经被校准:这些工具很强大,而且每一件都有说明了的边界。
关键论点,以及支撑它们的原文
对深度学习来说,值得使用张量,而不是普通的数值数组。
作者指出了相对于普通 n 维数组库的两项具体增加:自动微分,以及在 GPU 上运行的能力。论点是,这两项特性合起来,恰恰让神经网络既容易写又运行得快。
“第一,张量类支持自动微分。第二,它借助 GPU 来加速数值计算,而 NumPy 只能在 CPU 上运行。”
“First, the tensor class supports automatic differentiation. Second, it leverages GPUs to accelerate numerical computation, whereas NumPy only runs on CPUs.”
§2.1 Data Manipulation查看原文 →
在任何建模之前,杂乱的真实世界数据必须先用处理表格的工具清理干净。
作者走了一遍一张有缺失条目的小小房价表:类别型的屋顶类型列被变成指示列(缺失成为它自己的类别),数值型的房间数列用其均值填充,然后才被转换成张量。作者把这框定为速成课,而不是对这个库的正式教程的替代。
“然而,要把深度学习应用到真实世界,我们必须提取以任意格式存储的杂乱数据,并对它做预处理,使之适合我们的需要。”
“However, to apply deep learning in the wild we must extract messy data stored in arbitrary formats, and preprocess it to suit our needs.”
§2.2 Data Preprocessing查看原文 →
乘以一个矩阵应该被读作对向量的变换,而不是记账;这是从作者由标量和向量搭起来的铺垫中得出的。
作者指出,这样的乘积把向量从一个空间带到另一个可能大小不同的空间,给出旋转作为乘以方阵的熟悉情形,并指出矩阵—向量积恰恰是神经网络每一层计算其输出的方式。
“我们可以把与矩阵 $\mathbf{A}\in \mathbb{R}^{m \times n}$ 的乘法看作一种变换,把向量从 $\mathbb{R}^{n}$ 投影到 $\mathbb{R}^{m}$。”
“We can think of multiplication with a matrix \(\mathbf{A}\in \mathbb{R}^{m \times n}\) as a transformation that projects vectors from \(\mathbb{R}^{n}\) to \(\mathbb{R}^{m”
§2.3 Linear Algebra查看原文 →
另外 3 个论点
范数不是可有可无的旁白,而是书写学习目标所用的语言。
作者列出深度学习的目标——让观测数据的概率尽可能大,把预测拉近真实值,把不同人的表示推开、同时把同一个人的表示拉近——并观察到每一条都是关于距离的陈述,而实践中的距离是用范数来表示的。这把讨论直接交给了优化这类目标的微积分。
“这些距离构成了深度学习算法的目标,常常用范数来表示。”
“These distances, which constitute the objectives of deep learning algorithms, are often expressed as norms.”
§2.3 Linear Algebra查看原文 →
接着往下,训练并不优化我们真正在乎的量,而是它的一个平滑的替身。
作者点出准确率和曲线下面积是我们真正想要、却无法求导的目标,所以没有任何基于导数的优化器能作用于它们;切实可行的路线是最小化一个可微的替代品,其梯度指示该如何移动参数以降低损失。
“并非所有函数都是可微的,包括许多我们希望优化的函数,比如准确率和受试者工作特征曲线下的面积(AUC)。”
“Not all functions are differentiable, including many that we wish to optimize, such as accuracy and the area under the receiving operating characteristic (AUC).”
§2.4 Calculus查看原文 →
概率属于产生数据的过程,而我们由数据算出的数是统计量,它们朝着相反的方向做推断。
作者靠对称性论证,一枚公平硬币的二分之一是硬币的属性:正反面有给定分布的每个结果,都与它的镜像相配。要研究正面的未知概率,则必须收集抛掷的结果,并设计一个估计量,比如正面与抛掷次数之比;从明确公平的一对概率中模拟抽取,仍然返回不相等的计数,只有当抛掷次数增长到一万次,滚动的估计才落定到真值。
“这里,概率 $1/2$ 是硬币本身的属性。”
“Here, the probability \(1/2\) is a property of the coin itself.”
§2.6 Probability and Statistics查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么原地写入能省内存
每个普通的算术表达式都会新建一个对象,作者通过指出 Y = Y + X 会改变 Y 的身份,而 Z[:] = X + Y 保持 Z 的身份不变,来说明这一点。由于模型带着几百兆字节的参数、每秒要更新多次,反复分配既浪费内存,又会留下指向过时值的陈旧引用;写进已有的存储则两者都避免了。
机制 2
链式法则变成了矩阵运算
对于嵌套函数,导数相乘,作者把多元的版本写成一个偏导数矩阵乘以一个梯度向量。由于每一次梯度计算因此都是一个向量—矩阵乘积,线性代数就成了深度学习的引擎,而整个过程机械到可以通过沿依赖图向前走来求值、向后走来求导而自动化。
机制 3
为什么第二次检测会增加信心
只有当给定真实状态时,第二次测量的误差与第一次检测的误差互不相关,它才是有信息的。在这个假设下,两次阳性结果把作者的 HIV 概率从 13.06% 推到 83.07%,即使第二次检测明显更不准确。作者的反例表明了界限:把同一个检测再做一遍,只会复现同样的结果,什么也没增加。
常见误读
如果一场赌博的期望收益大于你投进去的,那么参与就是理性的选择。
该比较的正确汇总量是效用,而不是原始回报。在作者的例子里,这笔投资的期望回报是本金的 1.8 倍,期望效用却是 0.7——效用上有 30% 的期望损失——所以在那个效用函数下,把钱留着是更好的选择。仅凭平均值,也对分散程度或风险什么都说明不了。
“如果这真是你的效用函数,你也许最好把钱留在银行里。”
“If indeed this were your utility function, you might be best off keeping the money in the bank.”
§2.6 Probability and Statistics查看原文 →
不确定性不过是数据的短缺,所以收集足够的观测就能把它驱散。
估计误差只以大约样本量平方根分之一的速度下降,所以收益早早到来,然后停滞:从 10 个观测到 1000 个,使不确定性大约降为十分之一,而再来的 1000 个只把它改善大约 1.41 倍。此外,有一部分不确定性是现象本身固有的,而不是我们的无知,再多的额外数据也无法消除它。
“这是机器学习一个持续存在的特点:虽然往往有容易的收益,但要取得进一步的收益,需要非常大量的数据,往往还要伴随着巨大的计算量。”
“This is a persistent feature of machine learning: while there are often easy gains, it takes a very large amount of data, and often with it an enormous amount of computation, to make further gains.”
§2.6 Probability and Statistics查看原文 →
第 2 章的核心概念
- 张量(n 维数组)
- 一个有任意多条轴的数字数组;向量有一条轴,矩阵有两条,再往上我们就只说 k 阶张量。
- 适用处: 类似 NumPy 的 ndarray,但增加了自动微分和 GPU 执行;阶数的是轴的数量,而维数数的是分量的数量。
- 广播机制
- 一条规则,让两个形状不同的张量能按元素组合:先沿长度为 1 的轴复制,直到形状匹配。
- 适用处: 只有不匹配的轴长度为 1 时才行得通;否则形状必须本来就一致。
- 缺失值(插补与删除)
- pandas 标为 NaN 的条目;你要么估计替代值(插补),要么丢掉受影响的行或列(删除)。
- 适用处: 哪个选项合适取决于上下文;类别型的 NaN 可以成为它自己的一个类别,数值型的 NaN 常用该列的均值来填充。
- 原地操作
- 把结果写进已经分配好的内存,比如 Y[:] = X + Y,而不是让新对象被创建。
- 适用处: 只有当被覆盖的值在之后的计算中用不到时才安全。
- 转置
- 翻转矩阵的行和列,于是元素 (i,j) 变成元素 (j,i)。
- 适用处: m×n 的矩阵变成 n×m;只有方阵才可能等于它自己的转置。
- 对称矩阵
- 与自己的转置相同的方阵。
- 适用处: 只对方阵有定义。
另外 18 个概念
- 哈达玛积
- 两个形状相同的矩阵的按元素乘法。
- 适用处: 要求形状匹配;不是矩阵乘法。
- 点积
- 两个等长向量中相同位置上元素的乘积之和。
- 适用处: 向量必须有相同的维数 d。
- 范数
- 一个把向量送到标量的函数,度量它有多大。
- 适用处: 必须满足缩放性、三角不等式和正定性;度量的是大小,而不是维数。
- 降维
- 沿选定的轴通过求和或求平均把张量压缩,这会从输出形状中去掉那些轴。
- 适用处: keepdims 保留轴的数量,以便广播。
- 可微的代理
- 一个平滑的替身损失,之所以被优化,是因为我们真正在乎的指标没有可用的导数。
- 适用处: 只有当目标指标(如准确率或 AUC)不可微时才需要。
- 梯度
- 把一个标量函数对每个输入变量的偏导数收集起来的向量。
- 适用处: 对把 n 维向量映射到标量的函数有定义。
- 链式法则
- 嵌套函数的导数相乘,所以梯度变成一个向量—矩阵乘积。
- 适用处: 要求每个分量函数都可微。
- d2l 包
- 一个共享的代码库,标有 #@save 的函数存放在里面,以备日后重用。
- 适用处: 书籍工程上的一个便利,不是数学思想。
- 概率与统计
- 概率描述真实的生成过程;统计量是由观测数据算出的数。
- 适用处: 频率估计概率,但在有限样本中从不与之完全相同。
- 贝叶斯概率
- 用概率来表示信念的程度,包括一次性的事件,并随证据而更新。
- 适用处: 允许不同的人从不同的先验出发,所以结论是主观的。
- 估计量与一致性
- 一个为估计某个参数而设计的统计量;一致性意味着随着数据增多,估计会收敛到真值。
- 适用处: 收敛是渐近的;小样本可能与真实概率有明显的偏差。
- 抽样
- 从一个底层的随机过程中抽取实际的结果,比如反复抛一枚硬币。
- 适用处: 模拟抽样需要一个随机数生成器,或多项分布的抽取。
- 大数定律
- 随着重复次数增多,平均值收敛到真实概率,误差大约以 n 的平方根分之一的速度缩小。
- 适用处: 适用于重复事件的平均值,不适用于单个不可重复的事件。
- 检测的条件独立性
- 只有在给定真实状态时、两次测量的误差互不相关,它们才会增加信息。
- 适用处: 重复完全相同的检测时不成立,那样得不到新的认识。
- 期望
- 一个随机变量按概率加权的平均值。
- 适用处: 仅凭均值,对分散程度或风险什么也说明不了。
- 方差
- 与均值的期望平方偏差,用作风险的度量。
- 适用处: 与均值的原始差值的期望为零,所以需要平方。
- 协方差矩阵
- 去中心化向量的期望外积构成的矩阵;给出任何线性函数的方差。
- 适用处: 非对角元素只报告相关性的强度,而不是因果。
- 偶然不确定性与认知不确定性
- 问题本身固有的随机性,对比关于模型参数的、更多数据可以缩小的不确定性。
- 适用处: 作者指出这些标签在用语上略有滥用,因为从哲学上讲,所有的不确定性都是认知性的。
第 2 章划线与批注AI 陪读
“自动计算导数的能力,使你可以忘掉刚学的大部分微积分”
“the ability to automatically compute derivatives so that you can forget much of the calculus you just learned”
查看原文 →书的机智在起真正的教学作用:它事先告诉你哪些知识是脚手架,哪些是承重的。老实地说出实践者实际要带多少微积分。
“遇到困难时,有一些在官方文档里找答案的本事”
“some aptitude for finding answers in the official documentation when you get stuck”
查看原文 →把读文档与线性代数并列,是一个安静的论点:这是一门手艺,而不只是一套理论。第七项生存技能是最不数学的,大概也是用得最多的。
“第一,张量类支持自动微分。第二,它借助 GPU 来加速数值计算”
“First, the tensor class supports automatic differentiation. Second, it leverages GPUs to accelerate numerical computation”
查看原文 →整场深度学习革命被压缩进两个要点。两者都不是数学思想——都是工程。值得停下来想想,这个领域有多少东西建立在这里。
另外 17 条批注
“注意,我们向量的元素是一次一行地排布的,因此 x[3] == X[0, 3]”
“Notice that the elements of our vector are laid out one row at a time and thus x[3] == X[0, 3]”
查看原文 →这句顺带的话是后来会咬人的那一句。reshape 是对一块扁平缓冲区的重新解读,而不是重新排列——行主序是此后每一个形状 bug 背后的隐形契约。
“我们可能从多个变量指向同样的参数。如果我们不原地更新,就必须小心更新所有这些引用”
“we might point at the same parameters from multiple variables. If we do not update in place, we must be careful to update all of these references”
查看原文 →在这里,教程短暂地不再是数学,而成了系统编程。别名、过时的引用、泄漏——张量是披着向量外衣的指针。
“torch 张量和 NumPy 数组会共享它们底层的内存,通过原地操作改动其中一个,另一个也会随之改变。”
“The torch tensor and NumPy array will share their underlying memory, and changing one through an in-place operation will also change the other.”
查看原文 →被说成是便利,其实是一道暗门。“转换很容易”和“它们是同一块内存”是很不一样的说法,而第二个才是会在凌晨两点让你吃惊的。
“缺失值,它们是数据科学的“臭虫”,是你整个职业生涯中都要面对的持续威胁”
“missing values and they are the “bed bugs” of data science, a persistent menace that you will confront throughout your career”
查看原文 →这个比喻起的作用不止是增色——臭虫不会被解决,只会被管理。罕见的承认:工作中最杂乱的部分没有干净的理论。
“对于类别型的输入字段,我们可以把 NaN 当作一个类别。”
“For categorical input fields, we can treat NaN as a category.”
查看原文 →作为启发式偷偷带进来,却是一个有牙齿的建模决策:它假定缺失本身携带信号。有时是真的,有时是泄漏。文字没有标明二者的区别。
“一种常见的启发式做法是,用相应列的均值来替换 NaN 条目”
“one common heuristic is to replace the NaN entries with the mean value of the corresponding column”
查看原文 →注意与类别型情形的不对称:在那里,缺席变成了信息;在这里,它被抹进了平均值。同一个数据集,两种相反的哲学,相隔一段话。
“我们用阶来指轴的数量,而维数专门用来指分量的数量”
“we use order to refer to the number of axes and dimensionality exclusively to refer to the number of components”
查看原文 →一次小小的术语卫生,书坚持得对。“三维张量”是这个领域里被重载得最厉害的一个短语。
“在 Python 中,和大多数编程语言一样,向量的索引从 $0$ 开始,也叫从零开始的索引,而在线性代数中,下标从 $1$ 开始”
“in Python, as in most programming languages, vector indices start at \(0\), also known as zero-based indexing, whereas in linear algebra subscripts begin at \(1”
查看原文 →数学与代码之间这道差一的接缝贯穿整本书,而他们只标了一次就往前走。每个读者反正都会在这里绊一跤。
“虽然用张量这个词既指数学对象,又指它在代码里的实现,可能会让人困惑,但我们的意思通常可以从上下文中看出来。”
“While it may be confusing to use the word tensor for both the mathematical object and its realization in code, our meaning should usually be clear from context.”
查看原文 →令人钦佩地坦率,同时也耸了耸肩。机器学习里的“张量”与微分几何里的张量基本没有关系——它不过是个 n 维数组。借来的声望。
“如果这就是我们能做的全部,线性代数就不配有自己的一节了。”
“And if this was all we could do, linear algebra would not deserve its own section.”
查看原文 →作者们难得承认,一个主题需要挣得自己的位置。点积被框定为记账变成数学的那个点。
“我们可以把与矩阵 $\mathbf{A}\in \mathbb{R}^{m \times n}$ 的乘法看作一种变换,把向量从 $\mathbb{R}^{n}$ 投影到 $\mathbb{R}^{m}$”
“We can think of multiplication with a matrix \(\mathbf{A}\in \mathbb{R}^{m \times n}\) as a transformation that projects vectors from \(\mathbb{R}^{n}\) to \(\mathbb{R}^{m”
查看原文 →这里“投影”用得松——一般的线性映射不是投影。无关紧要,但这是细心的读者以后遇到真正的投影时会绊一下的那个词。
“并非所有函数都是可微的,包括许多我们希望优化的函数,比如准确率”
“Not all functions are differentiable, including many that we wish to optimize, such as accuracy”
查看原文 →整个领域的安静坦白:我们很少优化我们真正在乎的东西。下游的一切——用交叉熵代替准确率——都从这一句话而来。
“与 $\ell_2$ 范数相比,它对离群值不那么敏感。”
“Compared to the \(\ell_2\) norm, it is less sensitive to outliers.”
查看原文 →顺带一提地放进来,但这是 Lasso、稳健回归和一半正则化实践的种子。平方惩罚极端值;绝对值只是注意到它。
“最小化同一个人的照片的表示之间的距离,同时最大化不同人的照片的表示之间的距离”
“minimize the distance between representations of photos of the same person while maximizing the distance between representations of photos of different people”
查看原文 →抽象的范数一下子有了一张脸。这是偷渡进来作为例子的对比学习——也是这一节里对“这个向量有多大”为什么曾经重要的最清楚的陈述。
“我们相信,一旦你动了手,你会更愿意学习更多的数学”
“we believe you will be more inclined to learn more mathematics once you have gotten your hands dirty”
查看原文 →一个老实的教学赌注,而不是数学论断。它解释了本章的每一处省略——并悄悄押注好奇心是由使用产生的,而不是先于使用。
“当顶点数很多时,弧与割线的比值趋近于 1”
“the ratio between arc and secant approaches 1 for a large number of vertices”
查看原文 →阿基米德的招数一身二任:它引入了极限,也表明微积分起初是一种计算你本来就相信为真的东西的方法。
“虽然这个实验缺乏数学证明的严谨性,但我们能很快看出,确实有 $f'(1) = 2$”
“While this experiment lacks the rigor of a mathematical proof, we can quickly see that indeed \(f'(1) = 2”
查看原文 →注意,他们打印出来的那个循环在 h=1e-6 时会漂移——数值微分恰恰在数学说它该最好的地方背叛了自己。文字没有这么说,但运行它的读者会看到。
读后感AI 陪读
本章打赌:你动手之后会学到更多数学
整体来看,这一章是一个伪装成工具箱的论证。它一开头就点出了七项生存技能——而“在官方文档里找答案”与线性代数并列,正是本章真正论点的缩影:深度学习是一门以数学为底层的手艺,而不是附带了一些代码的数学。后面的一切都遵守这个顺序。张量排在最前,理由不是它优雅,而是两个工程事实(自动微分、GPU),它们合起来承载了这个领域近来的大部分历史。然后是 pandas 和缺失值,书称之为数据科学里的“臭虫”——这个比喻承认,工作中最杂乱的部分没有干净的理论,只有管理。只有在这之后,数学才到来,而且是限量配给的:线性代数到范数为止,微积分到链式法则为止,概率到切比雪夫为止。这条弧线相对于数学课程是有意倒过来的,作者也说明了原因——他们赌好奇心跟在使用之后,而不是先于使用,你一旦动了手,会学到更多的数学。这个赌注解释了每一处省略,也是阅读这一章时最重要的一盏灯。
细读之下,我看穿的是,本章最举足轻重的句子是它的旁白。reshape 是用一句顺带的关于行主序布局的话引入的——而这句话,而不是任何公式,才是此后每一个形状 bug 背后的隐形契约。原地操作的动机是别名和对同一批参数的多重引用,到这里,教程悄悄地不再是数学,而成了系统编程:张量是披着向量外衣的指针。NumPy 的互操作被说成是便利,但“转换很容易”和“它们共享内存”是不同的说法,只有第二个会在凌晨两点把你吵醒。ℓ1 范数对离群值不那么敏感,被放在半句话里一笔带过,其实正是 Lasso 和一半正则化实践的种子。而本章最坦率的一句话——我们想要优化的许多函数,比如准确率,是不可微的——是这个领域一直挂着的坦白:我们几乎从不优化我们真正在乎的东西,下游的每一个代理损失,都是从这个让步里传下来的。预备知识在散文没有标出的地方是承重的。
继续阅读
我最尖锐的判断是,这一章对自己的脚手架很老实,对自己的启发式却前后不一。它做了真正的术语卫生——用阶指轴的数量,用维数专指分量的数量;数学与代码之间从零还是从一索引的接缝;以及公开承认,机器学习里的“张量”与微分几何里的张量,除了名字,几乎没有共同点。然而在一段关于缺失数据的话里,它给出了两种相反的哲学,却没有指出其中的张力:把 NaN 当作一个类别,让缺席变得有信息;而均值插补则把缺席抹进平均值里。两者都说得通;在它们之间做选择是一个有牙齿的建模决策,却被呈现为家务。同一格调里更小的失误:把一般的线性映射叫作“投影”,以及邀请你用一个循环数值验证导数,而这个循环在 h=1e-6 时会明显漂移——有限差分的估计,恰恰在极限说它应该最精确的地方背叛了自己。相比之下,概率各节是本章火力全开的地方:HIV 的例子靠把条件独立当作承重的假设而不是藏起来,老实地赢得了它的意外,而频率派/贝叶斯派的框架、偶然不确定性/认知不确定性的区分,以及 1/√n 的速率,合在一起给了你一套词汇,来说你处于哪一种不知道之中。
我会这样告诉读者:别把这一章当作在有趣部分之前要跨过去的栏。读两遍——一次现在,一次在你的第一个模型让你吃惊之后——因为它的内容分布在括号里。把代码运行一遍,尤其是数值导数的循环和共享内存的转换;输出与文字不一致的地方,才是你真正学到东西的地方。抓住那四五句承担结构性工作的话(行主序布局、别名、不可微的目标、ℓ1 对 ℓ2、条件独立),把那些恒等式放掉——库会替你记住。并且从两个方向认真对待作者的赌注:他们说得对,你可以带着这么多数学开始,他们也在客气地告诉你,你将不得不回来。
在 FeedLitra 里读第 2 章,每段旁边都有这些卡片。
开始读书第 3 章:回归的线性神经网络
偏置项如何改变模型能表达的函数?
第 3 章是怎样展开的AI 辅助
开篇:最简单的学习问题,彻底解决。 本章从几乎不会出错的地方起步。房价给了它一个具体的回归场景——少数几个特征,一个数值标签——而两个假设承担了全部的工作:标签是特征的线性函数,而线性部分漏掉的东西是高斯噪声。从这些假设出发,平方损失不是风格上的偏好,而是一个结果:写出观测数据的似然,取它的负对数,剩下的是一个平方误差项,加上一个既不涉及权重也不涉及偏置的常数。在噪声方差固定的情况下,最小化平方损失就是最大化似然。这种把损失函数与一个概率故事早早等同起来的做法,是本章确立“它在全书余下部分要用的对象是推导出来的,而不是规定的”的方式。
第一段展开:如何真正得到参数,以及为什么简单的答案不能推广。 线性最小二乘有一个闭式解,w\ = (XᵀX)⁻¹Xᵀy,作者给出了它——然后立刻给它泄了气。这个公式只有在 XᵀX 可逆,也就是设计矩阵满秩时才存在且唯一,而且整个推导只限于这一个模型族。恰恰因为几乎没有什么有趣的模型提供这样的捷径,文本转向小批量随机梯度下降,作为通用的方法。对小批量*的辩护特别是同时在两个方面做出的:对整个数据集过一遍是浪费计算,而单个样本是浪费硬件,因为一次矩阵—向量乘积可以比许多单独的运算效率高出一个数量级,内存搬运主宰了真实的代价,而像批量归一化这样的层在批量大小为一时干脆表现不正常。向量化的演示——把两个 10,000 维的向量成批相加对比用 Python 循环相加——让速度的论证变得鲜明,不过值得注意,它是对单个运算的单个微基准,是示意性的,而不是决定性的。
重新框定:回归变成了网络。 机制定下来之后,本章做了它的第一次概念转折:把线性回归重画成一个单层全连接网络,d 个给定的输入喂给一个计算出来的输出神经元。这是整本书摆动所绕的铰链,因为此后的每种架构都是对这幅图景的精细化。作者引入生物神经元的类比来说明加权和,然后又有意地限制它——借用 Russell 和 Norvig 把飞机与鸟类相比较的说法,那里最初的灵感是真实的,但几个世纪以来鸟类学并没有指导过航空学。生物学仍然提供了把许多简单单元组合起来的高层想法;实际的推动力现在是数学、统计学和其他领域。这是一个类比而不是测量到的证据,这正是它所要的调子:这是对过度解读的告诫,而不是关于大脑的主张。
实现的一对:先手工,再用库。 合成数据那一节以框架的数据加载器收尾,随后本章把同一个模型建了两遍。从零开始的版本——模型、平方损失、一个 SGD 例程、轮次循环——只用到张量和自动微分,论据是以后任何想要自定义层或损失的人,都必须知道底下是什么。把这个理由讲完之后,文本反转了自己的强调:简洁的重写把手动的参数、损失和优化器丢掉,换成 LazyLinear、MSELoss 和 torch.optim.SGD,缩水的代码被呈现为只要框架已经满足需求就应优先选用的路线,因为库的版本经过优化和测试。手工的路径保留给发明新组件的研究者,以及输入维度需要小心处理的情形。两种实现并不冗余;每一种都做着另一种做不了的工作。
转折:优化从来都不是真正的问题。 本章在这里换了主题,方式是把此前的一切重新框定。拟合很容易;目标是找到模式而不是死记,而训练误差无法区分两者。原因是结构性的,而不是偶然的:模型是用后来给它打分的那个样本来挑选的,所以它的训练误差是总体误差的一个乐观的、有偏的估计。在留出的数据上,模型已经固定,且独立于样本,这把测量化约为普通的均值估计,得到一个老实的数字。作者把这一点推得更重——一个足够强大的模型可以拟合任意的标签,所以低训练误差什么也证明不了——同时小心地挡住相反的误读:它也并不表示泛化差,因为深度网络恰恰就是这样的模型,却仍然泛化得很好。去查看测试集这一诱人的捷径,靠引用 Ong 等人(2005)而被堵死,那里让测试数据进入模型选择,即使对复杂度被严格控制的模型,也会产生荒谬的结果。剩下的是一个专门的验证集,或者当数据太少、匀不出一份时用 K 折交叉验证。一个相关的纠正落在同一段里:目标是对没见过的输入做出准确的预测,而不是恢复真实的生成权重,因为深度模型一般没有唯一的参数解,甚至线性回归也要求特征线性无关,“那个”答案才有定义。
收尾:从钝器到连续的刻度盘。 诊断了欠拟合和过拟合之后,本章需要一个控制复杂度的手段。它先否决了粗糙的选项——丢掉特征——因为 k 个变量上 d 次单项式的数量会爆炸,所以把多项式从 2 次升到 3 次,复杂度会剧烈摆动;这个旋钮的档位太少,间隔太宽。惩罚权重的平方 L2 范数是精细的调节。机制上,把这个范数加进损失,会使每次更新都把每个权重拉向零,所以权重连续地收缩;又因为平方对大的分量惩罚得不成比例,让惩罚保持较小的最便宜办法,是把影响分散到许多特征上,而不是倚仗少数几个。对比了 L2 与 L1 并推导了更新式之后,作者在一个有意设得苛刻的合成任务上演示了它——200 维,20 个训练样本——其中 λ = 0 严重过拟合,而 λ = 3 在降低验证误差的同时抬高了训练误差。这个取舍被认定为正则化按设计在起作用,这也是本章的最后一句话:这个数据集是为夸大过拟合而造的,所以演示清楚地展示了机制,而不是证明一个典型的效应大小。本章最后把权重衰减折进框架的优化器,与中段的实现教训首尾相接——这个想法现在是一个参数,而不是你要写的一段代码。
关键论点,以及支撑它们的原文
线性回归的闭式解是一个走运的例外,而不是学习应当怎样进行的模板。
作者指出,正规方程的答案 w* = (XᵀX)⁻¹Xᵀy 只有在 XᵀX 可逆——即设计矩阵满秩——时才存在且唯一,而且整个推导只适用于线性最小二乘。恰恰因为几乎没有别的模型提供这样的公式,本章立刻转向小批量随机梯度下降,作为通用的方法。
“虽然解析解允许漂亮的数学分析,但要求有解析解的限制太严苛,会把深度学习几乎所有激动人心的方面都排除在外。”
“Although analytic solutions allow for nice mathematical analysis, the requirement of an analytic solution is so restrictive that it would exclude almost all exciting aspects of deep learning.”
§3.1 Linear Regression查看原文 →
在小的随机批量上更新,比用整个数据集或一次一个样本都更好。
紧接着这个转向,作者从两个方面论证:对整个数据集过一遍是浪费的,而单个样本浪费硬件,因为一次矩阵—向量乘积可以比许多单独的运算效率高出一个数量级,内存搬运主宰了代价,而像批量归一化这样的层,在批量大小为一时干脆表现不好。同样的向量化要点,通过把两个 10,000 维的向量相加来演示,一次批量运算比 Python 循环快得多——不过那只是对一个运算的单个微基准。
“执行一次矩阵—向量乘法,比执行同样数量的向量—向量运算,效率高出多达一个数量级。”
“It is up to an order of magnitude more efficient to perform a matrix–vector multiplication than a corresponding number of vector–vector operations.”
§3.1 Linear Regression查看原文 →
生物学启发了最初的人工神经元,但它不再是推动深度学习的力量。
作者承认,加权和单元是仿照一个真实神经元的漫画来建模的,而生物学仍然提供了把许多简单单元组装起来的高层想法。反对读出更多含义的论据是那个借自 Russell 和 Norvig 的类比:飞机受到鸟类的启发,但几个世纪以来鸟类学并没有引导过航空学;如今的进步同等地、甚至更多地来自数学、统计学和其他领域。这是一个类比,而不是来自测量的证据。
“同样,如今深度学习的灵感,同等地或更多地来自数学、语言学、心理学、统计学、计算机科学和许多其他领域。”
“Likewise, inspiration in deep learning these days comes in equal or greater measure from mathematics, linguistics, psychology, statistics, computer science, and many other fields.”
§3.1 Linear Regression查看原文 →
另外 3 个论点
先手工搭一遍,再换成框架——每一步都教了另一步教不了的东西。
作者先只用张量和自动微分实现了模型、平方损失、一个 SGD 例程和轮次训练循环,理由是以后任何想要自定义层或损失的人,都必须知道底下发生了什么。讲完这一点,本章反转了强调:简洁的重写把手动的参数、损失和优化器换成 LazyLinear、MSELoss 和 torch.optim.SGD,代码缩水,并依靠经过优化和测试的库版本——只要框架已经满足你的需求,这就是优先选用的路线,手工的路径则保留给发明新组件的研究者,以及输入维度需要小心处理的情形。
“此外,当需要定制模型、定义我们自己的层或损失函数时,了解底层是如何工作的会很有用。”
“Moreover, when it is time to customize models, defining our own layers or loss functions, understanding how things work under the hood will prove handy.”
§3.4 Linear Regression Implementation from Scratch查看原文 →
测试集永远不能用来选择模型,所以一个单独的验证集是不可或缺的。
作者的推理从这个事实出发:一个足够强大的模型可以拟合任意的标签,所以仅凭低训练误差,对泛化什么也证明不了——深度网络在实践中泛化得很好,却恰恰是这类模型。既然训练得分无法裁决,人们就去求助测试集;作者引用 Ong 等人(2005)表明,让测试数据进入模型选择,即使对复杂度被严格控制的模型,也会产生荒谬的结果。因此需要一个专门的验证集,或者在数据太少、匀不出一份时用 K 折交叉验证。
“我们能有把握地说的只有,仅凭低训练误差,还不足以证明泛化误差低。”
“All we can say with confidence is that low training error alone is not enough to certify low generalization error.”
§3.6 Generalization查看原文 →
权重衰减的工作方式,是接受更差的训练误差,以换取更好的验证误差。
作者首先否决了更粗糙的替代方案:丢掉特征太生硬,因为 k 个变量上 d 次单项式的数量会爆炸,甚至把多项式的次数从 2 升到 3,复杂度也会剧烈改变。惩罚权重的范数是更精细的刻度盘。在一个有意设得苛刻的合成任务上——200 维,只有 20 个训练样本——把 lambda 设为 0 会严重过拟合,而 lambda = 3 在抬高训练误差的同时降低了验证误差,作者认定这就是正则化按预期在起作用。这个数据集是为夸大过拟合而构造的。
“然而,简单地把特征扔掉,可能是一件太钝的工具。”
“However, simply tossing aside features can be too blunt an instrument.”
§3.7 Weight Decay查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么平方损失是自然的选择
假定标签等于一个线性预测加上高斯噪声。写出数据的似然并取其负对数,剩下一个平方误差项,加上一个不涉及权重或偏置的常数,所以在噪声方差固定的情况下,最小化平方损失恰恰就是最大化似然。
机制 2
为什么训练误差会奉承模型
拟合出的模型是用给它打分的那个样本来挑选的,所以它的训练误差是总体误差的一个乐观的、有偏的估计。在留出的数据上,模型已经固定,且独立于样本,所以测量它的误差就成了普通的均值估计,给出一个老实的数字。
机制 3
权重惩罚如何让权重收缩并分散
把平方 L2 范数加进损失,使梯度在每次更新时都把每个权重拉向零,所以权重连续地收缩。因为平方对大的分量惩罚得不成比例,让惩罚保持较低的最便宜办法,是把影响分散到许多特征上,而不是倚仗少数几个。
常见误读
如果一个模型把训练误差降到几乎为零,它就一定学到了真正的模式。
一个强大到能拟合任意标签的模型,不管有没有模式存在,都能达到低训练误差,所以这个数字对新数据不能得出任何结论;作者小心地补充说,它也并不意味着泛化差——深度网络的训练误差很低,却仍然泛化得很好。老实的估计来自留出的数据,在那里,模型在被打分之前就已经固定。
“我们能有把握地说的只有,仅凭低训练误差,还不足以证明泛化误差低。”
“All we can say with confidence is that low training error alone is not enough to certify low generalization error.”
§3.6 Generalization查看原文 →
只有恢复出产生数据的真实底层权重,训练才算成功。
实际的目标是在没见过的输入上预测准确的参数。作者指出,对于深度模型,唯一的参数解一般根本不存在,甚至线性回归也要求特征之间没有线性相关,唯一的答案才有定义——所以精确恢复是错误的衡量标准。
“然而,在机器学习中,我们往往不那么关心恢复真实的底层参数,而是关心能带来高度准确预测的参数。”
“However, in machine learning, we are often less concerned with recovering true underlying parameters, but rather with parameters that lead to highly accurate prediction”
§3.4 Linear Regression Implementation from Scratch查看原文 →
第 3 章的核心概念
- 线性回归
- 把一个数值目标预测为特征的加权和再加一个偏置。
- 适用处: 假定条件均值近似线性、噪声表现良好;不适用于类别预测。
- 平方误差损失
- 预测与标签之差的平方的一半,对样本取平均。
- 适用处: 它的二次形式惩罚大的误差,却对离群值过于敏感。
- 小批量随机梯度下降
- 每一步用一个小的随机批量的梯度来更新参数。 在一个小的随机批量上估计损失的梯度,然后让参数逆着它走一步。
- 适用处: 批量大小和学习率是超参数;随机性打破了确定性。 在这里使用它,尽管线性回归有闭式解,因为一般的网络没有。
- 超参数
- 不由训练循环更新的可调设置,在验证集上评判。
- 适用处: 由外部调节,例如通过贝叶斯优化,而不是梯度下降。
- 泛化
- 在训练中从没见过的数据上得到准确的预测。 模型发现的模式在新的、没见过的数据上是否成立,而不只是在训练集上。
- 适用处: 有别于单纯最小化训练损失,后者在深度学习中通常很容易。 只在独立同分布假设下才有意义;如果分布发生偏移,不再有进一步的假设就什么也说不了。
- 单层全连接神经网络
- 每个给定的输入都直接连到输出神经元的网络,只有一个计算单元。
- 适用处: 只有一个计算神经元,没有隐藏层,所以不能表达非线性函数。
另外 10 个概念
- 特征维数
- 输入层中输入的数量 d。
- 适用处: 只描述输入的宽度;对输出的数量或层数只字不提。
- 人工神经元
- 一个对输入信号加权、加上偏置求和、并可选地施加非线性的单元。
- 适用处: 对真实神经元的漫画式抽象,而不是忠实的神经科学模型。
- 数据加载器
- 一个可重用的包装器,负责加载、打乱和分批数据,让学习算法永远不用接触原始存储的细节。
- 适用处: 只帮助数据的管道;对模型质量或数据能否放进内存什么也没说。
- 从零实现加高层 API
- 本书的习惯:先手工实现一种方法,再用框架的捷径重做一遍。
- 适用处: 从零实现的版本能用,但不是生产级的。
- 过拟合
- 对训练数据的拟合,比对底层分布的拟合更紧。
- 适用处: 并不总是坏事:在深度学习中,最好的模型往往在训练集上的得分远好于留出集。
- 独立同分布假设
- 训练数据和测试数据是从同一个分布中独立抽取的。
- 适用处: 很强的假设,但没有它,我们就无法为把从 P 得出的预测迁移到另一个 Q 提供依据。
- 模型复杂度
- 一个模型类能拟合多宽范围的标签或函数;用参数的数量和参数可取值的范围来度量。
- 适用处: 很难在不同的模型类之间比较,例如决策树对神经网络。
- 权重衰减
- 在损失中加上对权重的平方 L2 范数的惩罚,由常数 lambda 控制。 每次更新都使权重向零收缩,因为 L2 惩罚的梯度把它们拉进来。
- 适用处: 限制的是参数的取值,而不是参数的数量;lambda 是在验证数据上拟合的超参数。 对其他优化器,L2 正则化可能不等于权重衰减,不过让权重收缩仍然有帮助。
- 交叉验证
- 把训练数据分成 K 个子集,轮流让其中一个充当验证集,然后对误差取平均。
- 适用处: 用于数据太少、留不出一份像样的验证集的时候;计算开销大。
- L1 与 L2 惩罚
- L2 把权重分散到许多特征上;L1 把大多数置零,起到特征选择的作用。
- 适用处: 两者都有效;选择取决于想要均匀分散还是稀疏。
第 3 章划线与批注AI 陪读
“这类浅层网络恰好包含了线性模型的集合,这囊括了许多经典的统计预测方法”
“this class of shallow networks happens to comprise the set of linear models, which subsumes many classical methods of statistical prediction”
查看原文 →漂亮的修辞倒置:不是线性回归是个婴儿版的神经网络,而是神经网络的框架吞下了两个世纪的统计学。教学上方便,历史上是反的。
“尽管我们永远不会看到面积恰好为零的新建房屋,我们仍然需要偏置”
“Even though we will never see any newly-built homes with precisely zero area, we still need the bias”
查看原文 →很好的直觉,打消了对截距的天真读法。偏置并不是关于零面积房屋的预测;它只是不必穿过原点的自由。
“这种二次性可能是一把双刃剑;虽然它鼓励模型避免大的误差,它也可能导致对异常数据过度敏感”
“this quadraticity can be a double-edge sword; while it encourages the model to avoid large errors it can also lead to excessive sensitivity to anomalous data”
查看原文 →在一段本来顺滑的陈述里唯一老实的裂缝。平方损失是一个有脾气的选择,而不是中立的尺子——那种脾气就是面对离群值时的怯懦。
另外 17 条批注
“要求有解析解的限制太严苛,会把深度学习几乎所有激动人心的方面都排除在外”
“the requirement of an analytic solution is so restrictive that it would exclude almost all exciting aspects of deep learning”
查看原文 →值得注意这个反转:闭式解被呈现为一种负债,而不是奖品。放弃精确答案,是进入有趣模型的入场价。
“处理器做数字的乘法和加法,比把数据从主存搬到处理器缓存要快得多”
“processors are a lot faster multiplying and adding numbers than they are at moving data from main memory to processor cache”
查看原文 →小批量通常被兜售为统计上方差的降低。这里真正的原因是内存带宽。是硬件,而不是理论,挑出了那个超参数。
“一个在 32 到 256 之间的数,最好是 $2$ 的大幂的倍数,是个不错的起点”
“a number between 32 and 256, preferably a multiple of a large power of \(2\), is a good start”
查看原文 →忽然间根本没有推导,只是一个带着定理的自信被偷渡进来的数。老实的承认在“一个不错的起点”这个短语里。
“即使我们的函数确实是线性且无噪声的,这些参数也不会是损失的精确极小值点,甚至不是确定性的”
“even if our function is truly linear and noiseless, these parameters will not be the exact minimizers of the loss, nor even deterministic”
查看原文 →悄悄拆掉了训练能恢复出真相的幻想。即使在可能的最好世界里,答案也会摇摆——而这种摇摆内建于方法,而不是数据。
“深度学习的实践者习惯把预测阶段称为推断,但这有点用词不当”
“Deep learning practitioners have taken to calling the prediction phase inference but this is a bit of a misnomer”
查看原文 →一次难得公开表达的术语上的不满。这个领域给一个借来的词改了名,而作者们显然在替统计学抱不平。
“最小化均方误差,等价于在加性高斯噪声的假设下对线性模型做极大似然估计”
“minimizing the mean squared error is equivalent to the maximum likelihood estimation of a linear model under the assumption of additive Gaussian noise”
查看原文 →回报:平方损失不是因为优雅才被选中的,它编码了对噪声的一个具体信念。这也意味着,你每次使用 MSE,不管有没有这个意思,都假定了高斯误差。
“尽管飞机可能受到鸟类的启发,几个世纪以来,鸟类学并不是航空创新的主要推动力”
“although airplanes might have been inspired by birds, ornithology has not been the primary driver of aeronautics innovation for some centuries”
查看原文 →让生物学那一节体面下台的优雅办法——神经元的图景作为来历故事挣得了它的位置,仅此而已。
“如果我们把损失从 $\sum_i (x_i - b)^2$ 改成 $\sum_i |x_i-b|$ 会怎样?”
“What if we change the loss from \(\sum_i (x_i - b)^2\) to \(\sum_i |x_i-b”
查看原文 →整个习题序列都在悄悄教一个教训:你的损失是对噪声的一个隐藏主张。均值对中位数,高斯对拉普拉斯——同样的数据,不同的信念。
“为什么这样天真的复合行不通?”
“Why would such a naive composition not work?”
查看原文 →一行就为书中其余部分的每个激活函数提供了理由。堆叠线性映射得到的只是另一个线性映射——没有非线性的深度只是演戏。
“提示:你卖的是苹果,不是油。”
“Hint: you are selling apples, not oil.”
查看原文 →习题里最好的一句。苹果是整数,且从不为负;油是连续的、可分的。高斯噪声两样都忘了。
“notebook 的可读性要求短小的代码片段,中间穿插解释,这个要求与 Python 库中常见的编程风格不相容。”
“Notebook readability demands short code fragments, interspersed with explanations, a requirement incompatible with the style of programming common for Python libraries.”
查看原文 →难得的老实:add_to_class 不是好的工程,而是对 notebook 这种载体的教学补丁。在你把这个招数引进真正的项目之前,值得记住这一点——尽管他们邀请你这么做。
“我们能从合成数据中学到什么呢?”
“what could we possibly learn from synthetic data?”
查看原文 →答案正是初学者会跳过的那个:合成数据检验的是算法,而不是世界。已知的真值,是你对付学习代码仅有的调试器。
“能以预先定义的顺序读取数据,对调试来说可能很重要”
“being able to read data in a pre-defined order may be important for debugging purposes”
查看原文 →一个承载着真正纪律的小细节:可复现性是一个按模式不同而做出的设计决策,而不是你一次扳动的全局开关。
“它要求我们把所有数据加载进内存,并执行大量随机的内存访问”
“it requires that we load all the data in memory and that we perform lots of random memory access”
查看原文 →他们先写慢的版本,然后在替换它之前,立刻准确说出它为什么慢。这是正确的顺序——在你亲身感受过 DataLoader 藏起来的东西之前,你无法体会它。
“魔数 0.01 在实践中往往很管用”
“The magic number 0.01 often works well in practice”
查看原文 →“魔数”大声说了出来,毫无歉意。初始化的尺度之后会变得极其重要;在这里它只是个耸肩。这个耸肩本身就是一张期票。
“由于我们的损失是在小批量上取平均计算的,我们不需要根据批量大小来调整学习率。”
“Since our loss is computed as an average over the minibatch, we do not need to adjust the learning rate against the batch size.”
查看原文 →容易一扫而过,但这是对此后每个放大规模的人都会咬一口的耦合——均值与求和的降维,悄悄重新缩放你的有效步长。
“我们不应该把能精确恢复出真值参数当作理所当然。”
“We should not take the ability to exactly recover the ground truth parameters for granted.”
查看原文 →他们戳破自己的演示,难能可贵。合成的设定被设计成会成功,而他们说了出来,而不是让你把运气误当作方法。
读后感AI 陪读
在你的数据上完美拟合,几乎什么也证明不了关于学习的事
整体来看,这一章有双重的脊梁:它把最简单的模型一路搭建到可运行的代码,然后立刻回过头来攻击这样搭起来所产生的自信。前一半向下走——房价、线性假设、平方损失、闭式解、小批量 SGD、向量化、极大似然的重新解释,最后把线性回归画成一个有 d 个输入和一个输出神经元的单层网络。后一半向上爬进泛化——训练误差是一个有偏的估计、留出的数据、验证集和 K 折交叉验证、欠拟合与过拟合、作为 L2 惩罚的权重衰减——只有看出后一半是前一半的账单,这条弧线才讲得通。你拟合了一个模型;本章随后追问,你究竟学到了关于世界的什么,而不是关于你那 20 行数据的什么,并用一个 200 维的合成任务来回答,那个任务被有意设计成拟合成功而泛化失败。
我看穿的,主要是这个框定。把线性模型呈现为一类“浅层网络”,说它“囊括”了经典的统计预测,是一种修辞上的倒置:教学上顺滑,历史上却是反的,它悄悄地把两个世纪的回归理论征召为深度学习的序幕,而不是它的祖先。同样的动作还出现在作者们自己对“推断”被重新命名为预测的恼火中——一个被该领域扭曲了的借来之词,在这里替统计学抱不平。生物神经元的绕道也得到同样的处理,被鸟类学那句话温和地放了下来:来历故事,仅此而已。使用这个框架时要意识到它,因为这个框架在做推导没做的论证工作。
继续阅读
我能给出的最尖锐的判断是,这一章其实是一章关于隐藏假设的章节,而其中最有价值的一条线,就是把平方损失和高斯噪声连起来的那条。MSE 不是一把中立的尺子。它的二次性——作者们在自己顺滑的陈述上割开的唯一老实的裂缝——是一种脾气,那种脾气就是面对离群值时的怯懦。一旦你接受了极大似然的等价关系,你就接受了,每一次使用 MSE 都是对你的误差如何分布的一个不言明的主张,而习题序列不遗余力地把这一点敲进来:把平方和换成绝对值之和,均值就变成了中位数,高斯变成了拉普拉斯,同样的数据,不同的信念。“你卖的是苹果,不是油”的提示,是本章最好的一句话,恰恰因为它从另一个方向打破了这个假设:苹果是整数,且从不为负,而加性高斯噪声两样都忘了。权重衰减属于同一个伪装信念的家族——惩罚平方的 L2 范数,是一个“小权重更合理”的先验,而不是中立的规律,把它与 L1 对照,使这个选择变得可见,而不是自动的。
第二件值得看穿的事,是“理论”往往其实是硬件或教学法穿着理论的衣服。小批量通常被兜售为方差的降低;这里给出的理由是,处理器做乘法比把数据从内存搬到缓存快得多——是带宽,而不是统计,挑出了那个超参数。紧接着的“一个在 32 到 256 之间的数,最好是 2 的大幂的倍数”完全没有推导,带着定理的自信到来;这句话里老实的词是“起点”。初始化为 0.01 被明确标为魔数,一个耸肩,其实是一张期票,因为初始化的尺度之后会变得极其重要。而 add_to_class 被直接承认是为 notebook 这种载体打的补丁,不是好的工程——在你把这个招数引进真正的代码之前,请记住这一点,不管他们多么热情地邀请你。同样,闭式解被引入后又被降级:精确性被呈现为一种负债,因为要求它就会把几乎所有有趣的东西排除在外。放弃精确答案,是入场的价格。
有几个更安静的细节,值得的关注比它们的体量所暗示的更多。因为损失是在小批量上取平均的,学习率不需要随批量大小而重新缩放——很容易一扫而过,而这恰恰是均值与求和之间的耦合,对此后每个放大规模的人,都会悄悄地重新缩放有效步长。为了调试,以固定顺序读取数据,而为了训练则打乱顺序,这是把可复现性作为按模式的设计决策,而不是一个全局开关。先写那个慢的内存加载器,并在替换它之前准确说出它为什么慢,是正确的顺序;在你亲身感受过 DataLoader 藏起来的东西之前,你无法体会它。还有,用 SGD 恢复出的参数并不是精确的极小值点,甚至不是确定性的,即使函数确实是线性且无噪声的——这种摇摆是方法的属性,而不是数据的。
我会这样告诉读者:从零实现和简洁的 PyTorch 重写,是同一个模型做两遍,重点不在第二遍。写出第一遍,而合成数据那一节,是使调试成为可能的东西——已知的真值,是你的学习代码将会拥有的唯一神谕,这就是对初学者“拿假数据能学到什么”这个问题的全部回答。然后认真对待作者们自己的警告:不要把精确恢复出真值参数当作理所当然;他们戳破自己的演示,是为了不让你把一次被设计好的成功误当作方法。最后,别跳过那道问为什么复合两个线性层什么也得不到的习题。这一行,老实回答的话,就是书中其余部分里每个激活函数的理由:堆叠线性映射得到的是另一个线性映射,没有非线性的深度只是演戏。本章收尾时给了你一个可用的模型,一个你现在知道是一种假设的损失,一个由缓存行塑造的优化器,一个其实是先验的惩罚,以及一个老实的交代:说明这一切都不能保证你学到了任何东西——这是比一个更整洁的章节会留下的更好的基础。
在 FeedLitra 里读第 3 章,每段旁边都有这些卡片。
开始读书第 4 章:分类的线性神经网络
为什么每个类别一个输出的冗余参数化,胜过只用 q-1 个输出?
第 4 章是怎样展开的AI 辅助
开篇:换一个问题。 本章一开头就把回归所回答的那个问题换掉了。任务不再是“多少”,而是“哪一个类别”,作者逐步说明了这种替换在结构上要付出什么代价。标签变成独热向量;输出层增长为每个类别一个仿射单元;而因为这些原始得分可以为负,也可以加起来是任何数——豪宅的例子里,购买可能性的线性估计一路冲过了 1——它们需要被压缩成能读作概率的东西。softmax 分两步完成这件事:取指数以保证为正,除以总和以保证总和为一。损失随后不是靠规定、而是靠推导到来的。假定标签是独立抽取的,数据集的似然就是各样本概率的乘积;乘积不好优化,所以取负对数,把乘积转换成求和——而这个和就是交叉熵。作者在开篇的结尾又从信息论的角度读了同一个目标,于是在写任何代码之前,同一个公式已经从两个方向到达了。
展开:从习题到可用的工具。 确立了目标之后,本章换了调子,开始搭建。Fashion-MNIST 被引入以取代 MNIST 作为基准——这是有意提高难度的升级,而不是中立地换一个数据集。一个 Classifier 基类被提取出来用于报告准确率,而 softmax 回归按刚推导出的交叉熵损失从零实现。随后是简洁的框架实现,也正是在这里,本章做出了它最尖锐的工程观察:softmax 和交叉熵不应该分作两步计算。单精度浮点数的范围大约是 1e-38 到 1e38,所以落在大约 [-90, 90] 之外的 logit 会毁掉朴素的 softmax。把每个 logit 都减去其中最大的那个,结果在数学上完全一样,同时把分子封顶在 1,并把分母限定在 1 与类别数之间。值得注意本章没有声称什么:LogSumExp 的融合排除了上溢,但移位后很小的负 logit 仍可能下溢为零,而零的对数会产生 NaN,只在反向传播时才浮现出来。这个修法是有方向的,不是彻底的。
转折:训练准确率什么也证明不了。 本章的铰链是承认到目前为止搭起来的一切度量的都是错的东西。它转向测试集——然后,用一个特有的双重动作,又拆了这个转向的台。一个全新的测试集给出总体误差的无偏估计,但只以样本量平方根分之一的速度:在 95% 置信度下达到 ±0.01 大约需要 10,000 个样本,如果你想通过 Hoeffding 得到有限样本的保证则大约需要 15,000 个,有限样本的界更保守。精度翻倍,数据要翻四倍。更糟的是,这个保证在重用时就蒸发了。“凌晨三点的灵感”这个故事让这一点变得具体:研究者在看到 f1 在留出集上的得分之后,设计了 f2,而 f2 因此是被测试数据塑造的;在二十个候选分类器之中,可能已经没有任何力量来排除偶然了。本章随后升级到统计学习理论,寻找一致收敛的界——而 VC 维在简单的类上干净地交出了它们(一个在 d 个输入上的线性模型,其 VC 维是 d+1;一条直线可以打散平面上的三个点,却不能打散四个点的每一种排布)。这次升级以老实的失败告终。深度网络有几百万个参数,能背下随机标签,并且常常随着增大而泛化得更好;在那个体制下,先验的保证会要求像是万亿个样本,而实践者用几千个就成功了。留出法和一致收敛这两种工具,都被表明是把泛化形式化了,却没有解释它。
第二个转折:分布本身在移动。 在假定训练和测试来自同一来源的前提下能说的话都说尽之后,本章攻击了这个假设。它首先确立了为什么偏移必须被限制,而不是一般地对待:在不受约束的偏移下,输入可以逐个像素地保持一模一样,而每个猫/狗的标签都被调换,这种情形与根本没有偏移无法区分,所以不可能有稳健的学习。这授权了接下来的分类法。协变量偏移有一个真正巧妙的纠正——你观察不到任何一个输入密度,但你可以把训练点标成“源”,把测试点标成“目标”,拟合一个逻辑斯谛分类器,并把它的几率读作密度比,于是 exp(h(x)) 成为每个训练样本带进重新加权的风险最小化中的重要性权重。这个纠正有一个本章明确说出的硬性前提:在目标赋予正概率而训练赋予零概率的地方,权重是无穷大,方法就坏了。覆盖是必需的,而不只是可取的。标签偏移从混淆矩阵和平均测试预测中恢复;概念偏移则需要逐步微调。驱动这一切的失败是历史上真实发生过的,而不是假想的——那个陆军的坦克探测器,学到的是有阴影的树对没有阴影的树,还有那家用校园学生捐款当作健康对照、把资金烧在极端协变量偏移上的创业公司。
收尾:准确率是错误的优化对象。 本章最后把框架拓宽到了完全超出独立同分布和静态的图景,勾勒出学习设定的分类法——批量、在线、老虎机、控制、强化学习——然后落在使本章对准确率的讨论显得不够的那个后果上。部署一个模型,意味着自动化决策,而自动化的决策会重塑它们当初被评估时所依据的分布。预测性警务把循环清楚地闭合起来:被标记的社区得到更多巡逻,更多巡逻使那里记录在案的犯罪更多,那份记录训练下一个模型,每一轮都在升级。贷款的例子是同样的机制,缩小的、喜剧版的——按鞋子发放信贷,很快每个申请人都穿牛津鞋,而实际的信用资质毫无改善。所以,这一章以从极大似然推导出一个干净的损失开篇,最后论证:把那个损失最小化得很好,并不等于造出了管用的东西,而反馈循环和公平性属于评估之内,而不是评估之后。
关键论点,以及支撑它们的原文
交叉熵不是随意的打分规则——它是从极大似然估计中自然掉出来的。
如果每个标签都是独立抽取的,整个数据集的似然就是各样本标签概率的乘积。乘积不好优化,所以作者取负对数,把乘积变成各样本损失的和——恰恰就是交叉熵。这一步依赖于独立性假设。
“我们将依靠极大似然估计,这与我们在第 3.1.3 节为均方误差损失提供概率论依据时遇到的方法完全相同。”
“We will rely on maximum likelihood estimation, the very same method that we encountered when providing a probabilistic justification for the mean squared error loss in Section 3.1.3.”
§4.1 Softmax Regression查看原文 →
测试集的误差只以样本量平方根分之一的速度逼近真实的总体误差,所以额外的精度要付出高昂的代价。
要有 95% 的把握使测得的误差落在真值的 ±0.01 之内,大约需要 10,000 个测试样本,而一个在有限样本中也成立的保证(Hoeffding)则需要大约 15,000 个——有限样本的界是两者中更保守的。因此精度翻倍,意味着数据要翻四倍。
“因此,要把测试误差估计得精确一倍,我们必须收集四倍大的测试集。”
“Thus, to estimate our test error twice as precisely, we must collect four times as large a test set.”
§4.6 Generalization in Classification查看原文 →
承认一个全新的测试集给出无偏的误差估计之后,作者立刻警告说,一旦它被重用,就不再可信了。
“凌晨三点的灵感”这个故事让这一点变得具体:研究者在看到 f1 在留出集上的得分之后,设计了 f2,所以第二个模型本身就是被测试数据塑造的。有了二十个候选分类器,人们可能已经没有任何力量来排除偶然。情况有多糟,取决于留出集的大小,以及这个集合只是用来调超参数,还是把信息直接泄漏进模型设计。
“一旦同一个测试集被用来评估多个模型,控制错误发现就可能变得困难。”
“Once the same test set is used to evaluate multiple models, controlling for false discovery can be difficult.”
§4.6 Generalization in Classification查看原文 →
另外 3 个论点
经典的复杂度度量无法解释深度网络为什么能泛化,所以由它们得出的保证在智识上有价值,在实践上却无法使用。
这套理论在简单的类上运作得很干净——一个在 d 个输入上的线性模型,其 VC 维是 d+1,一条直线可以标注平面上任意三个点,却不能标注四个点的每一种排布。相比之下,深度网络有几百万个参数,能背下随机标签,却在真实任务上泛化,而且往往越大越好;在那个体制下,先验的保证会要求像是万亿个样本,而实践者用几千个就成功了。
“然而,它们在实际问题上泛化得很好,而且令人惊讶的是,当它们更大更深、VC 维更高时,往往泛化得更好。”
“Nevertheless, they generalize well on practical problems and, surprisingly, they often generalize better, when they are larger and deeper, despite incurring higher VC dimensions.”
§4.6 Generalization in Classification查看原文 →
如果对训练分布和测试分布如何相关不做某种假设,就不可能有稳健的学习——这就是本章点名具体的、受限的几种偏移,而不是一般地对待偏移的原因。
如果偏移不受约束,输入可以逐个像素地保持一模一样,而每个猫/狗的标签都被调换,这种情形与根本没有偏移无法区分。这些失败是真实的,不是假想的:一个陆军的坦克探测器结果只学会了区分有阴影的树和没有阴影的树,还有一家用校园学生捐款当作健康对照的创业公司,遇到了极端的协变量偏移,把钱烧光了。
“如果对 $p_S$ 和 $p_T$ 如何相互关联不做任何假设,就不可能学出一个稳健的分类器。”
“Absent any assumptions on how \(p_S\) and \(p_T\) relate to each other, learning a robust classifier is impossible.”
§4.7 Environment and Distribution Shift查看原文 →
把模型投入生产,意味着自动化决策,所以单看准确率是评估了错误的东西——部署会重塑它当初被度量时所依据的那个分布。
预测性警务把一个循环闭合起来:被标记为高犯罪率的社区得到更多巡逻,更多巡逻在那里发现更多犯罪,那份数据训练下一个模型,每一轮都在升级。作者的贷款例子以缩小的形式照这个方式运行——按鞋子发放信贷,很快每个申请人都穿牛津鞋,而实际的信用资质毫无改善。
“在这一范围变化带来的其他后果中,我们会发现准确率很少是合适的度量。”
“Among other consequences of this change of scope, we will find that accuracy is seldom the right measure.”
§4.7 Environment and Distribution Shift查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
Softmax 把得分变成概率
仿射层的输出可以为负,也可以加起来是任何数;作者的豪宅例子表明,购买可能性的线性估计一路冲过了 1。对每个得分取指数使它为正,再除以总和强制输出总和为一,它们终于可以被读作类别概率了。
机制 2
减去最大的 logit 可防止上溢
朴素地计算 softmax 要对原始的 logit 取指数,而单精度浮点数的范围只有大约 1e-38 到 1e38,所以落在大约 [-90,90] 之外的 logit 会爆炸。把每个 logit 都减去其中最大的那个,结果不变,却把分子封顶在 1,并让分母保持在 1 与类别数之间,所以指数都保持在范围之内。
机制 3
由源域对目标域的分类器提供权重
在协变量偏移下,你看不到两个输入密度,但你可以把训练点标成“源”,把测试点标成“目标”,并拟合一个逻辑斯谛分类器。它的几率等于两个密度之比,于是 exp(h(x)) 成为每个训练样本带进重新加权的风险最小化中的重要性权重。
常见误读
一旦 softmax 被折进交叉熵损失,数值问题就解决了,对任何输入计算都是安全的。
这个技巧确实排除了上溢,因为减去最大的 logit 把分子封顶在 1,并为分母设了界。剩下的是另一个方向:移位后很小的负 logit 可能一路下溢到零,而取零的对数会产生 NaN 值,在反向传播时浮现出来。
“但我们不是把 softmax 概率传给新的损失函数,而是只传 logit,并在交叉熵损失函数内部一次性计算 softmax 及其对数,它会做一些聪明的事,比如“LogSumExp 技巧”。”
“But instead of passing softmax probabilities into our new loss function, we just pass the logits and compute the softmax and its log all at once inside the cross-entropy loss function, which does smart things like the “LogSumExp trick”.”
§4.5 Concise Implementation of Softmax Regression查看原文 →
只要你有一些来自目标域的无标签数据,重要性加权就能修复任何协变量偏移。
重新加权只有在训练分布真正覆盖了目标的支撑集的地方才管用。在目标赋予正概率而训练分布赋予零的点上,权重是无穷大,纠正就失效了——所以覆盖是前提条件,而不是细节。
“要让这个方案管用,我们需要目标(例如测试时)分布中的每个数据样本,在训练时都有非零的出现概率。”
“For this scheme to work, we need that each data example in the target (e.g., test time) distribution had nonzero probability of occurring at training time.”
§4.7 Environment and Distribution Shift查看原文 →
第 4 章的核心概念
- 分类
- 预测一个样本属于哪个类别,而不是多少。 预测一个样本属于几个离散类别中的哪一个,通常是挑出预测概率最高的那个。
- 适用处: 实践者用同一个词指硬性的分配和概率估计。 硬性的预测丢掉了某些应用所需要的概率信息。
- 独热编码
- 一个每个类别一个分量的向量,真实类别处为 1,其余为 0。
- 适用处: 之所以用它,是因为分类的类别通常没有自然的顺序;有序的类别可能更适合序数回归。
- Softmax
- 对每个输出取指数,再除以总和,把 logit 变成有效的概率向量。
- 适用处: 保序,所以 argmax 不需要 softmax;大的值有上溢的风险。
- 交叉熵损失
- 模型赋予真实标签的概率的负对数,对类别求和。 像交叉熵这样可训练的损失,代替了我们真正在乎的那个不可微的指标。
- 适用处: 对概率向量,下界为 0;用有限的权重永远达不到零。 朴素的对数实现在接近零概率时数值上不安全。
- 熵
- 在真实分布下的期望惊异度;数据能被压缩到多小的下限。
- 适用处: 用以 e 为底而不是比特来度量时,单位是奈特。
- 惊异度
- 你对一个事件有多惊讶,度量为你赋予它的概率的对数的负值。
- 适用处: 主观的:取决于观察者所赋予的概率。
另外 20 个概念
- Fashion-MNIST 数据集
- 一个 28x28 像素、10 个类别的服装图像数据集,用作 ImageNet 的小型替身。
- 适用处: 仍然很小且是灰度的,所以无法揭示只在大型多通道数据上才会出现的问题。
- 分类准确率
- 预测与真实标签相符的比例。
- 适用处: 不可微,所以只能度量,而不能直接优化。
- softmax 中的数值上溢与下溢
- 对很大的正 logit 或很大的负 logit 取指数,会超出或塌缩到浮点数所能表示的范围之外。
- 适用处: 靠减去最大的 logit 来缓解,但 log 0 仍可能在下游出现。
- LogSumExp 技巧
- 直接由 logit 计算 log-softmax,写成 o_j - max - log sum exp(o_k - max),从不形成原始概率。
- 适用处: 当你确实想要输出概率时,仍要保留普通的 softmax。
- 总体误差与经验误差
- 数据分布上的真实期望误差,对比有限数据集上观察到的误差比例。
- 适用处: 只有当分类器的选择没有碰过那个数据集时,这个估计量才是无偏的。
- 适应性过拟合
- 一旦测试结果影响了你接下来构建哪个模型,测试集就不再是干净的测试集。
- 适用处: 最坏情形的理论很暗淡,但实践表明这些分析可能过于保守。
- 一致收敛
- 一个保证:函数类中的每个分类器,其经验误差同时接近真实误差。 一个类中的每个模型,其训练误差同时接近其真实误差,所以挑选训练得最好的模型是安全的。
- 适用处: 之所以需要它,是因为学出来的分类器是用给它们打分的同一份数据挑选出来的。 必须依赖于模型类的某种性质;对死记硬背的模型不可能成立。
- VC 维
- 一个模型类能以所有可能的方式给其标注的点的最大数目。
- 适用处: 在统计理论中有用,但用到深度网络上则无能为力。
- 偏差—方差权衡
- 灵活的类能拟合训练数据,却可能过拟合;僵硬的类能泛化,却可能欠拟合。
- 适用处: 历史上被框定为学习的中心问题。
- 协变量偏移
- 输入分布变了,而标注规则 P(y|x) 保持不变。
- 适用处: 当 x 导致 y 时很自然;纠正需要目标分布的特征,而不是标签。
- 标签偏移
- 标签的边缘分布 P(y) 变了,而 P(x|y) 保持不变。
- 适用处: 当 y 导致 x 时合理,例如疾病导致症状。
- 概念偏移
- 标签本身的含义随时间或地点漂移。
- 适用处: 在时间或地理上往往是渐变的,这使它很难被注意到。
- 经验风险
- 训练数据上的平均损失,用作真实期望损失的替身。
- 适用处: 只是一个近似,因为整个总体是拿不到的。
- 重要性加权
- 按 p(x)/q(x) 给每个训练样本加权,使来源不对的数据模仿目标分布。
- 适用处: 这个比值未知,必须估计,例如用逻辑回归。
- 协变量偏移的纠正
- 用一个分类器区分源数据和目标数据,然后在最小化经验风险时,按 exp(h(x)) 给每个训练点加权。
- 适用处: 要求每个目标点在训练时都有非零的概率;否则权重会爆炸。
- 标签偏移的纠正
- 标签的频率变了,但以类别为条件的输入没变,所以权重是标签的似然比 p(y)/q(y)。
- 适用处: 需要一个准确的分类器、一个可逆的混淆矩阵,以及没有未见过的类别。
- 混淆矩阵
- 一张 k×k 的表,其单元格 c_ij 是验证预测中真实为 j 而模型说是 i 的比例。
- 适用处: 在来自训练分布的验证数据上估计,而不是在无标签的目标数据上。
- 概念偏移的纠正
- 任务本身缓慢漂移,所以你在新数据上微调现有的权重,而不是从头重新训练。
- 适用处: 任务的突然重新定义,可能需要收集新的标签并重新开始。
- 在线学习
- 数据一次到来一个样本;你先预测,然后看到标签并招致一个损失,每一轮都更新模型。
- 适用处: 不同于批量学习,那里训练好的模型被部署出去,且从不更新。
- 失控的反馈循环
- 模型自己的决策重塑了它之后所训练的数据,放大了它最初的偏见。
- 适用处: 只有当部署出去的预测影响未来的数据收集时才会出现。
第 4 章划线与批注AI 陪读
“当我们想回答“多少?”或“多少个?”这类问题时,回归就是我们伸手去拿的锤子。”
“Regression is the hammer we reach for when we want to answer how much? or how many? questions.”
查看原文 →漂亮的框定,但锤子的比喻与作者唱反调:下一段整个都在讲这把锤子多么经常是错的工具。
“你接下来打算读本书的哪一节?”
“Which section of the book are you going to read next?”
查看原文 →他们把读者滑进了例子清单里——你在句子进行到一半时就成了一个分类目标。俏皮,也让抽象变得有黏性。
“即使我们只关心硬性的分配,我们仍然使用做软性分配的模型”
“even when we only care about hard assignments, we still use models that make soft assignments”
查看原文 →这句顺带的话才是 softmax 存在的真正理由。软输出不是给我们的,是给梯度的——硬决策没有东西可以下降。
另外 17 条批注
“但出于对称性的考虑,我们使用一种略微冗余的参数化”
“but for reasons of symmetry we use a slightly redundant parametrization”
查看原文 →值得停一下:他们承认模型是过参数化的,然后耸耸肩。这种冗余意味着权重不是唯一的——一整类解给出完全相同的预测。
“买豪宅的时候,概率可能会超过 $1$!”
“the probability might exceed \(1\) when it comes to buying a mansion!”
查看原文 →这个玩笑起了真正的作用——它表明这个失败不是抽象的,而是线性在你外推的那一刻会做的事。
“沿着吉布斯的想法,能量等同于误差。”
“Following Gibbs’ idea, energy equates to error.”
查看原文 →六个字承担了巨大的概念重量。整个物理学的绕道,就是为了授权这一个类比——而这确实是“温度”至今仍活在采样代码里的原因。
“对于权重的任何有限设置,这都不可能发生”
“This can never happen for any finite setting of the weights”
查看原文 →所以损失有一个永远无法达到的下确界。训练永远在追逐一个达不到的零——这也悄悄地解释了,没有正则化时权重为什么会越漂越大。
“导数是我们模型所赋予的概率之差”
“the derivative is the difference between the probability assigned by our model”
查看原文 →整节的回报。所有那些取指数再归一化的机制,坍缩成预测减去真值——与平方误差同形,而他们说得对,这不是巧合。
“容易预测,就容易压缩。”
“Easy to predict, easy to compress.”
查看原文 →五个字让整个预测—压缩的等价事后看来显得理所当然。这是整个现代语言建模所倚靠的那句话。
“这使算法的发展偏向了特定的算法家族”
“This skewed algorithmic development towards specific families of algorithms”
查看原文 →埋在数据集描述里的一个尖锐的历史论断:基准塑造了研究,而不只是度量了研究。基准从来不是中立的。
“人类很擅长发现异常,因此可视化起到了额外的保障作用”
“Humans are very good at spotting oddities and because of that, visualization serves as an additional safeguard”
查看原文 →流水线中唯一真正属于人的一步,被框定为一件调试工具。你的眼睛就是单元测试。
“虽然直接优化准确率可能很困难(它不可微),但它往往是我们最在乎的性能度量。”
“Although it can be difficult to optimize accuracy directly (it is not differentiable), it is often the performance measure that we care about the most.”
查看原文 →安静的承认:整套机制优化的是一个代理。交叉熵是我们容忍的一个替身,因为它有梯度。
“分母(的对数)称为(对数)配分函数。它是在统计物理学中引入的”
“The (logarithm of the) denominator is called the (log) partition function. It was introduced in statistical physics”
查看原文 →很好的提醒,softmax 就是乔装的玻尔兹曼——归一化不是花招,而是借来的热力学。
“你不应该为任何严肃的目的原样使用这段代码”
“you should not use this code verbatim for any serious purpose”
查看原文 →宣布自己不适用的教学代码。老实,而且出奇地罕见——大多数教程让你靠 NaN 自己发现。
“我们已经达到了可以说是 1960–1970 年代统计建模的最先进水平”
“we have reached what would arguably be the state of the art of 1960–1970s of statistical modeling”
查看原文 →以最好的方式泄气。五十页的机制,只为抵达统计学家本来就在的地方——重点是脚手架,而不是模型。
“把锋利的棱角藏起来也有代价:不鼓励你自己添加新的、不同的组件”
“hiding the sharp edges also comes with a price: a disincentive to add new and different components on your own”
查看原文 →这一节里最尖锐的一段。抽象保护你不受 bug 之害,也让你不知道 bug 的存在。
“总是返回最可能的标签是个好主意吗?例如,你会为医学诊断这样做吗?”
“Is it always a good idea to return the most likely label? For example, would you do this for medical diagnosis?”
查看原文 →一道习题偷偷带进了真正的问题:argmax 假定所有错误的代价相同,而在基准之外,这几乎从不成立。
“我们只需在第一个训练轮次把数据集背下来,就能在训练集上达到完美的准确率”
“we can attain perfect accuracy on the training set by just memorizing the dataset on the first training epoch”
查看原文 →我见过的对训练准确率最干净的驳斥——不是警告,而是一个构造性的证明,说明这个数字一文不值。
“这些保证表明,要事先确保深度神经网络的泛化,需要荒谬数量的样本(也许是万亿个或更多)”
“these guarantees suggest that ensuring generalization of deep neural networks a priori requires an absurd number of examples (perhaps trillions or more)”
查看原文 →教科书罕见地事先承认,它即将教授的理论对你在乎的东西不管用。老实,但这让接下来的十页感觉像一场博物馆之旅。
“让我们有 95% 的把握相信 $\epsilon_\mathcal{D}(f) \in \epsilon(f) \pm 0.01$,那么我们将需要 10,000 个样本!”
“thus be 95% confident that \(\epsilon_\mathcal{D}(f) \in \epsilon(f) \pm 0.01\), then we will need 10,000 samples!”
查看原文 →然后是安静的点睛之笔:这恰恰就是基准测试集有 10,000 个样本的原因。这个数字不是大自然选的,是这个计算选出来的。
读后感AI 陪读
温度仍然出现在采样代码里,是因为配分函数
从头读到尾,这一章有一个标题没有宣传的形状。它一开头是一段整洁的推导——把“多少”换成“哪一个”,把标签编码成独热向量,给每个类别一个自己的仿射得分,用 softmax 把得分压进单纯形,再把交叉熵恢复为不过是写出来的极大似然。这一部分精炼得漂亮,它最好的时刻是旁白:我们即使只想要硬答案也使用软输出(硬决策没有梯度可供下降),参数化是明知故犯地冗余的,所以解是一整个等价类而不是一个点,损失有一个永远无法达到的下确界——这悄悄地解释了为什么未正则化的权重会永远向外游荡。物理学的绕道,一句话就回本了,“能量等同于误差”,而这一个类比,正是“温度”这个词在六十年后的采样代码中仍然出现的原因;归一化的分母不是便利,而是从热力学借来的配分函数。这一切都落在一个导数上,它不过是预测减去真值,与平方误差同形,而作者们说得对,这并不是巧合。
然后,调子两次转换,而这两次转换才是真正的内容。第一次转入工具:Fashion-MNIST、一个 Classifier 基类、先从零后简洁的实现。埋在数据集描述里的,是本章最尖锐的历史论断——一个容易的基准,扭曲了哪些算法家族得到了发展。基准并不度量一个领域,它们在引导它。实现各节对它们自己的局限出奇地老实:宣布自己不该被原样使用的代码,承认准确率——我们真正在乎的东西——不可微,因此交叉熵作为被容忍的代理上场,以及指出框架里融合的 softmax 加 log-sum-exp 藏着一个数值悬崖,否则你会以 NaN 的形式撞上它。关于抽象的代价的那一段是这一节里最好的:把锋利的棱角藏起来,既保护你不受 bug 之害,也让你不知道 bug 的存在。而结尾的泄气——五十页之后抵达的是 1960 年代的统计学——是对的,值得多坐一会儿。回报从来不是模型;而是你现在可以往上面挂任何东西的脚手架。
继续阅读
第二次转换,转入泛化,是本章不再是教程、而开始成为论证的地方。训练准确率不是靠警告、而是靠构造性的证明被驳回的:在第一个轮次就把数据集背下来。测试误差以 O(1/√n) 估计总体误差,本章把算术算了出来——在 95% 置信度下达到 ±0.01 需要 10,000 个样本——这恰恰是基准测试集有这么大的原因。这个数字是靠这个计算选出来的,不是大自然选的。然后是测试集的重用、适应性过拟合、错误发现;然后是一致收敛和 VC 维,与一个坦率的承认一起引入,承认这些界对我们实际训练的网络会要求万亿个样本。教一套理论,同时承认它不涵盖你感兴趣的对象,既罕见又令人钦佩,尽管这确实让这次绕道感觉像一场博物馆之旅。关于分布偏移的收尾材料是本章最有实际用处的——协变量偏移靠一个源域对目标域的逻辑斯谛分类器和 exp(h(x)) 的重新加权来纠正,标签偏移靠混淆矩阵和平均测试预测来恢复,概念偏移靠逐步微调来处理——然后是分类法,以及公平性和反馈循环的讨论,一道关于医学诊断的习题终于在这里兑现了:argmax 假定每个错误的代价相同,这在基准测试上是对的,几乎在别处都不对。
我会这样告诉读者:本章的标题低估了它。线性分类是半小时就能讲完的想法;其余的十分之九,是一堂持续的课,教你如何不信任自己的数字。训练准确率一文不值,测试准确率随重用而衰减,理论无法为我们部署的模型作证,我们最小化的损失不是我们想要的量,而我们将遇到的数据不会来自我们训练时的分布。作者们从未把这些化解为安慰,这是老实的做法。为了流畅去读推导,但为了判断力去读泛化和偏移的各节——它们是你忘了怎么对 softmax 求导之后仍然有用的部分。
在 FeedLitra 里读第 4 章,每段旁边都有这些卡片。
开始读书第 5 章:多层感知机
为什么更深的网络比更宽的网络更紧凑?
第 5 章是怎样展开的AI 辅助
开篇:拆解线性模型。 本章不是从多层感知机开始,而是从一个反对此前所述的论证开始。作者指出,线性模型默默地承诺了单调性——每个特征总是朝一个方向推动输出。有两个例子从相反的方向打破了这一点。健康状况在体温低于 37 °C 时随体温上升,高于它时则下降,所以没有哪个单一符号的系数能描述这种关系。还有,一张猫或狗的照片,在亮度被反转后标签不变,这毁掉了任何逐个读取像素的规则。第二个例子指向了超越单调性的更深的问题:一个特征的含义取决于周围的特征,而线性模型无法表示交互。所以本章给自己设定了一个搜索问题,然后立刻排除了显而易见的答案。堆叠仿射层没有用,因为代数会把“权重加偏置”之后再接“权重加偏置”折成单个权重矩阵和单个偏置;多出来的那一层什么也没买到。打破这种坍缩的,是在层与层之间插入一个按元素的非线性,在候选中 ReLU 成为默认选择——不是通过训练比赛,而是通过比较导数。ReLU 的导数要么原样通过输入,要么是零,而 sigmoid 的导数在原点处峰值只有 0.25,并向两侧衰减,所以信号在深的堆叠中会褪去。Sigmoid 保留给概率输出和循环模型中的门控。这一节以通用近似的结果结束,并附上了本章其余部分所依赖的一个但书:能够表示一个函数,并不意味着梯度下降能找到它,而且更深的网络往往比一个巨大的单层要紧凑得多。
展开:实现,然后是底下的机制。 架构定下之后,本章把它建了两遍——一遍从零开始,一遍用 Sequential 简洁实现——并顺带观察到训练循环足够模块化,可以原样沿用。然后它深入代码之下,推导前向传播和反向传播,以及关键的是,它们的相互依赖。反向传播重用前向过程产生的中间值,这意味着这些值必须保持存活,直到梯度计算完毕。它们的总大小随深度和批量大小同时增长,这就是本章对为什么训练比预测消耗多得多的内存、为什么用大批量的深度网络会把内存耗尽的解释。这个推导随后把本章的下一个话题交了出来:数值稳定性。梯度在穿过许多层时会消失或爆炸,还有第二种更奇怪的失败——排列对称性。
转折:从诊断到初始化。 这里是本章从描述模型转向修复模型的支点。对称性问题是两者中更尖锐的,因为优化碰不到它。如果每个隐藏单元都从相同的权重开始,每个都计算出同样的值,所以每个梯度元素都相同,于是每个单元得到同样的更新——永远如此。一个宽的隐藏层表现得就像一个单元,再多的梯度下降也分不开它们。补救必须来自训练开始之前,这使初始化成为本章对两种失败同时的回答。作者把输出的方差算成 n<sub>in</sub>·σ²·γ²,这要求 n<sub>in</sub>·σ² = 1;把同样的计算反向做一遍,要求 n<sub>out</sub>·σ² = 1。两者不能同时成立,所以 Xavier 初始化取折中,定在 2/(n<sub>in</sub> + n<sub>out</sub>)。这个推导的假设被直白地说出——零均值、相互独立的输入,忽略非线性——同时指出它依然管用,而初始化仍然是一个开放的研究领域。
第二种补救:暂退法作为结构化的噪声。 暂退法随后登场,是一种不同的干预,在训练期间而不是训练之前注入。每个激活以概率 p 被置零,幸存者除以 1 − p,于是该层的期望输出不变,而它确切的模式在批次之间不断变化。这个机制最好通过被丢弃的单元不做什么来读:它向前不贡献值,向后不贡献梯度,所以输出层没有一个稳定的单一单元可以倚靠,依赖被分散到整个层上。因为这种噪声是一种训练手段,而不是模型的一部分,所以在测试时被关掉。
收尾:Kaggle 房价流水线。 本章以应用模式收尾,把一切汇集起来做成一次提交。预处理遵循标准做法——把数值特征标准化,用该列的均值填补空白,对类别型做独热编码——这些被作为适合这个数据集的合理默认值提出,而不是通用的样板;特别是均值插补,假定值是随机缺失的,不然就会让数据产生偏差。损失函数得到最仔细的论证。对一栋价值 \$125,000 的俄亥俄州农村住宅来说,差 \$100,000 是毁灭性的,而在中位数超过 \$400 万的地方则近乎准确,所以没有哪个绝对误差的目标能同时适用两者;取对数之间的均方根差,使被最小化的量变成比例误差,这对于跨越很宽尺度的正值是正确的做法。模型和超参数的选择随后通过 K 折交叉验证来进行——把训练数据分成 K 折,依次在每一折上验证,取平均——明确地代替通过测试集反馈来选择,低训练误差与高 K 折误差之间的大差距被读作过拟合,正则化也许可以解决。本章以习题而不是结果收尾,指导读者按这种方式调参来提高分数,测试去掉每个预处理默认值时会坏掉什么,并警告说,如果拿不合理数量的配置去试,交叉验证本身也会退化。
关键论点,以及支撑它们的原文
每当一个特征的含义取决于周围的其他特征时,线性模型就不够用。
作者展示了单调性在两个方向上都失败:健康状况在体温低于 37°C 时随体温上升,高于它时则下降,而一张猫/狗的图像在被反转后标签不变,这毁掉了任何逐个像素读取亮度的规则。这些情形开启了本章,并为寻找非线性模型做了铺垫。
“也就是说,因为任何一个像素的意义,以复杂的方式取决于它的上下文(周围像素的值)。”
“That is, because the significance of any pixel depends in complex ways on its context (the values of the surrounding pixels).”
§5.1 Multilayer Perceptrons查看原文 →
在各种激活函数中,ReLU 是默认选择,因为它的导数对优化而言异常良好。
论证了某种非线性是必需的之后,作者比较了导数:ReLU 的要么是零,要么原样通过输入,而 sigmoid 的导数在原点处峰值只有 0.25,并向两侧衰减到零,所以信号在深的堆叠中会褪去。作者指出,这是曲线的性质,而不是完整的训练比较,并把 sigmoid 保留给概率输出和循环模型中的门控。
“使用 ReLU 的理由是它的导数特别良好:要么消失,要么就让参数通过。”
“The reason for using ReLU is that its derivatives are particularly well behaved: either they vanish or they just let the argument through.”
§5.1 Multilayer Perceptrons查看原文 →
训练消耗的内存比预测多得多,因为反向过程依赖于前向过程存储下来的东西。
反向传播重用前向过程产生的中间值,所以这些值必须保持存活,直到梯度计算完毕;它们的总大小随深度和批量大小同时增长,这就是用大批量的深度网络会把内存耗尽的原因。这直接来自本章对两个过程的推导。
“注意,反向传播会重用前向传播中存储的中间值,以避免重复计算。”
“Note that backpropagation reuses the stored intermediate values from forward propagation to avoid duplicate calculations.”
§5.3 Forward Propagation, Backward Propagation, and Computational Graphs查看原文 →
另外 3 个论点
没有哪一个单一的权重方差能同时让前向激活和反向梯度保持稳定,所以 Xavier 初始化取折中。
把梯度消失与爆炸的诊断变成补救,作者把输出的方差算成 n_in·σ²·γ²,这要求 n_in·σ² = 1,而同样的计算反向做一遍,要求 n_out·σ² = 1。两者不能同时成立,所以方差被设为 2/(n_in+n_out)——这是在零均值、相互独立的输入、且忽略非线性的条件下推导出来的折中,但在实践中很有效。
“这让我们陷入两难:我们不可能同时满足这两个条件。”
“This leaves us in a dilemma: we cannot possibly satisfy both conditions simultaneously.”
§5.4 Numerical Stability and Initialization查看原文 →
对房价来说,要紧的是相对误差,这就是为什么竞赛在对数尺度上给预测打分。
对一栋价值 $125,000 的俄亥俄州农村住宅来说,差 $100,000 是毁灭性的,而在中位数超过 $400 万的地方则近乎准确,所以单一的绝对误差目标无法同时适用两者;度量对数之间的均方根差,使被最小化的是比例误差。这适用于跨越很宽尺度的正值量,比如价格。
“对于房价,和股价一样,我们关心相对量多于绝对量。”
“With house prices, as with stock prices, we care about relative quantities more than absolute quantities.”
§5.7 Predicting House Prices on Kaggle查看原文 →
模型和超参数应该通过 K 折交叉验证来选择,而不是通过来自测试集的反馈。
动手演练把训练数据分成 K 折,依次在每一折上验证并取平均,习题随后指导读者按这种方式调超参数来提高分数;低训练误差与高得多的 K 折误差之间的大差距,被读作正则化也许可以修复的过拟合。作者把这些作为任务给出,没有报告结果,并警告说,如果试了不合理数量的配置,这个方法就会失效。
“为了选择模型并调整超参数,我们可以使用 $K$ 折交叉验证。”
“To select the model and adjust the hyperparameters, we can use \(K\)-fold cross-validation”
§5.7 Predicting House Prices on Kaggle查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么堆叠的仿射层会坍缩
如果一个隐藏层只施加权重和偏置,然后再送入另一个这样的层,代数就会把这两步折成一个权重矩阵和一个偏置,所以多出来的那一层没有买到任何新的表达能力。这就是本章要在层与层之间插入一个按元素的非线性的原因:它阻断了坍缩,让堆叠能够表示非单调的、相互作用的行为。
机制 2
相同的权重如何冻住一层
如果每个隐藏单元都从相同的权重开始,每个单元计算出同样的值,所以梯度的每个元素也相同。梯度下降于是到处施加同样的更新,这些单元永远保持相同,使一个宽的隐藏层表现得就像一个单元。
机制 3
暂退法如何分散依赖
训练时每个激活以概率 p 被置零,幸存者除以 1-p,所以该层的期望输出不变,而它确切的模式不断变化。被丢弃的单元向前不贡献值,向后不贡献梯度,所以输出层无法倚靠任何一个隐藏单元。
常见误读
既然一个有足够多单元的隐藏层几乎能表示任何函数,深度只是锦上添花,一个足够大的网络就能学会你需要的任何东西。
可表示性和可学习性是两个独立的问题:作者强调,能够表达一个函数,并不意味着梯度下降能找到它,而且更深的网络往往比单个巨大的层紧凑得多。这恰恰是本章用余下的篇幅讲激活的选择、梯度稳定性和初始化、而不是讲宽度的原因。
“不过,真正学出那个函数才是难点。”
“Actually learning that function is the hard part, though.”
§5.1 Multilayer Perceptrons查看原文 →
本章的预处理配方是安全的样板,所以标准化、用该列均值填补空白、独热编码,可以不加思考地用于任何表格数据。
这些被作为适合这个数据集的合理默认值给出,而不是保证——特别是均值插补,假定值是随机缺失的,不然就会使数据产生偏差。作者有意以一道习题收束这一节,问去掉每个默认值时会坏掉什么。
“把实值数据重新缩放到零均值和单位方差是一个好的默认做法。”
“Rescaling real-valued data to zero mean and unit variance is a good default.”
§5.7 Predicting House Prices on Kaggle查看原文 →
第 5 章的核心概念
- 多层感知机
- 堆叠的全连接层,其中前 L-1 层学习一个表示,最后一层充当线性预测器。
- 适用处: 层与层之间需要一个非线性,否则它等价于单个线性层。
- 单调性假设
- 线性迫使每个特征总是把输出推向同一个方向。
- 适用处: 在像体温 37°C 附近的风险这类情形下失效。
- 激活函数
- 一个按元素的可微变换,通常是非线性的,施加在层的仿射部分之后。
- 适用处: Sigmoid 和 tanh 会饱和,所以它们的梯度在远离零的地方消失。
- 通用近似器
- 即使只有一个隐藏层,只要单元足够多,也能表示几乎任何函数。
- 适用处: 可表示不等于可学习,而且更深的网络往往紧凑得多。
- 前向传播
- 从输入层到输出层计算并存储每一个中间值。
- 适用处: 只描述值的计算,不涉及梯度。
- 反向传播
- 用链式法则沿网络反向走一遍,得到参数的梯度。
- 适用处: 需要存储的前向值;它计算的是梯度,而不是更新。
另外 11 个概念
- 梯度消失与梯度爆炸
- 各层雅可比矩阵的长乘积可能缩小到零,也可能爆炸,破坏优化。
- 适用处: 由深度加上激活和初始化的选择引起。
- 排列对称性
- 一层中的隐藏单元是可互换的,所以相同的初始化会让它们一直相同。
- 适用处: 一种参数化的性质;用常数初始化使它成为实际的失败。
- Xavier 初始化
- 用方差 2/(n_in+n_out) 对权重采样,使输出和梯度的尺度在各层之间大致保持不变。
- 适用处: 推导时假定没有非线性、输入独立且零均值,但在实践中表现良好。
- 小批量随机梯度下降
- 在小批量上迭代地更新参数;它自己无法打破权重相同造成的对称。
- 适用处: 暂退法正则化可以打破单靠 SGD 打破不了的对称。
- 暂退法
- 训练时随机把每一层的一些激活置零,并对其余的重新缩放,使该层的期望输出不变。
- 适用处: 只在训练时使用;测试时通常关掉,不确定性估计是个例外。
- 共适应
- 一层倚赖前一层的某个特定激活模式,作者把它当作过拟合的标志。
- 适用处: 来自原始论文的直觉,而不是已被证明的机制。
- 平滑性
- 一个函数不应该对输入的微小变化反应强烈;用输入噪声训练是强制这一点的方法之一。
- 适用处: Bishop 的等价性是针对线性模型上的输入噪声证明的。
- 对数 RMSE 误差度量
- 用对数价格的均方根差来给房价预测打分,这样要紧的是相对误差而不是绝对误差。
- 适用处: 适合量值跨越很宽尺度的情形,比如价格。
- 交叉验证
- 把训练数据分成 K 折,依次在每一折上验证,并对验证误差取平均来挑选超参数。 把训练数据分成 K 份来挑选模型和超参数,而不碰测试数据。
- 适用处: 如果试了不合理数量的超参数选项,它就会失效。 要花 K 次训练的代价,而且仍然只是估计泛化。
- 缺失值(插补与删除)
- 填补缺失的条目,默认用该特征的均值。
- 适用处: 均值替换假定值是随机缺失的;否则会使数据产生偏差。
- 通过对数预测得到的相对误差
- 在对数上度量差异,这样计入的是比例而不是绝对的差距。
- 适用处: 只适用于比值要紧的正目标,比如价格。
第 5 章划线与批注AI 陪读
“线性蕴含了较弱的单调性假设”
“linearity implies the weaker assumption of monotonicity”
查看原文 →漂亮的次序:他们通过线性最廉价的后果来攻击它。如果连单调性都失败了,不必碰更难的部分,线性就死了。
“在一个反转图像并不改变类别的世界里,这种做法注定失败。”
“This approach is doomed to fail in a world where inverting an image preserves the category.”
查看原文 →一行致命一击。不是“难以拟合”,而是逻辑上不相容——反转像素,标签不变,所以没有哪个固定符号的权重能存活。
“我们就是不知道如何手工计算它”
“we simply do not know how to calculate it by hand”
查看原文 →这才是整章真正的支点:不是线性模型弱,而是人类的特征工程已经用尽。深度学习被推销为对无知的承认。
另外 17 条批注
“我们白忙一场,什么也没得到!”
“we gain nothing for our troubles!”
查看原文 →先搭一个坏掉的东西来教。读者必须先感受到坍缩,非线性才会显得是必要的,而不是装饰性的。
“不过,真正学出那个函数才是难点。”
“Actually learning that function is the hard part, though.”
查看原文 →通用近似在被引入的那一刻就被悄悄降级——是存在性定理,而不是工程上的承诺。C 语言的类比比引文起的作用更大。
“如果微妙的边界条件很要紧,那我们大概是在做(真正的)数学,而不是工程”
“if subtle boundary conditions matter, we are probably doing (real) mathematics, not engineering”
查看原文 →迷人,同时也是这个领域工作风格的坦白。测度为零救了他们——但那是一种约定,而不是定理,而他们也说了出来。
“在这种情形下,核方法要有效得多,因为它们能够精确地解决问题,即使在无穷维空间里也是如此”
“in this case kernel methods are way more effective, since they are capable of solving the problem exactly even in infinite dimensional spaces”
查看原文 →在一本深度学习教科书里,对竞争对手出奇地慷慨。老实的含义是:深度赢在紧凑,而不是表示能力的至高无上。
“想象一下,想在第 42 层和第 43 层之间再插入一层”
“imagine wanting to insert another layer between layers 42 and 43”
查看原文 →抽象的理由是记账,而不是数学。框架之所以存在,是因为给东西起名字让人受不了——一个出人意料地人性的理由。
“用放克乐大师詹姆斯·布朗的不朽名言来说,你必须“付出代价才能当老大”
“in the eternal words of funk virtuoso James Brown, you must “pay the cost to be the boss”
查看原文 →教科书每一节一个的笑话,恰好投放在读者将要略读的地方。这是贿赂,而且管用。
“学术论文不得不分配大量篇幅来推导更新规则”
“academic papers had to allocate numerous pages to deriving update rules”
查看原文 →一部安静的劳动史:自动微分不只是省了时间,它删除了整整一类可发表的工作。
“我们需要保留中间值,直到反向传播完成”
“we need to retain the intermediate values until backpropagation is complete”
查看原文 →这才是整个推导真正的回报——不是链式法则,而是你的 GPU 为什么会耗尽内存。理论兑现为一条错误信息。
“因此,我们容易遇到在把太多概率乘在一起时经常出现的同样的数值下溢问题”
“Thus we are susceptible to the same problems of numerical underflow that often crop up when multiplying together too many probabilities”
查看原文 →漂亮的一招:借用读者已有的直觉,然后立刻撤销它——矩阵没有对数空间这个逃生口。
“隐藏层的表现就好像它只有一个单元。”
“The hidden layer would behave as if it had only a single unit.”
查看原文 →对称性作为陷阱:模型在纸面上保持着表达力,事实上却被弄残了。梯度下降看不到自己的退化。
“这让我们陷入两难:我们不可能同时满足这两个条件。相反,我们只是尝试去满足”
“This leaves us in a dilemma: we cannot possibly satisfy both conditions simultaneously. Instead, we simply try to satisfy”
查看原文 →“我们只是尝试”——整个 Xavier 初始化,就是两个无法同时满足的约束之间的一个平均折中。老实,也有点泄气。
“尽管上述数学推理中“不存在非线性”的假设很容易被违反”
“Though the assumption for nonexistence of nonlinearities in the above mathematical reasoning can be easily violated”
查看原文 →这个推导把使网络成为网络的唯一东西假设掉了。它依然管用——这应该比实际情况更让我们困扰。
“优化只是达到目的的手段”
“optimization is merely a means to an end”
查看原文 →在好几页梯度和方差之后,支点来了:所有这些机制,服务于一个它自己回答不了的统计问题。
“那么你也许想给自己倒杯酒”
“then you might want to pour yourself a drink”
查看原文 →这个笑话起了真正的作用——这是一本教科书承认自己无法在不丧失权威的情况下解释自己的主题的方式。
“我们对深度学习的理解,在这两条战线上仍然像是狂野的西部”
“our understanding of deep learning still resembles the wild west on both fronts”
查看原文 →引人注目的是,这个领域的经典教科书,在泛化这一章开头就承认理论输了。民间知识被点名为一种合法的认知类别。
“通过让模型变得更有表达力,我们实际上可以进一步降低泛化误差”
“we can actually reduce the generalization error further by making the model even more expressive”
查看原文 →这一句话让书在两章之前教的复杂度对损失曲线失效。注意他们从未收回图 3.6.1——只是让它留在那里,受了伤。
“其中有些看似以某种方式限制了模型,另一些看似使它更有表达力,而所有这些,在某种意义上,都是为缓解过拟合而施加的”
“some of which seemingly restrict the model in some fashion and others that seemingly make it even more expressive, and all of which, in some sense, are applied to mitigate overfitting”
查看原文 →两个相反的动作用同一个理由,意味着这个理由什么也没解释。他们这么说很老实;值得注意“看似……看似……在某种意义上”的三重对冲。
读后感AI 陪读
仿射层在 ReLU 让它定型之前就坍缩回了线性
当作一个整体的运动来读,这一章是一个持续的论证,其推进的办法,是先搭一个坏掉的东西。它一开头不是赞美神经网络,而是起诉线性模型——并且精明地通过它最廉价的后果,也就是单调性,来起诉,因为如果连那个都失败了,整座大厦不必碰那些难的部分就倒了。图像反转的例子是致命一击:不是“线性模型拟合得不好”,而是“没有哪个固定符号的权重能在一个保持标签不变的变换下逻辑上存活”。然后是本章真正的支点,容易读过去:问题不是线性模型弱,而是我们不再知道如何手工算出能拯救它们的那些特征。深度学习被引入为对人类无知的承认,而不是对机器至上的宣称。本章随后堆叠仿射层,展示坍缩回线性,让读者在 ReLU 到来之前先感受到“我们什么也没得到”——于是非线性读起来是必要的,而不是装饰性的。通用近似被承认了,又在同一口气里被降级:它是一个存在性定理,而不是一个工程上的承诺,C 语言的类比比那些引文更有分量,并且对核方法给出了出奇慷慨的一点头,承认深度赢在紧凑,而不是表示能力的至高无上。
从这里开始,质地从论证变成了工程,而老实变得更有意思。使用框架和 Sequential 的理由,原来是记账,而不是数学——你受不了要给第 42 层和第 43 层重新编号——这是搭建一个抽象的出人意料地人性的理由。前向/反向传播推导真正的回报不是链式法则,而是那句关于保留中间量的话:理论兑现为你真会遇到的 GPU 显存不足错误。数值稳定性借用了你关于把许多概率相乘的直觉,然后又撤销了对数空间这个逃生口,因为矩阵没有这个。排列对称性是本章最尖锐的陷阱:一个在纸面上完全有表达力、事实上却被弄残的模型,而梯度下降在结构上对自己的退化是盲的。至于 Xavier 初始化,读了小字就会发现,它是两个无法同时满足的约束之间的一个平均折中,是在一个假设——没有非线性——之下推导出来的,而这个假设把使网络成为网络的东西都假设掉了。它依然管用。这应该比书所透露的更让我们不安。
继续阅读
最后的三分之一,是本章悄悄反过来对付书本身的地方。“优化只是达到目的的手段”把此前的一切重新框定为服务于一个它回答不了的统计问题的机制。这个领域的经典教科书随后承认理论输了——两条战线上都是狂野的西部——并把民间知识提升为一种合法的认知类别。一句话就让两章之前教的复杂度对损失曲线失效,指出更有表达力的模型可以泛化得更好;图 3.6.1 从未被收回,只是被留在那里,受了伤。暂退法随后登场,而整套正则化工具箱的理由,被承认涵盖朝相反方向的动作——有的限制,有的扩展——全都“在某种意义上”缓解过拟合,三重对冲,等于是说这个理由什么也没解释。笑话(詹姆斯·布朗、给自己倒杯酒)恰好落在读者将要略读的地方,而且起了真正的作用:这是一本教科书承认自己无法在不丧失权威的情况下解释自己的主题的方式。Kaggle 的房价压轴随后落到纯粹的手艺:标准化、均值插补、独热、对数 RMSE(因为价格上要紧的是相对误差)、K 折(因为你已经没有有原则的选择理论可以倚靠)。
我会这样告诉读者:本章的价值不是 MLP,那只有三行代码,而是它出奇地愿意展示自己的接缝。把那些对冲当作内容而不是填充来读——“我们只是尝试”“看似”“在某种意义上”标出了理解止步、实践接手的确切位置。注意这里几乎每个难忘的结果,都是一个存在性的论断,或者一个事后靠管用来辩护的平均启发式。这些推导值得做,不是因为它们预测性能,而是因为它们解释了你否则会盲目撞上的失败:耗尽的内存、死掉的对称单元、消失或爆炸的梯度。并且抓住本章半埋着的那个泄气的真相——采用深度,是因为特征工程已经没有主意了,而它的大部分机制是老实的猜测,碰巧管用。这不是怀疑这个领域的理由;这是在其中工作的正确姿态。
在 FeedLitra 里读第 5 章,每段旁边都有这些卡片。
开始读书第 6 章:深度学习计算
一旦你需要带有自己反向行为的自定义层,模块的抽象会发生什么变化?
第 6 章是怎样展开的AI 辅助
开篇:有动机地往下退一步抽象。 本章不是从代码开始,而是从一个关于工具的历史论证开始。作者观察到,深度学习库在抽象层面稳步攀升——从单个神经元,到层,再到你用几行代码就能组装的粗粒度块——恰如芯片设计从指定单个晶体管,到逻辑电路,再到编写代码一样。这一攀升是本章的前提,也是它的问题:一个只用过高层 API 的读者,被递给了现成的块,却从未见过它们是由什么构成的。所以本章宣布自己是一本“构建者指南”,并事先列出了行程:模型构建、参数、自定义层、保存模型和 GPU。这个框定的动作是有意的——这是一章把 API 使用者变成能构建 API 零件的人的章节。
展开:模块作为缺失的中间一级。 第一个实质性的小节论证,在单个层和完成的模型之间,确实需要某种东西,而这个论证是经验性的,而不是审美的。真实的架构会一遍又一遍地重复一组组的层;ResNet-152,计算机视觉的主力,是由一个重复了几百次的模式构成的,逐层描述它是不现实的。(作者指出这个设计的血统——2015 年 ImageNet 和 COCO 的获胜——以及这种重复分组的风格随后传播到了语言和语音工作中。)模块作为这个中间一级被引入,它的定义性质是递归可组合性:一个模块可以把其他模块作为子节点,而这些子节点又可以有它们自己的模块。这就是短短的代码能描述巨大网络的原因——你写的是按需制造并嵌套模块的代码,而不是逐一列举各层。本章随后展示写自己的模块要多么少:一个构造函数和一个前向传播,其余的都继承来,因为自动微分提供了反向传播。文中手写的 MLP 恰好定义了这两样东西。作者点出的唯一一个但书是,发明一个真正全新的层,确实需要思考梯度。
转折:模块是一个类,而不是一个栈。 本章关键的一招,是把模块的概念从 Sequential 上撬开,而 Sequential 是大多数读者会误当成整个想法的形状。Sequential 只是一种特殊的模块——按顺序保存它的子节点,并把每个的输出送进下一个——所以它只适合简单的链,别无其他。正确理解的模块,不过是一个定义前向传播并持有它所需参数的类,这意味着其中可以容纳任意的代码:分支、不训练的常数项,甚至循环。演示是那个在 while 循环里不断把输出减半、直到范数降到一以下的网络——这是任何层的堆叠都无法表达的模型。从这里开始,本章走过了参数是你能够触及的对象所带来的实际后果:访问它们、初始化它们,以及绑定它们,使网络中的两处共享同一个张量。
收尾:四个未了结的枝节,每个都是同一设计的后果。 其余的小节读起来是此前一切的实用残余。延迟初始化处理的事实是:一个层的权重形状取决于它的输入有多宽,而作者在写架构时可能并不知道;因此框架在定义时不创建任何参数,在有任何数据流过之前查看第一层的权重,什么也得不到。送进一批形状为 (2, 20) 的数据,框架就读出输入宽度是 20,并从那里开始向前确定各个形状。自定义层推广了先前的教训:新的层是通过子类化基类制作的,可以带参数,也可以不带。文件 I/O 给出了本章最尖锐的纠正:保存一个模型必须一分为二,因为架构留在代码里,只有参数被写出去。作者保存了一个 MLP 的参数字典,构造了同一个类的一个全新实例,把文件加载进去,并展示两个网络对同一输入给出一致的结果。这个拆分是被迫的,而不是风格上的——本章中段所授权的那些任意 Python,恰恰是无法被序列化的东西,所以参数文件只是从名字到张量的映射,永远不是一个自成一体的模型。GPU 以设备放置收尾:因为 CPU 与 GPU 之间的传输比算术本身慢得多,也因为当操作数位于不同设备时,运行时没有依据来决定结果该放在哪里,所以它拒绝悄悄地拷贝,而是报错。警示性的例子是把每个小批量的损失打印到终端,这会触发全局解释器锁,使每块 GPU 停摆——而把日志留在 GPU 内存里、成大块地运出去则不会。本章就这样结束在它开始的地方,谈的是你无法看穿的抽象的代价。
关键论点,以及支撑它们的原文
深度学习工具在抽象层面稳步上移,从单个神经元到层,再到整个粗粒度的块。
作者拿芯片设计做类比,芯片设计从指定单个晶体管,爬升到逻辑电路,再到编写代码;神经网络库也经历了同样的攀升,这就是本章回头去审视粗粒度的抽象是由什么构成的原因。
“随着时间的推移,深度学习的库已经演变为提供越来越粗粒度的抽象。”
“Over time, deep learning’s libraries have evolved to offer increasingly coarse abstractions.”
Chapter 6. Builders' Guide查看原文 →
在单个层和完成的模型之间,确实需要一级中间的东西,因为真实的架构会一遍又一遍地重复一组组的层。
ResNet-152,计算机视觉的中流砥柱,是由一个重复了几百次的层的模式构成的,所以逐层描述它是不现实的;这个设计赢得了 2015 年的 ImageNet 和 COCO 竞赛,这种重复分组的风格随后传播到了语言和语音工作中。因此,本章把模块作为这个中间一级引入。
“例如,ResNet-152 架构在计算机视觉中极受欢迎,它有几百层。”
“For example, the ResNet-152 architecture, which is wildly popular in computer vision, possesses hundreds of layers.”
§6.1 Layers and Modules查看原文 →
写你自己的模块只需要一个构造函数和一个前向传播,因为自动微分会替你处理反向传播。
文中手写的 MLP 只定义了它的初始化器和前向计算,其余都从父模块类继承;作者指出了例外,即你在发明一个真正全新的层时,确实需要考虑梯度。
“注意,除非我们实现一个新的层,否则不必操心反向传播方法或参数初始化。系统会自动生成这些方法。”
“Note that unless we implement a new layer, we need not worry about the backpropagation method or parameter initialization. The system will generate these methods automatically.”
§6.1 Layers and Modules查看原文 →
另外 3 个论点
延迟初始化让你在写架构时不必知道输入的维数。
在没有任何数据流过之前查看第一层的权重,什么也得不到,因为还不存在任何参数;一旦送进一批形状为 (2, 20) 的数据,框架就读出输入宽度是 20,并确定那一层的权重形状。
“一旦我们知道输入的维数是 20,框架就可以代入 20 这个值,确定第一层权重矩阵的形状。”
“As soon as we know the input dimensionality, 20, the framework can identify the shape of the first layer’s weight matrix by plugging in the value of 20.”
§6.4 Lazy Initialization查看原文 →
保存一个模型必须一分为二:架构留在代码里,只有参数被写出去。
作者把一个 MLP 的参数字典保存到文件里,然后在代码中构建同一个类的一个全新实例,并把文件加载进去;两个网络对同一输入返回相同的输出。这个拆分是被迫的,因为模型前向传播中的任意 Python 无法被序列化。
“因此,为了恢复一个模型,我们需要用代码生成架构,然后从磁盘加载参数。”
“Thus, in order to reinstate a model, we need to generate the architecture in code and then load the parameters from disk.”
§6.6 File I/O查看原文 →
因为跨设备的流量代价高昂,框架不会背着你替你拷贝数据。
CPU 与 GPU 之间的传输比算术本身慢得多,而当操作数位于不同设备时,运行时无法把它们放在一处,也无法决定答案该属于哪里,所以它报错,而不是猜测。作者警示性的例子是把每个小批量的损失打印到终端:那会触发全局解释器锁,使每块 GPU 停摆,而把日志留在 GPU 内存里、成大块地运出去则不会。
“但在设备之间传输变量是慢的:比计算慢得多。”
“But transferring variables between devices is slow: much slower than computation.”
§6.7 GPUs查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
嵌套让短短的代码建出庞大的网络
一个模块可以把其他模块作为它的子节点,而这些子节点又可以有它们自己的模块。所以你不必拼写出每一层,而是写按需制造模块并嵌套它们的代码,寥寥几行就可以描述一个重复分组多达几百个的网络。
机制 2
等数据来确定形状
一个层的权重形状取决于它的输入有多宽,而作者在写架构时可能并不知道。因此框架在定义时不创建任何参数;第一批真实数据到达、输入宽度已知的那一刻,它从第一层开始向前推进,并确定每一个形状。
机制 3
为什么混合设备的运算被拒绝
在 CPU 和 GPU 之间搬运张量,比在它们上面计算慢得多。当操作数位于不同设备时,运行时没有依据来选择把结果放在哪里或在哪里计算,所以它不悄悄地拷贝数据,而是停下来,让作者显式地移动。
常见误读
模块抽象基本上就是一个层的栈,所以 Sequential 能表达你需要的任何东西。
Sequential 只是一种特殊的模块,按顺序保存它的子节点,并把每个的输出送进下一个,所以它只适合简单的链。模块不过是一个定义前向传播并持有它所需参数的类,这意味着自定义的模块可以包含分支、不训练的常数项,甚至循环,就像那个在 while 循环里不断把输出减半、直到范数降到一以下的示例网络一样。
“一个模块可以描述单个层,由多个层组成的组件,或者整个模型本身!”
“A module could describe a single layer, a component consisting of multiple layers, or the entire model itself!”
§6.1 Layers and Modules查看原文 →
参数文件一旦在磁盘上,保存的模型就是完整的,可以单独重新加载。
这个文件只是从名字到张量的映射;你必须先在代码里重建同样的架构,然后把参数倒进去。作者明确说,模型内部的任意代码不能自然地被序列化,所以结构无法随参数文件一起走。
“因此,为了恢复一个模型,我们需要用代码生成架构,然后从磁盘加载参数。”
“Thus, in order to reinstate a model, we need to generate the architecture in code and then load the parameters from disk.”
§6.6 File I/O查看原文 →
第 6 章的核心概念
- 神经网络模块
- 一个可重用的单元,可以是一个层、一组层,或整个模型,并且能嵌套在更大的单元里。
- 适用处: 编程上它不过是一个必须定义前向传播并存储所需参数的类;有些模块完全不持有参数。
- Sequential 模块
- 一种特殊的模块,保存一个有序的子模块列表,并把每个的输出送进下一个。
- 适用处: 只适合简单的串联式架构;任何带分支或控制流的,都需要自定义模块。
- 常数参数
- 计算中既不是层激活、也不是可训练权重的项,所以反向传播永远不会更新它们。
- 适用处: 它们住在模块内部,但被排除在优化之外,例如一个随机抽取的固定权重矩阵。
- 绑定的参数
- 让两个层字面上共享同一个张量,这样编辑其中一个就会编辑另一个,它们的梯度也会相加。
- 适用处: 需要先运行一次前向传播,才能访问共享的参数。
- 延迟初始化
- 框架等待第一批真实数据,然后才决定参数的形状。
- 适用处: 只有输入维度未知的层才需要,但框架仍然从第一层开始依次初始化。
- 自定义层
- 你通过继承基础层类并定义前向传播,自己写出的新层。
- 适用处: 局部参数应该用内置的参数函数创建,这样访问、共享、保存和加载才能继续工作。
另外 2 个概念
- 参数字典
- 一个从名字到张量的映射,把整个网络的权重存进一个文件。
- 适用处: 它只存参数;加载之前必须在代码中重建架构。
- 计算设备
- 一个张量所在、其计算所运行的 CPU 或某块特定的 GPU。
- 适用处: cpu 涵盖所有的物理 CPU 和内存,而 gpu 设备只是一张卡。
第 6 章划线与批注AI 陪读
“就像半导体设计者从指定晶体管,到逻辑电路,再到编写代码”
“Just as semiconductor designers went from specifying transistors to logical circuits to writing code”
查看原文 →诱人的类比——但芯片之所以向上抽象,是因为底层是正确的;神经网络的层向上抽象时,底层在统计上仍然模糊。这把梯子藏的东西比在硬件里多。
“这些见解将使你从终端用户变成高级用户”
“These insights will move you from end user to power user”
查看原文 →本章真正的推销:不是新模型,而是在这个领域里社会位置的改变。注意它多么小心地警告这里没有新东西——却仍然坚持你不能跳过。
“我们常常发现,谈论比单个层大、但比整个模型小的组件,是很方便的”
“we often find it convenient to speak about components that are larger than an individual layer but smaller than the entire model”
查看原文 →模块概念老实的来历:不是关于网络的发现,而是言语上的便利。ResNet-152 的几百层让手写它们变得乏味,乏味滋生了一个抽象。
另外 15 条批注
“一个模块可以描述单个层,由多个层组成的组件,或者整个模型本身!”
“A module could describe a single layer, a component consisting of multiple layers, or the entire model itself!”
查看原文 →这种自相似性就是一行话概括整章——每个尺度上都是同一个接口,所以组合永远不会触底。这也是 nn.Sequential(NestMLP(), ..., FixedHiddenMLP()) 竟然说得出口的原因。
“我们只需要关心参数和前向传播方法”
“we only need to worry about parameters and the forward propagation method”
查看原文 →自动微分让模块抽象变得廉价。没有它,每个自定义块都得亏欠一次手推的反向传播,没人会为了好玩而去组合任何东西。
“据我们所知,没有任何标准的神经网络执行这种运算。”
“To our knowledge, no standard neural network performs this operation.”
查看原文 →作者们难得对自己的例子耸了耸肩。这个 while 循环是有意设计成没用的——教学选择了机制的清晰,而不是合理性,并且大声承认了这一点。
“这样系统就知道添加了哪些模块,并会正确地初始化每个模块的参数”
“In this way the system knows the added modules, and it will properly initialize each module’s parameters”
查看原文 →这里是习题 1 的答案,提前一页埋下了:一个普通的 Python 列表对框架的注册表是不可见的。抽象恰恰在记账所在之处漏水。
“它们不只是相等,而是由同一个张量表示的。”
“They are not just equal, they are represented by the same exact tensor.”
查看原文 →同一性对相等性——= 100 这个赋值就是为了暴露这个区别而设计的。聪明的教法:把改动当作别名的证据。
“第二个隐藏层和第三个隐藏层的梯度在反向传播期间被加在一起”
“the gradients of the second hidden layer and the third hidden layer are added together during backpropagation”
查看原文 →一句话就带过了,但这是关于权重绑定的深层事实——一个张量,两条路径,信号求和。权重绑定在 RNN 和嵌入中管用的全部理由就在这里。
“module.weight.data *= module.weight.data.abs() >= 5”
查看原文 →通过掩码的拒绝采样——乘以一个布尔值。它之所以能复现所述的分布,只是因为置零恰好是三种情形之一。一个巧妙的招数,对几乎任何其他目标都会悄悄失效。
“看起来我们在搭建网络时似乎马虎了事也蒙混过关”
“it might seem that we got away with being sloppy in setting up our networks”
查看原文 →好招:在解释之前先点出读者的不安。他们整整一章都在写 LazyLinear,却没问过形状是什么。
“只有第一层需要延迟初始化,但框架是依次初始化的”
“only the first layer requires lazy initialization, but the framework initializes sequentially”
查看原文 →一个小小的坦白:这个机制比故事要粗糙——形状是一次一个向前传播的,而不是全局求解的。所以 apply_init 里才有那次空的前向传播。
“return X - X.mean”
查看原文 →一个输出取决于整批均值的层——微妙地不是一个逐样本的函数。看上去无害,但它在推理时会在样本之间泄漏信息。书没有指出这一点。
“torch.matmul(X, self.weight.data) + self.bias.data”
查看原文 →这里用 .data 会脱离自动求导——这些参数永远不会收到梯度。一个悄悄破坏了它所教的东西的教学示例。
“模型本身可以包含任意的代码,因此它们不能那样自然地被序列化”
“the models themselves can contain arbitrary code, hence they cannot be serialized as naturally”
查看原文 →本章真正的承认:神经网络是一个程序,而不是一个数据结构。权重是唯一真正可移植的部分。
“所以我们想让你百分之百确定你想做一件慢的事,然后才让你去做。”
“So we want you to be 100% certain that you want to do something slow before we let you do it.”
查看原文 →难得一见,框架的拒绝帮忙被框定为教学法。错误信息就是老师。
“就像在队伍里排队点咖啡,而不是提前用手机预订”
“like ordering your coffee in a queue rather than pre-ordering it by phone”
查看原文 →这个类比很讨喜,但把要点说小了——真正的代价不是你的等待,而是咖啡师闲着。是设备断粮,不是延迟。
“它现在受制于令人畏惧的全局解释器锁,让一切都得等 Python”
“it is now subject to the dreaded global interpreter lock that makes everything wait for Python”
查看原文 →价值几千美元的硅片被一条打印语句扣作了人质。深度学习里最昂贵的一行代码往往是 print(loss)。
读后感AI 陪读
你可以安全地忘掉机器的多少
这一章读起来像是在递交一个工具箱,但它真正是一章关于抽象位于何处、要付出什么代价的章节。它以半导体的类比和从终端用户变成高级用户的承诺开篇——这是一个关于在这个领域里的社会位置、而不是新模型的推销——然后构建它的核心对象:模块,一开始就承认它是一种言语上的便利,而不是关于网络的发现。几百层的 ResNet 滋生了乏味,乏味滋生了接口,而这个接口在每个尺度上都是自相似的,这就是为什么一层、一个块和整个模型都可以放进同一个 Sequential 调用里。从这里开始,本章依次走过参数(访问、共享、初始化)、延迟的形状推断、自定义层、序列化,最后是设备——每一站其实都是同一个问题再问一遍:你可以忘掉机器的多少,忘错了地方又会被什么咬?
我看穿的是,几乎每一节都悄悄标出了抽象漏水的地方,有时是有意的,有时不是。模块之所以能自由组合,只是因为自动微分为反向过程买了单;一个普通的 Python 层列表会从框架的注册表中消失,因为魔法实际由之构成的是记账,而不是数学;绑定的权重是同一个张量,所以它们的梯度相加——这一句话承载了权重绑定在嵌入和 RNN 中管用的全部理由;延迟初始化是一层一层向前推进的,而不是全局求解形状,这就是为什么必须在 apply_init 里偷偷塞进一次空的前向传播。序列化那一节包含了本章最老实的一句话:网络是一个程序,而不是一个数据结构,所以只有权重会被带走,架构必须在代码里重建。而 GPU 那一节把同样的教训搬到硬件经济学上——异步咖啡的类比低估了它,因为一个多余的 print(loss) 的代价不是你的等待,而是一个空闲的加速器被解释器锁扣作了人质。
继续阅读
我最尖锐的判断是,教学示例没有看上去那么安全,而书并不总是这么说。减去批量均值的居中层根本不是一个逐样本的函数,在推理时会在样本之间泄漏;用 .data 写成的自定义线性层脱离了自动求导,所以它教你去注册的那些参数实际上永远学不到东西;按幅值掩码的初始化器只是碰巧复现了它声称的分布,因为置零恰好是允许的结果之一。这些问题很小,细心的读者一行就能修好——但它们之所以要紧,恰恰因为这是你停止抄写、开始自己写零件的一章,而这些示例就是模板。
对读者说:别因为这一章没有引入新模型就略读它。把它读成一张接缝的地图。把每一种便利——模块注册、延迟形状、保存的状态字典、隐式的设备放置——都当作你应该能用自己的话说清楚的契约,因为之后的调试,意味着确切知道你倚赖了其中的哪一个。并且把硬件的类比保持在一臂之外:芯片是从可证明正确的层向上抽象的,而神经网络的层是从统计上仍然模糊的层向上抽象的。这里的梯子比在硅里藏得更多,而知道它藏了什么,才是本章真正提供的晋升。
在 FeedLitra 里读第 6 章,每段旁边都有这些卡片。
开始读书第 7 章:卷积神经网络
卷积层究竟是如何编码像素相邻性的?
第 7 章是怎样展开的AI 辅助
开篇:是诊断,而不是介绍。 本章一开头就控诉了它刚刚教完的那个模型。作者观察到,把图像展平成向量,破坏了使它成为图像的唯一东西:全连接网络把它的输入当作一个无序的特征列表,所以像素可以被随机重排,而模型对此一无所知。这个结构性的论证——如果顺序可以被打乱而没有后果,那么空间布局就不携带任何信息——创造了本章的议程。随后的承诺异常强烈:卷积网络同时在两条战线上获胜,既需要更少的样本,又需要更少的计算,ImageNet 被拿出来作为历史的裁决(作者说,是卷积的方法终于推动了准确率)。这种双重的胜利,也是 CNN 此后从视觉迁移到序列、图和推荐系统的明言的理由。
展开:先构建算子,再把它交给梯度下降。 从动机出发,文本直接落到机制上。一个卷积层原来就是互相关加一个标量偏置——作者停下来化解了那个显而易见的反对意见,即真正的卷积会翻转核。这种翻转无关紧要,因为核是学出来的:一个严格卷积的层只是拟合翻转后的权重,并发出完全相同的输出,所以不同的只是存储的数字,而从不是行为。教学的顺序随后是先手工设计,后学习。[1,-1] 有限差分边缘检测器之所以优雅,恰恰因为目标算子是已知的——而作者小心地说,随着核变大、层数变多,这种奢侈就消失了。所以一个随机初始化的核在单个输入—输出对上被训练,十步梯度就把误差降到近乎为零,并恢复出一个几乎与手写滤波器相同的东西。两句结构性的旁白完成了这一节:堆叠拓宽了一个单元所看到的东西(在第二个 2×2 层之后,一个输出沿着全部四个中间值,一路追溯到全部九个原始输入,这就是深度存在的原因),而不填充的卷积悄悄地吃掉了图像——十个 5×5 的层把 240×240 缩成 200×200,丢掉大约 30%,而丢掉的恰恰是边界。一圈零买回了大小和边缘。在这一切底下是更深的论断:因为算术简单且严格局部,什么东西都不必在内存里传得很远,所以芯片设计者可以把预算花在快速的计算上,而不是大内存——这使价格可承受的计算机视觉成为可能,同时带着老实的但书:这样的硬件未必适合其他工作负载。
转折:表达力带着账单到来。 本章的支点是通道,它的语气也随之改变。输入和核变成更高维的张量——多输入的核把各通道的互相关求和,多输出的核堆叠 $c_o$ 个这样的核——而 1×1 卷积作为纯粹的极限情形浮现,一个逐像素的全连接层,只混合通道,别无其他。这里发出的是两个警告,而不是庆祝。第一,针对每个通道私有一个特征——一个管边缘,一个管角点——的直观图景:通道是被联合训练成共同有用的,所以一个特征通常作为通道空间里的一个方向存在,作者明确把逐通道或逐像素独立学习的天真读法放在一边。第二,针对“参数少就是便宜”的假设:代价按 $c_i \times c_o$ 缩放,具体的数字落得很重——一张 256×256 的图像,一个 5×5 的核,输入输出各 128 个通道,超过 530 亿次运算。每个权重在许多滑动乘法中被重复使用,所以参数数量与计算量完全分开了。(块对角的设计被点出为之后的补救办法,而 GPU 则是眼前的补救办法。)
收尾:零件被组装起来,以及对究竟缺了什么的裁决。 LeNet-5 作为本章的整合练习到来——一个带 sigmoid 激活和平均池化的两层卷积编码器,接上 120、84 和 10 个单元的稠密层——作者在 Fashion-MNIST 上训练了它。收尾的判断是历史性的,而不是技术性的:LeNet 的错误率离先进的现代架构,比离 MLP 所能达到的最好水平近得多,作者把这读作证据,说明这个架构思想在 1990 年代就已经是对的,缺的只是算力。最后一条说明把它变成了对现状的一句评论:曾经需要几个月底层工程的东西,如今只是几分钟的框架代码——这个结尾悄悄地为本章自己从零实现的 corr2d 提供了理由:那是你为了理解而做一次的事,而不是每次构建都做。
关键论点,以及支撑它们的原文
全连接网络无法利用相邻像素属于一体这个事实。
作者的推理是结构性的:这样的网络把输入当作一个无序的特征列表,所以对像素的任何重排都会产生同一个模型。如果顺序可以被打乱而没有后果,那么图像的空间布局对网络就不携带任何信息——这就是本章着手构建编码“附近的像素相关”这一先验的层的原因。
“因为这些网络对特征的顺序是不变的,所以不管我们是保留与像素空间结构相对应的顺序,还是在拟合 MLP 的参数之前,对设计矩阵的列做一次置换,我们都能得到相近的结果。”
“Because these networks are invariant to the order of the features, we could get similar results regardless of whether we preserve an order corresponding to the spatial structure of the pixels or if we permute the columns of our design matrix before fitting the MLP’s parameters.”
Chapter 7. Convolutional Neural Networks查看原文 →
否定了展平向量的做法之后,作者论证卷积网络同时在两条战线上获胜——它们需要更少的样本和更少的计算——这解释了它们为什么传播到了视觉之外。
佐证的是 ImageNet 基准,据作者说,只有卷积的方法在准确率上带来了显著的提升;这个论断是在历史结果的层面上做出的,在这部分正文里没有给出详细的数字。
“除了在获得准确模型方面的样本效率之外,CNN 在计算上也往往很高效,既因为它们需要的参数比全连接架构少,也因为卷积很容易在 GPU 核心上并行。”
“In addition to their sample efficiency in achieving accurate models, CNNs tend to be computationally efficient, both because they require fewer parameters than fully connected architectures and because convolutions are easy to parallelize across GPU cores”
Chapter 7. Convolutional Neural Networks查看原文 →
滤波器不必由工程师发明——梯度下降可以从输入及其期望输出的样本中把它们恢复出来。
作者首先展示了相反的情形:[1,-1] 有限差分边缘检测器之所以优雅,恰恰因为目标算子是已知的,而一旦核变大、层数变多,这种奢侈就消失了。从这里开始,一个随机初始化的核在单个输入—输出对上训练十步梯度,就把平方误差降到近乎为零,并最终与手写的核几乎相同——这是一个忽略了偏置项的玩具演示。
“最重要的是,统计学家(或工程师)并不需要发明合适的滤波器。相反,我们可以简单地从数据中学习它们。”
“Most importantly, it is not necessary that the statistician (or engineer) invents suitable filters. Instead, we can simply learn them from data.”
§7.2 Convolutions for Images查看原文 →
另外 3 个论点
卷积更深层的吸引力在于,它的算术简单且严格局部,这使得为它构建专门的硬件是值得的。
因为每个输出值只触及一个小的邻域,数据不必从内存中很远的地方搬运过来;作者指出,这使芯片设计者可以把预算花在快速的计算上,而不是大内存,这正是让价格可承受的计算机视觉成为可能的原因。但书附有一个但书:这样调校的硬件未必对其他种类的应用是最优的。
“可以看到,计算是直截了当的,而且最重要的是,高度局部。这使得显著的硬件优化成为可能,而计算机视觉近来的许多成果,正是因此才得以实现。”
“As can be seen, the computation is straightforward and, most importantly, highly local. This affords significant hardware optimization and many recent results in computer vision are only possible because of that.”
§7.2 Convolutions for Images查看原文 →
转到通道,作者承认它们增加了真正的表达能力,然后立刻警告说,这种灵活性是用计算量成倍膨胀来换的。
代价按输入通道数乘以输出通道数缩放,作者把它说得很具体:用 5x5 的核处理一张 256x256 的图像,输入输出各 128 个通道,需要超过 530 亿次运算,其中乘法和加法分开计数。书指出,之后的块对角设计是把这个数字降下来的办法之一。
“不过,请注意,这种灵活性是有代价的。”
“Note, though, that this flexibility comes at a price.”
§7.4 Multiple Input and Multiple Output Channels查看原文 →
在本章结尾,作者把 LeNet-5 放在了分界线的现代一侧,而不是与更早的全连接模型放在一起,把可用的计算量看作把它与今天的网络隔开的主要东西。
比较是在 Fashion-MNIST 上进行的:LeNet-5 的错误率结果与先进架构的错误率更接近,而不是与多层感知机所能得到的最好结果接近,这被读作证据,说明这个架构思想本来就是对的,缺的只是算力。
“正如我们将看到的,主要差异之一是,更大量的计算使显著更复杂的架构成为可能。”
“One of the primary differences, as we shall see, is that greater amounts of computation enabled significantly more complex architectures.”
§7.6 Convolutional Neural Networks (LeNet)查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么翻转无关紧要
严格的卷积与互相关的区别,仅在于把核水平和垂直地翻转。由于核不是预先固定的,而是用数据拟合出来的,一个严格卷积的层只是学出翻转后的权重,并发出完全相同的输出;不同的只是存储的权重,而不是层的行为。
机制 2
堆叠拓宽了一个单元所看到的东西
每个输出元素只依赖于它的核所覆盖的那个小的输入窗口,所以一个层看到的很少。把那个输出送进另一个层,新的元素就依赖于它下面的所有窗口:在第二个 2x2 层之后,单个输出可以追溯到全部四个中间值和全部九个原始输入,所以深度是检测更宽范围上的特征的办法。
机制 3
为什么边界需要填充
每一个不带填充的卷积都会从每条边上削掉一些像素,损失一层一层地累积:十个 5x5 的层把一张 240x240 的图像变成 200x200,丢掉大约 30%,而丢掉的恰恰是边界。在输入周围加一圈(通常为零的)像素,给核留出移动的余地,同时保住大小和边缘信息。
常见误读
每个通道是一个单独学出来的、检测某个特定视觉特征的探测器——一个通道管边缘,另一个管角点。
通道是被一起训练成共同有用的,所以一个特征常常表示为通道空间里的一个方向,而不是归某一个通道所有;作者明确把表示是逐像素或逐通道独立学出来的这种天真读法放在一边。
“相反,通道被优化成共同有用。”
“Instead, channels are optimized to be jointly useful.”
§7.4 Multiple Input and Multiple Output Channels查看原文 →
既然卷积网络的参数比全连接网络少得多,它们运行起来一定也更便宜。
参数数量和计算量在这里是分开的:随着窗口的滑动,每个核权重被重复用在非常多的乘法中,所以一小组参数仍然可以驱动数量巨大的运算——一个多通道层 530 亿次运算的估计就表明了这个规模。这就是作者在训练模型时去用 GPU 的原因。
“尽管 CNN 的参数更少,它们的计算仍可能比同样深度的 MLP 更昂贵,因为每个参数参与了多得多的乘法。”
“While CNNs have fewer parameters, they can still be more expensive to compute than similarly deep MLPs because each parameter participates in many more multiplications.”
§7.6 Convolutional Neural Networks (LeNet)查看原文 →
第 7 章的核心概念
- 卷积神经网络(CNN)
- 一类为利用图像等网格数据的空间结构而设计的网络。
- 适用处: 在相邻元素确实相关的地方效果最好;也被改造用于音频、文本、图。
- 特征维数
- 当二维的像素网格被丢弃时,图像就变成了长长的扁平向量。
- 适用处: 只有在不存在空间先验时,展平才是可以接受的,比如表格数据。
- 卷积层
- 一个让核在输入上滑动、计算互相关、然后加上一个标量偏置的层;核和偏置是它仅有的参数。
- 适用处: 这里只限单通道和二维;偏置是一个标量,还没有施加填充。
- 有限差分边缘检测器
- 1x2 的核 [1, -1],在相邻像素相同的地方输出零,在不同的地方输出非零,近似于水平方向的导数。
- 适用处: 只能检测垂直的边缘;施加在转置后的图像上,响应就消失了。
- 学习一个核
- 不是用手工设计滤波器的权重,而是随机初始化它们,并针对已知的输出,对平方误差做梯度下降来更新它们。
- 适用处: 在一个已知的输入—输出对上演示,忽略了偏置;现实的情形涉及许多层和通道。
- 特征工程
- 手工制作模型所用的滤波器或特征,学出来的核用数据驱动的估计取代了这种做法。
- 适用处: 当想要的算子精确已知时仍然有用,比如 [1, -1] 边缘检测器。
另外 10 个概念
- 感受野
- 对一个层的任何元素,在前向传播中能够影响其值的、前面各层的所有元素。
- 适用处: 可能比实际的输入大小还大;扩大它需要堆叠更多的层。
- 特征图
- 卷积层的输出,被看作传给下一层的、学出来的空间表示。
- 适用处: 只有空间维度,例如宽和高。
- 填充
- 在输入边界周围添加额外的、通常为零的像素,使核有移动的余地,输出也不会缩小。
- 适用处: 把填充设为核大小减一,可保持形状;奇数大小的核允许在两侧对称地填充。
- 步幅
- 卷积窗口每次滑动所移动的行数和列数;更大的步幅会对输出下采样。
- 适用处: 默认填充为 0、步幅为 1;输出大小用向下取整的除法。
- 通道维度
- 额外的轴(RGB 的大小为 3),使输入和隐藏表示成为三维张量。
- 适用处: 适用于输入和隐藏层;池化不碰它,而卷积会对它求和。
- 多输入通道的卷积核
- 一个核,每个输入通道持有一个 k_h x k_w 的切片;各通道的结果被加在一起。
- 适用处: 要求核的输入通道数等于数据的通道数。
- 1x1 卷积层
- 一种卷积,其唯一的计算是在每个像素位置上对通道做线性组合。
- 适用处: 无法捕捉相邻元素之间的空间交互;需要后面跟非线性,才不会被折叠。
- LeNet-5
- 一种早期的 CNN:两个带 sigmoid 和平均池化的卷积层,然后是三个全连接层,以 10 个类别输出结束。
- 适用处: 这里复现时,用一个 softmax 层取代了原来的高斯激活层。
- 卷积编码器
- 由卷积加池化块构成的堆叠,把图像变成通道更多但高和宽更小的特征图。
- 适用处: 它的四维输出必须先展平,任何全连接层才能读取。
- Fashion-MNIST 数据集
- 这里用来训练和评判 LeNet-5 的 28x28 灰度服装基准。
- 适用处: 用作与 MLP 和像 ResNet 这样先进得多的架构两者的比较点。
第 7 章划线与批注AI 陪读
“这种令人深感不满的做法,对于把得到的一维向量送入全连接的 MLP 是必要的”
“This deeply unsatisfying approach was necessary in order to feed the resulting one-dimensional vectors through a fully connected MLP”
查看原文 →“令人不满”这个词在起真正的修辞作用——作者们把展平框定为一种审美上的冒犯,于是这个修补感觉像是不可避免的,而不是被发明的。
“猪通常不会飞,飞机通常也不会游泳。”
“Pigs usually do not fly and planes usually do not swim.”
查看原文 →一句狡黠的旁白:它悄悄承认先验是统计性的,而不是绝对的——下一句话又立刻把它收了回去。“通常”这个对冲,就是一个词里的整套归纳偏置认识论。
“瓦尔多长什么样,并不取决于瓦尔多在哪里”
“what Waldo looks like does not depend upon where Waldo is located”
查看原文 →对权重共享可能最干净的陈述——并且注意它是关于世界的论断,而不是关于数学的。此后的一切,不过是用下标记法写出的这一句话。
另外 17 条批注
“从 $\mathsf{W}$ 到 $\mathsf{V}$ 的转换目前完全是装饰性的”
“The switch from \(\mathsf{W}\) to \(\mathsf{V}\) is entirely cosmetic for now”
查看原文 →值得停一下:目前还什么都没得到。重新索引是免费的;真正的动作在于,新的坐标让下一个假设变得可以表达。好的记法,就是论证藏身之处。
“只有当 $\mathsf{V}$ 和 $\mathbf{U}$ 实际上并不依赖于 $(i, j)$ 时,这才可能”
“This is only possible if \(\mathsf{V}\) and \(\mathbf{U}\) do not actually depend on \((i, j”
查看原文 →这是我想追问的障眼法——推导出来的是等变性(输入平移,输出平移),而这一节的标题却是不变性。书之前在括号里标出了这种混淆,然后却把这两个术语互换着使用。
“所有的学习都依赖于施加归纳偏置。”
“All learning depends on imposing inductive bias.”
查看原文 →本章老实的核心。参数的节省不是免费的午餐——而是对世界的一次赌注,下一个分句点出了输掉赌注的代价。
“我们在 (7.1.1) 中的原始定义,更准确地描述的是互相关。”
“Our original definition in (7.1.3) more properly describes a cross-correlation.”
查看原文 →承认了这个领域的命名错误,然后耸了耸肩。因为核是学出来的,翻转被吸收进了学出的权重里——这就是没人在乎的原因,尽管书在这里并没有这么说。
“增加通道,使我们能够找回一些失去的复杂度”
“Adding channels allowed us to bring back some of the complexity that was lost”
查看原文 →这是整节安静的记账技巧:局部性和共享沿空间剥掉了容量,通道沿深度又把它偷偷带了回来。预算从未真正被削减——只是被搬到了结构真正变化的地方。
“注意,这个核是有限差分算子的一个特例。”
“Note that this kernel is a special case of a finite difference operator.”
查看原文 →通回经典信号处理的桥梁——并把“学习一个核”重新框定为学习一个微分算子。忽然间,边缘检测器不再是个玩具,而是被离散化了的微积分。
“手工精确指定每个滤波器应该做什么,可能是不可能的”
“it might be impossible to specify precisely what each filter should be doing manually”
查看原文 →从工程转向学习的支点,被表述为投降,而不是胜利。梯度下降登场,不是因为它原则上更好,而是因为手工设计没有空间了。
“确实,学出来的核张量与我们之前定义的核张量 K 非常接近。”
“Indeed, the learned kernel tensor is remarkably close to the kernel tensor K we defined earlier.”
查看原文 →一个微小的、被设计好的演示——一条毫不含糊的边缘,一个 1×2 的核——却承载着本书的全部论点:别去设计滤波器,把它恢复出来。这个例子的朴素就是重点。
“无论这些层执行的是严格的卷积运算还是互相关运算,卷积层的输出都不受影响”
“the outputs of convolutional layers remain unaffected no matter such layers perform either the strict convolution operations or the cross-correlation operations”
查看原文 →学习吸收了数学家的抱怨。如果核是自由的,翻转它就是坐标的改变,而不是模型的改变——所以这个领域问心无愧地保留着这个错误的词。
“注意,感受野可能比输入的实际大小还大。”
“Note that the receptive field may be larger than the actual size of the input.”
查看原文 →像脚注一样顺带放进来,但这是深度本身的安静理由——填充的阴暗面,神经元“看到”了编造出来的零。
“这给了我们信心,让我们相信我们走在正确的道路上。”
“This gives us confidence that we are on the right track.”
查看原文 →这里教科书的声音滑向了信仰。生物学与我们的架构相像,是安抚,而不是证据——大脑也有许多我们无意复制的特征。
“它使 CNN 能够在图像内编码隐含的位置信息,只需学会“空白”在哪里”
“it allows CNNs to encode implicit position information within an image, simply by learning where the “whitespace” is”
查看原文 →美妙的反转:我们为记账方便而加的零,成了网络加以利用的信号。脚手架漏进了建筑里。
“它也许只是意味着通道空间里的某个方向对应着检测边缘”
“it may simply mean that some direction in channel space corresponds to detecting edges”
查看原文 →这一节唯一抵制自己教学法的地方——“通道 = 特征检测器”是每门课都教的直觉,而在这里被温和地收回了。
“卷积层之后通常跟着非线性。这确保了 $1 \times 1$ 卷积不能被简单地折叠进其他卷积”
“convolutional layers are typically followed by nonlinearities. This ensures that \(1 \times 1\) convolutions cannot simply be folded into other convolutions”
查看原文 →没有那句话,1×1 卷积就是冗余;有了它,它们就是一个设计原语。整个理由都挂在一个激活函数上。
“这相当于超过 530 亿次运算”
“this amounts to over 53 billion operations”
查看原文 →那个戳破整个“卷积很便宜”故事的数字。参数的节省和计算的节省不是一回事,而书只在一句近乎脚注的旁白里承认了这一点。
“在几乎所有情形下,最大池化(也这么叫)都比平均池化更可取。”
“In almost all cases, max-pooling, as it is also referred to, is preferable to average pooling.”
查看原文 →这一节里断言了两次,哪里都没有论证。藏在习题里的是“你为什么预期它们的效果不同?”——所以书知道欠一个理由,并把它外包给了读者。
“由于快门的运动,相机的振动可能把一切平移一个像素左右”
“vibration of the camera due to the movement of the shutter might shift everything by a pixel or so”
查看原文 →可爱的一招:池化的理由建立在物理硬件上,而不是数学上。不变性不是理论上的美好点缀——而是快门的拍击。
读后感AI 陪读
一句审美上的抱怨如何变成学习需要归纳偏置的证明
当作一个整体来读,这一章是一个伪装成教程的论证,它的脊梁是在三个尺度上重复的同一个动作:注意到世界里的某种结构,把它编码成一个约束,然后付出代价买回约束拿走的东西。它以一个审美上的抱怨开篇——把图像展平“令人深感不满”——而那个词比任何方程都干了更多活,因为它让这个修补感觉像是被发现的,而不是被发明的。从这里开始,推导几乎顺滑得过分:MLP 的权重矩阵从 W 重新索引为 V(书承认“目前完全是装饰性的”,而这恰恰是真正的论证藏身之处,因为新的坐标让下一个假设变得可以说出口),然后施加平移等变性和局部性,参数数量就坍缩了。老实的核心用一句话到来——“所有的学习都依赖于施加归纳偏置”——而“瓦尔多”那一句是它最好的注解,因为那是关于世界的论断,而不是关于数学的。此后的一切都是用下标记法写出的这个论断,并用“通常”来对冲:猪通常不会飞。我想在这里追问两件事。第一,推导出来的是等变性,而这一节的标题却是不变性;书在括号里标出了这种混淆,然后却把这两个词互换着使用,这正是细心的读者应该抓住、而不是原谅的那种滑动。第二,对视觉皮层的诉诸——“这给了我们信心,让我们相信我们走在正确的道路上”——是安抚,而不是证据;大脑有许多我们无意复制的特征。
中间的各节,是本章悄悄拆掉自己的经济学的地方。填充和步幅被呈现为记账,但有两句旁白超出了这个框架:感受野可以超过输入,这才是深度的真正理由,而我们为方便而加的零,成了网络学会读作位置的信号——脚手架漏进了建筑里。通道是核心的记账技巧:局部性和共享沿空间剥掉了容量,通道沿深度又把它偷偷带了回来,预算从未被削减,只是被搬到了结构真正变化的地方。1×1 卷积之所以作为一个设计原语存在,只是因为非线性使它不会折叠进它的邻居——整个架构思想倚靠在一个激活函数上。然后是戳破本章自己推销词的那个数字:530 亿次运算。参数的节省和计算的节省不是一回事,而书几乎是顺便承认了这一点。池化则相反,它最好的理由来自硬件而不是理论——快门的震动把一切平移一个像素——尽管“最大池化更可取”被断言了两次,却哪里都没有论证,把理由外包给了一道习题。书知道欠你这一个。
继续阅读
代码各节有意保持朴素,而这种朴素就是论点。一个检测垂直边缘的 [1,-1] 核是一个离散化的导数,这把“学习一个核”重新框定为学习一个微分算子,并把整个事业拉回了经典的信号处理。然后梯度下降从一个被设计好的小例子里恢复出那个核——而支点被表述为投降,而不是胜利:一旦你说不出每个滤波器应该做什么,手工设计就干脆没有空间了。互相关的坦白属于同一逻辑。这个领域用错了词,而没人在乎,因为学出来的核会吸收翻转;这是坐标的改变,而不是模型的改变。LeNet-5 以展示这些零件被组装成可用的东西来结束这条弧线,而关于几个月的底层工程如今只需几分钟的旁白,既是真的,也值得略加不信——实现的容易不等于理解。
我会这样告诉读者:别让推导的顺滑说服你,以为 CNN 是被推演出来的。它们是被押注出来的。本章里的每一项节省,都是关于图像的一次赌注——附近的像素相关,身份与位置无关——而本章出奇地坦率,说输掉这样的赌注,会让你损失准确率,而且没有办法从数据里挽回。像读方程一样仔细地读旁白;本章的老实就住在它的括号里、脚注里和习题里,在那里,混淆被标出,计算成本被承认,未经论证的论断被交到你手上。方程是容易的部分。
在 FeedLitra 里读第 7 章,每段旁边都有这些卡片。
开始读书第 8 章:现代卷积神经网络
暂退法和 ReLU 究竟如何改变 AlexNet 相对于 LeNet 的可训练性?
第 8 章是怎样展开的AI 辅助
开篇:一个时间顺序的框架,和一个奠基性的论证。 本章自称是对现代 CNN 架构按其出现顺序的导览,从 AlexNet 到 RegNet,然后立刻用 AlexNet 提出它的核心历史论断。2012 年以前,计算机视觉是一门流水线式的学科:先提取手工设计的描述子,如 SIFT 或 SURF,再把它们送入线性或核分类器,学习算法被当作事后才想到的东西。文本论证,AlexNet 的胜利不是来自某个聪明的新招数,而是来自用学出来的层级特征取代这条流水线——这一步只有在两个外部条件同时到来后才变得可能:ImageNet(2009),提供了大约一百万张 224×224 的图像,分属 1000 个类别,比早先的数据集大出一个数量级以上,并且通过对搜索引擎候选结果的众包审核来标注;以及 GPU 算力,形式是两块各为 1.5 TFLOPs 的 3GB GTX 580,其快速的卷积代码成为行业标准的 cuda-convnet。开篇以一个有意泄气的调子收束:这一突破的采用仍然滞后,因为工具还不存在——没有 DistBelief,没有 Caffe,Theano 的功能也很贫乏——直到 TensorFlow 改变了局面。
展开:对“我们该怎么花参数预算?”的四个相继的回答。 确立了 AlexNet 的代价是现实的问题之后,本章推进到各自细化同一个问题的架构。VGG 的回答是,预算应当花在组织成重复块的深度上,其依据是文本视为整个设计背后机制的一小段算术:两个堆叠的 3×3 卷积触及的像素与一个 5×5 相同,而三个的参数大约只相当于单个 5×5——所以同样的感受野可以用额外的非线性、而不是更宽的核来买到,这就是为什么在参数数量相当的情况下,深而窄的堆叠胜过浅而宽的。VGG-11 把它实例化为五个块,通道数翻倍到 512,而因为这些块是参数化的,它定义的是模型的一个家族,而不是一个网络,所以作者提出——作为一个可以争论的称呼,而不是定论——VGG 是第一个真正现代的 CNN。NiN 随后攻击作者所认定的 VGG 的真正瓶颈,那个过大的全连接头部:单个矩阵在 FP32 下占据近 400MB,而同时代的 iPhone 4S 总共只有 512MB,所以单是这个头部就可能超出一台设备。NiN 的补救办法是把它删掉,转而以一个通道数等于类别数的块收尾,再接全局平均池化,大幅削减参数,代价可能是训练更慢。GoogLeNet 以彻底拒绝核大小的问题来结束这一序列:别人在争论哪种卷积宽度更优时,Inception 块并行地运行好几种并把结果拼接起来,九个这样的块分成三组——配上全局平均池化的头部和主干—躯干—头部的骨架——赢得了 2014 年的 ImageNet 挑战赛。组装成五个阶段、带手工调校的通道比例,并在这里于 96×96 的 Fashion-MNIST 上训练,它既更便宜又更准确,这个结果使块级设计成为思考的单位具有了正当性。
第一个转折:从架构到训练,以及关于直觉的一课。 本章随后从拓扑转向归一化。批量归一化起初是建设性地被提出的,动机是来自日常实践的论证:标准化输入使估计问题保持可控,也适合优化器,那么为什么不在网络内部也这样做?它被打包成一个把数学与记账分开的层,在 LeNet 里以从零实现和高层实现两种形式演示。然后是本章最尖锐的批评段落。流行的解释——BatchNorm 之所以管用,是因为消除了“内部协变量偏移”——被斥为用词不当,并被举为为什么指导性的直觉必须与既定事实分开的首要例证;Ali Rahimi 在 2017 年 NeurIPS 时间检验奖演讲里援引的正是这一点,把深度学习的实践比作炼金术。经受住批评的是经验性的整体:预处理、数值稳定性,以及作者框定为一个意外之喜、而不是设计目标的正则化效应,其中小批量统计量的噪声是一个特性——因此有 50–100 个样本左右的最佳点,Teye 等人(2018)和 Luo 等人(2018)把它与贝叶斯先验和惩罚项联系起来,同时承认这一效应在理论上仍然刻画得很差。这项技术管用得极好;关于为什么管用所讲的故事则不然。
第二个转折:嵌套的函数类,以及对一个诱人推断的纠正。 从这里开始,本章转向是什么让深度变得可以信任,在这里它明确挡住了自己先前的论证所邀请的一种误读。如果深而窄胜过浅而宽,那么更多的层岂不是总是更好?不:只有当扩大后的函数类包含较小的那个时,额外的层才增加能力。对于非嵌套的类,增加复杂度可能把模型带离目标函数,所以深度并不自动意味着进步。残差块的存在恰恰是为了保证嵌套——每个新增的层都可以轻易地表示恒等,这把默认的假设从 f(x)=0 变成 f(x)=x,以至于可以在训练中途插入一个初始化为空操作的层。只有在这个条件下,极端的深度,像最初的 ResNet 的 152 层,才变得可以训练。变体随后作为成本与容量的工程而来:ResNeXt 指出,加宽通道要受到二次方的惩罚,而把它们分成 g 组则使计算和参数大约都除以 g,并通过把分组卷积夹在 1×1 层之间,修复了分组的缺陷——各组彼此看不到——那些 1×1 层只以廉价的 O(c·b) 代价,在分组的 O(b²/g) 工作之上恢复了跨通道的混合。DenseNet 则朝另一个方向推进,用拼接取代残差加法,这迫使用过渡层来控制通道数,并用 GPU 内存来付账。
收尾:设计把方向盘交给搜索,然后交给规模。 最后的乐章把此前的一切重新框定为一个关于谁来做架构决策的故事。GoogLeNet 的通道分配——第三阶段 2:4:1:1 的分支比例,是通过把输入削减到 96 和 16 个通道而得到的——之所以看上去任意,只是因为自动的设计探索工具那时还不存在;甚至张量的维数也得手工声明,而现在框架会推断它们。手工设计可行,但耗费人的时间,也没有最优性的保证,而穷举搜索更糟:AnyNet 的 17 个自由参数,每个仅有两个选项,就已产生 2¹⁷ = 131,072 种组合,而训练的随机性使单次运行不可复现,所以没有学到任何一般的东西(完整的架构搜索通常极其昂贵,并且只返回单个网络,不过 EfficientNet 表明这笔投资可以有回报)。因此 Radosavovic 等人(2020)优化的是网络的分布,假定存在一般的设计规则,使用廉价的低保真代理,并比较经验误差的累积分布函数。发现是具体的:跨阶段绑定瓶颈比例和组宽度不损失准确率,宽度和深度应该随阶段增长,而最佳的瓶颈比例是 k=1——也就是说,没有瓶颈。结果是 RegNetX,在这里演示为一个 32 层的模型,g=16,通道数为 32 和 80,深度为 4 和 6,在 96×96 的 Fashion-MNIST 上训练,而不是 ImageNet。本章的最后一句话把这条轨迹再延伸一步:有了像 LAION-400m 和 LAION-5B 这样的集合,学出来的结构如今胜过内建的先验,所以可扩展性在设计原则上排在局部性和平移不变性之上——尽管从 Transformer 衍生出的收益可以回移到 CNN 中,代价是更高的计算量。
关键论点,以及支撑它们的原文
2012 年以前,视觉的进步来自手工设计的特征,而转向学出来的特征,只有在大型带标签数据集和 GPU 算力到来之后才成为可能。
作者指出,经典的流水线把 SIFT 或 SURF 描述子送入线性或核模型,学习算法被当作事后才想到的东西。后来 ImageNet(2009)提供了大约一百万张 224x224 的图像,分属 1000 个类别——比早先的数据集大出一个数量级以上,通过对搜索引擎候选结果的众包检查来标注——而 Krizhevsky 和 Sutskever 在两块各能达到 1.5 TFLOPs 的 3GB GTX 580 上运行了快速卷积,由此产生的 cuda-convnet 成为行业标准。即便如此,采用仍因缺少工具而滞后:DistBelief 和 Caffe 还不存在,Theano 缺乏功能,直到 TensorFlow 改变了局面。
“学习算法常被认为是事后才想到的东西。”
“The learning algorithm was often considered an afterthought.”
§8.1 Deep Convolutional Neural Networks (AlexNet)查看原文 →
在 AlexNet 的代价的基础上,教训是:参数预算最好花在组织成重复块的深度上——这可以说使 VGG 成为第一个真正现代的 CNN。
一项详细的分析表明,在参数数量相当的情况下,深而窄的网络明显胜过浅而宽的,其依据是这样的算术:两个 3x3 卷积触及的像素与一个 5x5 相同,而三个的参数约相当于一个 5x5。VGG-11 把它实例化为五个块,通道数翻倍到 512,共八个卷积层和三个全连接层,而因为这些块是参数化的,它定义的是整个模型家族,而不是单个网络——作者把“第一个现代 CNN”的说法呈现为可以争论的,而不是定论。
“在相当详细的分析中,他们表明深而窄的网络显著优于其浅层的对应物。”
“In a rather detailed analysis they showed that deep and narrow networks significantly outperform their shallow counterparts.”
§8.2 Networks Using Blocks (VGG)查看原文 →
把 VGG 的负担接着往下带,作者论证,过大的全连接头部才是真正的内存瓶颈,所以 NiN 干脆把它去掉了。
VGG-11 的那一个巨大矩阵在 FP32 下占据近 400MB,而当时的 iPhone 4S 内存只有 512MB,所以单是这个头部就可能超出一台设备的预算。因此 NiN 以一个通道数等于类别数的块加上全局平均池化收尾,这大幅减少了参数——代价可能是训练更久。
“首先,架构末尾的全连接层消耗了巨量的参数。”
“First, the fully connected layers at the end of the architecture consume tremendous numbers of parameters.”
§8.3 Network in Network (NiN)查看原文 →
另外 3 个论点
不是去挑一个最好的核大小,正确的做法是并行地运行几种大小,并把它们的输出拼接起来。
别的工作试图确定从 1x1 开始的哪种卷积大小更优,而 Inception 块干脆同时使用多种分支大小。回报是具体的:GoogLeNet 由三组共九个 Inception 块构成,头部带全局平均池化,赢得了 2014 年的 ImageNet 挑战赛。
“当其他工作试图确定从 $1 \times 1$ 到 $11 \times 11$ 的哪种卷积最好时,它只是把多分支的卷积拼接起来。”
“While other works tried to identify which convolution, ranging from \(1 \times 1\) to \(11 \times 11\) would be best, it simply concatenated multi-branch convolutions.”
§8.4 Multi-Branch Networks (GoogLeNet)查看原文 →
批量归一化之所以有价值,是因为它同时打包了三样东西——输入预处理、数值稳定性和正则化——而它的小批量统计量中的噪声是一个特性,而不是缺陷。
论证从普通的标准化出发:把输入放在相近的尺度上,使估计问题保持可控,也适合优化器,这就促使人们在网络内部也这样做;作者称正则化的好处是意外之喜,而不是设计目标。Teye 等人(2018)和 Luo 等人(2018)随后把批量归一化与贝叶斯先验和惩罚项联系起来,这阐明了为什么大约 50-100 的小批量注入了恰当数量的噪声、效果最好——尽管这一效应在理论上仍然刻画得很差。
“事实证明,相当出人意料地,批量归一化同时带来了这三种好处:预处理、数值稳定性和正则化。”
“As it turns out, quite serendipitously, batch normalization conveys all three benefits: preprocessing, numerical stability, and regularization.”
§8.5 Batch Normalization查看原文 →
架构决策逐步从人手中移出——先是移入带有一般规则的、被搜索的设计空间,最后移交给干脆向上扩展的模型。
GoogLeNet 的通道分配之所以看上去任意,只是因为自动的设计探索工具那时还不存在:第三阶段通过把输入削减到 96 和 16 个通道,钉出一个 2:4:1:1 的分支比例,甚至张量的维数也得手工声明,而现在框架会推断它们。手工设计可行,但耗费人的时间,也没有最优性的保证,而穷举搜索更糟——AnyNet 的 17 个自由参数,每个仅有两个选项,就已给出 2^17 = 131072 种组合,而训练的随机性使单次运行不可复现,所以没有学到任何一般的东西(完整的神经架构搜索通常极其昂贵,并且只返回一个网络,不过 EfficientNet 表明它可以有回报)。Radosavovic 等人(2020)转而优化网络的分布,比较经验误差的累积分布函数:跨阶段绑定瓶颈比例和组宽度不损失准确率,宽度和深度应该随阶段增长,而最佳的瓶颈比例原来是 k=1,也就是没有瓶颈——就像一个 32 层的 RegNetX,g=16,通道数为 32 和 80,深度为 4 和 6,在这里于 96x96 的 Fashion-MNIST 上训练,而不是 ImageNet。本章以指出像 LAION-400m 和 LAION-5B 这样的巨大集合让学出来的结构胜过内建的先验作结,所以可扩展性现在排在局部性和平移不变性之上,尽管从 Transformer 得来的收益可以回移到 CNN 中,代价是更高的计算量。
“这在很大程度上是因为,在 GoogLeNet 被提出的时候,用于网络定义或设计探索的自动工具还不存在。”
“Much of it is due to the fact that at the time when GoogLeNet was introduced, automatic tools for network definition or design exploration were not yet available.”
§8.4 Multi-Branch Networks (GoogLeNet)查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么堆叠的 3x3 核胜出
两个 3x3 卷积触及的像素与一个 5x5 相同,而三个的参数大致相当于单个 5x5。所以同样的感受野可以用额外的非线性层、而不是更宽的核来买到,这就是为什么在相同的参数预算下,由小核构成的深而窄的堆叠胜过浅而宽的。
机制 2
分组降低成本,1x1 层恢复混合
通过加宽通道来买容量,要受到二次方的惩罚,而把通道分成 g 组则使计算和参数数量都大约除以 g。分组的缺陷是各组彼此看不到,所以在前后各放一个 1x1 卷积,恢复了跨通道的混合,同时只在分组的 O(b^2/g) 工作之上付出廉价的 O(c·b) 核代价。
机制 3
恒等偏置使深度变得安全
如果扩大后的函数类不包含较小的那个,增加层数可能把模型带离目标函数,所以深度并不自动意味着进步。残差块让每个新增的层都能轻易地表示恒等,这使各个类嵌套起来,并把默认的假设从 f(x)=0 变成 f(x)=x——这就是深达 152 层的网络变得可以训练的原因。
常见误读
批量归一化之所以管用,是因为它消除了网络内部的“内部协变量偏移”。
作者把这个短语当作用词不当,并把它举为为什么指导性的直觉必须与既定的科学事实分开的首要例子——Ali Rahimi 在 2017 年 NeurIPS 时间检验奖的演讲里用它把深度学习的实践比作炼金术。经受得住的是经验性的整体:小批量统计量的正则化噪声(因此有 50-100 个样本左右的最佳点,被 Teye 等人和 Luo 等人联系到贝叶斯先验和惩罚),再加上预处理和数值稳定性。这项技术管用得极好,尽管机制仍然刻画得很差。
“然而,我们认为,把这些指导性的直觉与既定的科学事实分开是很重要的。”
“However, we believe that it is important to separate these guiding intuitions from established scientific fact.”
§8.5 Batch Normalization查看原文 →
既然深而窄胜过浅而宽,堆叠更多的层就一定会让网络更强。
只有当扩大后的函数类包含较小的那个时,额外的层才增加真正的能力;对于非嵌套的类,一个更大的类即使复杂度增加,也可能偏离目标函数。这恰恰是残差块被构建成让每个新增的层都能轻易地表现为恒等的原因——甚至可以在训练中途插入一个初始化为空操作的层——而且只有在这个条件下,极端的深度,像最初 ResNet 的 152 层,才会有回报。
“他们提出的残差网络(ResNet)的核心思想是,每个额外的层都应该更容易地把恒等函数作为它的元素之一包含进去。”
“At the heart of their proposed residual network (ResNet) is the idea that every additional layer should more easily contain the identity function as one of its elements.”
§8.6 Residual Networks (ResNet) and ResNeXt查看原文 →
第 8 章的核心概念
- 表示学习
- 让模型从数据中学习它自己的分层特征,而不是由人来设计特征提取器。
- 适用处: 需要大数据和算力;对很小的数据集,手工设计的特征加凸方法可能获胜。
- 特征工程
- 手工设计像 SIFT 或 SURF 这样的提取器,好让一个简单的分类器能在它们之上工作。
- 适用处: 在 2012 年之前占主导地位;在数据稀缺或可解释性要紧时仍然有用。
- AlexNet
- 一个赢得 2012 年 ImageNet 的 8 层 CNN:比 LeNet 更大,使用 ReLU 激活、暂退法,用 GPU 训练。
- 适用处: 以现代标准看效率低下;它巨大的全连接层主宰了内存和 FLOPs。
- 对 GPU 的需求
- 数以千计的弱小并行核心,给出比 CPU 多得多的 FLOPs 和内存带宽,这正是深度网络所需要的。
- 适用处: 优势适用于稠密的并行数学,不适用于分支多的通用控制流。
- VGG 块
- 一组带填充的 3x3 卷积加 ReLU,以一个让高和宽减半的 2x2 最大池化结束。
- 适用处: 分辨率只在池化那一步下降,所以深度不再受输入大小的 log2 所限。
- 网络中的网络(NiN)块
- 一个普通的卷积,后面跟着 1x1 卷积,在每个像素上起类似全连接层的作用。
- 适用处: 之所以管用,只是因为新增的非线性使后面的全局平均池化变得有效。
另外 20 个概念
- 全局平均池化
- 对每个通道在所有空间位置上取平均来产生 logit,而不是一个巨大的学出来的矩阵。 在分类器之前把每个通道的高和宽压缩到 1,就像在 NiN 中那样。
- 适用处: 令人惊讶地并不损害准确率,还增加了平移不变性,但可能使训练变长。 只用在头部,在 GoogLeNet 的第五个模块之后。
- Inception 块
- 四个并行的分支,带不同的核大小和池化,沿通道拼接。
- 适用处: 回避了核的选择,而不是解决它;主要的超参数是每个分支的通道分配。
- 基础模型
- 整个预训练好的模型,被重用为不同但相关的任务的组件。
- 适用处: 在此被提到,作为同一抽象趋势的后期阶段,在本章中没有展开。
- 主干、躯干与头部
- 早期的卷积摄入图像,卷积块处理它,最后一部分把特征映射到任务上。
- 适用处: 一种关于结构的命名约定;GoogLeNet 真正的贡献是躯干的设计。
- 块级的网络设计
- 用重复的多分支阶段来构建网络,其通道划分是按阶段而不是按层来调节的。
- 适用处: 在 GoogLeNet 的时代,这种调节完全是手工的,所以那些数字大体上是任意的。
- 批量归一化
- 用当前小批量的均值和标准差对层的输入做归一化,然后用学出来的参数重新缩放和平移。
- 适用处: 在全连接的情形下,小批量大小为 1 时无用;在训练模式和预测模式下行为不同。
- 层归一化
- 同样的标准化,一次只施加在一个观测上,所以完全不考虑批量。
- 适用处: 与尺度无关,训练和测试时相同,但失去了批量噪声的正则化。
- 内部协变量偏移
- 最初的论断:BatchNorm 之所以有帮助,是因为各层的值分布在训练期间发生漂移。
- 适用处: 命名有误导性,也从未被严格确立;更接近概念漂移。
- 嵌套的函数类
- 更大的架构只有在包含较小的架构时,才会可靠地有帮助。 增加容量应当严格地扩大可达的函数集,而不是把它横向移动;恒等直通使这成为可能。
- 适用处: 非嵌套的扩大,不保证更接近真值函数。 仅凭嵌套,并不能证明复杂度可以无限增长。
- 残差块
- 一个学习 f(x)-x、并通过捷径把输入加回去的块,所以恒等容易表示。
- 适用处: 要求形状匹配;当通道或分辨率改变时,需要一个 1x1 卷积。
- 分组卷积
- 把输入和输出通道分成 g 个独立的组,使每个组只在自己内部做卷积,把代价和参数削减为 g 分之一。
- 适用处: 假定两个通道数都能被 g 整除,且除非加上 1x1 卷积,否则组与组之间不会交换信息。
- ResNeXt 块
- 一个残差块,其 3x3 分组卷积夹在两个 1x1 卷积之间,后者混合通道并恢复宽度。
- 适用处: 只有当中间通道 b 小于 c 时,它才是瓶颈块。
- DenseNet
- 一种网络,其中每一层与所有前面各层的输出做拼接,而不是相加,从而重用早先的特征。
- 适用处: 特征重用在参数上便宜,在 GPU 内存上昂贵。
- 过渡层
- 一个 1x1 卷积加步幅为 2 的平均池化,在稠密块之间缩小通道数和空间大小。
- 适用处: 之所以需要,恰恰是因为每个稠密块都在不断增加 growth_rate 个通道。
- 增长率
- 稠密块中每个卷积块贡献的输出通道数,控制通道的增长。
- 适用处: 只描述新增的通道;总宽度还取决于输入通道。
- AnyNet 设计空间
- 一个由主干、躯干和头部构成的模板,躯干被分成分辨率递减的多个阶段,每个阶段由若干块构成,由深度、通道、组数和瓶颈比例来参数化。 一整个网络家族,由共享的参数来描述,并作为一个分布而不是单个模型来评判。
- 适用处: 它优化的是网络的分布,而不是像 NAS 那样优化单个实例。 只有当好的设计足够常见、能被采样到时才有用。
- 神经架构搜索
- 通过暴力搜索、遗传算法或强化学习来自动选择架构,返回单个最佳网络。
- 适用处: 通常极其昂贵,这就是本章基本略去它的原因。
- 多保真度优化
- 用廉价的近似信号来评判候选者,比如训练几个轮次后的准确率,而不是完整训练。
- 适用处: 如果早期的准确率不能给最终的准确率排序,就会失效。
- 误差的经验累积分布函数
- 从一个设计空间中采样得到的误差分布;如果一个空间的曲线优超另一个,则它胜过后者。
- 适用处: 取决于采样分布 p 和样本量。
- RegNetX 设计原则
- 共享瓶颈比例和组宽度;宽度和深度随阶段增加;最好是完全没有瓶颈。
- 适用处: 从 ImageNet 规模的视觉实验中得出,不过它在更大规模和 RegNetY 上也成立。
第 8 章划线与批注AI 陪读
“学习算法常被认为是事后才想到的东西。”
“The learning algorithm was often considered an afterthought.”
查看原文 →九个字就概括了整整一个时代的优先级。值得记住,今天的共识——架构要紧,特征是学出来的——曾经是大约六个人的边缘立场。
“偶尔靠幸运的研究生的意外发现”
“occasionally on the serendipitous discoveries by lucky graduate students”
查看原文 →一份枯燥清单里的唯一一个笑话,同时也是关于研究实际如何运作的最老实的一句话。特征工程是制度化的运气。
“然而,这种表面上的强项也是它的阿喀琉斯之踵:通用核心的制造成本非常高。”
“This apparent strength, however, is also its Achilles heel: general-purpose cores are very expensive to build.”
查看原文 →硬件一节真正的论点:深度学习获胜,不是因为 GPU 很快,而是因为它的数学碰巧笨得足以并行。与游戏产业的一次幸运的巧合。
另外 17 条批注
“如果模型参数没有被恰当地初始化,sigmoid 函数在正区间可能得到几乎为 0 的梯度”
“if the model parameters are not properly initialized, the sigmoid function may obtain a gradient of almost 0 in the positive interval”
查看原文 →这句话是混乱的——sigmoid 在极端的输入处饱和,而不是“在正区间”,而且这个分句与它想拿来和 ReLU 作的对比相矛盾。在一篇本来很细心的文字里,这是罕见的失误。
“最后两层有超过 4000 万个参数,在一个有 6 万张图像的数据集上训练),几乎没有过拟合”
“the last two layers have more than 40 million parameters, trained on a datasets of 60 thousand images), there is hardly any overfitting”
查看原文 →悄悄地是本章最深的观察之一:参数数量作为容量的度量几乎毫无用处。经典的学习理论本该禁止这个结果。
“学术界花了很多年才接受这种概念上的转变”
“it took the academic community many years to embrace this conceptual change”
查看原文 →把滞后归因于缺少工具,太宽厚了。核方法有定理和体面;CNN 有基准。该领域抵制的是口味,而不是工具。
“为什么工程师们不再用 AlexNet 报告性能基准?”
“Why do engineers no longer report performance benchmarks on AlexNet?”
查看原文 →这里最尖锐的习题,因为它不是关于 AlexNet 的。它问的是,什么使得一个基准不再有信息量——而答案同样适用于 ImageNet 本身。
“这对网络施加了一个硬性的限制:在所有维度($d$)用尽之前,最多只能有 $\log_2 d$ 个卷积层”
“this imposes a hard limit of \(\log_2 d\) convolutional layers on the network before all dimensions (\(d\)) are used up”
查看原文 →一个几何记账的论证,而不是经验性的——深度被算术卡住了脖子。以这种方式重新表述问题,使块的设计显得是不可避免的,而不是聪明的。
“后者使用的参数数量大约与三个 $3 \times 3$ 卷积相当($3 \cdot 9 \cdot c^2$),即 $25 \cdot c^2$”
“the latter uses approximately as many parameters (\(25 \cdot c^2\)) as three \(3 \times 3\) convolutions do (\(3 \cdot 9 \cdot c^2”
查看原文 →注意这个障眼法:声称两个 3×3 有同样的感受野,但参数的比较悄悄换成了三个。老实的版本是 5×5 ≈ 25,对两个 3×3 = 18——既更便宜,又更非线性。
“一个直到最近才被 Liu 等人(2022)重新审视的设计决定”
“a design decision only to be revisited recently by Liu et al. (2022)”
查看原文 →八年未经检验的默认值。这个括号是作者承认,“金标准”多半意味着没人重跑过那个实验。
“VGG 定义的是一个网络的家族,而不只是某个具体的体现”
“VGG defines a family of networks rather than just a specific manifestation”
查看原文 →真正的贡献是研究对象的转变:从发表一个模型,到发表一个模型的参数化生成器。把 arch 写成元组列表,就是这个想法缩小到可以敲出来的样子。
“不再需要生成 XML 配置文件来指定一个网络”
“It is no longer necessary to generate XML configuration files to specify a network”
查看原文 →一个安静的提醒:架构的想象力受记法的速率限制。块之所以变得可以想象,部分是因为循环变得可以书写了。
“即使是高端手机,内存也不超过 8GB”
“even high-end mobile phones sport no more than 8GB of RAM”
查看原文 →本章中最快过时的一句话——而它在为 NiN 做论证上的工作。原则比数字活得久,但请注意,动机是部署的经济学,而不是准确率。
“注意,如果没有加入的非线性,全局平均池化不会有效。”
“Note that global average pooling would not be effective, were it not for the added nonlinearities.”
查看原文 →整节承重的一句话,却是一句顺带的旁白。平均化之所以无害,只是因为 1×1 层已经做了全连接头部过去做的逐位置混合。
“当时令研究者吃惊的是,这种平均化运算并没有损害准确率。”
“What surprised researchers at the time was the fact that this averaging operation did not harm accuracy.”
查看原文 →值得坐下来体会这个意外,而不是跳过它:它意味着巨大的全连接头部多半是冗余的容量,而该领域一直在为它支付 400MB。
“它只是把多分支的卷积拼接起来”
“it simply concatenated multi-branch convolutions”
查看原文 →这一招是拒绝回答这个问题。不去选一个核大小,而是让这个选择成为可学习的通道分配——藏在一个块里的架构搜索。
“源自电影《盗梦空间》里的那个梗“我们需要更深入”
“stemming from the meme “we need to go deeper” from the movie Inception”
查看原文 →一个自信到拿一个笑话来命名它核心原语的领域。可爱,同时也是这套设计有多少是等待辩护的感觉的一个小标记。
“在选择通道数量上有大量相对任意的超参数”
“the large number of relatively arbitrary hyperparameters in terms of the number of channels chosen”
查看原文 →令人耳目一新的坦率。所有那些 192/208/48/64 的比例被讲得好像有原则似的,然后作者承认它们是暴力搜索的残余——解释是对搜索结果事后补上的。
“原始设计包含许多通过中间损失函数来稳定训练的技巧”
“the original design included a number of tricks for stabilizing training through intermediate loss functions”
查看原文 →辅助损失是在更好的优化出现之前,深度所需要的脚手架。架构史的一半是后来消失的拐杖。
“它的计算实际上比它的前辈更便宜,同时提供了更好的准确率”
“it is actually cheaper to compute than its predecessors while simultaneously providing improved accuracy”
查看原文 →本章真正的情节在这里浮现:度量不再只是准确率,而成了每 FLOP 的准确率。此后的一切读起来都是在两项目标下的优化。
读后感AI 陪读
四千万个参数,六万张图像:AlexNet 违反了容量理论
当作一个整体来读,这一章其实不是一场七种架构的博物馆之旅——它讲的是一个领域如何学会停止设计网络、开始设计网络的空间,而按时间顺序的排列就是论证。AlexNet 以一个历史论断开篇:2012 年的突破,与其说来自一个聪明的模型,不如说来自学出来的层级特征、ImageNet 规模的数据,以及算术碰巧笨得足以并行的硬件这三者的巧合。本章老实地说,学习算法曾经是“事后才想到的东西”,特征工程靠的是制度化的运气,但在把该领域转向迟缓归咎于缺少工具时,它太宽厚了;核方法有定理和体面,CNN 只有基准测试,抵制是口味的问题。AlexNet 还偷偷带进来的东西——四千万个参数、六万张图像,几乎没有过拟合——按经典的容量理论本该是非法的,而文本把它放在括号里一带而过,而不是把它标成书中最深的未解事实之一。
从这里开始,每一节都剥掉一样人们以为必不可少的东西。VGG 真正的贡献不是 3×3 的堆叠,而是发表对象的改变:一个参数化的家族,而不是某个具体的体现,可以写成一个元组列表就能敲出来——架构的想象力原来受记法的速率限制,而块之所以变得可以想象,很大程度上是因为循环变得可以书写了。NiN 去掉了全连接的头部,承重的理由是以一句顺带的旁白到来的:全局平均池化之所以无害,只是因为 1×1 卷积已经做了全连接层过去做的逐位置混合。平均化竟然没有损失准确率这个意外,值得多停留一会儿,而它得到的比这少——这意味着该领域一直在为冗余的容量支付几百兆字节。GoogLeNet 随后完全拒绝了核大小的问题,把一个设计选择变成了可学习的通道分配:藏在一个块里的架构搜索,披着听起来有原则的 192/208/48/64 比例,而作者坦率地承认那是暴力搜索的残余,解释是事后补上的。它的辅助损失是老实的泄底:架构史的一半是后来在别处被解决的优化问题的脚手架。
继续阅读
本章中段——批量归一化和层归一化——是书在方法上最好的地方,因为它把数学和记账分开,把这个层演示了两遍,然后公开收回了民间的解释:内部协变量偏移是个用词不当,而正则化和收敛的效应是真的。这是如何讲授一项其原因仍未定论的技术的典范。ResNet 随后带来了这里唯一真正理论性的想法,嵌套的函数类和朝向恒等的偏置,它把深度重新框定为你可以无风险地添加的东西,而不是你赌上一把的东西。ResNeXt 和 DenseNet 随后最好读作同一个想法在预算约束下的版本:分组卷积廉价地买来宽度,拼接以 GPU 内存为代价买来特征重用,而过渡层的存在,就是为了付这笔账。请注意在 GoogLeNet 前后发生的、从未逆转的安静转向——度量不再是准确率,而成了每 FLOP 的准确率。此后的一切都是在两项目标下的优化,这就是为什么 AnyNet/RegNet 才是本章合适的结尾,而不是附录:有 17 个自由参数,你无法搜索,所以你必须假定存在一般的设计规则,用廉价的低保真代理来检验它们,并比较误差的分布,而不是单个冠军。绑定瓶颈比例和组宽度是免费的;宽度和深度应该随深度增长。这是应用于架构本身的经验科学。
我会这样告诉读者:别去背那七个网络,去记那三个动作——用学出来的选择取代手工的选择,用一个家族取代一个模型,用一个你能度量的分布取代一个家族。读括号和承认之处,因为本章就是在那里说出关于自己的真话:八年未经检验的默认值,直到 2022 年才被 Liu 等人重新审视,任意的通道比例,BatchNorm 被误称的理由。并把收尾的论断——可扩展性胜过归纳偏置——当作本章的论点,而不是它的结论:它得到此前一切的有力支持,但它也是那种,按本章自己的证据,会持续到有人费心重跑实验为止的共识。那道问为什么没有人再用 AlexNet 做基准的习题,是正文里最尖锐的东西,因为同样的问题正等着被拿来问 ImageNet,问 FLOP 作为代价代理,也问 RegNet 本身。
在 FeedLitra 里读第 8 章,每段旁边都有这些卡片。
开始读书第 9 章:循环神经网络
RNN 中隐状态的更新究竟是如何变成可训练参数的?
第 9 章是怎样展开的AI 辅助
开篇:工具箱里的一个缺口。 本章一开头就指出,到目前为止处理的一切——表格的行、图像——都是以定长向量的形式到来的,而大量有趣的数据并非如此。作者列出了输入或输出、或两者都是序列的任务:图像描述、语音合成、音乐生成、时间序列预测、视频分析、翻译、对话、机器人控制;文档是词的序列,病历是事件的序列,视频是帧的序列。没有一个适合放进定长的槽位,所以需要另一类模型,而循环神经网络被引入为通过循环连接来捕捉序列动态的模型——一个沿时间展开的网络,在每一步重用同样的参数。从这里开始,本章搭起了记法:由链式法则从左到右分解的序列,截断我们回看多远的马尔可夫条件,一次解码一个词元,以及一个让设定具体起来的合成训练示例。这里做了一个小而重要的让步:反向的分解在数学上同样有效,所以正向的顺序是实践上的选择,有三条理由为之辩护——它很直观,它可以扩展到任意长的序列,它尊重因果结构,因为未来的事件不能塑造过去的事件,而下一个值通常可以写成当前值加噪声的函数,反过来的关系则不成立。因此有训练中要尊重时间顺序这条一贯的建议。
第一段展开与第一个转折:预测的视野,以及转向文本。 本章随后把自回归的设定一直逼到它崩坏。当真实的过去可用时,单步预测很容易;多步预测则不然,因为模型必须把自己的输出作为输入喂回去。一个小误差扰动了下一步的输入,而偏差大致按“误差加上一个常数乘以前一个误差”这种形式的递归增长。正弦波的图让这一点可见:四步的预测仍然可用,再往后几乎一文不值——这与 24 小时的天气预报比长期预报好得多是同一个原因。确立了这个极限之后,本章从合成信号转向真实的文本,而问题变得机械:对原始字符串分词,建立词表,给词元编索引。随之出现的频率统计,给出了本章的第二个论证。词频急剧下降——第十常见的词出现的次数不到第一常见的词的五分之一——而在十个最频繁的词对中,有九个只由停用词构成,只有“the time”与这本书的实际内容有关。因此更长的 n 元语法绝大多数都很罕见。计数对频繁的单个词勉强管用,超出这个范围就崩溃了,这就是用神经语言模型而不是基于计数的模型的具体理由。
第二段展开:度量质量,以及循环的修补。 在构建模型之前,本章先定下怎么评判一个模型。原始似然偏爱短文本,所以《战争与和平》的得分会比《小王子》差得多,原因与模型质量毫无关系;缺的是一个平均值。对每个词元的交叉熵取平均再取指数,就得到困惑度,它的极限读起来很干净:完美预测时为 1,当模型对确实发生的事赋予零概率时为无穷大,而均匀猜测时恰好是词表大小——一个任何有用的模型都必须超越的非平凡基线。数据加载也被规定:序列以随机偏移划分为长度为 n 的输入,目标移动一个位置。然后是结构上的回报。一个 n 阶的马尔可夫模型需要大约 |V|^n 个存储的数,所以加长上下文使参数指数增长;循环的替代方案保留一个迄今所见一切的潜在摘要 h,并在给定该摘要的条件下对下一个词元建模,代价有界。这个公式是对熟悉的 MLP 隐藏层的一处小小改动——加上前一个隐状态乘以一个循环权重矩阵——之后该层的输出就是隐状态。参数不过是输入、循环和输出权重及其偏置,在每一步重用,所以数量不随序列长度增长。一小段代码演示表明,这两个矩阵乘积等于拼接后的输入与堆叠后的权重的单个乘积,而因为循环的边只在共享参数的情况下在相邻步之间传递信息,所以展开后的网络是一个普通的前馈计算,求值顺序毫不含糊。
第三个转折:一种新的深度,和一个被坦率标明的权宜之计。 得到了有界的参数之后,本章立刻收取了代价。序列长度引入了第二种深度:第一步的输入必须穿过 T 个时间步,所以反向过程要乘上大约 T 个矩阵的链,梯度变得不稳定。提供的补救是梯度裁剪——把梯度投影到半径为 θ 的球上。其理由是一个界,而不是一个优雅的论断:在利普希茨连续性之下,目标函数的变化不会超过利普希茨常数乘以学习率乘以梯度范数,所以限制范数就直接限制了单步所能造成的损害,也限制了任何一个小批量所能主宰的程度。没有它,一个巨大的梯度可以抹掉几千次迭代,并让训练倾向于发散或损失尖峰。作者承认了代价——对真实梯度的保真度下降,下降可能更慢,以及难以分析的副作用——并称它是一个值得保留的权宜之计。在实践中,它足以让字符级训练稳定,并支持以前缀为条件的解码。值得不要过度解读:裁剪限制的是更新的大小,所以它只驯服了爆炸的那一侧;梯度消失原封不动。
收尾:详细的推导。 本章最后是回到底层去,而不是往前走。它首先讨论随机截断,这是切断时间链在理论上更有原则的方式,并报告说,朴素的固定截断至少一样管用,可能的原因有三条:短跨度的梯度已经捕捉了要紧的东西,增加的方差抵消了准确性的收益,而短程交互的模型恰恰就是我们想要的——所以固定截断甚至起到轻度正则化的作用。这些是作为可能的解释给出的,而不是实测的比较。然后针对一个无偏置的线性 RNN 详细推导了沿时间的反向传播,其中梯度原来被循环权重矩阵的高次幂主宰,视该矩阵而定,把它推向爆炸或消失。这是本章真正的诊断,而它以正确地分派补救措施收尾:截断和缓存才是解决这种不稳定性的办法,而裁剪仍然是对步长的另一道更粗糙的防线。
关键论点,以及支撑它们的原文
有序的、变长的数据,需要一类不同于前面处理的定长表格和图像的模型。
作者列出了输入、输出或两者都是序列的任务——图像描述、语音合成、音乐生成、时间序列预测、视频分析、翻译、对话、机器人控制——并指出文档、病历和视频自然地表示为词、事件或帧的序列,没有一个适合放进定长向量。
“这些需求往往同时出现:像把一段文字从一种自然语言翻译成另一种、进行对话,或控制机器人这样的任务,都要求模型既摄入又输出具有序列结构的数据。”
“These demands often arise simultaneously: tasks such as translating passages of text from one natural language to another, engaging in dialogue, or controlling a robot, demand that models both ingest and output sequentially structured data.”
Chapter 9. Recurrent Neural Networks查看原文 →
从左到右分解序列,是一个实践上的选择,而不是数学上的要求。
在语言建模的链式法则视角的基础上,作者承认反向的分解在数学上同样有效,然后论证正向的顺序很直观,可以扩展到任意长的序列,也符合因果结构:未来的事件不能塑造过去,而且我们常常可以把下一个值写成当前值加噪声的函数,反过来的关系则不成立。因此有训练时总要尊重时间顺序的建议。
“第三,我们对预测相邻的词有更强的预测模型,而对任意其他位置的词则没有。”
“Third, we have stronger predictive models for predicting adjacent words than words at arbitrary other locations.”
§9.1 Working with Sequences查看原文 →
基于计数的语言模型扛不起语言统计的重担,这就是需要神经模型的原因。
词频急剧下降——第十常见的词出现的次数不到最常见的词的五分之一——而在十个最频繁的词对中,有九个只由停用词构成,只有“the time”与这本书的内容有关。因此更长的 n 元语法大多极其罕见,所以依赖计数的方法就崩溃了,尽管计数对频繁的单个词勉强管用。
“第三,许多 $n$ 元语法出现得非常少。这使某些方法不适合用于语言建模,并促成了深度学习模型的使用。”
“Third, many \(n\)-grams occur very rarely. This makes certain methods unsuitable for language modeling and motivates the use of deep learning models.”
§9.2 Converting Raw Text into Sequence Data查看原文 →
另外 3 个论点
对词元的交叉熵取平均再取指数,得到一个与长度无关的质量度量。
原始似然偏爱短文本,所以《战争与和平》的得分会比《小王子》差得多,原因与模型质量毫无关系——缺的是一个平均值。由此得到的困惑度有可读的极限:完美预测时为 1,当模型对确实发生的事赋予零概率时为无穷大,而均匀猜测时恰好是词表大小,这给出了一个任何有用的模型都必须超越的非平凡界。
“这使得不同长度文档上的表现可以比较。”
“This makes the performance on documents of different lengths comparable.”
§9.3 Language Models查看原文 →
在熟悉的隐藏层公式上加一个循环项,就得到一个参数数量不随序列长度增长的模型。
与 MLP 的隐藏层相比,循环层只是多加了前一个隐状态乘以一个权重矩阵,之后该层的输出是一个隐状态;参数不过是输入、循环和输出权重及其偏置,在每一步重用。一小段代码演示表明,这两个矩阵乘积等于拼接后的输入与堆叠后的权重的一个乘积,而因为循环的边只在共享参数的情况下在相邻步之间传递信息,所以展开后的网络是一个普通的前馈计算,顺序毫不含糊。
梯度裁剪是公认的权宜之计,但仍然值得,因为它限制了单次更新所能造成的伤害。
在利普希茨连续性之下,目标函数的变化不会超过利普希茨常数乘以学习率乘以梯度范数,所以把梯度投影到半径为 theta 的球上,直接限制了一步的损害,也限制了任何一个小批量的影响;没有它,一个巨大的梯度可以抹掉几千次迭代的进展,并让训练陷入发散或损失尖峰。代价是对真实梯度的保真度下降,以及可能更慢的下降,而作者承认副作用难以分析。
“说清楚,这是个权宜之计。”
“To be clear, it is a hack.”
§9.5 Recurrent Neural Network Implementation from Scratch查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
误差在 k 步预测中滚雪球
由于没有未来的观测可用,多步预测必须把自己的输出喂回作输入,所以一步上的小误差扰动了下一步的输入,而偏差大致按“bar 加 c 乘以前一个”的递归增长。作者的正弦波图表明,4 步的预测仍然可用,再往后几乎一文不值,而 24 小时的天气预报比更长的视野好得多。
机制 2
隐状态胜过更长的上下文窗口
一个 n 阶的马尔可夫模型需要大约 |V|^n 个存储的数,所以加长上下文使参数和存储呈指数增长。作者转而保留一个迄今所见一切的潜在摘要 h,并在给定 h 的条件下对下一个词元建模,这使代价保持有界;有了足够强大的更新函数,潜变量模型是精确的,尽管摘要本身的存储可能变得昂贵。
机制 3
时间深度使梯度爆炸或死掉
序列长度增加了第二种深度:第一步的输入必须穿过 T 个时间步,所以反向过程要乘上大约 T 个矩阵的链。通过推导一个无偏置的线性 RNN,作者表明梯度被循环权重矩阵的高次幂主宰,视该矩阵而定,把它推向爆炸或消失。
常见误读
既然裁剪保持了训练的稳定,它一定解决了长序列造成的梯度问题。
裁剪只限制更新的大小,所以它驯服了梯度爆炸,并让字符级训练和以前缀为条件的生成可以运作;消失的那一侧原封不动,这就是作者明确推导循环矩阵幂的不稳定性、并把截断和缓存(而不是裁剪)当作解决它的办法的原因。
“说清楚,这是个权宜之计。”
“To be clear, it is a hack.”
§9.5 Recurrent Neural Network Implementation from Scratch查看原文 →
随机截断是切断时间链在理论上更有原则的方式,所以应该比简单地在固定步数之后截断训练得更好。
作者报告说,常规截断至少一样管用,并给出三个可能的原因:短跨度的梯度已经捕捉了要紧的东西,随机化带来的额外方差抵消了准确性的收益,而短程交互的模型恰恰就是我们想要的,所以固定截断甚至起到轻度正则化的作用。这些是作为可能的解释给出的,而不是实测的比较。
“因此,常规截断的沿时间反向传播有一种轻微的正则化效应,这可能是可取的。”
“Hence, regularly truncated backpropagation through time has a slight regularizing effect that can be desirable.”
§9.7 Backpropagation Through Time查看原文 →
第 9 章的核心概念
- 循环神经网络
- 一种带有环的网络,环把信息从一个时间步带到下一个,并在每一步重用同样的参数。 一种网络,其每一步的隐状态由当前输入加上前一个隐状态计算而来,全程使用同样的权重。
- 适用处: 不是处理变长的唯一办法;CNN 和 Transformer 也可以对序列建模。 在很长的序列上做反向传播会引起梯度问题;适用于带有有序时间步的序列数据。
- 自回归模型
- 一种根据同一信号较早的值来预测其下一个值的模型。
- 适用处: 原始历史随 t 增长,所以除非使用窗口或摘要状态,输入长度是变化的。
- 马尔可夫条件
- 一个假设:只有最近几步要紧,所以更旧的历史可以被丢弃而不损失预测能力。
- 适用处: 对文本通常只是近似为真;更多的上下文仍有帮助,但收益迅速递减。
- 序列模型
- 对整个序列联合概率的模型;当词元是词时,称为语言模型。
- 适用处: “语言模型”这个术语甚至也用于非语言的序列数据。
- 潜在自回归模型
- 一种保留过去的未观测的滚动摘要、并随每次预测一起更新它的模型。
- 适用处: 摘要状态从不被观测,所以必须间接地学习。
- 独立同分布假设
- 这里放宽了:整个序列是独立抽取的,但同一个序列内部的各项彼此并不独立。
- 适用处: 序列内部既不要求独立性,也不要求平稳性,只要求整个序列上有固定的分布。
另外 17 个概念
- 提前 k 步预测
- 预测最后一个观测值之后的 k 个时间步,并把你自己的预测重用为输入。
- 适用处: 只对小的 k 可靠;超过几步,输出可能衰减成一个常数。
- 误差累积
- 每个预测出来的输入都带着误差,下一步会把它放大,所以偏差像滚雪球一样增长。
- 适用处: 特别是当模型输出被喂回作输入时出现。
- 词元
- 模型消费的、不可再分的最小文本单元;一个时间步容纳一个词元。
- 适用处: 什么算作词元是一个设计选择:字符、词,或词片。
- 词表
- 一个字典,把每个不同的词元映射到一个唯一的整数索引,未知词元送往一个特殊的词元。
- 适用处: 罕见的词元可能被丢弃,并替换为“<unk>”。
- 齐普夫定律
- 词频按其排名的幂次下降,在双对数图上给出一条直线。
- 适用处: 对 n 元语法也成立,但指数更小,取决于序列长度。
- 拉普拉斯平滑
- 给所有计数加上一个小常数,使没见过的词组合获得非零的概率。
- 适用处: 原始,并且在许多 n 元语法极其罕见时不适用。
- 困惑度
- 一种给语言模型打分的方式,看它对实际的下一个词元有多惊讶。 每个词元平均交叉熵的指数;把它读作等可能的下一个词元选项的有效数量。
- 适用处: 原始的序列似然难以解释和比较,这促成了这一度量。 只有当模型共享词表和分词方式时才可比;均匀预测给出的困惑度等于词表大小。
- 隐状态
- 一个向量,存储直到上一个时间步为止的序列信息,并供给当前步的计算。
- 适用处: 不同于隐藏层;它只能由先前时间步的数据计算出来。
- 带随机偏移的序列划分
- 每个轮次丢弃随机数量 d 个开头的词元,然后把其余的切成长度为 n 的子序列,这样就会看到不同的窗口。
- 适用处: 它并不对所有可能的子序列给出完全均匀的分布;完整句子的样本会打破定长分批。
- 字符级语言模型
- 一种预测下一个字符而不是下一个词的模型,所以词表很小。
- 适用处: 在这里选用它是为了简化训练;某一步的损失只取决于迄今所见的字符。
- 独热编码
- 把一个词元索引表示为长度等于词表大小的向量,其中只有一个非零项。 把每个词元表示为一个全零的向量,只在该词元的索引处有一个 1。
- 适用处: 之所以需要,是因为词表索引不携带相似性信息;代价随词表大小增长。 等价于一个固定的逐词元嵌入;可学习的嵌入可以取代它。
- 梯度裁剪
- 把过大的梯度重新缩放到固定半径的球上,同时保持其方向。
- 适用处: 只缓解梯度爆炸;对梯度消失毫无作用,并使更新偏离真实梯度。
- 沿时间的反向传播
- 一次一个时间步地展开 RNN,并把每个共享参数的梯度在它出现的每个位置上求和。 在展开的 RNN 上运行反向传播,逐时间步地计算并存储梯度。
- 适用处: 在长序列上精确地做既昂贵又不稳定,所以改用截断或随机化的变体。 适用于带隐状态的序列模型;在长序列上做完整的 BPTT 在计算上是不可行的。
- 预热期
- 把一个前缀送过模型来建立隐状态,而不输出预测。
- 适用处: 只在摄入用户提供的前缀字符时适用,在生成开始之前。
- 时间步的截断
- 在固定或随机的步数之后切断反向链,实践中靠分离梯度来做到。
- 适用处: 常规截断是标准做法;随机截断在实践中并没有好多少。
- 梯度消失与梯度爆炸
- 反复乘以循环权重矩阵,使梯度缩小到零或爆炸。
- 适用处: 由循环矩阵的特征值小于或大于 1 所驱动;这里甚至对线性、无偏置的 RNN 也有所展示。
- 链式法则
- 沿计算图组合偏导数,这里是逆着箭头的方向遍历。
- 适用处: 需要 prod 运算符来处理形状不同的矩阵、向量和标量。
第 9 章划线与批注AI 陪读
“正是神经网络的前馈性质,使计算的顺序毫不含糊”
“it is the feedforward nature of neural networks that makes the order of computation unambiguous”
查看原文 →漂亮的先发制人——作者在读者开口之前就点出了读者的反对意见,然后用“以精确的方式被定义”把它化解。有点披着安抚外衣的含糊其辞。
“它们往往仍然可以被表示为由定长向量组成的变长序列”
“they can often nevertheless be represented as varying-length sequences of fixed-length vectors”
查看原文 →这一行就是整章。诀窍不是逃脱定长——而是把它降一级,从样本降到词元。
“RNN 最近已经把相当大的市场份额让给了 Transformer 模型”
“RNNs have recently ceded considerable market share to Transformer models”
查看原文 →市场份额——对架构来说是个古怪的商业比喻。对过时很老实,同时仍然让你读下去;随后的理由是教学上的,不是技术上的。
另外 17 条批注
“如果我们不相信序列中的元素是相关的,我们一开始就不会费心把它们建模成序列。”
“If we did not believe that the elements in a sequence were related, we would not have bothered to model them as a sequence in the first place.”
查看原文 →循环,但循环得有用:建模的选择本身就是对世界的一个论断。数据不会宣布它是个序列;是我们决定它是。
“我们只要求这些序列本身是从某个关于整个序列的固定底层分布中采样的”
“we require only that the sequences themselves are sampled from some fixed underlying distribution over entire sequences”
查看原文 →独立同分布假设没有被放弃,只是被推高了一级——从时间步推到整个文档。下面每一个“灵活”的结果,都是靠这唯一幸存的刚性买来的。
“毕竟我们每天都在阅读文本,而这个过程是由我们预期哪些词会出现的能力引导的”
“After all we all read text every day, and this process is guided by our ability to anticipate which words”
查看原文 →从左到右的第一个理由,坦率地说是人类中心的——是我们的直觉,不是数学。令人钦佩地坦率,认为思维的方便也算一个理由。
“在某些情形下,我们可以找到 $x_{t+1} = f(x_t) + \epsilon$,其中 $\epsilon$ 是某种加性噪声,而反过来则不成立”
“in some cases, we can find \(x_{t+1} = f(x_t) + \epsilon\) for some additive noise \(\epsilon\), whereas the converse is not true”
查看原文 →清单上唯一真正非任意的理由:噪声的不对称性,也就是因果方向。前面两个理由是人体工学;这一个是物理学。
“不幸的是,在这种情况下,我们惨败了。”
“Unfortunately, in this case we fail spectacularly.”
查看原文 →教科书安排了自己的失败,这是到目前为止最有教益的一段。单步预测看起来很漂亮,恰恰因为它们从没被要求立足于自己的输出。
“未来 24 小时的天气预报往往相当准确,但超出这个范围,准确率就迅速下降”
“weather forecasts for the next 24 hours tend to be pretty accurate but beyond that, accuracy declines rapidly”
查看原文 →误差累积的分析其实是关于任何自回归生成器的一课——包括今天写文本的那些。让一个模型吃自己的输出足够久,它就会漂向一个常数,或陷入循环。
“然而,它们携带意义,在使用现代的、基于 RNN 和 Transformer 的神经模型时,没有必要把它们过滤掉”
“However, they carry meaning and it is not necessary to filter them out when working with modern RNN- and Transformer-based neural models”
查看原文 →为整整一个 NLP 手艺时代写的安静的讣告。停用词表是对弱模型的让步,不是关于语言的事实。
“在十个最频繁的词对中,有九个都是由停用词构成的,只有一个与这本书实际相关”
“Out of the ten most frequent word pairs, nine are composed of both stop words and only one is relevant to the actual book”
查看原文 →二元语法表承担了论证的工作:爬上 n 元语法的梯子,内容几乎浮不出来。频率与意义近乎正交。
“不同的 $n$ 元语法的数量并不那么大。这给了我们希望,语言中有相当多的结构”
“the number of distinct \(n\)-grams is not that large. This gives us hope that there is quite a lot of structure in language”
查看原文 →漂亮的推断:被观察到的组合空间的稀疏性,被读作约束的证据,而不是数据不足的证据。这个反转就是学习的全部理由。
“它需要理解文本,而不只是生成语法上合理的内容”
“it would need to understand the text rather than just generate grammatically sensible content”
查看原文 →是在那条界线变得模糊之前写的。2021 年代的一个警告,如今读起来像是一个该领域从未真正解决、只是跑过了的问题。
“I want to eat grandma”是一句相当令人不安的话,而“I want to eat, grandma”就温和得多”
“I want to eat grandma” is a rather disturbing statement, whereas “I want to eat, grandma” is much more benign”
查看原文 →这个笑话偷偷带进了一个真正的要点:模型的工作是在几种人类甚至从不觉得有歧义的读法之间做裁决。
“这完全忽略了词的意义。例如,“猫”和“猫科动物”应该出现在相关的上下文里”
“this entirely ignores the meaning of the words. For instance, “cat” and “feline” should occur in related contexts”
查看原文 →这才是对计数的真正控诉——不是数据稀缺,而是计数没有任何相似性的机制。一切都是互不相关的原子。
“我们在决定下一个选哪个词元时,所拥有的真实选项数的几何平均的倒数”
“the reciprocal of the geometric mean of the number of real choices that we have when deciding which token to pick next”
查看原文 →这一节里最好的一句话。困惑度不再是一个公式,而成了你有多困惑的计数,单位是分支。
“这提供了一个非平凡的上界,任何有用的模型都必须超越它”
“this provides a nontrivial upper bound that any useful model must beat”
查看原文 →值得钉住:老实的基线是词表大小。在你知道 |V| 之前,任何报告出来的困惑度都毫无意义。
“丢弃前 $d$ 个词元,其中 $d\in [0,n)$ 是均匀随机采样的”
“discard the first \(d\) tokens, where \(d\in [0,n)\) is uniformly sampled at random”
查看原文 →一个优雅的小窍门——随机的相位偏移让你在各轮次中免费得到全部 n 种对齐。尽管习题立刻承认它并不真正均匀。
“对于 (9.4.1) 中足够强大的函数 $f$,隐变量模型并不是一个近似。”
“For a sufficiently powerful function \(f\) in (9.4.2), the latent variable model is not an approximation.”
查看原文 →本章的支点。随 n 的指数级参数膨胀被换成了一个递归函数——原则上是无损的,代价只是搬到了 h 的容量里。
“严格来说,隐状态是我们在给定步骤所做任何事情的输入”
“Hidden states are technically speaking inputs to whatever we do at a given step”
查看原文 →关键的重新框定:隐状态不是一个层,而是你自己制造的一个输入。领域里的一个命名冲突,在这里被悄悄理清了。
读后感AI 陪读
负担不会消失,只会搬家:追踪它们去了哪里
当作一个整体来读,这一章是一个关于搬迁而不是逃脱的论证,而且老实到展示了它自己的接缝。它一开篇就把序列数据与前面各章的定长表格和图像输入对立起来,而关键的让步来得很早:序列可以被当作由定长向量组成的变长序列来处理。定长从未被击败,只是被降了一级——从样本降到词元。同样的动作贯穿始终。独立同分布假设不是被放弃,而是从时间步推高到整个文档,此后每一个灵活性的宣称,都是靠这唯一幸存的刚性买来的。n 元语法的指数级参数膨胀,换成了单个递归函数 f,伴随着一个惊人的承认:对于足够强大的 f,隐变量模型根本不是一个近似——代价只是搬到了隐状态的容量里。甚至隐状态本身也被重新框定:不是一个层,而是你给自己制造的一个输入。本章的思想脊梁,就是一连串这样的搬迁,最尖锐的读法,是追踪每一项负担落在了哪里,而不是接受它消失了。
展开是有意安排的。符号、自回归分解、马尔可夫条件和从左到右的解码排在最前,从左到右的动机按体面程度递增的顺序排列:我们自己的阅读习惯(坦率地说是人类中心的,也被坦白地如此标注),方便,最后是那个真正非任意的理由——加性噪声的不对称性,也就是说,因果方向。两条人体工学,加一条物理学。然后教科书安排了自己的失败,这是它最好的教学本能。合成数据上的单步预测看起来很漂亮,恰恰因为它们从不被要求立足于自己的输出;k 步的图在大约四步之后就衰减了,而天气预报的类比把这个教训推广到远远超出本章。让任何自回归生成器吃自己的输出足够久,它就会漂向一个常数或陷入循环——这个诊断恰好适用于今天的文本模型,却是写得好像在谈一个玩具。
继续阅读
文本处理一节随后做了安静的历史工作。分词、建立词表、索引,再看频率结构:齐普夫定律对一元语法和 n 元语法都成立,二元语法表几乎独自承担了论证,因为十个最频繁的词对中有九个是停用词的组合。频率与意义近乎正交。关于停用词携带意义、对现代模型不必过滤的旁白,是为一个 NLP 手艺时代写的一行讣告——那些列表是对弱模型的让步,从来不是关于语言的事实。然而对计数的决定性控诉,不是数据稀缺,而是没有任何相似性的机制:计数把“猫”和“猫科动物”当作互不相关的原子。反过来,关于不同的 n 元语法远少于组合空间所允许的观察,被读作语言约束的证据,而不是数据不足的证据,这个反转就是整个“学习而非制表”的理由。“我想吃奶奶”的笑话偷偷带进了真正的岗位说明:在人类从不觉得有歧义的几种读法之间做裁决。
困惑度得到了本章最好的一句话——每一步选择下一个词元时真实选项数的几何平均的倒数——这把一个公式变成了一个分支混乱度的单位。也请把随之而来的评论钉住:对词表做均匀猜测,是任何有用的模型都必须超越的一个非平凡的上界,所以一个报告出来的困惑度,在你知道词表大小之前毫无意义。随后的划分方案,丢弃一个均匀随机的 d 个词元的偏移,是一个优雅的技巧,让你在各轮次中免费得到全部 n 种对齐,而习题立刻承认它并不真正均匀——这是本章普遍愿意标出自己近似之处的一个小例子。
最后的乐章把序列长度当作深度的一条新轴,并为此付出代价。沿时间的反向传播产生 O(T) 次矩阵乘积,循环权重矩阵的高次幂,以及消失或爆炸的梯度;对无偏置线性 RNN 的详细推导让机制变得可见,而不是被断言。梯度裁剪,投影到半径为 theta 的球上,被正确地呈现为一个权宜之计:它限制了单步能造成的损害,却对梯度消失无能为力,这正是为什么本章必须另外论证随机截断并不胜过常规截断,以及为什么截断加缓存才承担了真正的重担。裁剪足以让字符级训练和以前缀为条件的解码保持稳定,这是一个关于工程容忍度的结果,而不是关于问题被解决了——没解决的那一半,正是 LSTM 和 GRU 的章节要处理的。
我会这样告诉读者:承认 RNN 已经把相当大的市场份额让给了 Transformer——一个古怪的商业比喻——是教学上的老实,而不是技术上的理由,这没问题,因为留下来的不是架构,而是概念上的装备。序列是一个建模的决定,而不是数据的属性(那句循环但有用的话:如果我们不相信元素是相关的,我们一开始就不会费心把它们建模成序列);困惑度作为分支因子;自喂式生成下误差的累积;用递归换参数数量;由重复相乘引起的梯度病态。这一切都可以迁移。有两点提醒。第一,关于前馈结构使计算顺序毫不含糊、因为它“以精确的方式被定义”的安抚,是披着先发制人外衣的含糊其辞——一次执行得很好的动作,在你之前说出你的反对意见,然后拒绝回答。第二,关于一个真正好的模型需要理解文本、而不仅仅是产出语法上合理的内容的评论,是在那条界线变得模糊之前写的;它现在读起来像是一个该领域从未解决、只是跑过了它的问题。为了它的搬迁和它安排的失败去读这一章,并不断追问它训练你问的那个问题:当一个困难从纸面上消失时,它实际上去了哪里?
在 FeedLitra 里读第 9 章,每段旁边都有这些卡片。
开始读书第 10 章:现代循环神经网络
GRU 的重置门和更新门如何对应到 LSTM 的三个门?
第 10 章是怎样展开的AI 辅助
开篇:一个没完成的论证。 本章不是从一个新模型开始,而是从普通 RNN 遗留下来的一笔债开始。梯度裁剪早先作为不稳定训练的补救办法被引入,作者现在重新翻出这个案子,表明它只是一半的补救:裁剪限制了爆炸的梯度,却对消退的梯度毫无作用。因此长程依赖仍然学不到,对旧架构怎么调都改变不了这一点。这个框定很重要,因为它设定了本章的逻辑——问题是结构性的,所以答案也必须是结构性的。LSTM 作为这个答案到来,它的决定性特征不是门本身,而是它们守护的记忆单元:一个沿权重为 1 的自环向前携带的内部值,只被门选择加进来或冲掉的东西修改。因为状态大多原封不动地传下去,误差信号可以完好无损地往回穿过许多步。作者通过取极限来证明这一点——遗忘门钉在 1,输入门钉在 0,单元的值就可证明地永远不变。值得注意这被多么小心地标为理想化:在训练好的网络里,门取软的中间值,所以梯度的保持取决于模型是否学会了合理的保留与冲掉的时机。认为 LSTM 彻底“解决”了梯度消失的常见读法,夸大了本章实际的论断。GRU 随后作为同一想法的精简版本到来,保留了门控的逻辑,活动部件更少。
展开:沿两条轴扩展架构。 有了门控,GRU 的代码也训练过之后,本章不再改进单元,而开始重新安排网络。第一个动作是深度。这里作者纠正了一个诱人的误读:RNN 看上去已经很深,因为第一步的输入在到达较晚的预测之前,要通过循环层的 T 次应用。但那是沿时间的深度;从任何单一步的输入到输出,中间只隔着一次变换。复杂的同一步内的关系需要更多,这就是堆叠层所提供的。第二个动作是朝另一个方向沿序列看。双向 RNN 被呈现为一个取决于任务的选择,而不是免费的升级,论证是通过填空句子进行的,其中空白之后的词决定哪个填充物是合理的——“not”适合一种后续而不适合另一种。右侧的上下文在填充被掩码的位置或编码一个序列时确实有帮助,但当下一个词元就是要预测的东西时,它就根本不可用,而且这样的模型训练起来还很昂贵。作者在确立的原则是,架构应当跟随任务的信息结构。
转折:从对序列建模到对序列做映射。 本章的支点出现在问题本身改变形状的时候。语言建模预测一个序列的下一个元素;机器翻译把一个序列映射到另一个不同长度、位置之间没有对齐的序列。这种重新框定立刻产生了实际的需求,本章按顺序走过它们:英—法的句对必须被分词,然后被填充或截断成等长的小批量。然而,填充引入了一个新的危险——填充词元不携带目标信息,所以把它们算进损失,就会奖励模型去预测填充物。修法是带掩码的损失:把每个目标位置与填充 id 比较,把被掩码的位置置零,只对真正的词元取平均。这是本章习惯的一个很好的例子:让一个工程上的方便造成问题,然后明确地为之付账。
回答它的架构。 编码器—解码器接口被引入为不对齐映射的抽象:编码器把变长的输入压缩成一个固定形状的状态,解码器消费这个状态。具体的实例是一个 RNN seq2seq 模型,带 GRU 编码器,以及一个在每个时间步把编码器的上下文摘要与自己的输入拼接起来、初始状态取自编码器的解码器。作者在这里最能澄清问题的动作是泄气式的——想象把编码器删掉,剩下的是一个根据前面的词元一次发出一个词元的模型,也就是说,一个普通的语言模型。解码器没有什么特别的;它是一个条件语言模型,而拼接的上下文就是条件作用变得可见的地方。训练使用教师强制,喂入真实的前一个目标,而不是模型自己的输出,数据准备那一步的带掩码损失在这里适用。
收尾:评估,然后搜索。 建好并训练了模型之后,本章需要一种评判其输出的办法,而 BLEU 提供了它:n 元语法的匹配,按精确率打分。作者明确指出由此产生的漏洞——很短的预测只有很少的 n 元语法可以出错,所以精确率可以逼近它的最大值,而目标的大部分都没有被翻译出来。BLEU 靠把精确率乘以一个基于目标长度与预测长度之比的指数惩罚来堵上这个漏洞,使提早停止成为输家策略。最后一节随后从打分转向解码,并把各种选项排成一个用计算量标价的谱系。贪心搜索在每一步取局部最可能的词元,便宜,但不保证找到最可能的整个序列。穷举搜索是最优的,但对于 10,000 的词表和长度 10,需要大约 10^40 次打分,而贪心只需 10^5。束搜索占据实用的中间地带:每一步保留 k 个候选,代价大约是 k·|Y|·T',并用一个按长度归一化的得分给最终候选排名。本章以老实而不是凯旋的调子结束——束搜索仍然是一种启发式,贪心搜索是 k = 1 的特例,所以束宽是实践者调节的一个旋钮,而不是一个被解决的问题。
关键论点,以及支撑它们的原文
梯度裁剪从来不是长程学习的真正解药:它防止梯度爆炸,却对它们消退无能为力,所以需要改变架构。
作者回忆说,书中早先为普通 RNN 引入的裁剪,是一个生硬的启发式,只是限制梯度的大小;它没有触及梯度消失问题。这个未解决的缺口,正是本章用来引出门控架构的动机。
“尽管这个权宜之计有效,它仍然留下了梯度消失的问题。”
“Despite the efficacy of this hack, it leaves open the problem of vanishing gradients.”
Chapter 10. Modern Recurrent Neural Networks查看原文 →
紧接着这个缺口,补救是结构性的:一个只是沿着权重为 1 的环向前携带的状态,正是让梯度能够幸存许多时间步的东西。
作者通过取极限情形来论证——如果遗忘门永久为 1、输入门永久为 0,那么内部值可证明地在所有时间步都不变,所以什么都不会衰减。作者指出这是一个理想化的情形,因为真实的行为取决于门学到了什么。
“直观地说,记忆单元避免了梯度消失问题,办法是让每个记忆单元内部状态中的值,沿着一条权重为 1 的循环边,在许多相继的时间步中层层传递。”
“Intuitively, the memory cell avoids the vanishing gradient problem by keeping values in each memory cell’s internal state cascading along a recurrent edge with weight 1 across many successive time steps.”
Chapter 10. Modern Recurrent Neural Networks查看原文 →
把 RNN 读作已经“深”只对了一半:它沿时间是深的,但从输入到输出是浅的,这就是要堆叠层的原因。
作者指出,第一个时间步的输入在影响较晚的预测之前,要通过循环层的 T 次应用——沿时间轴有很多深度——然而在任何单一步上,输入与输出之间只隔着一次变换。因此,表达复杂的同一步内的关系,需要额外堆叠的层。
“然而,我们往往还希望保留表达某个给定时间步的输入与同一时间步的输出之间复杂关系的能力。”
“However, we often also wish to retain the ability to express complex relationships between the inputs at a given time step and the outputs at that same time step.”
§10.3 Deep Recurrent Neural Networks查看原文 →
另外 3 个论点
朝序列的另一个方向看,是否应该使用未来的上下文,是任务的性质,而不是免费的升级。
作者用填空的句子,其中空白之后的词决定哪个填充物是合理的——“not”适合一种后续而不适合另一种——表明右侧的上下文对填充被掩码的词元和对编码确实要紧,而当任务是预测下一个词元时它就不可用。作者还指出,训练这样的模型因为梯度链很长而代价高昂。
“双向 RNN 主要用于序列编码,以及在给定双向上下文的情况下估计观测。”
“Bidirectional RNNs are mostly useful for sequence encoding and the estimation of observations given bidirectional context.”
§10.4 Bidirectional Recurrent Neural Networks查看原文 →
在序列到序列的解码器里,没有发生什么特别的事:它就是一个关于目标的语言模型,只不过碰巧以编码后的源为条件。
作者的推理是在思想中把编码器删掉:剩下的是一个根据前面的词元一次发出一个词元的模型,也就是一个普通的语言模型。实现通过在每个时间步把编码器的上下文摘要与解码器的输入拼接,并用编码器初始化解码器的状态,把条件作用变得明确。
“注意,如果我们忽略编码器,序列到序列架构中的解码器,行为就和普通的语言模型一样。”
“Note that if we ignore the encoder, the decoder in a sequence-to-sequence architecture behaves just like a normal language model.”
§10.7 Sequence-to-Sequence Learning for Machine Translation查看原文 →
在预测时,搜索策略处于一个谱系之上,而束搜索是用可调节的束宽买来的实用中间点。
作者首先指出,每一步取局部最可能的词元,不保证得到最可能的整个序列,然后给各种替代方案标价:词表 10,000、长度 10 时,穷举搜索大约需要 10^40 次打分,而贪心为 10^5,束搜索则通过每步保留 k 个候选、并用按长度归一化的得分给最终候选排名,代价大约是 k·|Y|·T'。作者强调它仍然是一种启发式,贪心搜索是 k=1 的情形。
“不幸的是,不能保证贪心搜索会给我们这个序列。”
“Unfortunately, there is no guarantee that greedy search will give us this sequence.”
§10.8 Beam Search查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么记忆单元让梯度保持存活
单元不是每一步都通过一个权重矩阵重写它的状态,而是在权重为 1 的自环上携带一个内部值,只让乘法门决定加进来或冲掉什么。因为状态大多原封不动地传下去,误差信号可以往回穿过许多步而不萎缩;在遗忘门为 1、输入门为 0 的极限情形下,状态恰好保持不变。
机制 2
在损失中把填充置零
等长的小批量是靠追加填充词元做出来的,这些词元不携带真实的目标信息,所以把它们算进去,就会奖励模型去预测填充物。因此训练损失通过把每个目标位置与填充词元 id 比较来构造一个掩码,把被掩码的位置乘以零,只对真正的词元取平均。
机制 3
为什么 BLEU 惩罚过短的输出
BLEU 按精确率奖励匹配上的 n 元语法,而很短的预测只有很少的 n 元语法可以出错,所以精确率可以达到最大值,而目标的大部分却缺失了。因此 BLEU 把精确率乘以一个基于目标长度与预测长度之比的指数惩罚,这样靠提早停止作弊,会降低最终的分数。
常见误读
LSTM 的记忆单元彻底解决了梯度消失,所以带门的 RNN 可以学习任意长的依赖。
这个保证只在作者为了直觉而构造的理想化极限中成立——遗忘门钉在 1,输入门钉在 0。在训练好的模型里,门取介于其间的软值,所以梯度的保持取决于网络是否学会了合理的保留与冲掉的时机,而非常长的序列仍然代价高昂。
“直观地说,记忆单元避免了梯度消失问题,办法是让每个记忆单元内部状态中的值,沿着一条权重为 1 的循环边,在许多相继的时间步中层层传递。”
“Intuitively, the memory cell avoids the vanishing gradient problem by keeping values in each memory cell’s internal state cascading along a recurrent edge with weight 1 across many successive time steps.”
Chapter 10. Modern Recurrent Neural Networks查看原文 →
既然更多的上下文只会有帮助,双向 RNN 就是更好的默认选择,预测下一个词元也应该用它。
双向模型只有在看到整个序列之后才产生它的输出,这使它适合编码和填充被掩码的位置,却在恰好需要预测未来词元时无法使用;它的训练代价也很高。这个选择跟随的是任务的信息结构。
“双向 RNN 主要用于序列编码,以及在给定双向上下文的情况下估计观测。”
“Bidirectional RNNs are mostly useful for sequence encoding and the estimation of observations given bidirectional context.”
§10.4 Bidirectional Recurrent Neural Networks查看原文 →
第 10 章的核心概念
- 记忆单元
- 一种取代普通循环节点的复合单元,在权重为 1 的自环上持有一个内部状态。
- 适用处: 只有当门学会了有用的保留/冲掉时机才有帮助;在长序列上仍然代价高。
- 乘法门
- 取 sigmoid 值的开关,决定什么进入状态、什么被遗忘、什么作为输出离开。
- 适用处: 门的值落在 (0,1) 之内,所以它们是软化而不是硬切换信息流。
- 门控循环单元(GRU)
- 一种更轻的门控单元,只有重置门和更新门,通常同样准确但更快。
- 适用处: 没有单独的记忆单元状态;用表达力换取速度。
- 双向 RNN
- 向前和向后读取一个序列,使每个输出都能看到过去和未来的词元。
- 适用处: 需要整个序列,所以适合标注而不是实时生成。
- 深度循环神经网络
- 堆叠的 RNN 层,每一层的输出序列送入下一层的输入,在时间和输入到输出两个方向上都有深度。
- 适用处: 常见的深度只有 1 到 8 层,而收敛需要仔细地调学习率和裁剪。
- 双向循环神经网络
- 两个单向 RNN 在同一输入上朝相反的方向运行,它们的输出在每个时间步拼接起来。
- 适用处: 适用于编码和填充被掩码的词元,不适用于从左到右的语言建模;训练代价高。
另外 10 个概念
- 序列到序列问题
- 把一个序列映射到另一个长度和词序可能不同的序列的任务,比如翻译或问答。
- 适用处: 由不对齐的句对来定义;需要成对的源/目标数据,而不是单一的文本流。
- 截断与填充
- 通过追加一个填充词元或切掉多余的词元,强制小批量中的每个序列都有相同的长度。
- 适用处: 需要记录真实的源长度,因为后面有些模型必须忽略填充。
- 编码器—解码器架构
- 一个网络把变长的输入压缩成一个状态;第二个网络把那个状态展开成变长的输出。
- 适用处: 当输入和输出长度不同、词元不对齐时需要。
- 上下文变量
- 对所有编码器隐状态的固定形状的摘要,通常只是最后一个。
- 适用处: 单个固定向量会成为长输入的瓶颈,这促成了第11章的注意力。
- 教师强制
- 训练期间,解码器读取真实的目标词元(移动一位),而不是它自己的预测。
- 适用处: 只在训练时可用;测试时,模型必须消费它自己的输出。
- 带掩码的损失
- 填充位置被乘以零,所以它们对交叉熵没有任何贡献。
- 适用处: 需要知道目标词表的填充词元 id。
- BLEU
- 一个检查预测中有多少 n 元语法出现在目标里的分数,再乘以一个针对过短预测的惩罚。
- 适用处: 只度量长度达 k 的 n 元语法重叠;只有当预测与目标一致时才等于 1。
- 贪心搜索
- 每一步都挑出单个概率最高的下一个词元,直到 <eos>。
- 适用处: 以 O(|Y|T') 的代价便宜,但不保证得到最可能的整个序列。
- 穷举搜索
- 枚举每个可能的输出序列,保留概率最高的那个。
- 适用处: 代价 O(|Y|^{T'}) 不可行:10000 个词元、长度 10 意味着 10^40 个序列。
- 束搜索
- 每一步保留 k 个最好的部分序列,而不是只保留一个,然后用按长度归一化的对数概率给最终候选打分。
- 适用处: 代价 O(k|Y|T');贪心搜索是 k=1 的特例。
第 10 章划线与批注AI 陪读
“尽管这个权宜之计有效,它仍然留下了梯度消失的问题。”
“Despite the efficacy of this hack, it leaves open the problem of vanishing gradients.”
查看原文 →教科书里罕见的老实:裁剪被直接称为权宜之计。爆炸的梯度得到了包扎;消失的则需要架构。
“尽管这些结果并不广为人知,因为论文是用德语写的”
“although the results were not widely known because the thesis was written in German”
查看原文 →一个领域的记忆受语言所限。六年的延迟,是用翻译的缺口买来的。
“一个带有权重固定为 1 的自连接循环边的节点”
“a node with a self-connected recurrent edge of fixed weight 1”
查看原文 →整个诀窍在一个分句里。永远乘以 1,是在反复相乘中幸存下来的唯一办法。
另外 17 条批注
“简单的循环神经网络以权重的形式拥有长期记忆。”
“Simple recurrent neural networks have long-term memory in the form of weights.”
查看原文 →这个名字终于读通了:不是“长/短期”,而是一种长的短期记忆,夹在缓慢的权重和转瞬即逝的激活之间的第三种时间尺度。
“跨许多时间步累积信息,而不影响网络的其余部分”
“accrue information across many time steps without impacting the rest of the network”
查看原文 →输出门为单元买来了隐私。一个能持有某样东西而不说出来的网络——这与其说是算术,不如说更接近意图。
“为什么隐状态需要*再次*使用 $\tanh$ 函数”
“why does the hidden state need to use the \(\tanh\) function again”
查看原文 →好习题——答案是 C_t 是许多由 tanh 限定了范围的项的和,所以它根本不是有界的。书悄悄留下了这个缺口,等你掉进去。
“mathbf{H}_t = \mathbf{Z}_t \odot \mathbf{H}_{t-1} + (1 - \mathbf{Z}_t) \odot \tilde{\mathbf{H}}_t”
查看原文 →GRU 的节省:把 LSTM 的输入门和遗忘门绑在一起,使它们之和必须为一。省了一个参数,状态也不能再无界增长了。
“从某种意义上说,这些网络是深的”
“there is a sense in which these networks are deep”
查看原文 →时间上的深度是免费且不可避免的;表示上的深度必须被构建出来。本章划分的这个区别,是大多数读者混为一谈的。
“构建这种深度 RNN 的标准方法惊人地简单:我们把 RNN 一个一个堆叠起来。”
“The standard method for building this sort of deep RNN is strikingly simple: we stack the RNNs on top of each other.”
查看原文 →“惊人地简单”在起修辞作用——把没有巧妙的想法本身框定为洞见。时间上的深度本来就是免费的;抽象上的深度必须另外加上去。
“权重 $\mathbf{W}_{\textrm{xh}}^{(l)} \in \mathbb{R}^{h \times h}$”
“the weights \(\mathbf{W}_{\textrm{xh}}^{(l)} \in \mathbb{R}^{h \times h”
查看原文 →对 l=1,输入是有 d 列的 X_t,所以第一层的 W_xh 必须是 d×h。文本悄悄地把 l>1 的情形沿用成一个笼统的论断——代码里的 num_inputs if i==0 else num_hiddens 比公式更清楚。
“常见的 RNN 层宽($h$)在 $(64, 2056)$ 的范围内”
“Common RNN layer widths (\(h\)) are in the range \((64, 2056”
查看原文 →2056 几乎肯定是 2048 的笔误——一个手滑敲错的 2 的幂。小事,但它透露出这些范围是被抄录下来的民间说法,而不是测量出来的。
“总的来说,深度 RNN 需要相当多的功夫(比如调学习率和裁剪)才能确保正常收敛。”
“Overall, deep RNNs require considerable amount of work (such as learning rate and clipping) to ensure proper convergence.”
查看原文 →这一节老实的句子,却埋在总结里。堆叠是一行代码加一周的看护。
“在对文本建模时,你想合并不同作者的来源吗?为什么这是个好主意?可能会出什么问题?”
“Would you want to combine sources of different authors when modeling text? Why is this a good idea? What could go wrong?”
查看原文 →一道超出了本章的习题。这是现代 LLM 整个训练数据配比的问题,在 2021 年作为家庭作业的旁白提出。
“我 ___ 饿,我能吃下半头猪。”
“I am ___ hungry, and I can eat half a pig.”
查看原文 →一个三行的升级,比方程更好地教会了双向性——空白的含义被尚未到来的词修正了两次。而且这就是掩码语言模型目标,缩小版的 BERT,在任何人说出口之前。
“由于梯度链很长,双向 RNN 的训练代价非常高。”
“Bidirectional RNNs are very costly to train due to long gradient chains.”
查看原文 →真正的反对意见是他们没有放在开头的那一条:双向模型不能用来生成。代价是较轻的罪过;这个架构干脆禁止了本章开头的那个任务。
“我们如何设计一个神经网络模型,使得在给定一个上下文序列和一个词的情况下,返回这个词在正确上下文中的向量表示?”
“How can we design a neural network model such that given a context sequence and a word, a vector representation of the word in the correct context will be returned?”
查看原文 →他们描述的是上下文嵌入,然后要求读者去发明它。答案就在两节之外,而且它不是 RNN。
“语言之间翻译的统计表述曾经很流行,甚至早于研究者让神经网络方法跑通(这些方法常被归并在神经机器翻译这个术语之下”
“statistical formulations of translation between languages had been popular (Brown et al., 1990, Brown et al., 1988), even before researchers got neural network approaches working (methods were often lumped together under the term neural machine”
查看原文 →这个括号被挂在了错误的分句上——前神经时代的统计方法从来没被称为神经机器翻译。一个在编辑中坍塌了的句子。
“num_steps=9, num_train=512, num_val=128”
查看原文 →约 17 万对里的 512 个训练对,截断到九个词元。这个数据集是披着翻译任务外衣的单元测试;从这里得到的任何 BLEU 分数都是演戏。
“现代的实现常常把长度相近的序列分桶,以避免在填充上浪费过多的计算。”
“Modern implementations often bucket sequences with similar lengths to avoid wasting excessive computation on padding.”
查看原文 →在本章花了一页教分桶所要避免的东西之后,作为琐事被丢进来。填充到全局的 num_steps 是教学上的选择,不是实践上的选择——值得说得更响。
“一个充当条件语言模型的解码器”
“a decoder that acts as a conditional language model”
查看原文 →这是本章的关键短语。从第 9 节以来的一切——下一个词元的预测——都被整个回收,只是在前面加了条件。翻译原来是带着提示的语言建模。
读后感AI 陪读
GRU 证明 LSTM 的复杂是工程口味
通读下来,这一章是一个长长的论证,只有一个反派:梯度消失,也只有一条出路:建一条穿过时间的加性路径。本章对此异常坦率——它直接称梯度裁剪为“权宜之计”,承认它只给爆炸的那一半包扎了伤口,然后用余下的篇幅表明,另一半无法被修补,只能绕开设计。LSTM 的回答就在一个分句里——一条权重固定为 1 的自连接循环边——一旦看到它,这个名字终于读通了:不是“长/短期”,而是一种长的短期记忆,夹在缓慢的权重和转瞬即逝的激活之间的第三种时间尺度。输出门是悄悄激进的部分:它让单元累积信息而不暴露它,一个能持有某样东西而不说出来的网络。GRU 随后作为一种节省措施到来——把输入门和遗忘门绑在一起,使它们之和为一——本章愿意在规范的版本之后立刻展示更便宜的变体,老实地说明这里有多少是工程口味,而不是推导。书确实留下了一些缺口:那道问隐状态为什么又需要 tanh 的习题,是叙述中一个真正的洞,因为单元状态是有界项的和,所以根本不是有界的;堆叠 RNN 的权重形状默默地假设 l>1,而代码比公式更清楚;“2056”作为层宽是被抄录下来的民间说法,而不是测量出来的。都是小事,但它们标出了文本是在报告实践而不是在推导它。
中间一幕谈的是大多数读者混为一谈、而本章划分得很清楚的一个区别:时间上的深度是免费且不可避免的,表示上的深度必须另外加上去。“惊人地简单”在那里起着修辞的作用——把没有巧妙的想法本身框定为洞见——而埋在总结里的老实句子是,深度 RNN 需要在学习率和裁剪上下相当多的功夫才能收敛。堆叠是一行代码加一周的看护。双向 RNN 是本章最尖锐的自我限制,而它低估了自己的反对意见:它以训练成本开头,而真正的要点是双向模型在结构上不能生成。它禁止了本章开头的那个任务本身。它能做的——用尚未到来的词去修正一个空白的含义,就像那三行“我 ___ 饿,我能吃下半头猪”的升级——是缩小版的掩码语言模型目标,在任何人说出 BERT 之前的 BERT。习题就这样一再跑在正文前面:在训练数据里混合不同作者,是整个 LLM 数据配比问题,在 2021 年作为家庭作业提出;“为一个词在其正确的上下文中返回一个向量”,是要求读者在真正的答案到来的两节之前发明上下文嵌入,而真正的答案不是 RNN。
继续阅读
最后一幕为本章赢得了它的标题。编码器—解码器,然后是带教师强制、掩码损失、贪心解码和 BLEU 的 seq2seq。关键的短语是“一个充当条件语言模型的解码器”:普通下一个词元那一章的一切都被整个回收,只是在前面加了一个条件。翻译原来是带着提示的语言建模——而这个重新框定,比任何门的方程都更是本章真正的用意。不过要对演示持怀疑态度。512 个训练对、截断到九个词元,是披着翻译任务外衣的单元测试;从那里得到的任何 BLEU 都是演戏,只用于证明管道能跑通。而关于真实系统按长度分桶的旁白,在花了一页教全局填充之后,作为琐事被丢下,值得被说得更响:你被教的填充是教学上的选择,不是实践上的选择。收尾的解码一节是本章最干净的推理——贪心便宜,却可能错过最可能的序列,穷举是最优的,却是指数级的,束搜索用一个按长度归一化的得分,在两者之间买到一个可调的点——值得注意,这纯粹是搜索,独立于此前的每一种架构。
我会这样告诉读者:别去背门的示意图。带走三样东西。第一,加性路径的想法——权重为 1 的携带,带门控的更新——它完全活过了 RNN,并作为残差连接,以及每一种现代架构对深度的回答而再次出现。第二,条件语言模型的框架,它是通往本章之后一切的真正桥梁。第三,对书的代码与书的论断之间的差距保持一种有效的不信任:本章在承认权宜之计、代价、看护时最好,而在允许一次玩具运行看起来像一个结果时最弱。把它当作注意力之前的最后一章来读——这里的架构在历史上必不可少,而且很大程度上已被取代,但它们所要解决的问题,以及这篇文字点出它们时的老实,则不会过时。
在 FeedLitra 里读第 10 章,每段旁边都有这些卡片。
开始读书第 11 章:注意力机制与 Transformer
在 Transformer 中,查询、键和值究竟来自哪里?
第 11 章是怎样展开的AI 辅助
本章在解释之前先说出了它的目的地——Transformer 如今主宰着自然语言处理和视觉——然后立刻把这种主宰重新框定为需要加以说明的东西。框定的手段是一个历史论断:大约三十年来,深度学习的进步主要靠增加算力和数据,而不是靠发明更好的架构,视觉由类 CNN 的模型把持,自然语言处理由类 LSTM 的模型把持,尽管有成千上万个被提出的替代方案。这就设定了本章真正的问题:Transformer 为什么打破了这个模式?答案被追溯到一个组件,注意力,它以一个朴素的来历故事被引入——它是针对一个具体失败的补丁,即编码器—解码器翻译中定长的上下文向量,其中整个源句子被挤进一个状态,而长输入干脆把它挤爆了。本章随后做了它第一个也是最重要的推广:注意力不是补丁,而是对键值对的数据库查找。姓到名的例子在这里起了作用——查询“Li”返回“Mu”,不管存储里有多少条目,而且允许不精确的匹配。因为这个查找几乎不带参数,也从不要求存储被简化,注意力继承了为变长输入服务而无需压缩的能力。
展开:有意绕道手工制作的加权
本章没有直接跳到学出来的版本,而是绕道高斯核回归,并明确地从三个方面为这次绕道辩护:它是最早的前身,它容易可视化,并且它暴露了手工设计的局限。第三条是承重的。核宽为 0.1、0.2、0.5 和 1 时的图,显示了设计者无法逃避的取舍——更窄的核把权重集中在更少的邻居上,得到更不平滑的估计——而 Silverman 1986 年的启发式,已经被迫让宽度取决于局部的数据密度,而不是固定它。手工调节撞上了一堵墙,而这堵墙促成了转向学习的打分。本章随后提供了机制:点积和加性的打分函数、掩码 softmax、批量矩阵乘法。关键点是 softmax 为什么要紧。它把任意的兼容性得分转换成和为一的非负权重,而因为这一步是可微的、梯度不消失,所以加权本身是与其他每个参数一起通过反向传播学出来的,而不是手工设定的。Bahdanau 注意力是第一份回报:冻结的上下文向量被一个在每个解码步重新计算的取代。
展开:从解码器的补丁到通用架构
本章在推广之前先把想法落到实处——Bahdanau 解码器被实现,在英—法翻译上训练,它的注意力权重被可视化——然后才开始推广。多头注意力随之到来,接着是自注意力,它需要位置信息,因为这个运算本身对顺序是盲的。正弦的解法是用类比来解释的:频率沿嵌入维度递减,就像二进制计数里较高的位比较低的位翻转得更慢,而对任何固定的偏移,从一个位置到另一个位置的移动是一个小的、与位置无关的旋转,所以相对距离变成了模型可以利用的线性关系。本章随后安排了与 CNN 和 RNN 的直接比较,而这个比较是整个论证的铰链。循环层的代价是 O(nd²),却需要 O(n) 个顺序步骤,最长路径为 O(n);卷积层的代价是 O(knd²),有 O(1) 个顺序步骤,路径为 O(n/k);自注意力把每个词元与其他每个相连,给出 O(1) 的顺序操作和 O(1) 的最大路径长度,计算量为 O(n²d)。文本小心地说明了这买到了什么。收益是延迟的结构,而不是算术——计算量实际上随序列长度呈二次方增长,对长输入甚至比循环更糟,这恰恰是为什么后来的视觉工作,如 Swin Transformer,要消除这种依赖。
转折:放弃循环,权衡被摆明
有了这个比较,本章干脆放弃了循环。Transformer 由堆叠的自注意力和逐位置 FFN 子层组装而成,用残差连接和层归一化连接;解码器增加了编码器—解码器注意力,并对自己的自注意力加掩码以保持自回归。向视觉的扩展紧跟其后:ViT 把图像块当作词元,用带步幅的卷积做块嵌入,用带 GELU MLP 的前归一化块,并把一个 <cls> 表示投影到标签上。在这里,本章做了一件结构上老实的事——它报告了自己的负面结果。它的 ViT 在 Fashion-MNIST 上没有胜过更早的 ResNet,而作者指出,即使在 ImageNet 的 120 万张图像上也有类似的发现,把差距归因于缺少卷积的先验;更早用 2×2 图像块或特殊注意力模式的尝试,扩展性也很差。这使本章的核心交易结晶了:Transformer 放弃了内建的归纳偏置,换取可扩展性。它在小数据上输,而随着模型、数据和算力一起增长,它不断改进。
收尾:缩放律,以及缩放的极限
最后的乐章兑现了这笔交易中可扩展性的一侧,然后对它加以限定。预训练被组织成三种模式——仅编码器(BERT)、编码器—解码器(T5)、仅解码器(GPT)——证据转向经验性:GPT-2,15 亿参数,在 40 GB 文本上预训练,不改变参数或架构就达到了最先进的语言建模,尽管文本严谨地说明它在其他任务上的结果只是有希望。损失随后随参数数量、训练词元数和 PetaFLOP/s-天而遵循幂律,GPT-3 在又多出两个数量级的算力上,也跟踪着预测的曲线。本章最后把这一点反过来对付自己。规模买到能力,却买不到服从:扩大模型并不会让它遵循用户的意图。那必须另外单独训练进去——在以指令形式表述的数据集上微调,可以改善在留出任务上的零样本表现,而 InstructGPT 式的与人类反馈对齐,就是产生 ChatGPT 类人行为的东西。从 Megatron-Turing 到 Llama 的综述,连同指令微调、RLHF 和思维链提示,把 GPT 这条线推向多模态的缩放,同时留下两个悬而未决的问题:如何一起提高模型规模、数据和算力仍有争论,而在固定的算力预算下,更多的训练词元可能比更多的参数更要紧。本章就这样结束在它开始的地方——以规模作为进步的引擎——只是引擎的极限现在被点了名,而不是被假定。
关键论点,以及支撑它们的原文
直到 Transformer 到来,深度学习的进步主要靠增加算力和数据,而不是靠发明更好的架构。
作者指出,尽管有数以千计的论文提出替代方案,类似经典 CNN 的模型在视觉中仍是最先进的,类 LSTM 的模型在自然语言处理中称霸了大约三十年的架构少有变化;这个框定为本章的问题做了铺垫:Transformer 为什么打破了这个模式。
“可以说,到那时为止,深度学习的迅速兴起似乎主要归因于可用计算资源的变化(得益于 GPU 并行计算的创新)和海量数据资源的可得(得益于廉价的存储和互联网服务)。”
“Arguably, to that point, the rapid emergence of deep learning appeared to be primarily attributable to shifts in the available computational resources (thanks to innovations in parallel computing with GPUs) and the availability of massive data resources (thanks to cheap storage and Internet services).”
Chapter 11. Attention Mechanisms and Transformers查看原文 →
把注意力想成数据库查找,解释了它如何以很少的参数、无需压缩地为任意大小的输入服务。
作者用了一个姓到名的数据库:查询“Li”返回“Mu”,不管数据库里有多少条目,而且允许近似的匹配。由于查找运算本身几乎不带参数,也从不需要简化存储,注意力继承了处理变长键值对集合的同样能力。
“没有必要为了让运算有效而压缩或简化数据库。”
“There is no need to compress or simplify the database to make the operations effective.”
§11.1 Queries, Keys, and Values查看原文 →
手工制作的注意力撞上了一堵墙,因为它的核宽必须在平滑性和局部细节之间做取舍,这就是为什么本章复活了一个半世纪前的方法,却只是为了越过它。
宽度为 0.1、0.2、0.5 和 1 的图表明,更窄的核把大的权重集中在更少的邻居上,得到更不平滑的估计,而 Silverman 1986 年的启发式,已经不得不让宽度取决于局部的数据密度,而不是固定它。作者给出了绕道的三个理由——最早的前身、容易可视化、暴露手工设计的局限——而第三条直接通向学出来的打分函数。
“显然,核越窄,估计越不平滑。同时,它对局部的变化适应得更好。”
“Clearly, the narrower the kernel, the less smooth the estimate. At the same time, it adapts better to the local variations.”
§11.2 Attention Pooling by Similarity查看原文 →
另外 3 个论点
接着这个比较,自注意力的并行性和短的连接路径,使得彻底放弃循环是有道理的,尽管节省的并不在原始的计算上。
并排摆开来看,循环层的代价是 O(nd^2),但需要 O(n) 个顺序步骤,最长路径为 O(n);卷积层的代价是 O(knd^2),有 O(1) 个顺序步骤,路径为 O(n/k);自注意力把每个词元直接与其他每个相连,给出 O(1) 的顺序操作和 O(1) 的最大路径,计算代价为 O(n^2 d)。
“值得注意的是,自注意力既享有并行计算,又享有最短的最大路径长度。因此,用自注意力来设计深度架构是很有吸引力的。”
“Notably, self-attention enjoys both parallel computation and the shortest maximum path length. Therefore, it is appealing to design deep architectures by using self-attention.”
§11.7 The Transformer Architecture查看原文 →
Transformer 放弃了内建的归纳偏置,换取可扩展性,所以它们在小数据上输,而随着模型、数据和算力一起增长,它们不断改进。
本章自己的 ViT 在 Fashion-MNIST 上没有胜过更早的 ResNet,而作者报告说,即使在 ImageNet 的 120 万张图像上也有类似的发现,把差距归因于缺少卷积的先验;更早用 2x2 图像块或特殊注意力模式的尝试,扩展性也很差。在另一边,GPT-2,15 亿参数,在 40 GB 文本上预训练,不改变参数或架构就达到了最先进的语言建模(它在其他任务上的结果只是有希望),而损失随参数数量、训练词元数和 PetaFLOP/s-天而遵循幂律,GPT-3 在又多出两个数量级的算力上,也跟踪着预测的曲线。
“然而,当在更大的数据集(例如 3 亿张图像)上训练更大的模型时,情况就变了:视觉 Transformer 在图像分类上大幅胜过 ResNet,显示出 Transformer 在可扩展性上固有的优越。”
“However, the picture changes when training larger models on larger datasets (e.g., 300 million images), where vision Transformers outperform ResNets by a large margin in image classification, demonstrating intrinsic superiority of Transformers in scalability”
§11.8 Transformers for Vision查看原文 →
反过来说:规模买到能力,却买不到服从,所以遵循人类指令必须另外单独训练。
作者指出,单纯地放大一个模型并不会让它遵循意图,然后引用了一些工作,表明在用指令描述的数据集上微调,可以改善在留出任务上的零样本表现,而 InstructGPT 式的与人类反馈对齐,就是产生 ChatGPT 类人的零样本行为的东西。
“然而,单纯增大模型规模,并不本质上让模型更好地遵循人类的指令。”
“However, simply increasing model size does not inherently make models follow human instructions better.”
§11.9 Large-Scale Pretraining with Transformers查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么一个固定的上下文向量行不通
经典的编码器把整个源句子挤进一个固定大小的状态,所以长输入会把它挤爆,解码器就翻错了。注意力则保留每个编码器的时间步,并在每个解码步重新构建一个新的加权混合,所以没有什么东西必须被压缩掉。
机制 2
Softmax 使注意力可学习
查询与键之间的任何兼容性得分都被送过 softmax,把原始得分变成和为一的非负权重。因为这一步是可微的、梯度不消失,加权本身就与其他每个参数一起通过反向传播被训练,而不是手工设定的。
机制 3
正弦编码相对位置
位置被写成正弦和余弦对,其频率沿维度下降,就像二进制计数里较高的位比较低的位翻转得更慢。对任何固定的偏移,从一个位置移到另一个位置是一个小的旋转,不依赖于你在哪里,所以相对距离变成了模型可以利用的简单线性关系。
常见误读
既然自注意力并行运行、把每个词元直接联系起来,它一定比循环层便宜。
改善的是延迟的结构,而不是算术:顺序步骤和最大路径长度降到 O(1),而计算量升到 O(n^2 d),因此随序列长度呈二次方增长——一旦序列变长,就比循环层的 O(nd^2) 更糟。后来的视觉工作,如 Swin Transformer,其存在恰恰是为了消除这种对输入大小的二次方依赖。
“结果,自注意力有 $\mathcal{O}(n^2d)$ 的计算复杂度。”
“As a result, the self-attention has a \(\mathcal{O}(n^2d)\) computational complexity.”
§11.6 Self-Attention and Positional Encoding查看原文 →
如果性能按幂律缩放,那么把模型做得足够大,最终就会让它做用户要求的事。
缩放律描述的是损失对参数、词元和算力的关系,而不是遵循指令;作者明确说,单靠规模并不会产生它,而在以指令措辞的任务上微调,或用人类反馈训练,才能交付它。本章还指出,一起提高这三个因素的配方仍有争论,而在固定的算力预算下,更多的训练词元可能比更多的参数更要紧。
“然而,单纯增大模型规模,并不本质上让模型更好地遵循人类的指令。”
“However, simply increasing model size does not inherently make models follow human instructions better.”
§11.9 Large-Scale Pretraining with Transformers查看原文 →
第 11 章的核心概念
- 注意力机制
- 一种把许多(键,值)对汇聚成一个输出的方式,按每个键与查询匹配的程度给每个值加权。
- 适用处: 权重只是关于相关性的一个直觉;它们在解释上真正意味着什么,仍未定论。
- 查询、键和值
- 一个数据库的类比:查询是查找的请求,键是可以被匹配的东西,值是被返回的东西。
- 适用处: 查询、键和值从哪里来,这一段没有解释;回归的读法在后面。
- Transformer 架构
- 一种机器翻译架构,完全放弃循环,用编排好的注意力把所有输入和输出词元联系起来。 一种只用注意力、前馈层、残差连接和层归一化构建的编码器—解码器模型。
- 适用处: 为翻译而引入,后来扩展到视觉、语音、强化学习和图。 最初用于序列到序列的文本;编码器或解码器也可以单独使用。
- 基础模型
- 在通用语料上以自监督目标预训练的大模型,然后针对具体的下游任务做微调。
- 适用处: Transformer 相对于旧架构的优势,被描述为在这种预训练范式下尤其宽。
- Nadaraya–Watson 估计量
- 对观测到的标签做核加权平均,被读作注意力,其中查询是评估点,训练对是键和值。
- 适用处: 不需要训练,并且如果核随数据增多而变窄就是一致的;核本身是启发式的。
- 缩放点积注意力
- 用查询与键的点积除以向量长度的平方根来打分,使得分的方差保持在 1 附近。
- 适用处: 要求查询和键共享维数 d,除非插入一个转换矩阵。
另外 19 个概念
- 加性注意力
- 把查询和键送过一个带 tanh 的单隐藏层小 MLP,产生一个标量得分,所以它们的维数不必匹配。
- 适用处: 增加了可学习的参数 W_q、W_k、w_v;主要在查询和键的长度不同时选用。
- 掩码 softmax 运算
- 在归一化之前,把填充位置推到一个极大的负得分,使它们的权重实际上变成零。
- 适用处: 一种工程捷径:为了避免对 GPU 不友好的条件语句,它有意在计算上浪费。
- Bahdanau 注意力机制
- 解码器在每一步通过关注所有编码器状态来重新计算它的上下文向量,而不是重用一个固定的状态。 解码器的前一个隐状态充当查询,而所有编码器的隐状态充当键和值,所以上下文变量是注意力汇聚的输出。
- 适用处: 去掉了早先手写体生成的注意力模型的单向对齐限制。 为 RNN 编码器—解码器翻译而定义,其中解码器的各步关注编码器的各步,而不是彼此关注。
- 多头注意力
- 查询、键和值被线性投影 h 次,并行汇聚,然后拼接并再次投影,这样每个头可以看输入的不同部分。
- 适用处: 只有把每个头的宽度设为 p_o/h,成本才保持不变。
- 自注意力
- 每个词元形成它自己的查询、键和值,所以每个词元关注同一序列中的其他每个词元。
- 适用处: O(n^2 d) 的复杂度使它对非常长的序列不切实际。
- 位置编码
- 额外的逐词元输入,这里是固定的正弦和余弦值,加到嵌入上,这样模型就能分辨词元的顺序。
- 适用处: 之所以需要,是因为单靠自注意力会丢掉序列顺序;可以是固定的,也可以是学出来的。
- 逐位置前馈网络
- 在每个序列位置上独立施加的同一个两层 MLP。
- 适用处: 各位置之间共享权重,所以相同的输入给出相同的输出。
- 掩码的解码器自注意力
- 解码器的注意力受到限制,使每个查询只能看到直到它自己的位置。
- 适用处: 之所以需要,是因为在预测时只存在已经生成的词元。
- Transformer 中的层归一化
- 沿特征维度而不是沿小批量做归一化。
- 适用处: 对变长的语言输入,比批量归一化更受偏爱。
- 视觉 Transformer
- 一种把图像切成图像块,并把它们喂给 Transformer 编码器做分类的模型。
- 适用处: 优势主要出现在更大的模型和更大的数据集上。
- 图像块嵌入
- 把图像切成固定的方块,并把每个投影成一个向量,做法是一个核和步幅都等于图像块大小的卷积。
- 适用处: 要求图像大小能被图像块大小整除;图像块的数量随分辨率呈二次方增长。
- 前归一化
- 把层归一化放在注意力或 MLP 之前,而不是残差连接之后。
- 适用处: 训练稳定性上的选择;它改变效率,而不改变层的输入/输出形状。
- 上下文学习
- 让一个预训练的语言模型根据一段描述加上提示中零个、一个或几个例子来解决一个任务,不更新权重。 塑造文本输入,使模型在不更新权重的情况下执行任务;也称为提示。
- 适用处: 需要一个大的预训练解码器;受上下文长度和无参数更新的限制。 不发生权重更新,所以任务必须能在上下文窗口里表达出来。
- 因果注意力
- 一种掩码模式,让每个目标词元只能关注过去和现在的词元。
- 适用处: 书警告说,这个名字与对因果性的研究关系不大。
- 幂律缩放
- 只要另外两个因素不是瓶颈,性能随模型规模、数据或算力在双对数坐标上呈直线改善。
- 适用处: 只有当另外两个因素没有限制时,每个因素才成立;如何把它们一起扩展的正确方式仍有争论。
- 样本效率
- 一个模型达到给定性能水平所需的训练词元有多少;更大的模型需要的更少。
- 适用处: 按相同性能下处理的词元数来度量,而不是按花费的总算力。
- 涌现能力
- 出现在较大的模型中、而在较小的模型中缺席的能力。
- 适用处: 单靠规模并不能产生遵循指令的能力;那需要微调或人类反馈。
- 思维链提示
- 在提示里演示中间的推理步骤,让模型一步步推理出难题。
- 适用处: 少样本,甚至带着“让我们一步一步想”这类提示的零样本也管用;可扩展到多模态输入。
- 带人类反馈的指令微调
- 在指令风格的数据上微调一个预训练好的模型,可选地加上来自人类判断的强化学习,使它遵循人类的意图。
- 适用处: 人类的输入可以被部分地替换为模型的输出(来自 AI 反馈的强化学习)。
第 11 章划线与批注AI 陪读
“核心的底层架构显然可以辨认出是经典思想的放大实现”
“the core underlying architectures were clearly recognizable as scaled-up implementations of classic ideas”
查看原文 →对一个营销新奇的领域来说,这是一个安静的泄气式承认:三十年的进展,同样的骨架。这份老实赢得了后来所说的“终于有些东西改变了”的论断。
“主要归因于可用计算资源的变化”
“primarily attributable to shifts in the available computational resources”
查看原文 →所以头十年是披着架构外衣的硬件和存储。当 Transformer 这一章开始听起来像天命时,值得记住这一点。
“尽管注意力权重究竟意味着什么——即它们应该如何解释,如果真能解释的话——仍然是一个模糊的研究话题”
“although what precisely the attention weights mean—i.e., how, if at all, they should be interpreted remains a hazy research topic”
查看原文 →“如果真能的话”是到目前为止最尖锐的短语。那个可爱的“feet”/“pieds”例子被给出,又被立刻化解——一本教科书拒绝兜售自己最好的轶事。
另外 17 条批注
“没有必要为了让运算有效而压缩或简化数据库。”
“There is no need to compress or simplify the database to make the operations effective.”
查看原文 →这才是对定长瓶颈的真正控诉:不是压缩有损,而是它从来没有必要。数据库的类比比大多数图示干了更多的活。
“这类似于传统的数据库查询。”
“This is akin to a traditional database query.”
查看原文 →漂亮的框定:硬查找是软注意力的退化一角。注意力与其说是一种新的运算,不如说是一个我们本来就有的运算的可微松弛。
“我们可以设计一个不可微的注意力模型,用强化学习方法来训练”
“we can design a non-differentiable attention model that can be trained using reinforcement learning methods”
查看原文 →没有走的路,一句话点了出来。可微性获胜,不是因为它对“注意力”更忠实,而是因为梯度便宜——一个伪装起来的选择效应。
“虽然这是一个很好的直觉,但重要的是要记住,它仅仅是一个直觉。”
“While this is a good intuition, it is important to remember that it is just that, an intuition.”
查看原文 →两页之内,就同一点的第二次警告。这种重复读起来与其说是教学,不如说是作者们对该领域实际怎么使用热图的畏缩。
“这个估计量的一个便利性质是,它不需要训练。”
“One of the convenient properties of this estimator is that it requires no training.”
查看原文 →五十年前的非参数方法,一致,没有参数——它是整章要远离的老实基线。让你问:学习究竟买到了什么?
“尽管核的函数形式不同。这引出了一个问题:这是否总是如此。”
“despite the different functional form of the kernel. This raises the question as to whether this is always the case.”
查看原文 →好招:三个核达成一致,是相似性函数的形状几乎无关紧要的证据。这个逗弄人的问题是在为“为什么杠杆是学出来的表示,而不是更巧妙的核”做铺垫。
“它展示了手工制作的注意力机制的局限”
“it demonstrates the limits of hand-crafted attention mechanisms”
查看原文 →这次绕道真正的目的,终于说出了口。Nadaraya–Watson 在输入空间里固定了相似性;Transformer 可以选择空间。这就是一个对比里的整章。
“略微浪费一点计算,要比代码里有条件(if then else)语句更快”
“it is faster to be slightly wasteful in computation rather than to have code with conditional (if then else) statements”
查看原文 →老实的承认:硬件塑造了数学。掩码不是一种理论装置,而是向 GPU 行的贿赂。
“实际上,这个实现稍微作弊了一点,把 $i > l$ 的 $\mathbf{v}_i$ 的值设为零”
“Actually, the implementation cheats ever so slightly by setting the values of \(\mathbf{v}_i\), for \(i > l\), to zero”
查看原文 →用 -1e6 而不是 -inf 也是一个软的谎言——有限,所以梯度只是消失,而不是真正不存在。在 fp16 下,这个界会溢出。
“把注意力权重归一化到 $1$,就像 (11.1.2) 中所做的那样,确保这一项完全消失”
“Normalizing the attention weights to \(1\), as is done in (11.1.3), ensures that this term disappears entirely”
查看原文 →漂亮的推导动作:著名的 QK/√d 是通过丢掉两项,从高斯核反向工程出来的。缩放点积是一个被剥掉的距离,而不是第一性原理。
“比如,只要键 $\mathbf{k}_i$ 是由层归一化生成的,情况就是如此。”
“This is the case, for instance, whenever the keys \(\mathbf{k}_i\) were generated by a layer norm.”
查看原文 →循环的便利——我们丢掉 ‖k‖²,是因为层归一化碰巧使它恒定,而层归一化待在那里,部分原因恰恰是注意力需要它。两个权宜之计互相支撑。
“序列到序列机制把中间状态当作任何可能作为输入的字符串的充分统计量”
“the sequence-to-sequence mechanism treats the intermediate state as a sufficient statistic of whatever string might have served as input”
查看原文 →用统计语言点出这个缺陷,比任何关于瓶颈的含糊说法都更尖锐:旧的架构在不存在充分性的地方断言了充分性。
“对齐只朝一个方向移动”
“the alignment moves only in one direction”
查看原文 →值得停一下:Graves 先有了注意力,却把它拴在单调的顺序上。Bahdanau 的贡献主要是去掉了一个约束——成为历史的是删除,而不是发明。
“另一个好处是,正如它的名字所表明的,这种注意力是加性的。这可能带来一些小小的计算节省。”
“Another benefit is that, as its name indicates, the attention is additive. This can lead to some minor computational savings.”
查看原文 →这个论断很单薄,而书自己也半知半觉——加性注意力需要为每个查询—键对做一次 h 维的 tanh,严格比一次矩阵乘法差。“节省”只存在于一个没有 BLAS 的世界里。
“我们用 $\mathbf{s}_{t' - 1}$ 作查询,用 $\mathbf{h}_{t}$ 同时作键和值。”
“We used \(\mathbf{s}_{t' - 1}\) as the query, and \(\mathbf{h}_{t}\) as both the key and the value.”
查看原文 →整套 QKV 的词汇是事后加在 Bahdanau 身上的,他一个字也没写过。教学干净,略有时代错置。
“让我们的注意力机制联合使用不同的表示子空间,可能是有益的”
“it may be beneficial to allow our attention mechanism to jointly use different representation subspaces”
查看原文 →注意这个对冲——“可能是有益的”。多头是靠希望而不是证明来辩护的;后来的工作发现许多头可以被剪掉而没有损失。
“我们设 $p_q = p_k = p_v = p_o / h$”
“we set \(p_q = p_k = p_v = p_o / h”
查看原文 →教科书把它呈现为成本控制的便利,但恰恰是这个选择使“多头”免费:与一个大头同样的 FLOPs,只是被划分了。子空间是从固定的预算里切出来的,而不是加到预算上的。
读后感AI 陪读
作者们对规模明显比对学习更有信心
当作一个整体来读,这一章有一个它自己的小节编号所掩盖的形状:它不是“这是注意力,这是 Transformer,这是 GPT”,而是一场关于学习比手工制作多买到了什么的持续论证,接着是一场关于规模比学习多买到了什么的论证——而作者们对后者明显比对前者更自信。它以一次泄气开篇,为此后的一切付了账:三十年的进展建立在同样的架构骨架之上,收益主要归因于算力和数据。这一承认是本章的道德锚点,值得带着往前走,因为一旦 Transformer 到来,行文就开始听起来像是天命,而开篇已经告诉你,天命主要是披着架构外衣的硬件。
展开的安排确实很好。定长的瓶颈被控诉,不是因为它有损,而是因为它没有必要——数据库的类比表明,一个查询可以直接寻址整个存储,不需要摘要,而硬查找是软注意力的退化一角,而不是另一种物种的运算。Nadaraya–Watson 的绕道是本章最好的教学决定:一个五十年前的估计量,不需要训练,是一致的,并且在三种不同的核下效果差不多。这种等价的回报是本章真正的论点,几乎是顺带说出的——相似性的函数形式几乎无关紧要;要紧的是,比较发生在一个学出来的空间里,而不是在原始的输入空间里。手工制作的注意力固定了度量;Transformer 可以选择它。从缩放点积到多头的一切,都在这一个对比的下游。
继续阅读
细读之下,我看穿的是,经典机制有多少是事后找理由,而不是推导出来的。著名的 QK/√d 是通过丢掉两项,从高斯核反向工程出来的,其中一项被丢掉的理由是层归一化使键的范数恒定——而层归一化本身待在架构里,部分原因恰恰是注意力需要这种条件。两个便利互相支撑,被呈现为一次干净的推导。掩码公开是向 GPU 行的贿赂:浪费的算术胜过分支,而掩码是用一个很大的有限负数而不是真正的 −∞ 实现的,所以梯度只是消失,而不是在构造上就消失(而这个界在半精度下并不安全)。加性注意力所宣传的“计算上的节省”,一碰到 BLAS 就站不住了——对每个查询—键对做一次 tanh,严格比一次矩阵乘法差。Bahdanau 的贡献在很大程度上是去掉了 Graves 的单调性约束:成为历史的是删除,而不是发明。而 QKV 的词汇是事后披在一篇根本没用过它的论文上的——教学干净,略有时代错置。多头的故事是最尖锐的例子:p_q = p_k = p_v = p_o/h 被呈现为成本控制,但它恰恰是让多头免费的选择。子空间是从固定的预算里切出来的,而不是加到预算上的,其理由是一句对冲的“可能是有益的”——是希望而不是证明,而后来的剪枝工作在很大程度上证实了这一对冲。
最老实的线索是关于解释的。几页之内,作者们两次警告热图的直觉只是直觉,而“how, if at all, they should be interpreted”(它们该如何解释,如果真能解释的话)里的“if at all”是本章最尖锐的一个分句。他们给出了迷人的 feet/pieds 对齐,然后立刻化解了它——一本教科书拒绝兜售自己最好的轶事。这种重复读起来与其说是教学,不如说是对该领域实际怎么使用那些图片的畏缩。同样说明问题的是一句话提到的,不可微的注意力可以用强化学习来训练。那条路并不是因为它对注意力不够忠实而被放弃的;而是因为梯度便宜。一个选择效应,被点了名,然后被抛在身后。
后半部分换了体裁。一旦 ViT 出现,论证就不再是机制性的,而成为经验性的:把图像块当作词元,前归一化的块,一个投影到标签的 cls 向量——以及发现 ViT 在小数据上输给 ResNet,在大规模上获胜。这个结果是整章的铰链,因为它把一个关于架构的论断,转换成了一个关于体制的论断。Transformer 的归纳偏置更弱,这在数据稀缺时是负债,而在数据充足时是资产。从这里开始,本章沿着幂律,经过 BERT、T5、GPT、Megatron-Turing、Llama,再到指令微调、RLHF 和思维链——而在这里,写作变得更薄、更像清单,因为可提供的理论更少。缩放律是稳健的经验规律,而不是解释,本章也没有假装不是,但读者应该注意到语域的转变:推导让位于引文。
我最尖锐的判断:这一章最好读作一个约束预算被好好花掉的故事。序列到序列断言,一个中间状态是输入的充分统计量——这是一个构造上就是假的论断,而用统计语言点出它,比任何关于瓶颈的说法都更有杀伤力。注意力通过把硬查找放松为可微的查找,买回了丢失的信息。然后此后的每一步,都去掉了又一个约束:单调的对齐、固定的相似性度量、单一的表示子空间、循环本身。Transformer 与其说是一项发明,不如说是这个删除过程的极限——当你剥掉每一个 GPU 愿意用计算量来付的结构性假设之后,剩下的东西。位置编码是唯一被加回去的约束,值得注意它是不情愿地加回去的,因为去掉循环把顺序信息也带走了。
我会这样告诉读者:别让最后那幅图的优雅说服你,以为这个设计是被推演出来的。把这一章读两遍,第二遍追踪哪些选择是有原则的(关注一切;学习比较的空间),哪些是硬件塑造的(掩码、头的划分、用点积而不是加性得分),哪些是碰巧留下来的、带着希望的约定(√d、头的数量、注意力图的解释价值)。把 Nadaraya–Watson 基线抓在手里,作为训练究竟让你挣得什么的参照点。把注意力热图当作诊断,永远不要当作解释——作者已经警告过你两次。并把缩放律各节读作对观察到的规律的报告,而不是自然定律:本章自己的开篇说过,过去十年的飞跃来自算力,而这一论断的老实版本是双向的。如果 Transformer 的优势在于它内建的假设更少,因此能吸收更多的数据,那么它的故事仍然是一个关于资源的故事,只是换了一件更好的外衣。
在 FeedLitra 里读第 11 章,每段旁边都有这些卡片。
开始读书第 12 章:优化算法
为什么 ReLU 缓解了梯度消失造成的停滞?
第 12 章是怎样展开的AI 辅助
开篇:两个目标之间有意的缺口。 本章不是从一个算法开始,而是从一个区别开始。优化是驱动深度学习训练的引擎,然而它的目标——训练误差——并不是深度学习的目标,后者是泛化误差。作者用手绘的一对曲线把这一点说得很鲜明:一条平滑的风险曲线和一条更崎岖的经验风险曲线,它们的极小值位于不同的地方,所以把训练曲线一直压到它的底部,未必会落在更好的模型上。作者坦率地说,这是一个一维的示意,而不是一个真实的网络,但它为此后的一切设定了框架。开篇还点出了本章余下部分会不断撞上的障碍——局部极小值、鞍点和梯度消失——并提供了那个难忘的论证,说明为什么下降停滞的典型地点是鞍点,而不是局部极小值:在梯度为零的点上,海森矩阵特征值的符号决定了裁决,而随着维度增长,要求许多特征值中的每一个都为正,变得几乎不可能。这里也落下了第二个框定的论断:尽管几乎每个深度学习目标都是非凸的,凸性是方法的行为真正可以被证明的地方,这为凸性入门和本章将要进行的完整收敛性证明提供了理由。
展开:从精确的曲率到廉价的曲率。 框架定下之后,本章完成了它的凸性机制(海森矩阵检验),并用三种办法处理约束——拉格朗日函数、惩罚、投影——然后才转到梯度下降本身:泰勒展开的依据、学习率的影响、局部极小值的陷阱、多元的更新,然后是具有二次收敛的牛顿法。牛顿法是本章的支点,因为它被引入就是为了被缩减。海森矩阵是一个 d 乘 d 的对象,其大约 d² 个元素太大而存不下,反向传播太昂贵;它的二次收敛只在凸性下成立;而在二阶导数为负的地方,它会愉快地往上坡走,在一个非凸的测试函数上,0.5 的学习率就能挽救这种失败。本章从中提炼出幸存的想法:只保留对角线。预条件给每个坐标自己的学习率,这足以修复一个以毫米度量的变量和一个以千米度量的变量之间的尺度不匹配,而代价只是一小部分。同样的“理论上很快,实践中已死”的裁决随后落在了线搜索上,因为每一步都需要在整个数据集上评估目标函数。
转折:随机性,以及它收取的价格。 这一裁决把本章交给了 SGD。对单个样本采样,把每次迭代的代价从 n 阶降到常数,同时让梯度仍是完整梯度的无偏估计——但噪声是要付账的。由于单个样本的梯度平均而言是对的,实际上却是有噪声的,抖动在极小值附近不会消失,固定的步长会让迭代点不断弹跳;速率必须衰减。作者具体演示了这种不对称:逆平方根衰减在五十步内就有改善,而指数衰减在迭代点到达之前就扼杀了进展。凸分析随后交出了承诺的证明,一个 O(1/√T) 的界,速率选为 r/(L·√T),并且推荐不放回采样。小批量作为两个极端之间谈判出来的和解登场。对 b 个样本取平均,梯度的期望不变,而标准差削减为 b^(−1/2)——对线性上升的计算量来说是次线性的回报,这恰恰是“硬件允许的最大批量”是错误结论的原因。论证的硬件方面来自向量化和分块的矩阵乘法,以及 CPU 缓存:以 64 列为一块相乘,已经差不多和整个 256×256 的乘积一样快。在 1,500 个样本的机翼任务上,全批量在六步之后停滞,单样本更新对每个样本来说很慢,而批量大小 100 在墙钟时间上胜过全批量下降——作者指出了但书:这只是一个小的白化数据集,加一个线性模型,而且较低的批量噪声也削弱了批量归一化从中得到的正则化效应。
扩建:自适应家族,是被组装出来的而不是被发明的。 本章最优雅的结构性动作,是把现代优化器呈现为已经有动机的各种修补的累积。小批量讨论中引入的过去梯度的漏式平均,直接通向动量,它的工作是修复病态的下降:梯度持续一致的方向会累积,符号翻转的方向会抵消,所以步长沿有用的轴增长,沿陡峭的轴平静下来,几何级数使有效步长约为 η/(1−β),有效样本量为 1/(1−β)。动量得到了动手的代码,以及一个二次凸的分析,表明坐标上的分解和更宽的收敛范围。Adagrad 随后从一个不同的动机——稀疏特征——到来,并把累积的平方梯度重用为海森矩阵对角线的廉价代理。从这里开始,每个后继者都修复它的前任:RMSProp 用漏式平均取代 Adagrad 无界的累加和——后者按固定的 t^(−1/2) 日程缩小步长,而不管实际的几何;Adadelta 靠使用参数变化的统计量,完全去掉了学习率;Adam 把动量与二阶矩的缩放融合,并加上偏差修正。关键是,Adam 不是作为打开就能忘的默认选项提供的:作者立刻指出,当二阶矩控制得不好时,它甚至在凸问题上也可能不收敛,而 Yogi 的基于符号的二阶矩更新和初始化(Zaheer 等人,2018)正是为驯服这一点而提出的。
收尾:调度和算法同样要紧。 表明没有哪个优化器能免去选择步长的需要之后,本章以学习率调度收尾。调度器按每次更新设定速率——平方根、因子、多步、余弦——而预热把速率从接近零向上拉,以避免早期发散。最后的观察绕回了开篇:衰减的速率不仅使收敛平滑,还提高了准确率,而且有点奇怪地,减少了过拟合。Fashion-MNIST 的运行表明,调度既改变了训练的平滑程度,也改变了过拟合的量,这是本章对其第一页论断的具体回报——两次运行可以达到同样的训练误差,却泛化不同,所以优化的选择从来不单是关于下降得更快。
关键论点,以及支撑它们的原文
优化和深度学习拉向不同的目标:一个降低训练集上的误差,另一个降低没见过的数据上的误差。
作者画了一条平滑的风险曲线和一条更崎岖的经验风险曲线,并指出它们的最低点位于不同的地方,所以把训练曲线压到它的底部,未必会落在更好的模型上——这诚然是一幅手工绘制的一维图景,而不是真实的网络。后来作者补充说,不同的算法和日程在同样的训练误差下可以给出不同的泛化。
“尽管优化为深度学习提供了一种最小化损失函数的方法,但从本质上讲,优化和深度学习的目标是根本不同的。”
“Although optimization provides a way to minimize the loss function for deep learning, in essence, the goals of optimization and deep learning are fundamentally different.”
§12.1 Optimization and Deep Learning查看原文 →
尽管几乎每个深度学习目标都是非凸的,学习凸优化仍然有回报。
作者的理由是实用的:凸性是方法的行为真正可以被证明的地方,所以本章包含了一个凸性入门,以及一个针对凸目标上一个简单随机方法的完整收敛性证明,这些洞见随后指导了如何处理非凸的情形。
“深度学习中产生的几乎所有优化问题都是非凸的。尽管如此,在凸问题的背景下设计和分析算法,已被证明很有启发。”
“Almost all optimization problems arising in deep learning are nonconvex. Nonetheless, the design and analysis of algorithms in the context of convex problems have proven to be very instructive.”
Chapter 12. Optimization Algorithms查看原文 →
曲率信息帮助很大,但在深度学习中,它必须被廉价地近似,而不是被精确地计算。
在牛顿法的基础上,作者指出海森矩阵是一个 d 乘 d 的对象,其大约 d 平方个元素太大而存不下,反向传播太昂贵;牛顿法也只在凸性下才二次收敛,并且在二阶导数为负的地方会往上坡走(在一个非凸的测试函数上,0.5 的学习率就能挽救它)。只保留对角线,就给每个坐标自己的速率——足以修复一个变量以毫米度量而另一个以千米度量时的不匹配,而代价只是一小部分。
“虽然由于计算代价,这些方法不能直接应用于深度学习,但它们为如何设计高级的优化算法提供了有用的直觉,这些算法模仿了下面概述的算法的许多可取性质。”
“While these methods cannot be applied to deep learning directly due to the computational cost, they provide useful intuition into how to design advanced optimization algorithms that mimic many of the desirable properties of the algorithms outlined below.”
§12.3 Gradient Descent查看原文 →
另外 3 个论点
线搜索和其他对整个数据集的步长规则在理论上很快,在深度学习的实践中已死,这就是随机梯度接管的原因。
每个线搜索步骤都需要在整个数据集上评估目标函数,作者称这代价太高;相比之下,对一个样本采样,把每次迭代的代价从 n 阶降到常数,同时让梯度仍是完整梯度的无偏估计。凸分析随后给出了一个量级为步数平方根分之一的界,速率选为 r/(L·sqrt(T))。
“然而,就深度学习的目的而言,这不太可行,因为线搜索的每一步都要求我们在整个数据集上评估目标函数。”
“However, for the purpose of deep learning this is not quite so feasible, since each step of the line search would require us to evaluate the objective function on the entire dataset.”
§12.3 Gradient Descent查看原文 →
小批量是正确的中间地带,而且在一次真实的回归运行中,它们在墙钟时间上获胜。
对 b 个随机抽取的样本取平均,梯度的期望不变,而标准差削减为 b 平方根分之一,但超过某一点后,额外的方差降低可以忽略不计,而计算量线性增长——以 64 列为一块相乘,已经差不多和整个 256×256 的乘积一样快。在 1,500 个样本的机翼任务上,全批量在 6 步之后停滞,单样本更新对每个样本来说很慢,而批量大小 100 在运行时间上胜过全批量下降。但书:这只是一个小的白化数据集,加一个线性模型,而且较小的批量噪声也削弱了批量归一化的正则化效应。
“由于小批量梯度是由 $b \stackrel{\textrm{def}}{=} |\mathcal{B}_t|$ 个被平均的独立梯度构成的,其标准差缩小为原来的 $b^{-\frac{1}{2}}$ 倍。”
“Since the minibatch gradient is composed of \(b \stackrel{\textrm{def}}{=} |\mathcal{B}_t|\) independent gradients which are being averaged, its standard deviation is reduced by a factor of \(b^{-\frac{1}{2”
§12.5 Minibatch Stochastic Gradient Descent查看原文 →
自适应方法是由较早的各种修补组装而成的,并不自动安全,所以二阶矩必须小心控制。
作者走过这条谱系——小批量、动量、逐坐标缩放,以及学习率与该缩放的解耦——并把 Adam 呈现为它们的组合。Adagrad 朴素的平方梯度累加和无界增长,按固定的 t 的负二分之一次方的日程缩小步长,而不管实际的几何,RMSProp 的漏式平均修复了这一点;而 Adam 反过来,甚至在凸问题上也可能不收敛,这促成了 Zaheer 等人(2018)改进的、基于符号的二阶矩更新和初始化。
“Adam 把许多优化算法的特点结合成一个相当稳健的更新规则。”
“Adam combines features of many optimization algorithms into a fairly robust update rule.”
§12.10 Adam查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么鞍点胜过局部极小值
在梯度为零的点上,海森矩阵特征值的符号决定了它是极小值、极大值还是鞍点。一个真正的极小值需要许多特征值中的每一个都为正,而随着维度增长,这越来越不可能,所以符号混合——鞍点——成了典型的停滞点。
机制 2
为什么 SGD 必须缩小它的步长
单个样本的梯度平均而言是对的,却有噪声,所以在极小值附近噪声不会消失,固定的步长会让迭代点不断弹来弹去。随时间缩小速率可以抑制这种抖动;作者表明逆平方根衰减在 50 步内就有改善,而指数衰减在到达之前就扼杀了进展。
机制 3
动量如何修正振荡
动量用过去梯度的衰减平均取代原始梯度。梯度持续指向同一方向的方向会累加起来,而符号翻转的方向则相互抵消,所以步长沿有用的轴增长,沿陡峭的轴平静下来——几何级数使有效步长约为 eta/(1-beta)。
常见误读
既然 Adam 把动量、逐坐标缩放和偏差修正捆绑在一起,它就是一个稳健的默认选项,你可以直接打开,不必再担心步长。
作者把 Adam 呈现为一种有用的组合,但立刻指出,当它的二阶矩估计控制得不好时,它甚至在凸问题上也可能不收敛,这恰恰是为什么有人提出了改进的更新和初始化作为修补。而且速率的日程仍然必须手工选择——Fashion-MNIST 的运行表明,调度既改变了训练的平滑程度,也改变了过拟合的量。
“Adam 把许多优化算法的特点结合成一个相当稳健的更新规则。”
“Adam combines features of many optimization algorithms into a fairly robust update rule.”
§12.10 Adam查看原文 →
因为对 b 个样本取平均会缩小梯度噪声,所以硬件允许的最大批量就是最佳选择。
噪声只随批量大小的平方根分之一下降,所以收益趋于平缓,而计算量却与 b 成比例地持续上升——作者表明 64 列的小批量已经差不多和整个矩阵乘积一样快,而在机翼任务上,1,500 的全批量在六步之后停滞,而 100 的批量在运行时间上胜过了它。较小的批量噪声也去掉了批量归一化从这种噪声中得到的一部分正则化效应。
“由于小批量梯度是由 $b \stackrel{\textrm{def}}{=} |\mathcal{B}_t|$ 个被平均的独立梯度构成的,其标准差缩小为原来的 $b^{-\frac{1}{2}}$ 倍。”
“Since the minibatch gradient is composed of \(b \stackrel{\textrm{def}}{=} |\mathcal{B}_t|\) independent gradients which are being averaged, its standard deviation is reduced by a factor of \(b^{-\frac{1}{2”
§12.5 Minibatch Stochastic Gradient Descent查看原文 →
第 12 章的核心概念
- 经验风险
- 在有限训练集上度量的平均损失,对比整个总体上的期望损失。
- 适用处: 它的极小值可能位于与真实风险极小值不同的位置。
- 鞍点
- 一个所有梯度都消失、但既不是局部极小值也不是全局极小值的点。
- 适用处: 由海森矩阵特征值的符号混合来识别;在高维空间中,比局部极小值更可能出现。
- 梯度消失
- 梯度太接近零,使参数更新长时间停滞。
- 适用处: 与饱和的激活函数有关;可用 ReLU 和重新参数化来缓解。
- 凸函数
- 一个弦永远不在函数之下的函数,等价地说,其海森矩阵永远不为负。
- 适用处: 大多数深度学习问题是非凸的,但凸分析仍然有启发意义。
- 拉格朗日函数
- 把每个约束乘以一个非负的乘子,加进目标函数;求解有约束的问题就变成了寻找一个鞍点。
- 适用处: 最优性的保证依赖于凸性;不起作用的约束的乘子趋于零。
- 惩罚法
- 不是精确地强制一个约束,而是把它的缩放后的违反量加进损失,这样它永远不会被严重破坏。
- 适用处: 只是近似地满足;在非凸问题中,凸情形的保证就丢失了。
另外 26 个概念
- 投影
- 把一个点拉回凸集中最近的点;已经在里面的点原封不动。
- 适用处: 对 l2 球方向得以保持,对像 l1 菱形这样的集合则不然。
- 权重衰减
- 在损失中加上平方范数的惩罚,这其实是对权重的近似范数球约束。
- 适用处: 只是近似地等价于半径约束;半径通过 lambda 间接控制。
- 梯度下降
- 反复逆着梯度走一步;一阶泰勒展开表明小步长会降低目标函数。
- 适用处: 只有当步长小到高阶项可以忽略时才降低函数值。
- 学习率
- 固定的步长;太小就爬行,太大就冲过头,还可能发散。
- 适用处: 由设计者选择;其安全范围取决于曲率和条件数。
- 牛顿法
- 通过把梯度乘以海森矩阵的逆来利用曲率,在极小值附近给出非常快的步子。
- 适用处: 海森矩阵的存储是 O(d^2),而且负的二阶导数会让这一步走上坡路。
- 海森矩阵的半正定性
- 一个二阶可微函数是凸的,当且仅当它的二阶导数矩阵在任何方向上都不会向下弯曲。
- 适用处: 需要二阶可微;可化约为沿每条线段的一维检验。
- 预条件
- 只用海森矩阵的对角线来重新缩放每个坐标,也就是每个变量一个学习率。 重新缩放坐标,使特征值变得相当,让下降更容易;精确的重新缩放需要特征值,所以使用廉价的近似。
- 适用处: 比完整的牛顿法弱,并且捕捉不到跨坐标的曲率。 精确的特征分解比解决问题本身代价还高;对角线的重新缩放是实用的折中。
- 带线搜索的梯度下降
- 保持梯度的方向,但用二分搜索找出使目标函数最小的步长。
- 适用处: 对深度学习不可行,因为每个搜索步骤都需要在整个数据集上评估目标函数。
- 小批量随机梯度下降
- 全批量梯度下降和单样本 SGD 之间的折中,主要为计算效率而选。 用一个小的随机批量的平均梯度来更新参数,而不是用单个样本或整个集合。
- 适用处: 它的大小由硬件驱动:设备数、向量化宽度和缓存带宽。 当额外的方差降低相对于线性增长的计算代价变得微不足道时,收益就停止了,而且批量必须能放进 GPU 内存。
- 动态学习率
- 一个随时间变化的日程 eta(t):分段常数、指数衰减或多项式衰减。
- 适用处: 衰减太快,优化会过早停止;太慢,则浪费时间。
- 向量化
- 在一次框架调用中完成许多算术运算,这样数据就留在缓存里,解释器开销只付一次。
- 适用处: 只有当涉及的矩阵或块能有效地放进缓存时才有帮助;库会处理分块。
- 漏式平均(速度)
- 一个滚动的和 v_t = beta*v_{t-1} + g_t,把过去的梯度混进当前的步长方向。
- 适用处: 大的 beta 在很长的范围上取平均;beta = 0 则还原为朴素的梯度下降。
- 动量
- 使用累积的速度而不是原始梯度,这样方向一致的会累积起来,来回振荡的会相互抵消。
- 适用处: 对病态问题最有价值;beta 太小则几乎不收敛。
- 病态问题
- 一个曲率随方向差异悬殊的目标,所以一个学习率要么太慢,要么发散。
- 适用处: 这里用拉伸的二次函数 f(x) = 0.1 x_1^2 + 2 x_2^2 来说明。
- 有效样本权重
- 因为过去的梯度按 beta 衰减,动量实际上平均了大约 1/(1-beta) 个梯度,走出大小为 eta/(1-beta) 的一步。
- 适用处: 在常数 beta 下的多步极限中成立;需要降低学习率才能保持稳定。
- 条件数
- 二次型矩阵的最大特征值与最小特征值之比;大的值使问题难以精确求解。
- 适用处: 对正定的二次目标有定义;在非凸的深度学习中只是一种直觉。
- Adagrad
- 一种优化器,对每个坐标累积平方梯度,并用其平方根去除学习率,使每个坐标有自己的日程。
- 适用处: 对凸问题足够;在深度学习中,它的衰减可能太激进。
- 稀疏特征
- 只很少出现的特征,所以在全局衰减的学习率下,它们的参数得到的有意义的更新很少。
- 适用处: 基于计数器的修补,在数据并不真正稀疏、只是梯度很少变大时就失效了。
- RMSProp
- 带有平方梯度的漏式(指数加权)平均的 Adagrad,这样学习率就不再被迫衰减。
- 适用处: 实验者仍然必须调度学习率;gamma 控制历史的长度。
- Adadelta
- 一种变体,保持两个漏式平均——平方梯度的和平方参数变化的——因此不需要学习率。
- 适用处: 使用 rho 作为它唯一的参数;跨坐标的自适应性降低了。
- Adam
- 结合漏式平均的动量和二阶矩,带偏差修正,然后像 RMSProp 那样重新缩放梯度。
- 适用处: 当二阶矩估计爆炸或梯度方差高时可能发散。
- Yogi
- 一种对 Adam 的修补,其二阶矩的更新量只取决于平方梯度,而不取决于它与旧估计的偏离程度。
- 适用处: 处理由稀疏或高方差更新引起的发散;其他细节在这里省略。
- 学习率调度
- 在训练过程中有意地选择学习率的大小、衰减和预热。 一个初始阶段,学习率线性上升到最大值,然后衰减。
- 适用处: 循环式的日程超出了这里的范围;框架提供调度器工具。 适用于任何调度器;对深的或不稳定的架构最有用。
- 学习率调度器
- 一个函数,在给定更新次数的情况下返回学习率,而不是保持它固定。
- 适用处: 需要选定的策略和视野;收益是经验性的,没有保证。
- 余弦调度器
- 一种日程,让速率沿着余弦曲线从初始值衰减到最终值。
- 适用处: 在计算机视觉中很流行;不保证有改进。
- 过拟合
- 训练准确率持续上升,而测试准确率停滞,两条曲线之间留下一道差距。
- 适用处: 这里它受优化选择的影响,而不只是受模型容量的影响。
第 12 章划线与批注AI 陪读
“大可满足于这样的认识:存在一系列咒语”
“might well content oneself with the knowledge that there exists an array of incantations”
查看原文 →“咒语”是作者在朝自己的读者眨眼——你在不理解的情况下念诵的魔法词。整章的推销词就在这一个讽刺的名词里。
“结果,这里的 g 不如 f 平滑。”
“As a result, here g is less smooth than f.”
查看原文 →漂亮的障眼法:有限的数据被建模成叠加在上面的一个余弦涟漪。作为漫画是老实的,但真实的采样噪声不是整齐的周期性摆动——这幅图之所以有说服力,部分是因为它被设计好了。
“只有一定程度的噪声,才可能把参数从局部极小值中敲出来。”
“Only some degree of noise might knock the parameter out of the local minimum.”
查看原文 →缺陷变成了特性——小批量的采样误差,在别处是个麻烦,在这里被重新命名为一种逃逸机制。深度学习反复出现的招数:有回报的马虎。
另外 17 条批注
“对高维问题来说,至少有一些特征值为负的可能性相当高。”
“For high-dimensional problems the likelihood that at least some of the eigenvalues are negative is quite high.”
查看原文 →这是这一节真正的回报:在高维空间中,要求所有 k 个特征值同号是一个巧合。所以局部极小值罕见,而鞍点无处不在——这悄悄消解了对被困住的民间恐惧。
“并不真正需要找到最好的解”
“it is not really necessary to find the best solution”
查看原文 →在好几页列举陷阱之后,出路是降低标准。不是认命——它出自第一节:真正的目标本来就从不是训练的极小值。
“如果算法即使在凸的设定下表现也很差,那么通常我们不应指望在别处看到很好的结果”
“if the algorithm performs poorly even in the convex setting, typically we should not hope to see great results otherwise”
查看原文 →在一本非凸的书里设一章凸性,老实的理由:凸性是一个过滤器,而不是模型。它可以驳倒一个算法,却永远无法为之背书。
“这可以带来令人兴奋的新优化变体,比如。”
“This can lead to exciting new optimization variants such as”
查看原文 →这句话就这么停住了。一条从未被填上的悬空引文——书的构建流水线留在行文里的化石。
“要看出逆命题不成立,考虑两个不相交的集合”
“To see that the converse is not true, consider two disjoint sets”
查看原文 →措辞草率:被展示的根本不是逆命题,而是并集不继承凸性。证明是对的;贴在上面的逻辑标签是错的。
“lambda f(x) + (1-\lambda) f(x') \geq f(\lambda x + (1-\lambda) x”
查看原文 →值得停下来看几何,而不是符号:弦位于曲线之上。后面的一切——琴生不等式、下水平集、局部即全局——不过是这一幅图景的重用。
“凸函数的期望不小于期望的凸函数”
“the expectation of a convex function is no less than the convex function of an expectation”
查看原文 →琴生不等式不是一个新事实,而是带有无穷多个 λ 的凸性。把它称为“用更简单的表达式去界住复杂的表达式”的工具,是实践者的读法——这恰恰是变分界后来立身的方式。
“这并不意味着不可能有多于一个的全局极小值,甚至也不意味着一定存在一个”
“this does not mean that there cannot be more than one global minimum or that there might even exist one”
查看原文 →我最敬重的一个但书。凸性给你的是没有陷阱,而不是一个目的地——exp(x) 永远下降,永远到不了。
“我们有 $f(x^{\ast}) < f(x)$”
“we have \(f(x^{\ast}) < f(x”
查看原文 →严格不等式被偷渡进了局部极小值的定义——用通常的 ≤,这个反证需要更小心。在一个本来整洁的论证里,这是个小失误。
“重力将与盒子侧壁所能施加的力相平衡”
“the forces of gravity will be balanced out with the forces that the sides of the box can impose”
查看原文 →盒子里的球是这一节里最好的东西:乘子是接触力,不起作用的约束是球从未碰到的墙,所以 α=0。物理学没点名,就解释了互补松弛。
“事实上,我们一直在使用这个技巧。考虑权重衰减”
“In fact, we have been using this trick all along. Consider weight decay”
查看原文 →追溯性的揭示——权重衰减一直是伪装起来的拉格朗日函数。这是书的招牌动作:先告诉你机器,再表明你已经盲目地驾驶了它九章。
“在实践中,这被证明比精确满足要稳健得多”
“In practice this turns out to be much more robust than exact satisfaction”
查看原文 →是断言,而不是论证。为什么近似更稳健?老实的答案——梯度讨厌硬墙——没有说出来。
“虽然对 $\ell_2$ 球来说,这保持方向不变,但情况未必如此”
“While for \(\ell_2\) balls this leaves the direction unchanged, this need not be the case”
查看原文 →L1 产生稀疏性的原因,安静的核心:菱形的角使方向弯折,所以投影把坐标一下子压到零。文本指了出来,然后往前走了。
“凸函数的主要目的,是为优化算法提供动机”
“the main purpose of convex functions is to motivate optimization algorithms”
查看原文 →一个罕见的承认:整套凸性的机制是脚手架,而不是地基。深度学习是非凸的,而我们照样靠借来的直觉做推理。
“函数 $f(x)$ 的值可能会下降”
“the value of function \(f(x)\) might decline”
查看原文 →“可能。”现代训练的整座大厦都建立在一个对冲的动词之上,而这个对冲是对的。
“这意味着,如果二阶导数为负,我们可能会朝增加的方向走”
“This means that if the second derivative is negative we may walk into the direction of increasing”
查看原文 →牛顿法不寻找极小值——它寻找驻点。在鞍点上,它愉快地往上爬。当人们把二阶方法称为“更聪明”时,值得记住这一点。
“优化研究者称之为线性收敛”
“optimization researchers call this linear convergence”
查看原文 →这是反的——二次的误差衰减叫作二次收敛;线性是 α|e| 的情形。在一本细心的书里,这是个真正的失误,对初读者来说还容易造成困惑。
读后感AI 陪读
我们优化的东西与我们想要的东西之间的楔子永远不会合上
当作一个整体来读,这一章是一本关于不诚实地形的老实之书。它一开篇就在优化的目标和深度学习的目标——训练误差对泛化误差——之间打进一个楔子,而这个楔子永远不会合上;这就是本章可以列举局部极小值、鞍点和梯度消失,然后耸耸肩说我们不必找到最好的解的原因。这个耸肩不是失败主义,而是第一节的逻辑兑现了:训练的极小值从来就不是目标。一路上,本章表演了它的招牌式反转,把小批量的噪声从缺陷变成了把参数从坏盆地里敲出来的逃生口,并表明在高维空间中,要求所有特征值同号是一个巧合——所以鞍点,而不是陷阱,才是真正的地形,而对局部极小值的民间恐惧悄悄地消散了。凸性一节是脚手架,书也这么说:凸性是一个过滤器,它可以驳倒一个算法,却永远无法为之背书,而它的全部机制归结为一幅图景,位于曲线之上的弦,被重用为琴生不等式、下水平集、局部等于全局。约束伴随着本章最好的意象到来——盒子里的球,乘子作为接触力,未被碰到的墙什么也不贡献——随后是追溯性的揭示,权重衰减一直就是一个拉格朗日函数,这是书的一贯习惯:让你开了九章的机器,才给它命名。从这里开始,这条弧线毫不留情地讲求经济:梯度下降由一个带对冲的泰勒“可能”来辩护;牛顿法被揭示为驻点的搜寻者,愉快地爬上鞍点,这应该让任何人对二阶“聪明”的崇敬有所收敛;预条件只保留海森矩阵的对角线,因为那是我们负担得起的;线搜索被干脆放弃,因为对整个数据集走一步是负担不起的;SGD 用一个 O(1) 的无偏梯度换掉 O(n) 的梯度,付出的是噪声,迫使衰减是多项式而不是指数的;小批量买到了梯度偏差的 b^(-1/2) 削减,加上对缓存友好的向量化。然后是自适应的家族,那是被精炼了四次的同一个想法:累积梯度统计量,作为穷人版的海森矩阵对角线(Adagrad),阻止累积扼杀步长(RMSProp),用参数变化的单位完全去掉学习率(Adadelta),把一阶和二阶矩与偏差修正融合起来(Adam),并驯服由此产生的方差(Yogi)。收尾的转折是最安静也最有用的:在所有这些算法设计之后,调度学习率——预热以熬过最初的几步,之后是余弦或多步衰减——与优化器的选择同样重要,而衰减在提高准确率的同时,奇怪地减少了过拟合,这直接绕回了本章开头的泛化差距。我会这样告诉读者:本章值得信任,但并非不会出错——它把二次收敛误标为线性,把一个非逆命题称为逆命题,把一个严格不等式偷渡进局部极小值的定义,留下一个从未得到引文的悬空的“such as.”,并用一个整洁的余弦涟漪来说明经验风险的粗糙,那更像漫画,而不是采样噪声。读几何,而不是符号;注意什么是被断言的而不是被论证的(投影比精确满足“更稳健”,L1 菱形产生稀疏性的角,只得到过路的一句话);并认真对待开头关于“咒语”的笑话,因为本章真正的成就,是把其中少数几个转变成了理由,同时坦率地说其余的仍然是我们照样在用的咒语。
在 FeedLitra 里读第 12 章,每段旁边都有这些卡片。
开始读书第 13 章:计算性能
混合式编程如何在获得符号式速度的同时保留命令式的调试?
第 13 章是怎样展开的AI 辅助
本章一开头就确立了为什么计算性能值得有单独的一章:一旦数据和模型变大,把活干完的代价就变得与建模的选择同样举足轻重。切入点是编程风格的对比。命令式的 Python 把每条语句单独交给解释器,所以每次调用的开销一遍又一遍地付,而每个中间值都一直存活,直到外层函数返回。在单个慢设备上,这种记账隐藏在算术里;一旦算术搬到快速的 GPU 上,它就开始占主导。符号式编程与此相对:一个先看到整个程序的编译器,可以把 print(1+2+3+4) 重写为 print((1+2)+(3+4)),或把它折叠成 print(10),并且可以在一个值死去的那一刻就释放内存——这些优化对逐步执行是不可得的,代价是调试更困难。混合式是本章的解决办法,保留命令式的编写体验,同时把编译好的图交给运行时。
从这里开始,本章下降到硬件,把机器一个部件一个部件地游览一遍,作为瓶颈的目录:以 PCIe 相连的组件、内存、存储、缓存和向量单元、带张量核心的 GPU,以及网络。两个机制撑起这一节。第一,起头的那一次读取主宰了内存的代价——发送地址并建立传输大约要 100 ns,而随后每条记录大约 0.2 ns 就到了,使第一次访问比它的后继者贵几百倍;长的连续运行摊薄了这一建立开销,分散的访问则每次都要付。第二,缓存之所以存在,是因为否则核心会断粮:一个带向量单元的 2 GHz 四核处理器可以消耗大约 256 GB/s,而它的内存接口只供给 20–40 GB/s,所以昂贵的芯片面积被拨给 L1/L2/L3,用来容纳一个可重用的工作集。存储带着一个针对诱人的简化的警告:SSD 不只是一块快的硬盘。它的吞吐优势是巨大的——100,000–500,000 IOPs 对磁盘的大约 100,1–3 GB/s 对 100–200 MB/s——然而写入是以 256 KB 或更大的块进行的,而且单元会磨损,所以按比特的随机写入表现很差;控制器缓和了这一点,却没有消除它。
支点出现在本章把这些延迟和带宽的事实转化成训练策略的时候。在 GPU 之间拆分工作有三种办法——把网络划分到各设备上、按层拆分、拆分数据——选择的是数据并行,前提是模型能放进一块 GPU。每块 GPU 保留一份完整的拷贝,并处理小批量的不同切片,所以同步在每个小批量只发生一次,这个方案到处都能推广。反对模型并行的论证明确是关于通信而不是算术的:按层或按通道切开一个网络,需要大量的同步和屏障操作,而层与层之间的接口必须运送足以淹没总线的激活和梯度的量,NVLink 每条服务器链路 300 Gbit/s、对消费级卡的 100 Gbit/s,标出了这个上限有多硬。AlexNet 的按层拆分被读作 2GB GPU 的产物,一个此后已被解除的约束。老实的极限也被说出:数据并行无法训练比一块 GPU 的内存更大的模型,而且有 k 块 GPU 时,有效批量增长 k 倍。
实现随论证而来。一个从零开始的 LeNet 版本手工构建 allreduce 和小批量拆分,然后一个简洁的高层 DataParallel 版本训练 ResNet-18。LeNet 的实验同时也纠正了“更多的 GPU 意味着更快的训练”这一假设:在批量大小和学习率不变的情况下,两块 GPU 让测试准确率大致保持原样,并且没有产生有意义的加速,因为模型太小,让第二块设备忙不起来。加速需要每块 GPU 有足够的工作,而不只是更多的 GPU。
收尾的乐章把总线的教训推广到分布式基础设施。梯度在哪里求和,原来要紧得多,尽管数学上没有变:把 160 MB 聚合到一块 GPU 上大约花 60 ms,经过 CPU 中转大约花 80 ms,而把同样的数据拆成四个 40 MB 的部分并行聚合,只需 15 ms,因为真实的总线带宽各不相同。环形同步把这推得更远——在一个理想化的环上,把梯度切成 n 块,每块从不同的节点发出,总时间是 (n−1)/n,不管 n 多大都约为 1,而在八块 V100 上实测的 160 MB 环形同步大约 6 ms,胜过 PCIe,不过当框架未能组装出大的突发传输时,真实的数字会变差。扩展到许多机器时,单台服务器有限的带宽使发送时间随 m 个工作者按 O(m) 增长,而 n 台服务器各持有 O(1/n) 的参数,把它降为 O(m/n),恢复了常数级的扩展。本章以使这一切变得可处理的抽象收尾:工作者按键推送梯度、拉取更新后的值,这个设计的理由是梯度求和是一个可交换的归约,所以到达的顺序无关紧要。
关键论点,以及支撑它们的原文
在运行之前编译整个程序,让系统能以逐步执行做不到的方式做优化。
与刚刚被批评的逐行风格相对,编译器可以先看到全部代码:示例程序可以被重写成 print((1 + 2) + (3 + 4)),或干脆塌缩成 print(10),而且内存可以在一个值不再需要时立即释放——权衡是这样的代码更难调试。
“这之所以可能,是因为编译器在把代码变成机器指令之前,可以看到完整的代码。”
“This is possible since a compiler gets to see the full code before turning it into machine instructions.”
§13.1 Compilers and Interpreters查看原文 →
对于跨多块 GPU 的训练,拆分数据是默认该伸手去拿的办法,前提是每块 GPU 都能容纳模型。
每块 GPU 保留模型的一份完整拷贝,并处理小批量的不同切片,所以同步在每个小批量只需要一次,这个方案适用于任何情形;作者指出,AlexNet 把各层拆分到不同设备上,只是因为当时的 GPU 只有 2GB 内存,这个约束此后在很大程度上已被解除。它仍然无法训练比一块 GPU 的内存更大的模型,而且有 k 块 GPU 时,有效批量增长 k 倍。
“总的来说,只要我们能用上内存足够大的 GPU,数据并行就是最方便的做法。”
“By and large, data parallelism is the most convenient way to proceed, provided that we have access to GPUs with sufficiently large memory.”
§13.5 Training on Multiple GPUs查看原文 →
模型并行败在通信代价上,而不是算术上。
这是作者偏爱拆分数据的理由:按层或按通道切开一个网络,会迫使产生大量的同步和屏障操作,而层与层之间的接口必须运送足以淹没 GPU 总线的激活和梯度的量——NVLink 在服务器卡上每条链路 300 Gbit/s,而消费级卡上是 100 Gbit/s,显示了这个互连的限制有多真实。
“然而,我们需要非常大量的同步或屏障操作,因为每一层都依赖于所有其他层的结果。”
“However, we need a very large number of synchronization or barrier operations since each layer depends on the results from all the other layers.”
§13.5 Training on Multiple GPUs查看原文 →
另外 3 个论点
尽管数学是一样的,梯度在哪里求和,会让同步时间改变一个很大的倍数。
把总线层面的教训付诸实践:把 160 MB 聚合到一块 GPU 上大约花 60 ms,经过 CPU 中转大约花 80 ms,但把同样的数据拆成四个 40 MB 的部分并行聚合,只需 15 ms,因为真实的硬件总线带宽各不相同。
“然而,我们面对的是真实的物理硬件,其中不同的总线有不同的带宽,如第 13.4 节所讨论的。”
“However, we are dealing with real physical hardware where different buses have different bandwidth as discussed in Section 13.4.”
§13.7 Parameter Servers查看原文 →
在环上传递梯度块,使聚合时间大致与参与的设备数量无关。
接着关于聚合地点的论点:在一个理想化的环上,把梯度切成 n 块,每块从不同的节点发出,总时间是 (n-1)/n,不管 n 多大都约为 1,而实测中,在八块 V100 GPU 上对 160 MB 做环形同步大约需要 6 ms,胜过 PCIe 总线。当框架未能组装出大的突发传输时,真实的数字会更差。
“换句话说,聚合梯度所花的时间不会随着环的增大而增长。”
“In other words, the time spent to aggregate gradients does not grow as we increase the size of the ring.”
§13.7 Parameter Servers查看原文 →
把参数分散到许多服务器上,去除了单台服务器的带宽瓶颈,恢复了常数级的扩展。
把同样的聚合教训推广到许多机器:一台服务器的带宽是有限的,所以有 m 个工作者时发送时间按 O(m) 增长,而 n 台服务器各自只存储 O(1/n) 的参数,把它降为 O(m/n)。工作者随后按键推送梯度、拉回更新后的值,这是稳妥的,因为梯度求和是一个可交换的归约,到达的顺序无关紧要。
“此时每台服务器只需存储 $\mathcal{O}(1/n)$ 的参数,因此更新和优化的总时间变成 $\mathcal{O}(m/n)$。”
“At this point each server only needs to store \(\mathcal{O}(1/n)\) of the parameters, hence the total time for updates and optimization becomes \(\mathcal{O}(m/n)”
§13.7 Parameter Servers查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么逐行的 Python 运行得慢
每条语句都单独交给解释器,所以每次调用的开销一遍又一遍地付,而每个中间值都必须保持存活,直到函数结束。在单个慢设备上这几乎看不出来;一旦算术在快速的 GPU 上运行,记账就开始占主导。
机制 2
第一次读取主宰了内存的代价
发送地址并建立传输大约花 100 ns,而随后的每条记录大约 0.2 ns 就到了。因此起头的那次读取比后继者贵几百倍,所以读取很长的连续运行,把这一建立开销摊到许多记录上,而分散的访问每次都要重新付。
机制 3
缓存让断粮的核心有东西吃
一个带向量单元的 2 GHz 四核处理器可以消耗大约 256 GB/s,但它的内存接口只供给 20-40 GB/s,所以核心会闲着等数据。小而快的本地存储(L1/L2/L3)容纳工作集,让它被重用而不是被重新取回,这就是为什么要把芯片面积花在它们身上。
常见误读
一旦数据并行就位,增加更多 GPU 就会缩短训练时间。
只有当每块 GPU 有足够的工作时才会出现加速。在 Fashion-MNIST 上训练 LeNet,批量大小和学习率不变,用两块 GPU,测试准确率大致相同,也没有带来有意义的加速,因为模型实在太小,让额外的设备忙不起来。
“不幸的是,这里得不到有意义的加速:模型实在太小;而且我们只有一个小数据集,我们实现多 GPU 训练的略显不成熟的做法,遭受了显著的 Python 开销。”
“Unfortunately there is no meaningful speedup to be gained here: the model is simply too small; moreover we only have a small dataset, where our slightly unsophisticated approach to implementing multi-GPU training suffered from significant Python overhead.”
§13.5 Training on Multiple GPUs查看原文 →
SSD 只是更快的硬盘,所以任何访问模式在它上面都会很快。
SSD 在吞吐量上确实大获全胜——100,000 到 500,000 IOPs 对硬盘的大约 100,1-3 GB/s 对 100-200 MB/s——但它们是以 256 KB 或更大的整块来写入的,而且单元会磨损,所以按比特的随机写入表现非常差。控制器和固件缓和了这一惩罚,却没有消除它。
“因此,SSD 上按比特的随机写入性能非常差。”
“Consequently bit-wise random writes on SSD have very poor performance.”
§13.4 Hardware查看原文 →
第 13 章的核心概念
- 命令式编程
- 写出逐条运行的语句,Python 解释它们时改变程序的状态。
- 适用处: 方便,也容易调试,但在快速的 GPU 或多块 GPU 上,解释器的开销会增长。
- 符号式编程
- 先定义整个计算,把它编译,然后带着输入运行它。
- 适用处: 更难调试,但允许编译器优化和独立于 Python 的部署。
- 突发读取
- 付一次地址建立的代价之后,读取一长串连续的内存记录。
- 适用处: 只有当访问是顺序的才有帮助;随机读取就失去了这个优势。
- 向量化
- 一条指令在宽寄存器里同时对许多数字进行操作。
- 适用处: 提高 CPU 的吞吐量,但仍然被 GPU 的核心数量远远甩在后面。
- 缓存层次
- 小而快的本地存储(L1/L2/L3),在主存太慢时让核心保持有数据可吃。
- 适用处: 花费芯片面积,而缓存未命中或伪共享会让并行代码更慢。
- 张量核心
- GPU 上专门用于深度学习中小型矩阵乘法的电路。
- 适用处: 只针对 4x4 到 16x16 之间的小矩阵做了优化,取决于精度。
另外 7 个概念
- 数据并行
- 每块 GPU 持有模型的一份完整拷贝,并处理小批量的不同切片;梯度被求和并广播回去。
- 适用处: 不让你训练比一块 GPU 的内存更大的模型。
- 模型并行
- 把网络本身拆分到各 GPU 上,要么把各层分配给设备,要么拆分每一层的通道/单元。
- 适用处: 需要紧密的同步和大量 GPU 间的传输;没有强大的框架支持时不推荐。
- allreduce
- 一种运算,把一个向量在所有设备上求和,并把结果广播回每个设备。
- 适用处: 需要先把数据拷贝到累加的设备上。
- 小批量随机梯度下降
- 在小的随机批量上计算的训练更新;这里每块 GPU 在自己的分片上计算部分梯度。
- 适用处: 有 k 块 GPU 时,有效批量增长 k 倍,所以学习率可能需要调整。
- 参数服务器
- 一个中心的(或分片的)存储,汇总来自工作者的梯度,并把更新后的参数发回去。
- 适用处: 单台服务器有限的带宽使它成为瓶颈;分片到 n 台服务器上则恢复了扩展性。
- 环形同步
- 把梯度切成块,并在 GPU 构成的环上传递,让所有链路同时工作。
- 适用处: 对 p3 和 DGX-2 式的 NVLink 拓扑是最优的,并非对每台服务器都是。
- 带推送和拉取的键值存储
- 一种抽象,工作者按层的键推送梯度,并拉回汇总后的值。
- 适用处: 之所以管用,是因为梯度汇总是一个可交换的归约,所以到达的顺序无关紧要。
第 13 章划线与批注AI 陪读
“编译器可能优化并把上面的代码重写成 print((1 + 2) + (3 + 4)),甚至 print(10)”
“a compiler might optimize and rewrite the above code into print((1 + 2) + (3 + 4)) or even print(10)”
查看原文 →这一节里最干净的例证——但请注意,它挑了一个所有输入都是常量的例子,悄悄地讨好了符号式编程。真实的网络没有这种奢侈。
“这是因为我们不知道变量 e 和 f 是否会被程序的其他部分使用”
“This is because we do not know whether the variables e and f will be used by other parts of the program”
查看原文 →命令式代码真正的代价不是算术,而是无知。解释器必须囤积,因为它们看不到前面。
“这看起来几乎好得难以置信:写和以前一样的代码,只需转换模型”
“This seems almost too good to be true: write the same code as before and simply convert the model”
查看原文 →作者用这样的措辞半承认了这一点。实践中,torch.jit.script 一遇到带有有趣控制流的东西就噎住了——而这恰恰是命令式风格曾被称赞的那种代码。
另外 17 条批注
“Python 是单线程的,这在未来不太可能改变”
“Python is single-threaded and this is unlikely to change in the future”
查看原文 →写得很自信,却已经过时了——移除 GIL 的工作在此之后落地了。值得读作 2020 年代假设的一张快照。
“通过 PyTorch 得到的基准输出快了几个数量级。”
“The benchmark output via PyTorch is orders of magnitude faster.”
查看原文 →一个被有意预先安置的错误结论,两句话之后被收回。好的教学:先让读者感受到没同步的计时的陷阱,再给它命名。
“第一次读取比后续读取贵 500 倍”
“the first read is 500 times as expensive as subsequent ones”
查看原文 →这一个比率,比本章大部分内容更多地解释了深度学习的性能——连续的布局、批处理,以及为什么跨步访问会要你的命。
“能够训练一个网络(例如用一周)与根本无法训练(用 3 个月,从而错过截止日期)之间的区别”
“the difference between being able to train a network (e.g., in a week) and not at all (in 3 months, thus missing the deadline)”
查看原文 →坦率的框定:这里的不可行是制度性的,而不是数学性的。硬件一章真正的主题是截止日期。
“如果它们转得再快得多,就会因盘片受到的离心力而碎裂”
“If they were much faster they would shatter due to the centrifugal force exerted on the platters”
查看原文 →本章最直率的一句话:100 IOPs 的上限不是工程上的懒惰,而是材料科学。是物理决定了这个数字,而不是摩尔定律。
“比特率只随信息密度的平方根增长”
“the bit rate only scales with the square root of the information density”
查看原文 →一个可爱的、宣传不足的后果——容量按面积增长,吞吐量只按穿过它的一条线增长。更密的磁盘排空起来相对更慢。
“不建议把 SSD 用于交换文件或大量聚合的日志文件”
“it is not recommended to use SSDs for swapping files or for large aggregations of log-files”
查看原文 →注意这意味着什么:存储设备的寿命以写入次数来度量,所以你的访问模式实实在在地消耗着硬件。很少有程序员用这样的单位思考。
“这样一块芯片的内存接口只支持 20–40 GB/s 的数据传输,也就是少了一个数量级”
“the memory interface of such a chip only supports 20–40 GB/s data transfer, i.e., one order of magnitude less”
查看原文 →这个算术就是缩小了的整个硬件一章——计算跑到了内存前面 10 倍,而每一个缓存、每一个分块的技巧,都是对这个差距的补偿。
“在这个操作期间,两个处理器都在等待。”
“During this operation both processors wait.”
查看原文 →伪共享是本章最好的警示故事:两个在逻辑上毫无共同之处的线程,被一个缓存行串行化了。并行被几何结构惩罚了。
“硬件与算法的这种共同演化,导致了这样一种局面:无论好坏,深度学习是首选的统计建模范式。”
“This co-evolution of hardware and algorithms has led to a situation where for better or worse deep learning is the preferable statistical modeling paradigm.”
查看原文 →“无论好坏”承担了重担。作者们承认这个方法获胜,部分是因为硅片碰巧偏爱稠密的矩阵乘法——一个关于芯片的事实,冒充成关于智能的事实。
“稀疏矩阵和向量的访问模式,与 GPU 所擅长的高带宽突发读取操作不太合拍”
“the access pattern of sparse matrices and vectors do not go well with the high bandwidth burst read operations where GPUs excel”
查看原文 →前一个承认的反面:任何稀疏或不规则的东西,都被逐出研究的时尚,不是因为它是错的,而是因为它基准测试成绩差。
“各个块可以按需增加或移除,以便得到更紧凑的芯片并处理良率问题(有缺陷的模块可能不被启用)”
“individual blocks can be added or removed as needed to allow for more compact chips and to deal with yield issues (faulty modules might not be activated)”
查看原文 →所以你在其间选购的产品等级,部分是一张制造缺陷的地图。“中端”的 GPU 往往是一块坏掉的旗舰,被老实地卖了出去。
“任何头脑正常的机器学习研究者,都不会用它来构建服务器集群。”
“No machine learning researcher within their right mind would use it to build a cluster of servers.”
查看原文 →一个罕见的笑话,当之无愧地占有一席之地——它通过展示设计空间的一角是荒谬的,让四个设计参数变得好记。
“我们建议你,在验证实验结果之前,先在纸上勾勒出一个新算法的性能。”
“We recommend that you sketch out the performance of a novel algorithm on paper before verifying the experimental results.”
查看原文 →这一节真正的寓意,而且是方法论的,不是事实性的:如果你不能把自己的吞吐量预测到一个数量级之内,你就不理解自己的代码。
“这仍然是一个困难的问题,而且不清楚是否有可能在非平凡的问题上取得良好的(线性的)扩展。”
“It remains a difficult problem and it is unclear whether it is possible to achieve good (linear) scaling on nontrivial problems.”
查看原文 →令人耳目一新:一本教科书以开放的耸肩而不是一份食谱结束一个小节。模型并行被点了名,然后被礼貌地挥手打发了。
“因此,由于其带宽代价和复杂性,我们不推荐这种方法。”
“Thus, we do not recommend this approach due to its bandwidth cost and complexity.”
查看原文 →正文中间一句直率的裁决。书解释模型并行,主要是为了告诉你别用它——这是 2GB GPU 时代的历史遗物,为了教学而保留下来。
“然而,增加更多 GPU 并不能让我们训练更大的模型。”
“However, adding more GPUs does not allow us to train larger models.”
查看原文 →让本章过时的一句话。写于模型能放进一张卡的时候;今天的大模型时代恢复的,恰恰是刚被打发掉的模型并行。
读后感AI 陪读
计算跑在喂它的内存前面:优化的根源
这一章是全书里深度学习不再是数学、而成为有预算的工程问题的唯一地方,它的弧线是从抽象一路稳步下降到物质。它以编程范式——命令式对符号式——开篇,并给出老实的诊断:解释器的罪过不是算术慢,而是无知:它必须囤积每一个中间量,因为它看不到下一行想要什么。所选的例证(输入全是常量,折叠成 print(10))悄悄地讨好了符号式的一边,而书自己的对冲,“这看起来几乎好得难以置信”,告诉你这些脚本化工具对带有有趣控制流的代码实际交付的是什么。然后地板落到硬件上,这里本章变得真正出色:一个算术比较——一块芯片计算得比它的内存接口所能喂的快一个数量级——悄悄解释了此后每一个缓存、分块和批处理的技巧。第一次读取比后续读取贵 500 倍,解释了连续的布局;旋转盘片的 IOPs 上限是由离心力而不是摩尔定律设定的;比特率只随信息密度的平方根增长,所以更密的磁盘排空起来相对更慢;SSD 的寿命以写入次数来度量,这意味着你的访问模式实实在在地消耗着硬件。伪共享是书里最好的警示故事:两个在逻辑上毫无共享的线程,被缓存行的几何结构串行化了。从这里开始,它爬回多 GPU 训练——网络划分和按层拆分被点了名,又被礼貌地打发掉,数据并行用 allreduce 从零实现,然后交给框架——最后是参数服务器、环形同步和推/拉键值抽象,其中组织原则总是带宽拓扑,而不是优雅。我看穿的,也是我认为本章最勇敢的时刻,是那句括号里的“for better or worse”(无论好坏):承认深度学习获胜,部分是因为硅片碰巧奖励稠密的矩阵乘法,而任何稀疏或不规则的东西,都因为基准测试成绩差而被逐出研究的时尚,而不是因为它是错的。这是一个关于芯片的事实披着关于智能的事实的外衣,而作者们让它留在那里。同样的坦率贯穿于把不可行框定为制度性的——一周对三个月、以及错过截止日期——也贯穿于 GPU 产品等级,它们部分是一张制造缺陷的地图,中端的卡是一块关掉了一些模块的旗舰。本章也显然是一份 2020 年前后的文献。“Python 是单线程的,这在未来不太可能改变”此后已被超越;而“增加更多 GPU 并不能让我们训练更大的模型”这句话,是让一切过时的句子,因为大模型时代恢复的,恰恰是本章主要为了劝阻你而解释的模型并行。不要把这些读作错误,而要读作关于约束曾经是什么的化石记录。我会这样告诉读者:认真对待方法论的建议,因为那才是真正的寓意,它比这里的每一个数字都活得更久——在测量之前,先在纸上勾勒你的算法的预期性能。关于 PyTorch“快了几个数量级”的那个被预先安置的错误结论,在解释了同步之后两句话就被收回,它的存在是为了教你,基准测试默认是撒谎的。如果你不能把自己的吞吐量预测到一个数量级之内,你就还没有理解你的代码,而且没有哪个框架会替你理解它。学比率,不要学规格;规格会过期,比率则继续主宰。
在 FeedLitra 里读第 13 章,每段旁边都有这些卡片。
开始读书第 14 章:计算机视觉
图像增广和微调改善泛化的方式究竟有何不同?
第 14 章是怎样展开的AI 辅助
开篇。 本章从日常的利害关系而不是理论出发,为计算机视觉奠基:医学诊断、自动驾驶汽车、摄像头监控、智能滤镜。附在这些例子上的论断是,深度学习是近来进展背后的引擎,而组织性的想法由此而来——CNN 学到的逐层图像表示可以跨任务重用。从这个前提出发,作者为本章规划了一条路线:先是图像增广和微调,被呈现为泛化的工具;然后是目标检测;然后是语义分割;然后是风格迁移;最后是两个流行的基准数据集,在那里本章的内容和更早各章的内容被一起应用。因此,开篇既是动机又是地图,而地图是按顺序兑现的。
第一段展开:从“是什么”到“是什么、在哪里”。 目标检测作为分类问题的拓宽而登场——模型必须说出类别并定位它——本章用它最长的篇幅,构建让位置变得可训练的机制。位置成为两种可以互相转换的格式的边界框;锚框随后在各个尺度和宽高比上按像素生成;IoU 提供了相似性度量;而一个指派算法把每个锚框变成一个带标签的训练样本。演练的 IoU 矩阵是这里教学的核心:最大的元素把真实框 B3 指派给锚框 A2,那一行和那一列被划掉,过程重复,给出 B1→A7、B4→A5、B2→A9,之后剩下的锚框只有在它们的 IoU 超过 0.5 时才被匹配。对一只狗和一只猫运行,这使得 A4 是猫,A1 是狗,A2 因阈值是猫,而 A0 和 A3 低于阈值,成为背景——负锚框。预测随后把标注反过来运行:偏移被反演以恢复出框,而非极大值抑制修剪掉重叠。
检测内部的转折:一项成本约束重塑了设计。 本章最举足轻重的动作,是让一个计数论证来规定架构。覆盖每一个尺度—比例对,会产生 w·h·n·m 个框,而在一张 561×728 的图像上,即使每个像素五个,也已经产生了两百多万个需要标注和预测的框。因此作者只保留共享第一个尺度或第一个比例的对——每个像素 n+m−1 个——并对像素采样而不是使用所有像素,公开接受有些真实的形状会被漏掉。因为锚框必须被这样限量,预测不能来自对像素的全连接层;它们是在多个尺度的特征图上以卷积方式做出的。一个带填充 1 的 3×3 卷积在各位置之间共享参数,一个空间位置上的单元共享一个感受野,十张 4×4 的图给出十六组锚框,每个共享中心三个锚框。较小的顶层特征图带有较大的感受野,因此适合较大的物体。SSD 恰恰把这一点付诸操作:一个基础网络加上多尺度块,在 256×256 的输入上,产生 32、16、8、4 和 1 的特征图——5444 个锚框,尺度从 0.2 到 0.88——它们的输出在三个维度上各不相同,被展平以便可以拼接。小批量的标签被填充成 (batch, m, 5),用 −1 标记非法的框,而损失的改进(平滑 L1、焦点损失)为这一节收尾。
第二段展开:同样的效率逻辑,用在 R-CNN 家族上。 本章随后把检测的历史重述为一连串被移除的冗余。R-CNN 对每个区域候选运行一次 CNN,所以几千个候选意味着几千次对严重重叠的像素的前向传播;fast R-CNN 对整张图像只运行一次 CNN,让 RoI 池化通过子窗口最大值,把每个候选的特征裁成固定形状,重叠的工作只计算一次。一旦冗余的计算消失了,下一个收益来自学习候选本身:faster R-CNN 把区域候选网络自己的二分类和框预测折进目标函数,这样候选是端到端训练的,用少得多的候选也能保持准确率。Mask R-CNN 通过利用像素级的标签走了最后一步——RoI 池化让位于带双线性插值的 RoI 对齐,以保留空间信息,再加上一个预测像素级位置的全卷积头。最后这一步也是通往下一个任务的铰链。
第三段展开:下沉到像素。 语义分割和 Pascal VOC2012 数据集把标注转移到像素层面,其中标签本身是图像,相同颜色的像素共享一个类别。这是本章停下来纠正一个诱人的捷径的地方:分割数据不能像分类图像那样被缩放,因为把预测出来的像素类别缩放回原来的大小是不准确的——所以特征和标签被一起裁剪到固定的 320×480 区域。使像素分辨率的输出成为可能的机制是转置卷积,先是直观地引入(让输入通过核广播),然后是代数地:把卷积写成 y = Wx,W 是一个稀疏的 4×9 矩阵,那么上采样运算就是乘以形状为 9×4 的 Wᵀ。因此这个层只是调换了卷积的前向和反向过程,随之而来的是第二个纠正:它不是逆。在超参数匹配的情况下,一个 10→20 的卷积后跟一个 20→10 的转置卷积,返回一个形状为 (1, 10, 16, 16) 的张量——但形状一致并不说明值一致。FCN 随后堆叠 CNN 特征、一个 1×1 层和转置卷积,为每个输入像素发出一个类别预测。
收尾:还有什么可以被训练,以及在真实数据上会发生什么。 风格迁移提供了本章概念上的倒置:这里可训练的东西是合成的图像本身。它被存为一个模型参数,其前向过程只是返回它,使它成为唯一被更新的变量,而一个冻结的预训练 VGG 提供特征——内容来自第四块的最后一个卷积层,风格来自每一块的第一个卷积层,风格被编码为格拉姆矩阵。内容、风格和总变差损失按 1、1e4 和 10 加权,经过 500 个轮次,产生一幅图像,保留了内容照片的风景,同时采用了风格图像的色块;作者坦率地说,这只是一次凭肉眼判断的定性运行,那些权重是特定于实验的旋钮,在保留、风格化和平滑之间做取舍。本章随后落在两个 Kaggle 基准上,在那里工作明显从模型设计转向了数据管道和特征重用。CIFAR-10 意味着把原始图像文件重新组织成按类别的文件夹,并留出验证集(50000 张训练图像和 300000 张测试图像,其中 290000 张不评估以防作弊),做增广,训练 ResNet-18,再在训练加验证集上重新训练以利用所有标签,然后提交。120 个犬种的任务把同样的配方放大到更大的 ImageNet 式图像——随机缩放裁剪到 224,比例 0.08–1.0,加上色彩抖动——并把一个冻结的预训练 ResNet-34 的 1000 维输出送入一个小的 1000-256-120 头。只有这个头被迭代,这节省了计算和内存,但正如作者所指出的,让提取器无法适应新的任务。本章就这样结束在它开始的地方——被重用的预训练表示上——只是现在代价和局限都被明确了。
关键论点,以及支撑它们的原文
深度学习是近来计算机视觉进步背后的力量,而本章是围绕重用 CNN 学到的逐层图像表示来组织的。
作者点名医学诊断、自动驾驶汽车、摄像头监控和智能滤镜,作为立足于视觉的日常系统,然后设定本章的路线:用图像增广和微调帮助泛化,然后是目标检测、语义分割和风格迁移,最后把本章和早先各章的内容应用到两个流行的基准数据集上。
“近年来,深度学习一直是推动计算机视觉系统性能前进的变革性力量。”
“In recent years, deep learning has been the transformative power for advancing the performance of computer vision systems.”
Chapter 14. Computer Vision查看原文 →
检测把每个锚框变成一个训练样本,其类别和偏移标签来自一个贪心的最大 IoU 指派,外加阈值回退。
在演练的 IoU 矩阵里,最大的元素把真实框 B3 指派给锚框 A2,它的行和列被划掉,过程重复,给出 B1→A7、B4→A5、B2→A9;只有在那之后,剩下的锚框才被匹配,而且只有当它们的 IoU 超过预先定义的 0.5 时。对一只狗和一只猫的五个锚框运行这一过程,使 A4 是猫,A1 是狗,A2 因阈值是猫,而 A0 和 A3 低于 0.5,成为背景——负锚框。
“为了训练一个目标检测模型,我们需要为每个锚框准备类别和偏移标签,前者是与该锚框相关的物体的类别,后者是真实边界框相对于该锚框的偏移。”
“In order to train an object detection model, we need class and offset labels for each anchor box, where the former is the class of the object relevant to the anchor box and the latter is the offset of the ground-truth bounding box relative to the anchor box.”
§14.4 Anchor Boxes查看原文 →
因为锚框必须被限量,预测是在多个尺度的特征图上以卷积方式做出的,而不是对像素用全连接层。
用全连接层对每个尺度上的 h·w·a 个锚框分类,被称为不可行,所以一个带填充 1 的 3×3 卷积在所有位置之间共享参数;一个空间位置上的单元共享一个感受野,所以十张 4×4 的图给出 16 组锚框,每个共享中心 3 个锚框。较小的顶层特征图有较大的感受野,因此适合较大的物体:SSD 的五个块在 256×256 的输入上给出 32、16、8、4 和 1 的特征图,也就是 5444 个锚框,尺度从 0.2 到 0.88,而在三个维度上各不相同的输出被展平,这样就可以拼接。
“我们利用输入图像在某个感受野内的信息,来预测输入图像上靠近该感受野的锚框的类别和偏移。”
“we use the information of the input image in a certain receptive field to predict the classes and offsets of the anchor boxes that are close to that receptive field on the input image.”
§14.5 Multiscale Object Detection查看原文 →
另外 3 个论点
去掉了冗余的计算之后,下一个收益来自学习候选本身,然后是把特征对齐到像素。
Faster R-CNN 的目标函数包含区域候选网络自己的二分类和框预测,所以候选是端到端训练的,网络学会生成高质量的候选——用少得多的候选也能保持准确率。Mask R-CNN 随后通过把 RoI 池化换成使用双线性插值来保留空间信息的 RoI 对齐层,加上一个预测像素级位置的全卷积头,来利用像素级的标签。
“由于端到端的训练,区域候选网络学会了如何生成高质量的区域候选,这样就能用从数据中学到的、数量减少的区域候选,在目标检测中保持准确。”
“As a result of the end-to-end training, the region proposal network learns how to generate high-quality region proposals, so as to stay accurate in object detection with a reduced number of region proposals that are learned from data.”
§14.8 Region-based CNNs (R-CNNs)查看原文 →
在风格迁移中,可训练的东西是合成的图像本身,预训练的网络保持固定,由三个加权的损失决定结果。
作者把合成的图像存为一个模型参数,其前向过程只是返回它,这样它就是训练期间唯一被更新的变量,而一个冻结的预训练 VGG 提供特征——内容来自第四块的最后一个卷积层,风格来自每一块的第一个卷积层,风格被编码为格拉姆矩阵。内容、风格和总变差损失按 1、1e4 和 10 加权,经过 500 个轮次,给出一幅保留内容照片的风景和物体、同时采用风格图像的色块的图像;这只是一次凭肉眼判断的定性运行,那些权重是特定于实验的旋钮,用来在保留、风格化和平滑之间做取舍。
“这幅合成的图像是风格迁移过程中唯一需要更新的变量,也就是训练期间需要更新的模型参数。”
“This synthesized image is the only variable that needs to be updated during the style transfer process, i.e., the model parameters to be updated during training.”
§14.12 Neural Style Transfer查看原文 →
在真实的竞赛数据上,工作从模型设计转向整理文件,以及重用与数据集相称的冻结的预训练特征。
原始的 Kaggle 图像被重新组织成按类别的文件夹,并留出验证集——CIFAR-10 竞赛集有 50000 张训练图像和 300000 张测试图像,其中 290000 张不评估以防作弊,而最终的模型在训练加验证集上重新训练,以利用所有标签。对于 120 个犬种,更大的、大小不一的 ImageNet 式图像得到不同的增广(随机缩放裁剪到 224,比例 0.08–1.0,加上色彩抖动),而一个预训练的 ResNet-34 把 1000 维的特征送入一个小的 1000-256-120 头;只有这个头的参数被迭代,这节省了计算和内存,但让提取器无法适应新的任务。
“整理完数据集之后,同一类别的图像将被放在同一个文件夹下。”
“After organizing the dataset, images of the same class will be placed under the same folder.”
§14.13 Image Classification (CIFAR-10) on Kaggle查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么锚框要按每个像素设上限
覆盖每一个尺度—比例对,会产生 w·h·n·m 个框,而在一张 561×728 的图像上,即使每个像素五个,也已经产生了两百多万个需要标注和预测的框。所以作者只保留共享第一个尺度或第一个比例的对,每个像素 n+m−1 个,并改为对像素采样——接受有些真实的形状会被漏掉。
机制 2
所有候选共享一次 CNN 前向
R-CNN 对每个区域候选运行一次 CNN,所以每张图像几千个候选,意味着几千次对严重重叠的像素的前向传播。Fast R-CNN 对整张图像只运行一次 CNN,让 RoI 池化通过子窗口最大值,把每个候选的特征裁成固定形状,这样重叠的工作只计算一次。
机制 3
转置卷积是矩阵转置
把卷积写成 y = Wx,W 是一个稀疏的 4×9 矩阵;上采样运算就是乘以形状为 9×4 的 Wᵀ,这就是这个层只是调换了卷积的前向和反向过程的原因。超参数匹配时,就还原出输入的形状——只是形状,而不是值——让网络为每个输入像素发出一个预测。
常见误读
转置卷积是卷积的逆,所以在卷积之后运行它就会还原出原来的输入。
它只是调换了卷积的前向传播和反向传播——等价地说,乘以转置后的权重矩阵。超参数匹配时,它还原出输入的形状,就像一个 10→20 的卷积后跟一个 20→10 的转置卷积,返回一个与原来的 (1, 10, 16, 16) 形状相同的张量,但形状一致并不说明值一致。
“因此,转置卷积层只需调换卷积层的前向传播函数和反向传播函数:它的前向传播和反向传播函数,分别把输入向量乘以 $\mathbf{W}^\top$ 和 $\mathbf{W}$。”
“Therefore, the transposed convolutional layer can just exchange the forward propagation function and the backpropagation function of the convolutional layer: its forward propagation and backpropagation functions multiply their input vector with \(\mathbf{W}^\top\) and \(\mathbf{W}\), respectively.”
§14.10 Transposed Convolution查看原文 →
分割数据可以像分类图像那样缩放到固定形状,因为任何输出之后都可以被缩放回去。
这里的标签是图像,其中相同颜色的像素共享一个语义类别,而把预测出来的像素类别缩放回原来的大小是不准确的;因此作者把特征和标签一起裁剪到固定的 320×480 区域,而不是缩放。
“为了避免这个问题,我们把图像裁剪成固定的形状,而不是缩放。”
“To avoid this issue, we crop the image to a fixed shape instead of rescaling.”
§14.9 Semantic Segmentation and the Dataset查看原文 →
第 14 章的核心概念
- 泛化
- 一个训练好的模型在它没见过的数据上表现如何,而不只是在它的训练图像上。
- 适用处: 这里是通过数据一侧和初始化一侧的技巧来追求的,而不是通过新的架构。
- 逐层的表示
- 深度网络同时在几个抽象层次上编码一幅图像,这些层次可以被许多视觉任务重用。
- 适用处: 被表述为本章后面各节的组织性想法,在这一段里还没有演示。
- 目标检测
- 一种视觉任务,既找出图像里有什么物体,也找出它们在哪里。
- 适用处: 不同于分类,它假定可能存在多个感兴趣的物体。
- 边界框
- 标出物体位置的矩形,由两个对角,或由中心加宽和高来给出。
- 适用处: 只限矩形;它无法描述物体的确切轮廓。
- 锚框
- 在每个像素上以不同的尺度和宽高比生成的许多候选框之一,之后向真实框的方向调整。
- 适用处: 使用所有尺度—比例的组合代价太高,所以只保留含有第一个尺度或第一个比例的组合。
- 交并比(IoU)
- 两个框的像素集合的杰卡德指数:交集面积除以并集面积。
- 适用处: 范围从 0(没有重叠)到 1(两个框相同)。
另外 21 个概念
- 非极大值抑制
- 按置信度给预测框排序,保留最高的那个,丢掉与之重叠超过 IoU 阈值的任何框;重复。
- 适用处: 一个贪心的移除规则,所以有用的框可能被删掉;存在软化的变体。
- 锚框的标注
- 每个锚框从与其 IoU 最高的真实框得到一个类别,如果那个 IoU 低于阈值,则为背景。
- 适用处: 取决于所选的 IoU 阈值,比如 0.5;背景的偏移被掩码掉。
- 多尺度锚框
- 使用不同分辨率的特征图,来放置少量大锚框或大量小锚框,而不是在每个像素上都放锚框。
- 适用处: 假定特征图一个位置上的单元在输入上共享一个感受野。
- 偏移掩码
- 一个零/一的掩码,把背景锚框的偏移标签置零,这样它们就不影响损失。
- 适用处: 只过滤偏移,不过滤类别标签。
- 单发多框检测(SSD)
- 一种检测模型,堆叠一个基础网络和几个逐步缩小的特征图块,在每个尺度上预测锚框的类别和偏移。
- 适用处: 众多检测器中的一种,尽管它的设计原则可以迁移。
- 填充的非法边界框
- 加进去的一行哑标签,使每张图像都有 m 个框;它的类别是 -1,这样就可以被忽略。
- 适用处: 只是因为小批量的拼接要求框的数量相等才需要。
- 类别预测层
- 一个输出 a(q+1) 个通道的 3x3 卷积,这样每个空间位置携带以此为中心的所有锚框的类别得分。
- 适用处: 取代全连接层,以避免过重的参数化。
- 下采样块
- 两个带填充的 3x3 卷积加步幅为 2 的 2x2 最大池化,让高和宽减半,并扩大感受野。
- 适用处: 借用了 VGG 块的设计。
- 焦点损失
- 一种重新加权的交叉熵,缩小已经被很好分类的样本的损失,让训练专注于困难的样本。
- 适用处: 需要超参数 gamma 和 alpha;主要在容易的负样本占主导时有用。
- 感兴趣区域(RoI)池化层
- 一个输出形状由你直接指定的池化层,这样形状不同的区域产生形状相同的特征。
- 适用处: 会对子窗口大小取整,所以与 RoI 对齐相比,它丢失了精细的空间精度。
- 区域候选网络
- 一个小网络,在锚框上预测物体/背景和框,以产生候选,并与检测器联合训练。
- 适用处: 只取代选择性搜索;fast R-CNN 流水线的其余部分不变。
- 语义分割
- 按语义类别把图像划分成区域,在像素层面上标注和预测。
- 适用处: 不区分单个的实例;那是实例分割。
- 转置卷积
- 一个 CNN 层,通过让每个输入元素穿过核铺开、并把重叠的结果相加,来扩大高和宽。
- 适用处: 填充施加在输出上,步幅指的是中间结果,而不是输入;形状与输入相同并不意味着值相同。
- 全卷积网络
- 一种网络,提取 CNN 特征,用 1x1 卷积把通道映射到类别,然后上采样回输入的高和宽。
- 适用处: 在步幅为 32 的上采样下,高或宽不能被 32 整除的输入,需要裁剪成 32 的倍数。
- 双线性插值上采样
- 通过把每个输出像素映射回实数值的输入坐标,并按距离把最近的四个像素混合,来缩放图像。
- 适用处: 这里主要用作转置卷积核的初始化,而 1x1 层使用 Xavier 初始化。
- 风格迁移
- 优化一幅图像,使它保留一幅图像的内容,同时采用另一幅的风格。
- 适用处: 需要一个预训练的特征提取器和逐图像的优化,而不是单次前馈。
- 格拉姆矩阵的风格表示
- 一个层的特征在通道之间的相关,用作风格的签名。
- 适用处: 除以 chw,这样数值不会随特征图的大小增长。
- 总变差损失
- 对相邻像素之间差异的惩罚,平滑高频噪声。
- 适用处: 减少噪声,但权重过大会过度平滑细节。
- 内容层和风格层
- 选定的 VGG 层,其输出定义内容和风格特征。
- 适用处: 靠近输入的层捕捉细节,靠近输出的层捕捉全局信息。
- 冻结的预训练特征提取器
- 保持预训练网络的权重固定,把它的输出用作固定的图像特征。
- 适用处: 当新任务的数据接近预训练的分布时管用,比如 ImageNet 的一个子集。
- 图像增广
- 只在训练期间施加的随机变换,用来扩大有效的数据多样性。
- 适用处: 增广的随机性在验证和预测时必须去掉。
第 14 章划线与批注AI 陪读
“图像增广在当时很可能对 AlexNet 的成功是不可或缺的。”
“It is probably true that image augmentation was indispensable for the success of AlexNet at that time.”
查看原文 →“很可能是真的”在教科书里是个古怪的对冲。老实,但它揭示出深度学习的民间说法有多少建立在未经检验的归因而不是消融实验上。
“对训练样本的随机调整,使模型更少依赖某些属性”
“random tweaks of training examples allow models to rely less on certain attributes”
查看原文 →这才是真正的论证,而且比“更多数据”更强。增广是关于我们想要哪些不变性的编码先验——一个作为数据技巧偷渡进来的、关于世界的论断。
“上下翻转不如左右翻转常见。”
“Flipping up and down is not as common as flipping left and right.”
查看原文 →书从来没说为什么,而理由很要紧:重力。我们的视觉世界在垂直方向上是不对称的,所以垂直翻转可能产生一幅从不出现的图像。这里的沉默掩盖了一个真正有趣的原则。
另外 16 条批注
“这个对比实验能否支持“图像增广可以缓解过拟合”这个论点?为什么?”
“Can this comparative experiment support the argument that image augmentation can mitigate overfitting? Why?”
查看原文 →这一节最尖锐的一句话,而且是在习题里。它悄悄邀请读者怀疑正文刚刚断言的东西——在 CIFAR-10 上跑一次,几乎什么也证明不了。
“研究者花费了研究经费中的几百万美元”
“researchers have spent millions of dollars from research funding”
查看原文 →经济学浮出水面的罕见时刻。迁移学习被推销为一种技术方法,其实它是摊销别人资本的一种办法——预训练的权重是一种补贴。
“我们假定这些模型参数包含从源数据集学到的知识,而这些知识也将适用于目标数据集。”
“We assume that these model parameters contain the knowledge learned from the source dataset and this knowledge will also be applicable to the target dataset.”
查看原文 →两个叠在一起的假设,事先都无法验证。微调管用,而没有人能事先告诉你,你的源和目标是否足够接近。这个方法从头到尾都是经验性的。
“输出层的模型参数将使用 $10\eta$ 的学习率来迭代”
“a learning rate of \(10\eta\) will be used to iterate the model parameters in the output layer”
查看原文 →10 是从哪里来的?哪里也不是——是一个披着记号外衣的、行之有效的启发式。值得注意深度学习的实践有多少是靠这样的数字运转的。
“事实上,ImageNet 数据集里有一个“热狗”类。”
“In fact, there is a “hotdog” class in the ImageNet dataset.”
查看原文 →一个令人愉快的笑点:整个演示微调的是一个本来就知道答案的模型。习题把教程自己的设定变成了笑话,然后让你去利用它。
“我们假定图像中只有一个主要物体,并且只关注如何识别它的类别”
“we assume that there is only one major object in the image and we only focus on how to recognize its category”
查看原文 →书在这里终于承认了此前每一章所倚靠的虚构。分类从来不是对“看”的描述;它是对“看”的一次方便的截肢。
“虽然这些锚框可能覆盖所有的真实边界框,但计算复杂度很容易过高。”
“Although these anchor boxes may cover all the ground-truth bounding boxes, the computational complexity is easily too high.”
查看原文 →每一种锚框方案背后的老实承认:穷尽式的覆盖只有在你把它削弱之后才负担得起。n+m-1 的招数纯粹是披着设计外衣的预算算术。
“in_height / in_width # Handle rectangular inputs”
查看原文 →一整个几何上的头疼事,埋在一条尾随的注释里。归一化的坐标使宽高比 r 的含义,与上面公式所承诺的不同——文本从没这么说。
“我们需要为每个锚框准备类别和偏移的标签”
“we need class and offset labels for each anchor box”
查看原文 →这是真正的概念支点:检测不再是“找到那个框”,而变成了在一个固定的猜测网格上做分类加回归。此后的一切都机械地跟着来。
“只有当这个 IoU 大于预先定义的阈值时,才把 $B_j$ 指派给 $A_i$”
“assign \(B_j\) to \(A_i\) only if this IoU is greater than a predefined threshold”
查看原文 →两种指派体制被粘在一起——对 n_b 个框的贪心全局匹配,然后是带阈值的自由混战。接缝在 A0 和 A3 掉出去成为背景的例子里显露了出来。
“我们可以对这些相对位置和大小施加变换,这可能导致更均匀分布、更容易拟合的偏移”
“we can apply transformations to those relative positions and sizes that may lead to more uniformly distributed offsets that are easier to fit”
查看原文 →这一节最坦率的一句话。代码里那些 10 和 5 不是物理学,而是为让梯度表现良好而选的白化常数。深度学习的手艺层,短暂地显露了出来。
“由于我们不关心背景检测,这个负类的偏移不应影响目标函数”
“Since we do not care about background detection, offsets of this negative class should not affect the objective function”
查看原文 →这个掩码就是教一个损失函数闭嘴的办法。负样本仍然对类别投票,只是不对几何投票——一种值得注意的不对称。
“那些置信度得分不是最大的被抑制”
“those with non-maximum confidence scores are suppressed”
查看原文 →NMS 是对模型从未学会为每个物体输出一个框的坦白。我们在推理时硬加上一个手写的贪心过滤器,却把这条流水线叫作端到端的。
“combined = torch.cat((keep, all_idx))”
查看原文 →一个靠统计重复来做的集合差——聪明,但它之所以管用,只是因为 all_idx 保证是唯一的。一种被当作惯用法的脆弱习语。
“conf[below_min_idx] = 1 - conf[below_min_idx]”
查看原文 →悄悄地重新解释了置信度那一列:对背景条目来说,它现在表示对背景的置信度。容易读错输出张量。
“$1 \times 1$、$1 \times 2$ 和 $2 \times 2$ 的物体在一幅 $2 \times 2$ 的图像上,分别可以以 4、2 和 1 种可能的方式出现”
“1 \times 1\), \(1 \times 2\), and \(2 \times 2\) objects can appear on a \(2 \times 2\) image in 4, 2, and 1 possible ways”
查看原文 →一个组合论证,顶替了一个统计论断。数出放置的方式,并不等于小物体在真实照片中更常见——这个直觉很可爱,但不是推导出来的。
读后感AI 陪读
一章教科书承认,分类是对视觉的一次截肢
这一章读起来像一场缓慢的坦白。它以两个泛化的技巧开篇,以两个 Kaggle 排行榜结束,而在中间,它拆掉了此前每一章所站立的前提。露出马脚的是目标检测开头的一句话:到目前为止“我们假定图像中只有一个主要物体”。这个假设从来不是关于图像的事实;而是对“看”的一次截肢,方便到我们把它叫作分类。一旦本章承认了这一点,此后的一切都是把缺失的结构放回去的一连串尝试——先是框,然后是像素,然后在风格迁移里,是图像本身成为被优化的对象。
展开的内容对它自己的机制出奇地老实,而老实多半在页边。增广被说成是“更多数据”,但真正的论证埋在一行之后:随机的调整使模型更少依赖某些属性。这不是一个数据技巧,而是关于世界有哪些不变性的先验——这就是为什么左右翻转是标准的而上下翻转不是。书从来没说重力这个词,而这种沉默让读者错过了一个真正有趣的原则。微调被框定为技术,但文本不小心提到了几百万美元的研究经费;预训练的权重是一种补贴,而迁移学习是花别人的资本的记账方法。有两个叠在一起的、无法验证的假设撑着它——参数包含知识,以及这些知识可以迁移——没有人能事先告诉你,你的源和目标是否足够接近。输出层 10 倍的学习率不知从何而来。热狗的演示微调了一个在 ImageNet 里本来就有热狗类别的网络,而习题难能可贵地把这变成了笑话,然后让你去利用它。
继续阅读
检测各节是手艺层显露得最清楚的地方。锚框起初是穷尽式的覆盖,随即被削弱到负担得起的程度:n+m−1 的招数是披着设计外衣的预算算术。要紧的支点很安静——“我们需要为每个锚框准备类别和偏移的标签”——在它之后,检测不再是“找到物体”,而是在一个固定的猜测网格上做分类加回归,这就是为什么此后的一切都机械地跟着来。指派把两种不相容的体制粘在一起,一个贪心的全局匹配,然后是一个带阈值的自由混战,接缝在那个有两个锚框干脆掉出去成为背景的演练例子里清晰可见。偏移变换是本章最坦率的一句话:那些神奇的 10 和 5 之所以存在,是为了让梯度表现良好,而不是因为几何要求它们。对背景偏移的掩码,教会损失在几何上保持沉默,同时仍对类别投票。而 NMS 是所有承认中最坦率的——一个手写的贪心过滤器,在推理时硬加上去,放在一条我们一直称为端到端的流水线里,因为模型从来没有学会为每个物体发出一个框。演示中把偏移置零,干净地隔离了 NMS,这在教学上是对的,在实践中却有误导:真实的偏移会让基于 IoU 的抑制删掉正确的框。也要留意实现的细节——通过统计重复来做的集合差,之所以管用只是因为索引数组是唯一的,而置信度那一列对背景行默默地翻转了含义。
从 SSD 出发,本章爬上 R-CNN 家族,读成一条弧线,它是同一个想法的重复:别再重新计算你可以共享的东西。逐候选区域的特征变成共享的特征,手工做的候选区域变成学出来的,粗糙的池化变成像素对齐的。然后语义分割把标注降到像素,转置卷积提供了往回上升的算术——而矩阵转置的框定是本章给你一个真正的理由而不是一份食谱的唯一地方——FCN 几乎令人扫兴,只是特征加 1×1 加上采样。风格迁移随后把整个设定倒过来:网络被冻结,图像是参数,三个加权的损失在内容、格拉姆矩阵风格和平滑度之间协商。这是书里最清楚的一次演示,说明损失函数是一种偏好的陈述,而不是一次度量。
我最尖锐的判断:本章最严谨的时刻,是习题里的一个问题——这个对比实验能否支持“增广可以缓解过拟合”这个论点?在 CIFAR-10 上跑一次不能,而习题邀请你怀疑它上面一页的文字。这种张力贯穿始终。行文在断言;习题和尾随的注释在拆台。甚至那个可爱的组合论证,说小物体在网格上有更多可能的放置方式,也是在数数,而不是关于真实照片的统计。
所以我会这样告诉读者:别为了架构去读这一章,它们过时得很快。为了数字从哪里来而读它。每当你遇到一个没有推导的常数——10η、那些 10 和 5、一个 IoU 阈值、一个焦点损失的 γ、一个风格权重——就标出来。这些标记就是计算机视觉作为一门学科的真正地图:在厚厚的一层校准过的手艺之上,薄薄的一层原则,由基准测试固定在原位。结尾的两个 Kaggle 小节不是凑数的;它们是本章真正论点的操作形式。整理图像文件夹、选择增广、冻结一个 ResNet-34 并只训练一个小头——这就是实际的工作。理论告诉你上采样是一个转置。竞赛告诉你,别人预训练好的特征,加上细致的管道,才是取胜的东西。两者都是真的,而它们之间的差距,就是你将实际生活的地方。
在 FeedLitra 里读第 14 章,每段旁边都有这些卡片。
开始读书第 15 章:自然语言处理:预训练
BERT 究竟是如何让一个词元的向量随上下文变化的?
第 15 章是怎样展开的AI 辅助
开篇。 本章一开头就点出了自己的前提:有用的文本表示可以从大规模的原始语料库中学出来,无需标注,因为文本自己提供了监督。这个框定立刻把本章要覆盖的领域一分为二——word2vec 和 GloVe 为每个词元产生一个固定的向量,不管它出现在哪里,而 BERT 产生的向量会随上下文弯曲——本章余下的部分,本质上就是从第一种走向第二种的旅程。第 15.1 节随后从底部出发,问一个词嵌入是干什么用的,并先给出否定的回答:独热编码在结构上对相似性毫无用处,因为任意两个不同词的独热向量之间的余弦相似度恰好是零。相似性无法从这样的编码中读出来;它必须被学进实值向量里。从这个缺口出发,作者引入了 skip-gram(从中心词预测周围的词)和 CBOW(反过来),推导了它们的损失和梯度,并把两者归类为自监督:它们所拟合的条件概率,只是从原始语料库里读出来的,所以不涉及任何人工标注。
第一段展开:让训练负担得起。 刚刚推导出的梯度暴露了一个代价问题,而第 15.2 节就是对它的回应。因为两个模型都在整个词典上对预测归一化,每个梯度都带着一个对所有词的求和,所以代价随词表大小缩放。负采样用少数几个独立的是/否判断——一个针对真实的上下文词,K 个针对采样出来的噪声词——取代了那一个归一化的预测,这样代价跟着 K 走,而不是跟着词典走;层次 softmax 作为另一种近似被提供。本章随后变得具体,构建了 PTB 的流水线:对高频词子采样,提取中心/上下文词对,抽取负样本,并用掩码和标签填充小批量,这样变长的上下文集就可以分批了。子采样值得说一说,因为它容易被误认为去除停用词。这种丢弃是概率性的、依赖频率的:只有相对频率高于阈值的词才有资格被丢,而有资格的词有时仍会幸存。在 PTB 上,阈值取 1e-4 时,“the”被保留的比例不到它原来的二十分之一,而不是被删除,而像“join”这样的罕见词则被完整保留。这背后的理由在信息上与在计算上一样多——几乎出现在每个窗口里的词,对意义说得很少,却消耗了大部分计算。流水线就位之后,skip-gram 用带掩码的二元交叉熵进行预训练。
转向全局统计。 本章第一个真正的支点是解释性的,而不是架构性的:它把 skip-gram 的损失重新读作针对全语料共现分布的交叉熵。这个重新框定之所以有用,恰恰因为它暴露了两个缺陷。对预测分布的归一化仍然要求对词表求和,而交叉熵给大语料库所产生的庞大罕见共现事件的长尾,分配了不成比例的权重。GloVe 随后被呈现为对这两者的回答:用一个加权的平方损失去拟合共现计数的对数,加上逐词的偏置项和一个压低交叉熵过度奖励的罕见事件的权重函数。作者小心地表明这种形式不是任意的。从另一头推导,从共现概率的比值出发,p(w|ice)/p(w|steam) 的表——“solid”约 8.9,“gas”约 0.085——显示这个比值追踪着一个词属于这两个词中的哪一个,而要求调换下标会使比值取倒数,就迫使出现指数的形式和偏置加对数计数的方程。因为一个词出现在另一个词的窗口里,蕴含着反过来也成立,计数是对称的(x_ij = x_ji),所以一个词的中心向量和上下文向量在数学上是可以互换的,直接把它们加起来。局限是被标出而不是被藏起来的:“water”(1.36)和“fashion”(0.96)都靠近 1,尽管它们与这一对词处于相反的关系中。这一节从另一个方向攻击罕见词和未见过的词,结束了词层面的线索——fastText 的子词 n 元语法,以及 BPE 为固定大小的词表学出来的变长子词。
第二个转折:上下文。 到目前为止的一切,都共有一个缺陷,再怎么更好地拟合也修不好。如果一个词元得到一个固定的向量,一词多义就无法表示:“a crane is flying”里的“crane”和“a crane driver came”里的“crane”意思不同,却得到同样的向量,“bank”在一个讲钱的句子和一个讲坐下的句子里也一样。这促成了依赖周围序列的表示,而本章按顺序走过这条谱系。ELMo 提供了冻结的双向特征,被硬加到现有的、针对特定任务的模型上——而作者在这里提出了比“特征变好了”更尖锐的论证。他承认 ELMo 在六项 NLP 任务上推进了最先进的水平,然后把这个让步翻转过来:这些系统每一个仍然需要为它自己的任务手工设计的架构,这在各个问题之间无法扩展。瓶颈在架构,而不是特征,所以该领域转向了与任务无关的预训练。GPT 就是这一步,但它是从左到右的,而方向原来在实质上而不是表面上要紧:自回归模型只以前面出现的东西为条件,所以由右侧上下文携带的意义是看不见的。“i went to the bank to deposit cash”与“i went to the bank to sit down”里的“bank”,从 GPT 得到完全相同的表示。任何声称仅仅读一个句子就使模型对上下文敏感的说法,在这里都失败了。BERT 被定位为 ELMo 的双向性与 GPT 的任务无关性的融合,这恰恰是它从两侧预测被掩码词元的原因。
实现与收尾。 本章最后的乐章是建设性的:BERT 的输入嵌入和它的两个预训练任务——掩码语言建模和下一句预测——被用代码实现。掩码的配方得到了它自己的理由,因为 80/10/10 的划分看起来像是个怪癖,直到它所修复的不匹配被点名。人为的掩码符号只在预训练期间存在,在微调时从不出现,所以只用它来训练,就是用模型再也不会见到的输入来训练模型;把被选中位置的一部分换成随机的词或原来的词元,使输入保持真实,而随机的替换充当噪声,阻止模型完全依赖被掩码的槽位。本章随后组装了 MLM 的数据提取、填充,以及一个 WikiText-2 的 Dataset 类,在那个语料上预训练一个小的 BERT,并通过闭合它所打开的循环而结束:词元“crane”被表明在不同的上下文中得到了明显不同的表示。诊断静态向量局限的那个例子,成了局限已被克服的演示——这就是本章赢得自己的弧线,而不只是罗列四个模型的方式。
关键论点,以及支撑它们的原文
独热向量是表示词的死胡同,这就是本章转而从学出来的嵌入出发的原因。
作者指出,任意两个不同词的独热向量之间的余弦相似度恰好为零,所以这种编码在结构上无法说出两个词是相像的——相似性必须被学进实值向量里。
“一个主要原因是,独热词向量无法准确地表达不同词之间的相似性,比如我们经常使用的余弦相似度。”
“A main reason is that one-hot word vectors cannot accurately express the similarity between different words, such as the cosine similarity that we often use.”
§15.1 Word Embedding (word2vec)查看原文 →
词嵌入可以不用任何人工标注就学出来,因为文本本身提供了监督。
Skip-gram 和 CBOW 是在根据周围的词预测一个词的条件概率上训练的;由于这些目标只是从原始语料库里读出来的,作者把两者归类为自监督,而不是碰巧缺少标签的监督学习。
“由于监督来自没有标签的数据,skip-gram 和连续词袋都是自监督模型。”
“Since supervision comes from the data without labels, both skip-gram and continuous bag of words are self-supervised models.”
§15.1 Word Embedding (word2vec)查看原文 →
把 skip-gram 的目标读作对全语料共现统计的拟合,暴露了两个缺陷,而这个重新框定通向了 GloVe。
作者表明,skip-gram 的损失相当于针对全局共现分布的交叉熵,但对这些预测分布的归一化,又要求对整个词表求和,而交叉熵给大语料库所产生的众多罕见事件分配了太多的权重;GloVe 的回答是改用加权的平方损失去拟合计数的对数。
“尽管交叉熵损失函数常用来度量概率分布之间的距离,它在这里可能不是一个好的选择。”
“Though being commonly used for measuring the distance between probability distributions, the cross-entropy loss function may not be a good choice here.”
§15.5 Word Embedding with Global Vectors (GloVe)查看原文 →
另外 3 个论点
GloVe 的形式不是任意的选择:它可以从共现概率的比值推导出来,这也是它每个词的两个向量可以互换的原因。
作者列出 p(w|ice) 与 p(w|steam) 之比的表——“solid”约 8.9,“gas”约 0.085——显示这个比值追踪着一个词属于哪一个;要求调换下标会使比值取倒数,就迫使出现指数的形式和偏置加对数计数的方程。因为一个词出现在另一个词的窗口里,蕴含着反过来也成立,计数满足 x_ij = x_ji,所以中心向量和上下文向量在数学上是等价的,直接把它们加起来。作者也点出了局限:“water”(1.36)和“fashion”(0.96)都落在 1 附近,尽管它们的关系是相反的。
“在 (15.5.4) 中调换词下标 $j$ 和 $k$,必须有 $f(x)f(-x)=1$,所以一种可能是 $f(x)=\exp(x)$,即,”
“Switching word indices \(j\) and \(k\) in (15.5.5), it must hold that \(f(x)f(-x)=1\), so one possibility is \(f(x)=\exp(x)\), i.e.,”
§15.5 Word Embedding with Global Vectors (GloVe)查看原文 →
给每个词元一个固定的向量,对有多个义项的词行不通,这促成了依赖周围序列的表示。
作者的例子是“crane”:在“a crane is flying”和“a crane driver came”里,这个词意思不同,而 word2vec 和 GloVe 却给它同一个向量;同样的要点也用“bank”在一个讲钱的句子和一个讲坐下的句子里来说明。在本章结尾,一个小的 BERT 被预训练,词元“crane”明显地在不同的上下文中得到了不同的表示。
“这促成了上下文敏感的词表示的发展,其中词的表示取决于它们的上下文。”
“This motivates the development of context-sensitive word representations, where representations of words depend on their contexts.”
§15.8 Bidirectional Encoder Representations from Transformers (BERT)查看原文 →
光有更好的特征是不够的——手工搭建的、针对特定任务的架构才是真正的瓶颈,所以该领域转向了与任务无关的预训练。
作者承认,把 ELMo 冻结的双向特征硬加到现有模型上,在六项不同的 NLP 任务上推进了最先进的水平,然后把这一点翻转过来:这些解决方案每一个仍然需要为它自己的任务设计的架构,对每个问题都重复一遍是不现实的。
“然而,为每个自然语言处理任务设计一个特定的架构,在实践中并非易事。”
“However, it is practically non-trivial to craft a specific architecture for every natural language processing task.”
§15.8 Bidirectional Encoder Representations from Transformers (BERT)查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么完整的 softmax 负担不起
Skip-gram 和 CBOW 都在整个词典上做归一化,所以每个梯度都含有对所有词的求和,代价随词表大小增长。负采样绕开了这一点,办法是把一个预测变成针对真实上下文词外加 K 个采样噪声词的少数几个是/否判断,这样代价跟着 K 走,而不是跟着词典大小走。
机制 2
丢掉频繁的词有帮助
非常常见的词几乎出现在每个上下文窗口里,所以它们的共现对意义说得很少,却仍然消耗了大部分计算。因此作者以与其相对频率挂钩的概率随机丢弃它们,这样有信息的词对主导训练,每一遍也变得更便宜。
机制 3
为什么掩码要混入真实的词元
人为的掩码符号只在预训练期间存在,在模型被微调时从不出现,所以纯粹用它来训练会造成不匹配。把被选中位置的一部分换成随机的词或原来的词,使输入保持真实,而且因为随机的插入起噪声的作用,阻止模型完全倚靠被掩码的位置。
常见误读
子采样就是把停用词扔掉——一旦去掉“the”和“a”,语料库就干净了。
这种丢弃是概率性的、依赖频率的:只有相对频率超过阈值的词才有资格被丢掉,即使那样,它们有时仍会幸存。在 PTB 语料库上,阈值取 1e-4 时,“the”仍以不到它原来的二十分之一的比例被保留,而不是被彻底删除,而像“join”这样的罕见词则被完整保留。
“我们可以看到,只有当相对频率 $f(w_i) > t$ 时,(高频)词 $w_i$ 才可能被丢弃,而且词的相对频率越高,被丢弃的概率越大。”
“We can see that only when the relative frequency \(f(w_i) > t\) can the (high-frequency) word \(w_i\) be discarded, and the higher the relative frequency of the word, the greater the probability of being discarded.”
§15.3 The Dataset for Pretraining Word Embeddings查看原文 →
任何读一个句子的模型都是上下文敏感的,所以像 GPT 这样从左到右的语言模型已经能处理多个词义。
方向很要紧:自回归模型只以前面出现的东西为条件,所以由右侧上下文携带的意义对它是看不见的。作者的例子是“i went to the bank to deposit cash”与“i went to the bank to sit down”里的“bank”——尽管词义不同,GPT 给出的表示却完全相同,这恰恰是 BERT 要用两侧来预测被掩码词元的原因。
“然而,由于语言模型的自回归性质,GPT 只往前看(从左到右)。”
“However, due to the autoregressive nature of language models, GPT only looks forward (left-to-right).”
§15.8 Bidirectional Encoder Representations from Transformers (BERT)查看原文 →
第 15 章的核心概念
- 词嵌入
- 把每个词映射到一个实值向量,作为它的特征表示。
- 适用处: 经典的嵌入为每个词元给出一个固定的向量,不管上下文。
- 文本表示的自监督预训练
- 通过根据周围的文本预测一段被隐藏的文本,从原始文本中学习,所以不需要人工标签。
- 适用处: 需要大语料库;监督信号只来自文本的共现。
- 独热编码
- 一个长度为 N 的向量,全是零,只在该词的索引处有一个 1。
- 适用处: 任意两个不同的独热向量之间的余弦相似度为 0,所以相似性无法被编码。
- skip-gram 模型
- 用一个中心词来预测它周围的上下文词,给每个词一个中心向量和一个上下文向量。
- 适用处: 对整个词表做 softmax 归一化,使精确的梯度代价高昂。
- 连续词袋(CBOW)
- 根据上下文词向量的平均来预测中心词。
- 适用处: 与 skip-gram 不同,通常用上下文词向量作为最终的表示。
- 负采样
- 用针对一个真实上下文词和 K 个采样出来的噪声词的二元事件,取代完整的 softmax。 一种近似训练,让每个中心词—上下文词对与几个采样出来的噪声词配对,而不是在整个词表上归一化。
- 适用处: 代价随 K 缩放,而不是随词典大小;需要预先定义好的噪声分布。 采样出来的噪声词必须不是该中心词实际的上下文词。
另外 16 个概念
- 层次 softmax
- 把词的概率计算为沿着二叉树通向该词叶子的路径上一连串二元决策的乘积。
- 适用处: 代价随词表大小是对数的;取决于所选的树结构。
- 高频词的子采样
- 随机丢掉非常常见的词,使训练聚焦于有信息的共现,并且运行得更快。
- 适用处: 只有相对频率超过阈值 t 的词才有可能被丢弃。
- 用于填充小批量的掩码
- 一个 0/1 的变量,标出拼接起来的上下文/噪声槽位中哪些是真实的,这样填充就被排除在损失之外。
- 适用处: 掩码标记填充;另一个单独的标签变量标记正例与负例。
- 全局共现计数
- 在整个语料库中,词 wj 出现在以 wi 为中心的上下文窗口里的频繁程度。
- 适用处: 它是语料库层面的统计量,可以预先计算,而不是对每个小批量重新采样。
- GloVe 的加权平方损失
- 一种损失,用内积加两个偏置去拟合对数共现计数,由 h(x) 加权。
- 适用处: 只有非零的共现计数才有贡献,因为 h(0)=0。
- 共现概率之比
- 用 p(w_k|ice) 除以 p(w_k|steam),揭示出 w_k 与哪个词相关。
- 适用处: 接近 1 的比值,无法区分与两者都相关和与两者都无关。
- 子词嵌入
- 把一个词表示为它的字符 n 元语法向量之和。
- 适用处: 词表更大,计算代价比 skip-gram 更高。
- 字节对编码
- 贪心地合并最频繁的相邻符号对,以构建变长的子词。
- 适用处: 跨越词边界的对被排除;结果取决于数据集。
- 上下文敏感的表示
- 一个依赖于周围序列、而不只是词元的词向量。
- 适用处: word2vec 和 GloVe 与上下文无关,无法处理一词多义。
- BERT 输入序列
- 一个词元流,用 <cls> 和 <sep> 标记包住一段或两段文本。
- 适用处: 最多容纳两个文本序列;它的嵌入由词元、片段和位置三部分相加。
- 掩码语言模型
- 通过隐藏 15% 的词元,并从两侧预测它们来预训练。
- 适用处: 人为的 <mask> 词元在微调时从不出现,所以替换是随机化的。
- 下一句预测
- 一个二元任务,问第二个句子是否真的跟在第一个后面。
- 适用处: 标签从语料库里免费得到;一半的配对是随机采样的负例。
- 与任务无关的预训练
- 一个预训练好的模型,只加一个新的输出层,就针对许多任务微调。
- 适用处: 对比 ELMo,后者的预训练权重被冻结,并送入定制的架构。
- 掩码语言建模的 80/10/10 替换
- 在被选中的 15% 位置中,80% 变成“<mask>”,10% 保持不变,10% 变成一个随机的词。
- 适用处: 只适用于非特殊的词元;“<cls>”和“<sep>”从不被预测。
- MLM 的填充权重
- 被填充的预测槽位的权重为 0.0,所以它们对损失没有任何贡献。
- 适用处: 只过滤被填充的预测位置,而不是被填充的输入词元。
- 上下文敏感的 BERT 表示
- 同一个词元,随周围文本的不同,得到不同的编码向量。
- 适用处: 用一个微型的 2 层 BERT 演示,而不是原始的模型大小。
第 15 章划线与批注AI 陪读
“bank”的向量表示,在“go to the bank to deposit some money”和“go to the bank to sit down”中是一样的”
“the vector representation of “bank” is the same in both “go to the bank to deposit some money” and “go to the bank to sit down”
查看原文 →整章的动机,压缩进一个同形异义词里。注意那个安静的承认:word2vec 在我们还没学会它之前,就已经被框定为将被取代的东西了。
“模型通过海量文本数据的监督来学习,而无需昂贵的标注工作!”
“models learn through supervision from massive text data without expensive labeling efforts!”
查看原文 →这个感叹号在起说服的作用。标签不是缺席——它们只是免费的,是从词序里收割来的。称之为“无需标注”,掩盖了有人决定了上下文算作真值。
“由于任意两个不同词的独热向量之间的余弦相似度为 0,独热向量无法编码词之间的相似性”
“Since the cosine similarity between one-hot vectors of any two different words is 0, one-hot vectors cannot encode similarities among words”
查看原文 →干净的一行拆台。但真正的控诉不是零相似度——而是每一对都同样地为零,所以几何结构根本不携带任何信息。
另外 17 条批注
“假设给定中心词时,上下文词是独立生成的(即条件独立)”
“Assume that the context words are independently generated given the center word (i.e., conditional independence)”
查看原文 →一个坦率地说是错误的假设——给定“loves”,“the”和“man”怎么会独立。然而模型管用。值得坐下来想想:这个分解是一种计算上的便利,而嵌入扛得住它。
“每个词有两个 $d$ 维的向量表示”
“each word has two \(d\)-dimensional-vector representations”
查看原文 →整节中解释得最不够的设计选择。为什么是两个?因为一个词不该以很高的概率预测它自己——一个向量会迫使 u·v 的自相似性占主导。文本从没这么说。
“skip-gram 模型的中心词向量通常被用作词的表示”
“the center word vectors of the skip-gram model are typically used as the word representations”
查看原文 →“通常”是破绽。在所有那些推导之后,学到的一半参数是靠约定而不是靠论证被扔掉的。
“(15.2.2) 中的联合概率,只有当所有词向量都等于无穷大时才被最大化到 1”
“the joint probability in (15.2.3) is maximized to 1 only if all the word vectors are equal to infinity”
查看原文 →这一段最尖锐的时刻:在修补之前,老实地展示一个退化的目标。负采样在这里不是一个优化技巧——而是阻止问题变得空洞的东西。
“它与低频词“intel”的共现,在训练中比与高频词“a”的共现更有用”
“its co-occurrence with a low-frequency word “intel” is more useful in training than the co-occurrence with a high-frequency word “a”
查看原文 →子采样被当作效率偷渡进来,其实它是一种信息论的修正——频繁的词是低惊异度的,因此是低信号的。删掉数据让表示变得更好,而不只是更快。
“window_size = random.randint(1, max_window_size)”
查看原文 →窗口大小对每个中心词重新掷骰子——一个安静的技巧,在没有任何显式的距离衰减的情况下,给附近的词更大的权重。随机性在干核的活。
“while len(negatives) < len(contexts) * K:”
查看原文 →负样本随上下文的数量而缩放,所以 K 是按每个配对而不是按每个中心词算的。很容易误读成总共 5 个噪声词。
“# 噪声词不能是上下文词”
“Noise words cannot be context words”
查看原文 →一个纯度检查,每抽一次就要扫描一遍列表——而且只对这个中心词是局部的。从全局看,你的“噪声”是别人的上下文。这个近似愉快地容忍了这一点。
“取 0.75 次幂”
“raised to the power of 0.75”
查看原文 →著名的魔法指数,引入时除了“根据 word2vec 论文中的建议”之外什么都没有。一个压平频率的经验性权宜之计,被当作经文传了下来。
“来自大语料库的大量罕见事件,常常被交叉熵损失赋予了过多的权重”
“a large number of rare events from a large corpus are often modeled by the cross-entropy loss to be assigned with too much weight”
查看原文 →这才是 GloVe 真正的动机,却几乎是顺带说出的。交叉熵执意要解释长尾;带 h(x) 的平方损失则让你可以对它耸耸肩。
“因为 $h(0)=0$,任何 $x_{ij}=0$ 的平方损失项都可以省略”
“because \(h(0)=0\), the squared loss term for any \(x_{ij}=0\) can be omitted”
查看原文 →这是障眼法:log x_ij 在零处没有定义,而权重函数恰好让那一项消失。优雅与回避,在同一行里。
“由于初始化的值不同,同一个词在训练之后,在这两个向量里仍可能得到不同的值”
“owing to different initialization values, the same word may still get different values in these two vectors after training”
查看原文 →数学上相同,实践中却有分歧——所以 GloVe 干脆把它们加起来。一个关于对称性的定理,被一个求平均的权宜之计回答了。
“必须有 $f(x)f(-x)=1$,所以一种可能是 $f(x)=\exp(x)$”
“it must hold that \(f(x)f(-x)=1\), so one possibility is \(f(x)=\exp(x”
查看原文 →“一种可能”承担了重担。这个推导其实是反向工程:他们知道想要 exp,然后找到允许它的约束。
“word2vec 和 GloVe 都没有探究词的内部结构”
“the internal structure of words was neither explored in word2vec nor in GloVe”
查看原文 →一整章的机制,而这一句话点出了它的盲点:两个模型都把“help”和“helping”当作互不相关的陌生人。
“在 fastText 中,罕见词甚至词表外的词也可能得到更好的向量表示”
“rare words and even out-of-vocabulary words may obtain better vector representations in fastText”
查看原文 →整个回报在一个分句里——而它只在承认了两项代价之后才到来。老实的权衡核算,在教科书里很罕见。
“词表大小无法预先确定”
“the vocabulary size cannot be predefined”
查看原文 →这才是对 fastText 的 n 元语法的真正控诉:不是准确率,而是无法控制。BPE 被引入是作为一件预算工具,而不是一位更聪明的语言学家。
“跨越词边界的对不予考虑”
“pairs crossing word boundaries are not considered”
查看原文 →作为效率上的说明偷渡进来,却是一个语言学上的承诺:词是封死的单元。现代的分词器恰恰模糊了这一点。
读后感AI 陪读
不是提高准确率,而是关于模型拒绝看到什么的承认
通读下来,这一章是一个以富有成效的方式不断拆自己的台的论证——而这就是它真正的教学法。它一开头就承诺,自监督白送你表示,然后用五个小节表明,有多少代价是悄悄付的:“不需要标注”的框定掩盖了词序已被宣布为真值;上下文词之间的条件独立被断言,又立刻被任何真实的句子违反;会把所有向量送向无穷大的退化目标,在负采样来救场之前被老实地展示出来;对数共现在零处没有定义,直到一个加权函数礼貌地让那一项消失。本章的弧线不是 word2vec → GloVe → fastText → BERT 这样一把精度的梯子。它是一连串关于每种表示拒绝看见什么的承认,每个修补都比它所回答的问题更窄。我看得最清楚的是:文本反复把工程上的便利,以理论的外衣呈现。0.75 的指数像经文一样到来,带着一个引文,没有理由。每个词有两个向量是结构上的必需——没有它,一个词的自相似性会主宰它自己的预测——但书从不这么说,随后又用“通常”一词扔掉一半参数。GloVe 证明中心向量和上下文向量是对称的,然后又把它们加起来,因为初始化无论如何会使它们不同;一个定理,被一个求平均的权宜之计回答了。exp 的推导是从答案反向工程出来的。子采样被推销为速度,其实是信息论:删掉频繁的词会改进嵌入,因为低惊异度的词元携带低信号。甚至随机的窗口大小也是披着外衣的距离核。这些都不是丑闻——它们是一个管用的方法实际的样子——但一个把推导当作承重部分的读者,会学到错误的教训。我最尖锐的判断是关于本章的铰链的,它比看上去更安静。word2vec 和 GloVe 决定性的局限从来不是准确率;而是两者都把“help”和“helping”当作陌生人,并把“bank”的每一次出现当作同一个词。fastText 用子词 n 元语法回答了第一个,随即失去了对词表大小的控制——所以 BPE 登场,不是作为更聪明的语言学家,而是作为一份预算。BERT 回答了第二个,而本章收尾的演示,“crane”在不同的句子里得到不同的向量,正是第一页上那个同形异义的抱怨终于被兑现。本章是一个循环,而它在开篇第一段就告诉了你它的结局。我会这样告诉读者:静态嵌入的那一半不是在通往 BERT 的路上要略读的、已经过时的背景。那是你学到的地方:每一个现代的设计选择——子词单元、被采样的目标、双向性、80/10/10 的掩码——之所以存在,是因为更早的某样东西是空洞的、无法控制的,或是盲目的。把 BPE 拒绝跨越词边界读作它所是的那个语言学承诺,而不是它被伪装成的效率说明。并且请注意,书里最有价值的句子,是那些承认代价的:靠词表膨胀买来的罕见词的收益,交叉熵执意要去解释一条平方损失可以耸耸肩放过的长尾。迁移的是那些让步,而不是梯度。
在 FeedLitra 里读第 15 章,每段旁边都有这些卡片。
开始读书第 16 章:自然语言处理:应用
截断和填充到 500 个词元,会如何影响长评论?
第 16 章是怎样展开的AI 辅助
开篇。 本章一开头就兑现了此前的成果。建好预训练的文本表示之后,本章陈述了它的前提:这些表示是输入,现在要紧的是把它们送入真正干活的架构。两个下游任务被点名作为载体——情感分析和自然语言推断——而 BERT 微调则留作第三乐章。这个框定有意是应用性的而不是理论性的:问题不再是如何学习词义,而是在它之上构建什么。
展开。 情感分析排在最前,本章立刻把它化约为已经熟悉的东西。因为情感可以归结为离散的极性或等级,这个任务不过是把一个变长序列映射到一个固定的标签——朴素的文本分类。斯坦福的 IMDb 语料库提供的恰恰是这种形状,训练集和测试集各有 25,000 条评论,正负标签平衡,尽管本章坦率地说,这只是单一的电影评论领域里的二元极性。随后依次在 GloVe 嵌入上运行两种架构,一个 RNN 设计和一个 textCNN 设计,这一节以 textCNN 的训练结束。这一段含蓄的教训是,预训练的嵌入加一个适度的、针对特定任务的躯体就足够了。
转向句子对。 本章随后从单个文本转向文本之间的关系。自然语言推断问的是,一个假设的真假在多大程度上归因于一个前提,而裁决的空间恰好是三个:蕴含、矛盾或中性。每一个都钉在一个演练的例子上——拥抱某人蕴含表达了喜爱,运行代码与睡觉矛盾,而音乐家为我们表演则对他们是否著名不置可否,中性被定义为前两个标签未能覆盖的一切的残余。SNLI 及其加载器随后被引入,然后是带有“关注—比较—聚合”流水线的可分解注意力模型。在这里,本章做出了它最尖锐的机制性论断:推断所需要的是哪些词对应哪些词,而不是它们出现的顺序。拿“i do need sleep”对“i am tired”走一遍,把 sleep 联系到 tired 就是敲定这个关系的东西,所以对所有词元对的注意力就足够了,既不需要循环,也不需要卷积。随之而来的有两点提醒。图中一对一的连线是显示上的方便;真正的机制是软对齐,把每个词元与每个词元相权衡。而这恰恰是为什么要讨论代价:MLP f 是一次喂入一个词元,而不是每一对,所以它运行 m + n 次,而不是 m × n 次,把一个二次方的打分问题分解成线性的,使关注这一步变得负担得起。
第二个转折,以及交易。 本章真正的支点出现在它把自己前面的几页倒过来的时候。为每个任务手工设计一个单独的架构——这里一个 RNN,那里一个 textCNN,成对的用一个可分解注意力模型——是无法扩展的,而 BERT 被作为确实扩展了的替代方案提出:在它被提出的时候,在许多任务上达到最先进的水平,只需极小的架构改动。原因是一个躯体,不同的读出。BERT 为 <cls> 词元返回一个表示,也为每个输入词元返回一个;整个序列的任务只读 <cls>,词元层面的任务读每个词元,而换成带平方损失的连续输出,就把分类变成了回归。所以,在整个任务家族之间,真正改变的只有输入的格式,以及哪些表示送进新增的层。本章用具体的例子走过这些家族——CoLA 判断语法上的可接受性(“I should study.”可以,“I should studying.”不行),语义文本相似度从 0 到 5 打分,只需要一个连续的输出和均方误差,而问答则用单独的参数,把每个段落词元打分为跨度的起点和终点,就像把“mask makers”作为关于 N95 口罩的答案提取出来那样。
收尾。 本章最后做的,正是它刚刚论证的那件事:在 SNLI 上微调一个小的预训练 BERT,除了在 <cls> 表示上加一个两层 MLP 之外什么也没有,批量大小 512,最大长度 128,学习率 1e-4,训练 5 个轮次。收尾的说明对这笔交易的两面都很老实。选择小的版本是为了让演示能在大多数机器上运行,这意味着报告出来的准确率低于基础模型所能达到的。而适度的新增的头,掩盖了真正的账单:微调更新的是 BERT 自己的参数,基础版 1.1 亿个,大版 3.4 亿个。BERT 靠花参数来买掉设计的功夫——所以在内存或时间受限的地方,本章早先那些手工设计的 RNN、CNN 和注意力模型并没有过时,仍然是可行的选择。
关键论点,以及支撑它们的原文
情感分析可以当作朴素的文本分类来处理。
因为情感可以归结为离散的极性或等级,这个任务就变成了把一个变长序列映射到一个固定的标签;斯坦福的 IMDb 语料库提供的恰恰是这个,训练集和测试集各有 25000 条评论,正负标签平衡——尽管它只涵盖电影评论这单一领域里的二元极性。
“由于情感可以被归类为离散的极性或等级(例如正面和负面),我们可以把情感分析看作一个文本分类任务,它把一个变长的文本序列转换成一个定长的文本类别。”
“Since sentiments can be categorized as discrete polarities or scales (e.g., positive and negative), we can consider sentiment analysis as a text classification task, which transforms a varying-length text sequence into a fixed-length text category.”
§16.1 Sentiment Analysis and the Dataset查看原文 →
对句子对的推断只有三种可能的裁决:蕴含、矛盾或中性。
作者把每个标签钉在一个演练的句子对上:拥抱某人蕴含表达了喜爱;运行代码与睡觉矛盾;音乐家为我们表演则对他们是否著名不置可否,所以是中性,定义为前两个标签没有覆盖的一切。
“中性:所有其他情形。”
“Neutral: all the other cases.”
§16.4 Natural Language Inference and the Dataset查看原文 →
模型为了推断所需要的是哪些词对应哪些词,而不是它们出现的顺序。
在句子对推理的设定的基础上,作者拿前提“i do need sleep”对假设“i am tired”走了一遍,其中把“sleep”联系到“tired”就是敲定这个关系的东西。这幅图示只是为了显示才用一对一的连线;实际的机制是权衡所有的对。
“借助注意力机制,我们可以把一个文本序列中的词元与另一个中的每个词元对齐,反之亦然。”
“With attention mechanisms, we can align tokens in one text sequence to every token in the other, and vice versa.”
§16.5 Natural Language Inference: Using Attention查看原文 →
另外 3 个论点
为每个 NLP 任务手工设计一个单独的架构无法扩展,这就是为什么要转而微调一个单一的预训练模型。
把早先针对特定任务的设计倒过来,作者指出,BERT 在被提出时,在许多任务上推进了最先进的水平,同时只需极小的架构改动——交易是它发布的两个版本,分别有 1.1 亿和 3.4 亿个参数。
“当存在空间或时间约束时,这些模型是有帮助的,然而,为每个自然语言处理任务设计一个特定的模型在实践中是不可行的。”
“These models are helpful when there is space or time constraint, however, crafting a specific model for every natural language processing task is practically infeasible.”
§16.6 Fine-Tuning BERT for Sequence-Level and Token-Level Applications查看原文 →
单文本分类、文本对分类或回归、标注,以及问答,都可以通过给 BERT 加上全连接层来涵盖。
作者用具体的例子走过这些家族:CoLA 问一个句子在语法上是否可接受(“I should study.”可以,“I should studying.”不行);语义文本相似度从 0 到 5 打分,只需要一个连续的输出和均方损失;问答则用单独的参数,把每个段落词元打分为跨度的起点和终点,就像把“mask makers”作为关于 N95 口罩的答案提取出来那样。
“与图 16.6.1 相比,唯一的区别在于,在文本标注中,输入文本中每个词元的 BERT 表示,都被送入同样的额外全连接层,输出该词元的标签,比如词性标签。”
“Comparing with Fig. 16.6.1, the only distinction lies in that in text tagging, the BERT representation of every token of the input text is fed into the same extra fully connected layers to output the label of the token, such as a part-of-speech tag.”
§16.6 Fine-Tuning BERT for Sequence-Level and Token-Level Applications查看原文 →
对于 SNLI,微调 BERT 只需要在“<cls>”表示上加一个两层的 MLP,别无其他。
作者通过加载一个小的预训练 BERT,并用批量大小 512、最大长度 128、学习率 1e-4 和 5 个轮次在 SNLI 上微调它,演示了这一点;选用小的版本是为了让演示能在大多数机器上运行,所以得到的准确率低于基础模型所能达到的。
“如图 16.6.2 所示,为自然语言推断微调 BERT,只需要一个由两个全连接层组成的额外 MLP(见下面 BERTClassifier 类中的 self.hidden 和 self.output)。”
“As Fig. 16.6.2 indicates, fine-tuning BERT for natural language inference requires only an extra MLP consisting of two fully connected layers (see self.hidden and self.output in the following BERTClassifier class).”
§16.7 Natural Language Inference: Fine-Tuning BERT查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
对齐胜过词序
注意力让一个句子的每个词元都与另一个句子的每个词元相权衡,所以前提里的词“sleep”可以与假设里的词“tired”匹配。关系随后就从这些匹配上的对中读出来,这就是模型不需要循环或卷积来追踪顺序的原因。
机制 2
为什么打分保持线性
MLP f 是一次喂入一个词元,而不是每一对,所以它运行 m + n 次,而不是 m x n 次。这样分解打分,把二次方的代价变成线性的,也是使关注这一步变得负担得起的原因。
机制 3
一个躯体,不同的读出
BERT 为“<cls>”词元和每个输入词元返回一个表示。整个序列的任务只读“<cls>”,词元层面的任务读每个词元,而换成连续输出加平方损失就涵盖了回归,所以在各个任务家族之间,只有输入的格式,以及哪些表示送进新增的层,会改变。
常见误读
既然 BERT 只需要硬加上几个额外的层,它就是廉价的选择,会让手工搭建的 MLP、CNN、RNN 或注意力模型过时。
小小的新增的头隐藏了真正的账单:微调更新的是 BERT 自己的参数,而最初的版本持有 1.1 亿和 3.4 亿个。在空间或时间受限的地方,手工设计的、针对特定任务的模型仍然是可行的选择。
“然而,这一好处是以为下游应用微调数量巨大的 BERT 参数为代价的。”
“However, this benefit comes at the cost of fine-tuning a huge number of BERT parameters for the downstream applications.”
Chapter 16. Natural Language Processing: Applications查看原文 →
对齐的示意图意味着,每个词恰好与另一个句子中的一个词配对。
那些一对一的配对出现,只是为了让想法可见。模型依靠的是软对齐,把一个序列的每个词元与另一个序列的每个词元相权衡,这也是为什么关注这一步的代价会被讨论。
“借助注意力机制,我们可以把一个文本序列中的词元与另一个中的每个词元对齐,反之亦然。”
“With attention mechanisms, we can align tokens in one text sequence to every token in the other, and vice versa.”
§16.5 Natural Language Inference: Using Attention查看原文 →
第 16 章的核心概念
- 情感分析
- 研究人们在其产生的文本中的情感,被当作文本分类来处理。
- 适用处: 当情感可以归结为离散的极性或等级时管用。
- 下游任务
- 一个具体的 NLP 问题,通过把预训练的表示送入一个任务模型来解决。
- 适用处: 假定有用的预训练表示已经存在。
- BERT 微调
- 以极小的架构改动,让预训练的 BERT 适应序列层面或词元层面的任务。 重用预训练的 BERT 并加上小的额外层,从零训练这些层,同时更新 BERT 自己的参数。
- 适用处: 在空间和时间上代价高,因为 BERT 的所有参数都被更新。 需要足够的算力,因为最初的版本持有 1.1 亿和 3.4 亿个参数。
- 自然语言推断
- 判定一个前提句子和一个假设句子之间的逻辑关系。
- 适用处: 需要句子对;单序列分类是不够的。
- 可分解注意力模型
- 一种注意力加 MLP 的模型,没有循环或卷积,先关注,再比较,然后聚合。
- 适用处: 忽略词元的顺序;只依靠软对齐。
- SNLI 数据集
- 一个用于推断的带标签英语句子对的大型基准。
- 适用处: 测试词表必须来自训练集,所以新的测试词元是未知的。
另外 2 个概念
- 序列层面与词元层面的应用
- 输出是对整个输入的一个标签的任务,对比每个词元一个标签的任务。
- 适用处: 序列层面只用“<cls>”表示;词元层面使用每个词元的表示。
- 陈旧的梯度参数
- 像 MaskLM 和 NextSentencePred 这样仅用于预训练的头,在微调期间保持不变。
- 适用处: 要求在训练步骤中允许陈旧的梯度。
第 16 章划线与批注AI 陪读
“这一好处是以微调数量巨大的 BERT 参数为代价的”
“this benefit comes at the cost of fine-tuning a huge number of BERT parameters”
查看原文 →教科书里罕见的老实时刻——最强的工具不是默认的那个。写于 2021 年,而“空间或时间有限”这个但书只是变得更加相关。
“我们通过截断和填充,把每条评论的长度设为 500”
“we set the length of each review to 500 with truncation and padding”
查看原文 →固定长度 500 个词元,而直方图上大多数评论远在 250 以下——批量的便利悄悄买来了一片 <pad> 的海洋。没人问这对模型有什么影响。
“双向 LSTM 在最后一层的、初始和最终时间步的隐状态被拼接起来”
“the hidden states (at the last layer) of the bidirectional LSTM at both the initial and final time steps are concatenated”
查看原文 →听上去优雅,但有 500 个填充步时,“最终时间步”往往读到的是填充。这个设计在纸面上干净,在实践中漏水。
另外 17 条批注
“self.pool = nn.AdaptiveAvgPool1d(1)”
查看原文 →文字三次说到时间维度上的最大池化,而代码悄悄用了平均池化。一个真实的不匹配——恰恰是让读者能确认自己真的读过代码的那种。
“就把任何文本序列想成一幅一维图像”
“just think of any text sequence as a one-dimensional image”
查看原文 →整节都倚靠这一个类比。它之所以管用,是因为 n 元语法确实是局部的——但它也悄悄承认,卷积并不在乎数据意味着什么,只在乎它们是相邻的。
“一个带有可训练的权重,另一个带有固定的权重”
“one with trainable weights and the other with fixed weights”
查看原文 →披着架构外衣的对冲:让一份拷贝去适应,把另一份冻结以防过拟合。在一个 25000 个样本的数据集上同时押两注。
“中性:所有其他情形。”
“Neutral: all the other cases.”
查看原文 →第三类是通过排除来定义的——一个废纸篓标签。这恰恰是为什么 NLI 的标注有噪声,而模型学到的是标注者的习惯,而不是逻辑。
“前提:一个人正在运行《动手学深度学习》中的代码示例。”
“Premise: A man is running the coding example from Dive into Deep Learning.”
查看原文 →教科书把自己写进了自己的例子。可爱,但它也悄悄显示了一个“逻辑”标签偷偷带进了多少世界知识——运行代码意味着醒着,只是因为我们知道人类是什么。
“无论是“著名”还是“不著名”,都不能从“正在为我们表演”这一事实中推断出来”
“neither “famous” nor “not famous” can be inferred from the fact that “are performing for us”
查看原文 →中性是老实的类别,也是倾倒场所——标注者无法决定的任何东西都落在这里。三个平衡的类别看上去很干净;边界却一点也不。
“我们必须把训练集构建的词表用作测试集的词表”
“we must use the vocabulary constructed from the training set as that of the testing set”
查看原文 →对抗一整类沉默的泄漏的一行纪律。比看上去更值钱。
“比起保留前提和假设中词元的顺序更简单,我们可以直接对齐词元”
“Simpler than preserving the order of tokens in premises and hypotheses, we can just align tokens”
查看原文 →这个模型全部的赌注:扔掉词序,仍然得到逻辑。它竟然行得通,令人吃惊——也暗示了它为什么最终行不通。
“这个分解技巧只导致 $f$ 的 $m + n$ 次应用(线性复杂度)”
“This decomposition trick leads to only \(m + n\) applications (linear complexity) of \(f”
查看原文 →名字就是从这里来的,也是真正的洞见:廉价是靠拒绝让这一对在点积之前交互买来的。一切有表达力的事都发生在后面,在比较之中。
“predict_snli(net, vocab, ['he', 'is', 'good', '.'], ['he', 'is', 'bad',”
查看原文 →一个被选得容易的测试用例——词汇性的反义,恰恰是对齐词袋模型能抓到的线索。困难的情形(否定的辖域、量词)无人问津。
“为每个自然语言处理任务设计特定的模型在实践中是不可行的”
“crafting a specific model for every natural language processing task is practically infeasible”
查看原文 →整章的支点,几乎是带着歉意说出来的。我们刚刚建起来的一切,正在被重新框定为博物馆的展品。
“BERT 在不同应用中所需要的“极小的架构改动”,就是额外的全连接层”
“the “minimal architecture changes” required by BERT across different applications are the extra fully connected layers”
查看原文 →“极小”承担了重担:架构几乎不变,因为 3.4 亿个参数已经吸收了难度。简单是在上游付的账。
“唯一的区别在于,在文本标注中,每个词元的 BERT 表示”
“the only distinction lies in that in text tagging, the BERT representation of every token”
查看原文 →序列层面读 <cls>,词元层面读每个位置——同一个躯体,不同的取点。这才是真正统一的想法,朴素得几乎令人尴尬。
“我们可以计算从位置 $i$ 到位置 $j$($i \leq j$)的一个有效跨度的得分 $s_i + e_j$,并输出得分最高的跨度”
“we can compute the score \(s_i + e_j\) for a valid span from position \(i\) to position \(j\) (\(i \leq j\)), and output the span with the highest score”
查看原文 →注意文本一带而过的那个不对称:训练时独立地优化起点和终点,而推理时通过一个约束把它们耦合起来。模型从未学到 i≤j——它是事后手工强加的。
“BERT 需要极小的架构改动(额外的全连接层)”
“BERT requires minimal architecture changes (extra fully connected layers)”
查看原文 →整章的论点,在一个分句里。“极小”在起修辞作用——这个架构之所以极小,只是因为预训练是极大的。代价搬了家,没有消失。
“我们如何利用 BERT 来训练语言模型?”
“How can we leverage BERT in training language models?”
查看原文 →一道悄悄带着倾向的习题。BERT 是双向的,所以不作弊就不能成为从左到右的语言模型——这个问题其实是在要求学生发现一个局限,而不是一个应用。
“num_heads=4, num_blks=2, dropout=0.2, max_len=max_len)”
查看原文 →一个真正的 bug,不是教学:这个函数把 num_heads、num_blks、dropout 作为参数,然后又硬编码覆盖了它们。为 bert.base 传入 12 个头,你会悄悄地建出一个 4 头的模型——恰恰是这一节所布置的那道习题。
读后感AI 陪读
一个教学上的招数:把模型建得足够好,好让你感受到它们的代价
当作一个整体来读,这一章是一个伪装成综述的支点。它一开头就承诺,预训练的文本表示可以被送入下游任务所需要的任何架构,然后用它的前半部分手工做到了这一点——GloVe 加双向 LSTM,然后是 GloVe 加一维 CNN,都在 IMDb 情感上——之后转向用 SNLI 和可分解注意力模型处理句子对,最后宣布“为每个 NLP 任务设计特定的模型在实践中是不可行的”,并把一切都交给 BERT 微调。因此,本章的架构就是一个论证:把量身定做的模型建得足够好,让你感受到它们的代价,然后让它们退休。这在教学上行得通,但这意味着前半部分是由一位已经知道结局的作者写成的博物馆展品,读者应当注意到,这些展品是被精心挑选得讨喜的。
我看穿的,主要是文字与代码之间的差距。文字三次说到时间维度上的最大池化,然后却实例化了 AdaptiveAvgPool1d——一个真实的不匹配,也是有用的,因为这恰恰是只有真正打开代码的读者才能抓到的东西。BERT 微调一节把 num_heads、num_blks 和 dropout 作为参数,然后又把它们硬编码覆盖了,所以那道要你放大到 bert.base 的习题,会悄悄地建出一个四头的模型。别处的滑移更安静:把每条评论填充到 500 个词元,而大多数评论在 250 以下,然后把双向 LSTM 在“初始和最终时间步”的隐状态拼接起来——一个纸面上干净的设计,在实践中往往读到的是填充。还有,跨度预测头在训练时独立地优化起点和终点,而推理时则通过事后硬加的 i≤j 约束把它们耦合起来;模型从未学到据说它所遵守的顺序。这些都不是致命的,但合在一起,它们显示出一本解释比实现更光鲜的书。
继续阅读
我最尖锐的判断是关于“极小”这个词的。本章的论点——BERT 只需要额外的全连接层,就能覆盖单文本分类、文本对分类和回归、标注以及问答——是对的,也真正优雅:统一的想法只是你在哪里取表示,<cls> 用于序列层面的决策,每个词元位置用于词元层面的决策。同一个躯体,不同的取点。但这个架构之所以极小,只是因为预训练是极大的;难度被上游的 3.4 亿个参数吸收了,而不是被化解了。书在一处老实得令人钦佩,在那句承认这一好处“是以微调数量巨大的 BERT 参数为代价的”、而当空间或时间有限时这很要紧的话里——这是一个写于 2021 年的但书,此后只是变得更有牙齿了。代价搬了家;它没有消失。相关的:可分解注意力模型之所以配得上它的名字,是因为它拒绝让前提和假设在点积之前交互,这买来的是线性而不是二次方的代价,并把所有表达力推到了后面的比较步骤里。这是这笔交易老实的形状,比附在上面的准确率数字更有价值。
我还要告诉读者,对全程的评估保持不信任。SNLI 的中性类是通过排除来定义的——“所有其他情形”——这使它成了一个废纸篓标签,也是 NLI 标注有噪声、模型最终学到的是标注者的习惯而不是推理的主要原因。本章自己的插图显示了一个“逻辑”标签偷偷带进了多少世界知识:运行一段代码意味着醒着,只是因为我们已经知道人类是什么。而且演示的例子选得很宽厚。“He is good”对“he is bad”是词汇性的反义,恰恰是一个对齐词元袋模型能抓到的线索;否定的辖域、量词和单调性则无人问津。与此相对,有一行真正的纪律值得称赞——坚持用训练集来构建测试集的词表,这悄悄堵住了一整类沉默的泄漏。
最后两点。textCNN 一节完全倚靠一个类比,“把任何文本序列想成一幅一维图像”,它成立是因为 n 元语法确实是局部的——但它也承认,卷积只在乎相邻,从不在乎意义。而它的双嵌入技巧,一份可训练、一份冻结,是披着架构外衣的对冲:在 25,000 个样本上同时押两注。所以,为了取点与头的想法清楚的阐述,和对注意力复杂度老实的核算去读这一章;带着怀疑去读代码;并把那道问如何利用 BERT 做语言建模的习题,当作它真正的样子——不是一个应用的提示,而是一个邀请,让你发现双向编码器不作弊就不可能成为从左到右的语言模型。
在 FeedLitra 里读第 16 章,每段旁边都有这些卡片。
开始读书第 17 章:强化学习
Q 学习如何放弃“环境的行为是已知的”这一假设?
第 17 章是怎样展开的AI 辅助
开篇:一种不同的问题。 本章不是从一种形式体系开始,而是从一个对比开始。作者观察到,在普通的深度学习中,测试时的每个预测都独立成立——对这幅图像分类,然后对下一幅,第一个选择中没有任何东西改变第二个。强化学习打破了这种独立性。在这里,每个决策都会重塑后面决策所处的情境,而且是在学习者无法控制的变量之下。所给的例子有意多种多样——规划一次投递的路线、在围棋里走一步、选择在 Netflix 上推荐什么——但它们说的是同一点:早先的一个选择缩小了后面的可能。确立了跨时间的耦合就是问题之后,本章预告了它穿过这个问题的路线:马尔可夫决策过程作为形式对象,值迭代和 Q 学习作为两个算法,深度强化学习作为地平线之外的远方。
展开:形式化,然后分解。 MDP 作为使序贯决策可处理的装置到来——状态、动作、转移函数、奖励,以及把未来求和的折扣回报。承重的部分是马尔可夫假设,即下一个状态只取决于当前状态和所采取的动作。作者与其说把它当作一种限制,不如说当作一个关于记账的设计选择:如果下一个状态无法从当前的描述中预测,补救的办法是重新定义什么算作状态,而不是放弃这个模型。一个由加速度操控的机器人,光凭它的位置是无法预测的,但把位置与速度配成一对,那么下一对就是当前这一对和动作的函数。代价是更大的状态空间,心甘情愿地付。由这个假设得出本章赖以运转的恒等式:因为未来只取决于你落在哪里,一条轨迹可以在它的第一步之后切断,所以从现在起的平均回报,等于所走的这一步的平均奖励,加上从由此到达的状态出发的折扣平均回报——折扣保证了总和即使在无穷无尽的轨迹上也保持有限。值迭代随后被推导为不过是把这个恒等式一遍又一遍地应用;动态规划的论证表明,随着轮数无界增长,不管从哪里开始,估计都会收敛到最优值。演示是 4×4 的 FrozenLake 网格,其中唯一的奖励 1 位于目标处,通过假定动作可靠地移动机器人、使转移是确定性的而加以简化。
转折:放弃模型。 支点是一个被直白陈述的局限——值迭代只有在整个 MDP 已经已知、包括转移概率的情况下才能运行,而这很少成立。Q 学习的回答,是把对所有可能的下一个状态按转移加权的平均,换成机器人实际落到的那一个下一个状态。作者小心地不让这看起来像障眼法:那个落脚的状态,本身就是机器人行动时从转移概率中抽取的,所以动力学仍然进入了目标——是通过收集到的经验而不是一个显式的公式送进来的。Q 学习摆脱的,是事先把模型写下来的需要,而不是对环境行为的依赖。这个重新框定立刻提出了一个问题:该收集哪种经验。因为每次更新都是一个约束,把一个状态—动作对的值与其他对的值联系起来,所以只覆盖空间的一小片的数据,会在各处都破坏估计,而不只是在机器人没去的地方。因此有了探索:ε-贪心或 softmax 把随机的选择混进贪心策略里。而这种混合不是折中,而是机制——多半贪心地行动,恰恰是让高估能够自我纠正的原因。一个价值被夸大的动作会被选中,并被真正执行;它返回的微薄的奖励送进下一次更新,把估计压下去。一个完全随机的策略最终会到达每个状态,但需要数量庞大的轨迹,而且切断了探索与驱动纠正的、不断演变的估计之间的联系。
收尾:对所交易之物的一份账目。 本章以用信息这种货币点出无模型自由的代价而结束。值迭代在每次更新时都可以查阅完整的模型;Q 学习必须从它自己的轨迹中推断出同样的内容,所以需要多得多的轮数。在同一个带确定性动作的 FrozenLake 网格上,它确实到达了最优解——但要在大约 250 次迭代之后。收尾的说明就这样映照了本章的结构:每朝对环境的假设更少迈一步,都要用样本来付账,而读者被安置在深度强化学习的位置上,那里函数近似才是让这笔账在大规模下付得起的东西。
关键论点,以及支撑它们的原文
强化学习是一个不同于普通深度学习的问题,因为决策是跨时间联系在一起的,而不是各自独立的。
作者一开篇就指出,在标准的深度学习中,每个测试预测都是独立的,而在这里,每个选择都重塑了后面选择所处的情形,且是在学习者无法控制的变量之下。投递包裹、在围棋里走子、在 Netflix 上推荐节目,都被作为早先的一个选择缩小了后面的可能的例子提出。
“关键的想法是,在每个阶段,这些我们往往不能控制的变量,会影响未来整个事件的序列,例如,如果在仓库里打包出现了延迟,零售商可能需要用空运而不是陆运来发送包裹,以确保及时送达。”
“The key idea is that at each stage these variables that we do not often control affect the entire sequence of events in the future, e.g., if there were delays in packing the box in the warehouse the retailer may need to send the package via air instead of ground to ensure a timely delivery.”
Chapter 17. Reinforcement Learning查看原文 →
值迭代是实用的,因为反复应用“奖励加下一个价值”的恒等式,不管估计从哪里开始,都会落定到最优值。
作者从动态规划的恒等式出发论证,随着更新的轮数无界增长,不管初始化如何,估计都逼近最优价值函数,然后在 4x4 的 FrozenLake 网格上演示,其中唯一的奖励 1 在目标处。演示通过假定动作可靠地移动机器人、使转移是确定性的而加以简化。
“事实证明,当 $k \to \infty$ 时,值迭代算法所估计的价值函数收敛到最优价值函数,而与初始化 $V_0$ 无关,$$V^*(s) = \lim_{k \to \infty} V_k(s);\ \textrm{for all states } s \in \mathcal{S}.$$”
“It turns out that as \(k \to \infty\) the value function estimated by the Value Iteration algorithm converges to the optimal value function irrespective of the initialization \(V_0\), \[V^*(s) = \lim_{k \to \infty} V_k(s);\ \textrm{for all states } s \in \mathcal{S”
§17.2 Value Iteration查看原文 →
从 Q 学习的目标中去掉转移函数是正当的,而不是障眼法。
接着值迭代要求整个模型已知这一点,作者把对下一个状态按转移加权的平均,换成机器人实际落到的那一个下一个状态。由于那个状态本身就是机器人行动时从转移概率中抽取的,动力学仍然进入了目标——只是通过收集到的数据,而不是一个显式的公式。
“所以优化目标也能接触到转移函数,只不过是隐式地,通过机器人收集到的数据。”
“So the optimization objective also has access to the transition function, but implicitly in terms of the data collected by the robot.”
§17.3 Q-Learning查看原文 →
另外 2 个论点
一个只访问空间的一小片的数据收集策略,会在各处都破坏价值估计,而不只是在它没去的地方。
作者强调,Q 学习的更新是一个约束,把一个状态—动作对的值与其他对的值联系起来,所以对空间的稀薄覆盖,使整个估计成了对最优估计的糟糕近似。这就是为什么动作要与随机的选择混合,而不是总取当前最好的。
“这是因为 Q 学习的目标(或值迭代)是一个把所有状态—动作对的值联系在一起的约束。”
“This is because the Q-Learning objective (or value iteration) is a constraint that ties together the value of all state-action pairs.”
§17.3 Q-Learning查看原文 →
无需环境模型就能学习的自由,是用样本代价来付的。
在本章结尾,作者把差距归因于信息:值迭代可以查阅完整的模型,而 Q 学习必须从它自己的轨迹中推断出同样的东西,因此需要多得多的轮数。在同一个带确定性动作的 FrozenLake 网格上,它确实到达了最优解,但要在大约 250 次迭代之后。
“发生这种情况,是因为值迭代算法能够接触到完整的 MDP,而 Q 学习不能。”
“This happens because the Value Iteration algorithm has access to the full MDP whereas Q-learning does not.”
§17.3 Q-Learning查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么现在的价值分解为奖励加下一个价值
因为下一个状态只取决于当前状态和动作,一条轨迹可以被切成它的第一步和之后的一切。因此,从现在起的平均回报,等于所走的这一步的平均奖励,加上从你落到的地方出发的折扣平均回报,而折扣使这个总和即使对无穷无尽的轨迹也保持有限。这个恒等式,就是本章每个算法所迭代的东西。
机制 2
扩大状态恢复了马尔可夫性
如果下一个状态无法单从当前的描述预测出来,补救的办法是重新定义什么算作状态,而不是放弃这个模型。一个由加速度控制的机器人,光凭它的位置是无法预测的,但把位置与速度配成一对,就使下一对成为当前这一对和动作的函数。代价是更大的状态空间。
机制 3
被高估的动作如何自我降级
收集数据的策略多半挑选当前看起来最好的动作,所以价值被高估的动作会被选中并被真正执行。它返回的微薄的奖励送进下一次更新,把它的估计压下去。这只有在探索与不断演变的估计保持联系,而不是预先固定下来时才行得通。
常见误读
既然转移概率从 Q 学习的目标中消失了,这个方法的运作就不依赖环境的行为了。
依赖是转移了,而不是消失了:每次更新中用到的下一个状态,是从那些被去掉的转移概率中采样的,所以动力学是由机器人自己的经验提供的。Q 学习避免的,是需要事先把模型写下来,这恰恰是它需要多得多轮数据的原因。
“所以优化目标也能接触到转移函数,只不过是隐式地,通过机器人收集到的数据。”
“So the optimization objective also has access to the transition function, but implicitly in terms of the data collected by the robot.”
§17.3 Q-Learning查看原文 →
如果数据覆盖狭窄是问题所在,那么完全随机地行动就是收集数据最安全的方式。
完全随机的策略最终确实会到达每个状态,但作者指出,它需要非常大量的轨迹。推荐的做法是多半仍选当前最好的动作,混入一些随机性,这也让自我纠正得以运作:一个被高估的动作被试过,返回微薄的奖励,并在下一次更新时被压下去。
“这个特定的 $\pi_e$ 称为 $\epsilon$-贪心探索策略,因为它以概率 $1-\epsilon$ 选择(在当前估计 $\hat{Q}$ 下的)最优动作,而以其余的概率 $\epsilon$ 随机探索。”
“This particular \(\pi_e\) is called an \(\epsilon\)-greedy exploration policy because it chooses the optimal action (under the current estimate \(\hat{Q}\)) with probability \(1-\epsilon\) but explores randomly with the remainder probability \(\epsilon”
§17.3 Q-Learning查看原文 →
第 17 章的核心概念
- 强化学习
- 用来构建一个接一个地做决策的系统的技术,其中每个选择都会改变后面的情形。
- 适用处: 当未来的决策依赖于过去的决策时适用;与标准的深度学习不同,测试时的预测不是独立的。
- 马尔可夫决策过程
- 一个关于系统状态如何随动作的施加而变化的四部分模型:状态、动作、转移概率、奖励。
- 适用处: 要求下一个状态只取决于当前状态和动作;否则就扩大状态(例如加上速度)。
- 折扣因子
- 一个小于一的数,缩小遥远未来的奖励,这样即使是无穷无尽的轨迹,回报也是有限的。
- 适用处: 小的值推动走短的、到达目标的路径;接近 0.99 的值鼓励在承诺之前探索。
- 价值函数
- 如果你从一个状态出发,并按给定的策略持续行动,所期望的折扣回报。
- 适用处: 相对于一个策略来定义;最优的那个由最优策略达到。
- 动态规划原理
- 现在的价值等于眼前的奖励,加上你接下来落到的地方的平均价值;最优路径的尾部本身也是最优的。
- 适用处: 建立在马尔可夫假设之上;它是本章所有强化学习算法的基础。
- 值迭代
- 用动态规划恒等式反复更新价值估计,直到它们落定到最优值。
- 适用处: 假定环境的行为已知;Q 学习把它推广到未知的环境。
另外 4 个概念
- 策略
- 给定状态时动作的条件分布;确定性策略是把所有概率放在一个动作上的特例。
- 适用处: 在每个状态上,概率之和必须为一。
- Q 学习
- 根据采样的转移而不是已知的转移函数,来更新动作的价值。
- 适用处: 数据集中不存在的状态—动作对的价值,被设为负无穷。
- 探索与利用
- 把当前最好的动作与随机的动作混合起来,使数据覆盖整个空间。
- 适用处: 纯随机的策略能到达所有状态,但需要非常多的轨迹。
- 自我纠正的性质
- 被高估的动作会被挑选出来,产生很差的奖励,并在下一次更新时被降级。
- 适用处: 依赖于探索策略与不断演变的 Q 估计联系在一起。
第 17 章划线与批注AI 陪读
“零售商从离你家最近的仓库里找到衣服”
“the retailer finding the clothes in the warehouse closest to your house”
查看原文 →以包裹投递开篇很聪明:它偷偷带进了整个结构——许多行动者,没有单一的控制器,效用只在最后才实现。但请注意这个障眼法:真实的物流是由人类和求解器优化的,而不是强化学习。这个例子教的是问题的形状,而不是强化学习实际的胜利。
“在标准的深度学习中,一个训练好的模型对某个测试数据的预测,并不影响它对未来某个测试数据的预测”
“in standard deep learning the prediction of a trained model on one test datum does not affect the predictions on a future test datum”
查看原文 →这是我读过的对这个区别最干净的一句话陈述。强化学习所有的困难都住在这个被打破的独立性里:一旦你自己的输出成了你下一个输入的原因,独立同分布就死了,监督学习大多数让人安心的保证也随之而去。
“需要注意,奖励是由用户(创建强化学习算法的人)带着目标设计的。”
“It is important to note that the reward is designed by the user (the person who creates the reinforcement learning algorithm) with the goal in mind.”
查看原文 →像脚注一样顺带放进来,却是整个伦理和工程的关键。智能体优化的恰恰是你写下的,而不是你的本意。教科书把杠杆交给你,却走过了错误设定正是大多数真实的强化学习项目死掉的地方这一事实。
另外 15 条批注
“对于大的折扣因子,比如 $\gamma = 0.99$,机器人被鼓励去探索,然后找到最佳轨迹”
“For large values of the discount factor, say \(\gamma = 0.99\), the robot is encouraged to explore and then find the best trajectory”
查看原文 →这里要小心——γ 并不会鼓励探索。它只是让智能体对延迟的奖励有耐心。探索是一个独立的问题,由 ε-贪心、熵奖励等等来处理。这句话把远见与好奇混为一谈,而初学者会把这种混淆带下去。
“如果我们把状态 $s_t$ 选为元组 $(\textrm{location}, \textrm{velocity})$,那么这个系统就是马尔可夫的”
“if we chose our state \(s_t\) to the tuple \((\textrm{location}, \textrm{velocity})\) then the system is Markovian”
查看原文 →本章老实的一招。马尔可夫性不是世界的属性;而是你如何切分世界的属性。任何对历史的依赖都可以被吸收进状态——这也是安静的逃生口:推得足够远,状态空间就会爆炸。Atari 的四帧堆叠正是这个招数。
“从当前状态出发的平均回报,等于从下一个状态出发的平均回报,加上走到下一个状态的平均奖励”
“the average return from the current state is the sum of the average return from the next state and the average reward of going to the next state”
查看原文 →“相当直观”承担了很多。这个分解之所以成立,只是因为马尔可夫假设加上期望的线性——它只有在你接受了未来不在乎你是怎么到达的之后才直观。下游的一切,值迭代和 Q 学习都一样,不过是这一行被重新排列。
“V^*(s) = \mathrm{argmax}_{a \in \mathcal{A}} \Big\{ r(s,a) + \gamma \sum_{s' \in \mathcal{S}} P(s' \mid s, a) V^*(s') \Big”
查看原文 →一个有真正牙齿的笔误:这里应当是 max,而不是 argmax。一个返回值,另一个返回动作。上面一行,针对 π* 的,才是 argmax 的版本。值得标出来,因为一个从这里重建贝尔曼方程的读者,会建错。
“最优轨迹的剩余部分也是最优的”
“the remainder of an optimal trajectory is also optimal”
查看原文 →九个字里的贝尔曼的整个帝国。而反面才是让它可用的东西:你永远不需要在轨迹上搜索,只需在单步上搜索。从指数到多项式的这种压缩,才是真正的发现。
“动作是“上”($\uparrow$)、“下”($\rightarrow$)、“左”($\leftarrow$)和“右”($\rightarrow$)”
“actions that are “up” (\(\uparrow\)), “down” (\(\rightarrow\)), “left” (\(\leftarrow\)), and “right” (\(\rightarrow”
查看原文 →“下”被画成了右箭头,而“右”也被画成了右箭头——一个括号里两处符号错误。很小,但说明问题:行文校对过,记法没有。
“机器人有可靠的动作,即 $P(s' \mid s, a) = 1$”
“the robot has reliable actions, i.e. \(P(s' \mid s, a) = 1”
查看原文 →注意这种简化的代价:FrozenLake 的全部意义就是湿滑的冰面,而他们把它冻得结结实实。在确定性转移下,这只是最短路径搜索,而值迭代真正的卖点——处理随机性——从未得到演示。
“Q 学习背后的关键想法,是把上式中对所有 $s' \in \mathcal{S}$ 的求和,换成对机器人所访问过的状态的求和。”
“The key idea behind Q-Learning is to replace the summation over all \(s' \in \mathcal{S}\) in the above expression by a summation over the states visited by the robot.”
查看原文 →本章的支点,几乎是随口说出的。用来自经验的样本取代期望,是把规划变成学习的那一步——这意味着,智能体自己的行为现在决定了它能知道什么。这恰恰是为什么从这里开始,探索变得不可避免。
“我们没有作弊:当机器人在状态 $s_t^i$ 使用策略 $\pi_e$ 采取动作 $a_t^i$ 时,下一个状态 $s_{t+1}^i$ 是从转移函数中抽取的一个样本”
“We have not cheated: as the robot uses the policy \(\pi_e\) to take an action \(a_t^i\) at state \(s_t^i\), the next state \(s_{t+1}^i\) is a sample drawn from the transition function”
查看原文 →带防御性的“我们没有作弊”是无模型强化学习老实的核心:转移模型从不消失,它只是藏在数据里。采样就是模型,伪装起来了。
“不属于数据集的状态—动作元组 $(s, a)$ 的值,被设为 $-\infty$”
“The value of state-action tuples \((s, a)\) that are not a part of the dataset is set to \(-\infty”
查看原文 →一个像脚注一样偷偷塞进来的惊人选择——它还悄悄地与下面的代码矛盾,代码把 Q 初始化为零。负无穷还会毒害对未见动作的每一个 max。
“对所有状态 $s \in \mathcal{S}$ 的 $Q^*$ 的估计都会很糟,而不只是 $\pi_e$ 访问过的那些”
“the estimate of \(Q^*\) at all states \(s \in \mathcal{S}\) will be bad, not just the ones visited by \(\pi_e”
查看原文 →这一节里最有力的一句话。贝尔曼一致性是一个全局约束,所以局部的无知不会被局部地限制住——误差沿着每一条状态链向后传播。
“坏的动作,例如在 $\hat{Q}(s,a)$ 中被高估了价值的动作,会被机器人探索,但它们的价值在下一次更新中是正确的”
“Bad actions, e.g., ones whose value is overestimated in \(\hat{Q}(s,a)\), are explored by the robot but their value is correct in the next update”
查看原文 →起作用的是乐观:高估是自我惩罚的,因为它邀请了恰好驳倒它的那次试验。尽管“它们的价值是正确的”读起来像是“被纠正了”的笔误——而在实践中,由于 max 运算符,高估往往并没有被这么整齐地纠正。
“这种不仅收集新数据,还收集正确种类的数据的能力,是强化学习算法的核心特征”
“This ability to not only collect new data but also collect the right kind of data is the central feature of reinforcement learning algorithms”
查看原文 →这里是真正的分界线——不是奖励对标签,而是谁来选择数据集。监督学习继承它的数据;强化学习自己撰写自己的数据,并且必须接受它没能去看的一切。
“我们假定机器人的动作是可靠的,即 $P(s' \mid s, a) = 1$”
“we assume the robot has reliable actions, i.e. \(P(s' \mid s, a) = 1”
查看原文 →一个被随口说出的大幅简化——FrozenLake 恰恰以它的湿滑著称,而去掉它,就去掉了使目标中的期望根本要紧的随机性。
“Q 学习大约在 250 次迭代之后,可以为这个问题找到最优解”
“Q-learning can find the optimal solution for this problem roughly after 250 iterations”
查看原文 →一个老实而被低估的承认:不知道 MDP 的代价是用经验来付的。也值得注意,ε 始终保持在 0.9——几乎是纯粹的随机游走,没有衰减日程。
读后感AI 陪读
老实的 MDP 和尖锐的核心框定,被一个有误导性的开篇例子削弱了
当作一个整体来读,这一章是一次从问题到算法的压缩的下降,它的架构比它的执行要好。它以一次包裹投递开篇——许多行动者,没有中心控制器,只在最后才实现的回报——这在命名任何一个符号之前,就偷偷带进了序贯决策的整个形状。这个开头在教学上很聪明,却悄悄地有误导性:真实的物流是由人类规划者和组合求解器解决的,而不是强化学习,所以这个例子教的是问题的结构,而不是强化学习的任何实际胜利。本章随后靠一句话挣得了自己的位置,这是我读过的对这个领域最尖锐的框定:在标准的深度学习中,对一个测试数据的预测不影响对未来测试数据的预测。强化学习所有困难的东西,都住在这个被打破的独立性里。一旦你自己的输出造成了你的下一个输入,独立同分布就死了,监督学习那些让人安心的保证也随之而去。
MDP 一节是本章最强的一段,主要因为它在教科书通常虚张声势的地方很老实。它承认,马尔可夫性不是世界的属性,而是你如何把世界切分成状态的属性——把速度附加到位置上,系统就成了马尔可夫的,这也是 Atari 的四帧堆叠所利用的安静的逃生口,也是安静的陷阱,因为推得足够远,状态空间就会爆炸。贝尔曼分解被呈现为“相当直观”,这承担了大量未被承认的工作:它成立,是因为马尔可夫假设加上期望的线性,而它只有在你接受了未来不在乎你是怎么到达的之后才直观。下游的一切——值迭代、Q 学习,以及推而广之的深度强化学习——都是这一行被重新排列。最优性原理,用九个字说出来(“最优轨迹的剩余部分也是最优的”),是贝尔曼的整个帝国,它真正的有效载荷是反面:你永远不必在轨迹上搜索,只需在单步上搜索。从指数到多项式的这种压缩,才是真正的发现,而本章把它说了出来,却没有真正庆祝。
继续阅读
有两个弱点反复出现,值得点名。第一,记法没有像行文那样细心地校对过。最优值方程在需要 max 的地方写成了 argmax——一个返回值,另一个返回动作,而一个读者靠这一页重建贝尔曼方程,会建错。动作的符号把“下”和“右”都画成右箭头。关于未访问的状态—动作对被设为负无穷的说法,与代码直接矛盾,代码把 Q 初始化为零;而负无穷会毒害对未见动作的每一个 max。这些单个来看都很小,合起来却有腐蚀性,因为这恰恰是读者分不清笔误与微妙之处的材料。
第二,也是更实质的,贯穿全文的例子被拔掉了牙。FrozenLake 以湿滑的冰面著称,而本章通过假定确定性的转移,把它冻得结结实实。在 P(s'|s,a)=1 的情况下,问题归结为最短路径搜索,目标中的期望毫无分量,而值迭代真正的卖点——处理随机性——从未被演示。本章还在说大的折扣因子“鼓励探索”时,把耐心与好奇心混为一谈;γ 让智能体对延迟的奖励有远见,仅此而已。探索是一个独立的问题,由 ε-贪心和熵奖励来解决,一个把二者合并的初学者,会把这种混淆带进此后的每一个算法。Q 学习的演示更加重了这一点,它把 ε 始终保持在 0.9,没有衰减日程——近乎纯粹的随机游走,却装扮成一个策略。
Q 学习一节是本章真正的论证落地的地方。支点几乎是随口说出的:把对所有下一个状态的求和,换成对实际访问过的状态的求和。这一个替换把规划变成了学习,并带来一个文本以罕见的坦率点出的后果——“我们没有作弊”,因为下一个状态确实是从转移函数中采样的。转移模型在无模型强化学习中从不消失;它藏在数据里。采样就是伪装起来的模型。由此得出整章最好的观察:如果你的探索策略忽略了状态空间的一部分,那么对 Q* 的估计在各处都很糟,而不只是在被忽略的区域。贝尔曼一致性是一个全局约束,所以局部的无知不会被局部地限制住——误差沿着每一条状态链向后传播。而本章收尾的洞见是这个领域正确的分界线:不是奖励对标签,而是谁来撰写数据集。监督学习继承它的数据;强化学习自己写自己的,并且必须接受它拒绝去看的一切。max 运算符的乐观使这一点变得可处理——一个被高估的动作会邀请恰好驳倒它的那次试验——尽管文本在这里高估了整齐程度,因为在实践中,max 恰恰也是让高估偏差持续存在的原因。
我会这样告诉读者:从这一章里拿走 MDP 的形式体系和贝尔曼递归,并信任它们,因为它们被清楚而老实地呈现了。把方程当作草稿,重新推导,而不是照抄。在脑子里恢复那层冰——把湿滑打开,看看值迭代会怎么做——因为确定性的版本教了算法的机制,却藏起了它的目的。并抓住本章径直走过的那条脚注:奖励是你设计的,而智能体优化的恰恰是你写下的,而不是你的本意。本章把那根杠杆交给你,就继续往前走了,但错误设定是大多数真实的强化学习项目死掉的地方。把它读作对问题和两个经典算法的一张干净、紧凑的地图,而不是让强化学习奏效的指南。
在 FeedLitra 里读第 17 章,每段旁边都有这些卡片。
开始读书第 18 章:高斯过程
边际似然如何自动挑选长度尺度?
第 18 章是怎样展开的AI 辅助
开篇:重新安置建模假设。 本章开头是一次重新框定,而不是一项技术。普通的模型把它们的承诺藏在权重里——数量众多、单个毫无意义、没有人能检查和判断的参数。高斯过程则把假设直接放在函数上:任何对高斯参数线性的模型,本来就是一个高斯过程,所以这一步在一般性上不花任何代价。直线的情形让这一替换变得具体,对斜率和截距的先验变成了零均值函数和协方差 1 + xx′,之后人们直接对函数采样,再也不碰参数。从这里开始,作者引入核作为模型真正的接口,带有两个你真能对之推理的旋钮。长度尺度从 0.1 扫到 10,显示了它们做什么:一旦两个输入相隔超过长度尺度,它们的函数值基本上就不相关,所以曲线可以自由地在它们之间摆动——短的长度尺度给出快速变化的样本,以及一离开数据就膨胀的误差棒,长的则给出平滑的拟合。振幅只是把一切在垂直方向上拉伸。附带了两个老实的但书:这些值是凭肉眼选的,有原则的选择被推迟了,而且这些图的垂直尺度各不相同。
展开:闭式的预测,然后是函数空间的视角。 建立了函数上的先验之后,作者表明你永远不需要无穷多个样本来使用它。把联合高斯分布以观测为条件,解析地给出预测均值和协方差,所以除了核的超参数之外,没有什么需要训练的。一个单观测的例证承载了这一点:f(x₁) = 1.2,相关性为 0.9,把预测拉到约 1.08;把相关性提高到 0.95,把它拉到 1.14,误差棒更紧,不过由于只有一个数据点,不确定性仍然很宽。两个结构性的事实随之而出——均值取决于观测到的目标,而预测方差则不然,以及这种精确性历来带着三次方的代价,把训练集限制在一万个点左右。本章随后把这一转变形式化为真正的函数空间:一个高斯过程完全由它的均值函数和协方差函数确定。
转折:无限极限,在那里模型类合并。 支点是这样一个推导:取一个带高斯权重的径向基函数的加权和,它的协方差是对基函数中心的有限求和,然后让中心的数量无界增长。求和变成黎曼积分,而积分计算出的东西正比于 RBF 核。结论很尖锐:一个无穷参数化的模型在运行时不需要任何参数,因为整个函数上的先验都由一个闭式的协方差承载。作者随后借 Neal 1994 年的结果把论证转向外部——一个无限宽的贝叶斯神经网络就是一个带特定核的高斯过程——所以网络和核方法远没有通常所描绘的那么不同。但书使它不至于变成口号:闭式只对某些转移函数(如 erf 单元)已知,而由此得到的神经网络核是非平稳的,在原点附近行为不同,不像 RBF 核在各处看起来都一样。这也是本章先发制人地回应显而易见的反对意见的地方:无限的容量并不意味着过拟合,因为先验把质量集中在一个狭窄的平滑变化的函数家族上,而核的假设做的是参数数量否则会做的正则化。
收尾:实用的配方,以及误差棒的含义。 最后的乐章是动手的演练,有意与“没有什么要训练”的读法相矛盾。首先,检查先验:0.2 的长度尺度产生的样本函数,对数据而言变化太快,所以作者在拟合之前,把它重新初始化为 0.4。然后通过最大化边际似然来学习超参数,恢复出长度尺度 0.299 和噪声标准差 0.24——后者几乎精确。但成功明确地没有保证,而本章解释了目标为什么有相互竞争的最优点:长的长度尺度使函数几乎平坦,并把数据的变化记到大的噪声账上,而短的则让函数去追逐数据,留给噪声可解释的很少。两种说法在局部都是自洽的,目标是非凸且不可分解的(因此要用全批量 Adam 或 L-BFGS,不能用小批量),而糟糕的起点会落进错误的盆地。本章以一条解释性的纪律而不是一个结果结束:后验把关于隐函数的可约的认知不确定性,与不可约的偶然噪声分开,而一根误差棒在你说清它是哪一个、在什么尺度上之前,毫无意义。作者的证据是实践的惨状——未定义的误差棒、方差与标准差、标准差与标准误、置信区间与可信集之间的滑移——而演练出来的后果很尖锐:隐函数的 95% 可信集不应该吞下观测到的点;要覆盖它们,需要把噪声方差加回去。在 GPyTorch 里的最后一遍,在生产级工具里重现了整条流水线。
关键论点,以及支撑它们的原文
最好把你的建模假设放在函数上,而不是参数上。
作者的开篇动作:典型模型里的权重数量众多,单个几乎没有意义,而核让你陈述你真能判断的高层性质——摇摆得多厉害,尺度有多大。直线的例子让这一替换变得具体:对斜率和截距的先验变成了零均值函数和协方差 1+xx',之后可以直接对函数采样,而无需碰任何参数。而且因为任何对高斯参数线性的模型(包括无限宽的网络)都是一个高斯过程,函数空间一下子涵盖了许多熟悉的模型类。
“这些参数往往数量众多,且相对无法解释——比如神经网络的权重。”
“These parameters are often numerous and relatively uninterpretable — such as the weights of a neural network.”
§18.1 Introduction to Gaussian Processes查看原文 →
少数几个可解释的核旋钮,确定了平滑度、垂直尺度,以及不确定性增长得多快。
把建模移到函数空间之后,作者通过把长度尺度从 0.1 扫到 10,表明这些旋钮做什么:随着它增大,样本明显更不摇摆,因为相隔超过长度尺度的输入变得基本上不相关。相比之下,振幅只是在垂直方向拉伸函数,而不改变它变化得多快。但书也说明了:这里这些值是凭肉眼选的,通过边际似然自动选择被推迟了,而且这些图的垂直尺度各不相同。
“我们看到振幅参数影响函数的尺度,但不影响变化的速率。”
“We see the amplitude parameter affects the scale of the function, but not the rate of variation.”
§18.1 Introduction to Gaussian Processes查看原文 →
预测及其误差棒,出自简单的高斯条件化,是闭式的。
接着函数上的先验,作者指出你永远不需要抽取无穷多个样本:把联合高斯分布以观测为条件,解析地给出预测均值和协方差,所以除了学习核超参数之外,没有什么需要训练的。一个单点的例证承载了这个想法——观测到 f(x₁)=1.2,相关性为 0.9,把预测拉到均值约 1.08,把相关性提高到 0.95,把它拉到 1.14,误差棒更紧,不过由于只看到了一个点,不确定性仍然很宽。值得注意,均值取决于观测到的目标,而预测的不确定性则不然,而且这种精确性历来是以三次方的代价换来的,把训练集限制在一万个点左右。
“注意,我们实际上不必取无穷多个样本来计算这个期望;正如我们稍后将看到的,我们可以用闭式计算这个期望。”
“Note that we do not actually have to take an infinite number of samples to compute this expectation; as we will see later, we can compute the expectation in closed form.”
§18.1 Introduction to Gaussian Processes查看原文 →
另外 3 个论点
推到无限极限,神经网络和高斯过程就不再是分开的模型类。
这是作者把论证转过来的地方:用无穷多个基函数构建了一个高斯过程之后,他指向 Neal 1994 年的结果:一个有无穷多隐藏单元的贝叶斯神经网络,成为一个带特定核的高斯过程,所以网络与核方法并不像通常所描绘的那么不同。但书是这样的:闭式的核只对某些转移函数(如 erf 单元)已知,而由此得到的神经网络核是非平稳的——在原点附近行为不同,不像 RBF 核,其行为在各处看起来都一样。
“神经网络并不像我们把它们说成的那样不同。”
“Neural networks are not as distinct as we make them out to be.”
§18.2 Gaussian Process Priors查看原文 →
在拟合之前先看先验的样本,并记住拟合超参数是个非凸问题。
在动手演练中,0.2 的长度尺度产生的先验函数,对手头的数据来说变化太快,所以作者在拟合之前把它重新初始化为 0.4——检查先验是否合理是配方的一部分。最大化边际似然随后恢复出长度尺度 0.299 和噪声标准差 0.24,后者极其接近真值。但作者警告说,这种稳健性没有保证:因为长的长度尺度只有与大的噪声一起才可信,而短的长度尺度留给噪声去背锅的变化很少,目标有局部最优,糟糕的起点可能落进其中一个。
“在拟合数据之前,重要的是考虑我们是否设定了一个合理的先验。”
“Before we fit the data, it is important to consider whether we have specified a reasonable prior.”
§18.3 Gaussian Process Inference查看原文 →
在你说清它是哪种不确定性、画在什么尺度上之前,一根误差棒毫无意义。
得到了一个有两个可分离来源的后验——关于无噪声函数的可约的疑虑(认知的,随数据而缩小)和不可约的观测噪声(偶然的)——作者坚持要标明一幅图展示的是哪一个。他的证据是实践的状况:论文常常展示未定义的误差棒,并在方差与标准差、标准差与标准误、置信区间与可信集之间滑来滑去。演练例子中的实际后果是,隐函数的 95% 可信集,作为认知部分的两个标准差,不该吞下观测到的点;要覆盖观测,需要加上噪声方差。
“不精确说明不确定性代表什么,它基本上就毫无意义。”
“Without being precise about what the uncertainty represents, it is essentially meaningless.”
§18.3 Gaussian Process Inference查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
长度尺度如何让函数摆动
核说明了两个函数值有多强地相关,作为它们输入相距多远的函数。一旦两个输入相隔超过长度尺度,它们的值几乎不相关,所以函数可以自由地在它们之间摆动,远处的数据几乎不约束一个预测。因此,短的长度尺度给出快速变化的样本,以及离开数据就迅速膨胀的不确定性,而长的则给出平滑的拟合;振幅只重新缩放垂直方向的分散。
机制 2
无穷多个凸起坍缩成一个核
从一个模型开始,它是径向基函数的加权和,权重是高斯的;它的协方差是对基函数中心的有限求和。让基函数的数量无界增长,那个求和就成了黎曼积分,其值正比于 RBF 核。所以一个无穷参数化的模型在运行时根本不需要任何参数——整个函数上的先验由一个闭式的协方差函数承载。
机制 3
为什么超参数拟合有相互竞争的最优点
边际似然必须解释所有观测到的变化,而它可以用两种互不相容的方式做到。长的长度尺度使底层函数几乎平坦,所以数据里的摆动必须记到大的噪声方差账上;短的长度尺度则让函数自己去追逐数据,留给噪声可解释的变化很少。两种说法在局部都说得通,所以非凸的目标有分开的盆地,糟糕的起点可能落进错误的那个。
常见误读
一个有无穷多参数、能拟合任何连续函数的模型,肯定会在小数据集上过拟合。
容量和过拟合在这里是分开的两个问题:RBF 高斯过程是通用近似器,却在少量数据上泛化得很好,因为它的先验把大部分权重分配给一个狭窄的、合理的、平滑变化的函数家族。核里编码的强假设——相关性随输入距离衰减,带着特定的长度尺度和振幅——做的是参数数量否则不得不做的正则化。
“带 RBF 核的高斯过程是一个通用近似器,能够以任意精度表示任何连续函数。”
“A Gaussian process with an RBF kernel is a universal approximator, capable of representing any continuous function to arbitrary precision.”
§18.2 Gaussian Process Priors查看原文 →
既然作者说高斯过程回归基本上没有训练,这个方法就是开箱即用的,没有什么要调。
不需要训练的是后验本身,一旦核固定,它就从高斯条件化中掉出来。核的长度尺度、振幅和噪声水平仍然必须被学习,而作者的做法是最大化边际似然——一个既不凸、也不对数据点可分解的目标,所以不能用小批量,而是用 Adam 或 L-BFGS 以全批量运行,而初始化是在检查了先验样本之后有意选择的。
“预测均值明显依赖于目标值 $\textbf{y}$,而预测方差则不然。”
“The predictive mean explicitly depends on the target values \(\textbf{y}\) but the predictive variance does not.”
§18.3 Gaussian Process Inference查看原文 →
第 18 章的核心概念
- 高斯过程
- 函数上的一个分布:任何有限个函数值的集合都是联合高斯的。 函数上的一个先验,完全由一个均值函数和一个协方差(核)函数确定。
- 适用处: 要求高斯参数或基函数的形式;需要一个均值函数和协方差函数。 需要函数值的联合高斯性;非高斯的似然需要近似推断。
- 协方差函数(核)
- 给出两个输入处函数值之间协方差的函数;它设定泛化的行为。
- 适用处: RBF 假定相关性随输入距离衰减,这未必适合所有数据。
- 偶然不确定性与认知不确定性
- 认知不确定性来自信息的缺失,并随数据的积累而缩小。 认知不确定性是关于真实的无噪声函数的可约的疑虑;偶然不确定性是更多数据也无法消除的观测噪声。
- 适用处: 有别于观测噪声,后者在核上加一个对角项。 这里认知不确定性表现为 np.diag(post_cov),偶然不确定性表现为 post_sig_est**2;这种划分假定噪声模型是正确的。
- 超参数
- 这里是核的振幅和长度尺度,对函数尺度和平滑度的可解释的旋钮。
- 适用处: 好的值对泛化要紧;边际似然可以自动设定它们。
- RBF 核
- 最常见的协方差函数,带有一个振幅和一个长度尺度,控制变化。
- 适用处: 是平稳的,所以无法表达在输入空间中变化的性质。
- 平稳核
- 只取决于输入之间差值的核,所以函数的行为在各处看起来都一样。
- 适用处: 神经网络核是非平稳的,在原点附近看起来不同。
另外 4 个概念
- 边际似然
- 给定超参数时数据的概率,用来学习核的设置。
- 适用处: 通过对数行列式和线性方程组的求解,代价为 O(n^3)。
- 用于超参数学习的边际似然
- 把函数积分掉,得到仅给定核超参数和噪声时数据的似然,你可以最大化它来学习它们。
- 适用处: 非凸,且不对数据点分解,所以不能用小批量,糟糕的初始化可能落进局部最优。
- 精确的高斯过程推断
- 闭式的后验预测,只在似然是高斯的时候才有。
- 适用处: 对分类或非高斯似然,以及超过大约 10,000 个点的数据集,就失效了。
- 95% 可信集
- 预测均值两侧两个标准差,表达关于真值函数在哪里的信念。
- 适用处: 对隐函数来说,它不该包含数据点;要覆盖观测,需要加上噪声方差。
第 18 章划线与批注AI 陪读
“有一个不断出现的笑话:“一切都是高斯过程的特例”
“There is a running joke that “everything is a special case of a Gaussian process”
查看原文 →这个笑话同时也是个警告:一个解释一切的框架什么也约束不了。带高斯权重、对参数线性,是一个真正的限制,而这个笑话悄悄藏起了它在哪里咬人。
“高斯过程和深度神经网络不是相互竞争的方法,而是高度互补的”
“GPs and and deep neural networks are not competing approaches, but highly complementary”
查看原文 →注意那个防御性的姿态——一本深度学习书里的一章,必须为核为什么仍然要紧辩护。重复的“and”的笔误,是对这是活文本的一个很好的提醒。
“这些函数中的每一个都与我们的数据完全一致,完美地穿过每一个观测”
“each of these functions are entirely consistent with our data, perfectly running through each observation”
查看原文 →只因为这里假定无噪声才是真的,而这一点直到最后才被承认。读者会带走一幅错误的图景:插值就是高斯过程所做的事。
另外 17 条批注
“创建出一个有 95% 的概率包含函数真值的可信区间”
“creating a credible interval that has a 95% probability of containing the true value of the function”
查看原文 →不加限定地溜了进来:那是在模型之下的 95%,逐点的,而不是联合的。老实的措辞会损害这幅图的修辞。
“幸运的是,有一种稳健而自动的办法来指定这些超参数,那就是所谓的边际似然”
“Fortunately, there is a robust and automatic way to specify these hyperparameters, using what is called the marginal likelihood”
查看原文 →“稳健且自动”承担了很多——边际似然优化是非凸的,在稀疏数据上会愉快地使长度尺度塌缩。这张期票的日期标在后面的一本 notebook 里。
“我们的不确定性仍然正当地相当大,因为我们只观测到了一个数据点!”
“our uncertainty is still righly quite large, because we have only observed a single data point!”
查看原文 →两面板的相关性演示是这一段里最好的教学:把条件化画成穿过一个椭圆的一条水平线。关于高斯过程回归的一切都在那幅图里。
“此外,任何高斯过程 f(x) 都可以表示成方程 (18.2.1) 的形式”
“Moreover, any Gaussian process f(x) can be expressed in the form of equation (18.2.1)”
查看原文 →反过来才是真正的内容所在,而它被一个分句断言了,没有证明——它需要可能无穷多的基向量和一个 Mercer 式的论证。
“对参数做推理相对乏味,这些参数基本上无法解释”
“it is relatively tedious to reason about the parameters, which are largely uninterpretable”
查看原文 →“乏味”说轻了。真正的动作是,函数空间里有着同样的信息,而坐标是我们真能持有看法的——平滑性、周期性——而不是权重。
“令 $c_J = \log J$、$c_1 = -\log J$,并且 $c_{i+1}-c_{i} = \Delta c = 2\frac{\log J}{J}$”
“Let \(c_J = \log J\), \(c_1 = -\log J\), and \(c_{i+1}-c_{i} = \Delta c = 2\frac{\log J}{J”
查看原文 →回报在这里:无穷多个权重逐渐缩小的 RBF 凸起,变成了一个闭式的核。一旦你只碰它们的协方差,无穷多个参数就不再可怕。
“也许对过参数化神经网络的所有大惊小怪都是错置的。”
“Perhaps all the fuss about overparametrized neural networks is misplaced.”
查看原文 →一句论战式的旁白,溜进了教科书。作者有马在赛,而这一章悄悄地是一个论证,而不只是一份阐述。
“后来于 1996 年发表,因为它是 NeurIPS 最声名狼藉的拒稿之一”
“later published in 1996, as it was one of the most infamous NeurIPS rejections”
查看原文 →这一节里最好的一句话,而且是一条关于同行评审的脚注。领域的传说被偷渡进了推导——提醒我们,什么算重要,是很晚才被决定的。
“Radford Neal 发现的这一联系,促使机器学习研究者离开神经网络,转向高斯过程。”
“This connection, discovered by Radford Neal, triggered machine learning researchers to move away from neural networks, and towards Gaussian processes.”
查看原文 →注意总结没有点名的那个讽刺:九十年代清空了神经网络房间的同一个结果,如今被引来为神经网络辩护。定理没有变;变的是时尚。
“预测均值明显依赖于目标值 $\textbf{y}$,而预测方差则不然。”
“The predictive mean explicitly depends on the target values \(\textbf{y}\) but the predictive variance does not.”
查看原文 →高斯过程回归里最奇怪的事实。你的误差棒是由你看的地方画出来的,而不是你看到了什么——是采样的几何,而不是证据。事后关于超参数的对冲,承担了很多。
“给了高斯过程一个“慢”的名声,而这个名声近十年来已经不准确了”
“have given GPs a reputation for “being slow” that has been inaccurate now for almost a decade”
查看原文 →听得出的恼火。名声比它的成因活得久,在方法里如此,在人身上也如此。
“不精确说明不确定性代表什么,它基本上就毫无意义。”
“Without being precise about what the uncertainty represents, it is essentially meaningless.”
查看原文 →整章的道德中心,而且是关于诚实地画图,而不是关于数学。误差棒是一个读写能力的问题。
“我们既不希望、也不期望它包含这些数据点。”
“We would not want nor expect it to contain the data points.”
查看原文 →好的教学:点名了不该发生的事。大多数读者的本能是,好的区带应该把那些点吞进去。
“学到的噪声极其接近真实的噪声,这有助于表明我们的高斯过程对这个问题是设定得非常好的”
“the learned noise is extremely close to the true noise, which helps indicate that our GP is a very well-specified to this problem”
查看原文 →很方便——数据是由一个平滑的正弦加高斯噪声生成的,恰恰是核的假设。一个自我验证的演示。
“为了简单地重现上面的基本回归,这可能看起来是很多代码,从某种意义上说,确实如此。”
“This may seem like a lot of code to simply reproduce the basic regression above, and in a sense, it is.”
查看原文 →教科书里罕见的老实——承认库的版本对于玩具情形更糟,只靠未来来为之辩护。这才是框架真正的论证:你为选项权付出前期的代价。
“因为边际似然不对数据样本分解,我们不能在数据的“小批量”上使用优化器,并保证收敛。”
“Because the marginal likelihood does not factorize over data instances, we cannot use an optimizer over “mini-batches” of data and be guaranteed convergence.”
查看原文 →这里是高斯过程为什么从未搭上深度学习缩放浪潮的安静的结构性原因。没有分解,就没有 SGD,就没有廉价的扩展。一句话解释了十年的分道扬镳。
“与标准的深度学习不同,把边际似然优化得好,与良好的泛化有很强的对应关系”
“Unlike in standard deep learning, doing a good job of optimizing the marginal likelihood corresponds strongly with good generalization”
查看原文 →惊人的反转——在深度网络里,优化得更狠可能有害;在这里,目标实际上是值得信赖的。边际似然已经包含了奥卡姆惩罚,所以没有什么东西需要你来保护自己。
读后感AI 陪读
读者从早先的图中吸收到:高斯过程是靠插值运作的
本章分三步走——直觉、理论、实践——而这个走法就是论证。它一开篇就把高斯过程推销为函数上的分布,在那里你不再摆弄无法解释的权重,而是陈述你对函数本身的信念:它有多摇摆、多高、多平滑。一切都是高斯过程的特例这个不断出现的笑话,是被作为魅力提出来的,其实它是本章的承重论断,也是它最弱的时刻:一个涵盖一切的框架什么也约束不了,而真正的限制——对高斯参数是线性的——被藏在笑声后面。中间一段偿还了理论的债务:RBF 核作为逐渐缩小的基函数凸起的无限极限而出现,无限宽的网络变成高斯过程,后验和边际似然以闭式到来。最后一段把整个循环手工走了一遍,然后又在 GPyTorch 里走了一遍,而这种重复是书里老实的部分——它承认对于玩具问题,库更糟,只能作为对规模的首付款来辩护。
我看穿的,多半是修辞性的。早先的图画的是无噪声的函数,穿过每一个观测,所以读者把插值当作了高斯过程所做的事,而噪声模型直到最后才被坦白。可信区间被描述成有 95% 的概率包含真值,没有“在这个模型之下”,也没有“逐点”。边际似然优化被称为稳健且自动,而它其实是非凸的,在稀疏数据上会愉快地使长度尺度塌缩。最后的演示是自我验证的:正弦加高斯噪声,用一个恰好假设这一点的核去拟合,而恢复出来的噪声与真值吻合,因为它就是这么造出来的。这些没有一样是不老实的,但全部都是教科书在讨好自己的方法,而本章其实是一篇安静的论战——关于对过参数化网络大惊小怪可能搞错了地方的旁白,是一位有马在赛的作者,而对高斯过程和深度网络是互补的这一点的防御性坚持,是深度学习书里一章核方法的破绽。
继续阅读
本章最尖锐的东西,也是它半遮半掩的东西:预测方差不依赖于 y。你的误差棒是由你选择去看的地方画出来的,而不是由你在那里看到了什么——是采样的几何,而不是证据。紧挨着它的,是解释了高斯过程去了哪里的结构性事实:边际似然不对数据分解,所以没有小批量,没有 SGD,没有廉价的扩展。一句话就说明了十年的分道扬镳。还有值得做的反转:与深度学习不同,把高斯过程的目标优化得更狠,往往泛化得更好,因为奥卡姆惩罚已经在目标之内,而不是作为正则化硬加上去的。历史的讽刺没有被点名——Neal 的无限宽结果在九十年代清空了神经网络的房间,如今却被引来为神经网络辩护;定理从未改变,改变的只是时尚。
我会这样告诉读者:最好的教学是那幅两面板的相关高斯图,把条件化画成穿过一个椭圆的水平切片——关于高斯过程回归的一切都住在那里,所以在任何代数之前,先坐下来细看它。道德中心是一句关于图的话,而不是数学:不精确说明不确定性代表什么,它就基本上毫无意义。为了函数空间的重新框定和这条纪律去读这一章,并以它们应得的怀疑去读它的无噪声图、它自我验证的演示,和它的“稳健且自动”。
在 FeedLitra 里读第 18 章,每段旁边都有这些卡片。
开始读书第 19 章:超参数优化
在 HPO 的 API 里,搜索器和调度器如何划分决策?
第 19 章是怎样展开的AI 辅助
开篇:被提成经济问题的问题。 本章一开头就把超参数点名为支配学习和模型结构的设置——学习率、权重衰减、暂退率、层数和滤波器数量——并观察到在实践中它们是由人手工、靠试错设定的。第一步是确立这是站不住脚的,而论证是用价码而不是诉诸优雅来做出的:在 EC2 g4dn.xlarge 上,一次 CIFAR-10 的 ResNet 运行要花两个多小时,所以顺序地试十个配置就要消耗大约一天,而因为好的取值在不同数据集和模型之间会变,这一天必须在下一个问题上再花一遍。从这个代价出发,本章推出它的核心重新框定:调参成了一个嵌套的全局优化问题,在内层训练循环之外包着一个对配置空间的外层搜索。对这个外层问题的两个约束立刻被固定下来。目标必须是验证误差,而不是训练损失,因为训练损失在把正则化关掉时最小——把暂退率或权重衰减设为零,训练的数字改善而泛化变差,所以优化训练损失会系统性地选出错误的设置。而且搜索必须是无梯度的:验证误差对超参数的梯度,需要对整个训练过程求微分,随机的训练使每次测量无论如何都有噪声,而近似的超梯度方法还不具备竞争力。剩下的是样本高效的黑箱搜索,而本章的第一个实例是随机搜索——具体地展示在单个超参数上,为 softmax 分类采样学习率,并保留得分最低的那个。它被认可为正确的通用基线,简单,而且比网格搜索好,后者的等间距网格会随维度爆炸;但同一段话也标出了它的缺陷,本章余下的部分都在攻击它:随机搜索从不调整它的采样分布,而对毫无希望的配置和有希望的配置一视同仁地花掉完整的训练预算。
展开:三次相继的修补。 从基线出发,本章分层向外搭建。首先是一次方法论的纠正,而不是算法的:不能凭单次运行来评判一个 HPO 方法。随机搜索与贝叶斯优化的比较用不同的随机种子重复了 50 次,并作为统计量报告,由此得到的曲线说明了这一点——它们在大约 1000 秒之前无法区分,贝叶斯优化只在那之后才领先,而这个差距,任何一次有噪声的单次运行都很容易显示得反过来。其次是并行。层数或滤波器更多的配置训练起来就是更慢,所以同步的一批会让快的试验等慢的试验;一旦某个工作者空闲就立刻派发一个新的试验,消除了这种空转,使随机搜索大致快了工作者数量那么多倍。本章小心地说明了所宣称的是什么——收益在墙钟时间上,而不是总计算量上,而且它是用更多硬件买来这一收益的——并指出这里的异步之所以平凡,恰恰因为随机搜索是独立抽取的,而重用过去观测的方法需要额外的机制。第三是多保真度。资源预算 r 是基于这样的观察引入的:训练误差往往随 r 增长而下降,而代价随之上升,这使一次短的运行成为长运行的廉价预览。逐次减半利用了这一点:把许多配置运行 r_min 个轮次,只保留前 1/η,把幸存者的预算乘以 η,然后重复——这样同样的总开销就能覆盖多得多的候选。
转折:本章自己的修补,被本章自己的诊断所诊断。 支点是,逐次减半恰恰重新引入了并行刚刚消除的那个缺陷。一个档位必须等该档位的每个观测都到了才能晋升,所以落后者——每层滤波器更多、训练得比精简的更慢的配置——使工作者搁浅,就像在那个两工作者的日程里,Worker-1 等着慢的 Trial-2;只要一个档位的大小不是工作者数量的倍数,也会出现空转。ASHA 是解决办法:一旦某个档位上有 η 个观测,就晋升一个配置,而不等档位填满。本章明确说明,这是一次交易,而不是免费的改进。基于 η 个结果做出的晋升有时是错的,而辩护是概率性的,而不是有保证的——排名在档位之间保持相当一致,而每个档位随着填满变得更有信息,所以只有最早的、信息最稀疏的晋升是不稳的。值得注意,这与本章对多保真度一般所采用的老实是同一种:早期的档位被当作仅仅有信息,而不是可靠的法官,因为有噪声的学习曲线意味着低预算的排名可能误导,未来的赢家可能被丢弃。所主张的是损害有限,而不是没有损害。
收尾:让方法可操作。 论证了这笔交易之后,本章以兑现它收尾。ASHA 的回报用本章一直积累的词汇表述——零空转的同步——然后这个方法在 Syne Tune 里具体地运行,由 grace_period(在任何配置可以被评判之前的最小预算 r_min)和 reduction_factor(η,保留的比例,以及幸存者预算的乘数)参数化。因此,收尾落在开篇的代价论证所指的地方:一个自动化的、并行的、有预算意识的、不让任何工作者等待的搜索。
关键论点,以及支撑它们的原文
手工调超参数太慢,不切实际,而且结果无法迁移到新的任务上。
作者给它标了价:一次 ResNet 在 CIFAR-10 上的运行,在 EC2 g4dn.xlarge 实例上要花两个多小时,所以仅仅一个接一个地试十个配置,就烧掉大约一天——而且因为好的取值在数据集与数据集、模型与模型之间会变,那一天的工作必须在下一个问题上重复。正是这个代价,促成了搜索的自动化。
因为每次评估都代价高昂、无梯度而且有噪声,HPO 算法必须从很少的样本里找到好的配置。
作者推理说,计算验证误差对超参数的梯度,意味着对整个训练过程求微分,而且随机训练的随机性使每次测量无论如何都有噪声;近似的超梯度方法存在,但还不具备竞争力。排除了梯度之后,只剩下样本高效的黑箱搜索。
“此外,评估 $f$ 的计算负担,要求 HPO 算法用尽可能少的样本去逼近全局最优。”
“Furthermore, the computational burden of evaluating \(f\) requires HPO algorithms to approach the global optimum with as few samples as possible.”
§19.1 What Is Hyperparameter Optimization?查看原文 →
随机搜索是正确的通用基线,然而它浪费预算,因为它从不从已经见到的东西里学习。
作者展示了它在单个超参数上的运作——通过采样取值并保留给出最低验证误差的那个,来调节 softmax 分类的学习率——这就是它简单、被广泛使用、并且比网格搜索好的原因,后者固定的等间距网格会随维度数爆炸。反面是,它从不调整它的采样分布,对毫无希望的配置和有希望的配置花同样的完整训练预算。
“第一,它不会根据迄今收集到的先前观测来调整采样分布。”
“First, it does not adapt the sampling distribution based on the previous observations it collected so far.”
§19.1 What Is Hyperparameter Optimization?查看原文 →
另外 3 个论点
不能凭单次运行来评判一个 HPO 算法;每个实验必须用不同的随机种子重复,并作为统计量报告。
作者的比较把随机搜索和贝叶斯优化各用不同的种子运行 50 次。这两条曲线在大约 1000 秒之前无法区分,只在那之后贝叶斯优化才领先——这个差距,任何一次有噪声的单次运行都很容易显示得反过来。
“因此,在比较不同的算法时,把每个实验运行几次,并报告统计量,比如在基于随机数生成器不同种子的、多次重复的总体上的均值或中位数,至关重要。”
“Hence, when comparing different algorithms, it is crucial to run each experiment several times and report statistics, such as mean or median, across a population of multiple repetitions of an algorithm based on different seeds of the random number generator.”
§19.2 Hyperparameter Optimization API查看原文 →
一旦某个工作者空闲就开始一个新的试验,消除了同步造成的空转,使随机搜索大致快了并行工作者数量那么多倍。
作者指出,层数或滤波器更多的配置就是要花更长的时间,所以在同步的一批里,快的试验坐在那里等慢的;异步派发消除了这种等待。因为随机搜索的样本是独立抽取的,这样做很平凡——重用过去观测的方法需要额外的机制。作者明确说明,收益在墙钟时间上,而不是总计算量上,并且它需要比顺序设定更多的硬件。
逐次减半继承了完全相同的同步问题,而放弃同步,值得为它造成的更草率的晋升决定付出代价。
作者解释说,一个档位必须等该档位的每个观测都到了才能晋升,所以落后者——例如每层滤波器更多、训练得比精简的更慢的配置——使工作者空闲,就像在那个两工作者的日程里,Worker-1 等着慢的 Trial-2;只要一个档位的大小不是工作者数量的倍数,也会出现空转。ASHA 的异步晋升偶尔是错的,但作者判断,实践中这没有太大伤害,收益超过了它。
“在任何分布式系统中,同步通常意味着工作者的空闲时间。”
“In any distributed system, synchronization typically implies idle time for workers.”
§19.5 Asynchronous Successive Halving查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么训练损失不能用来挑设置
超参数不是在训练期间学出来的,而最小化训练损失会把每个正则项推向乌有:零暂退率或零权重衰减更好地拟合训练集,却泛化得更差。所以搜索必须改为按留出的验证误差给每个配置打分。
机制 2
廉价的短运行如何买到更多的试验
训练误差往往随预算 r 增长而下降,而代价随之上升,所以一次短的运行是廉价的预览。逐次减半把许多配置运行 r_min 个轮次,只保留前 1/eta,把幸存者的预算乘以 eta,这样同样的总开销就能覆盖多得多的候选。
机制 3
为什么基于 eta 个结果的晋升是可以容忍的
ASHA 一旦某个档位上有 eta 个结果,就晋升一个配置,而不是等待完整的档位。排名在档位之间保持相当一致,而每个档位随着填满变得更有信息,所以早期的、信息稀疏的晋升是唯一不稳的,而且没有工作者会空转。
常见误读
如果一个配置达到更低的训练损失,它就是更好的配置,所以搜索目标可以就是训练损失。
目标必须是留出的验证数据上的误差。训练损失在把正则化关掉时最小——把暂退率或权重衰减设为零,训练的数字改善而泛化变差——所以优化它会系统性地选出错误的设置。
“不幸的是,我们不能简单地通过最小化训练损失来调整这些超参数,因为那会导致在训练数据上过拟合。”
“Unfortunately, we cannot simply adjust these hyperparameters by minimizing the training loss, because this would lead to overfitting on the training data.”
§19.1 What Is Hyperparameter Optimization?查看原文 →
既然弱的试验被提早停止,早期的档位一定是可靠的法官,多保真度方法也可以被信任,永远不会丢弃本来会赢的配置。
作者把早期的证据当作仅仅有信息,而不是可靠的:学习曲线有噪声,所以低预算下的排名可能误导,而 ASHA 基于少到 eta 个结果做出的晋升,被承认有时是次优的——论证是排名足够一致,而档位随着填满变得更有信息,所以损害是有限的,而不是没有。
“大多数配置都被提早停止,只有表现更好的配置存活到 $r_{max}$。”
“Most of the configurations are stopped early and only the better performing configurations survive until \(r_{max”
§19.4 Multi-Fidelity Hyperparameter Optimization查看原文 →
第 19 章的核心概念
- 超参数
- 用户必须配置的设置,比如学习率、批量大小、权重衰减或层数,它们不是在训练期间学出来的。
- 适用处: 它们不能靠最小化训练损失来调节,因为那会把正则化推向零。
- 超参数优化
- 把超参数的自动搜索框定为一个全局优化问题,通常是最小化留出的验证误差。
- 适用处: 每次评估都需要完整训练,所以是嵌套的、昂贵的;目标函数的梯度不易得到。
- 配置空间
- 超参数取值的可行集,每个都有数据类型、有界的范围和可供采样的先验分布。
- 适用处: 太窄,最优点被排除在外;太宽,预算变得不可行;有依赖关系的超参数不在这里的范围内。
- 随机搜索
- 从配置空间中独立采样配置,直到预算耗尽,并返回观察到的最好的那个。
- 适用处: 它忽略过去的观测,对每个配置,好的和坏的一视同仁地花同样的资源。
- 异步随机搜索
- 一旦某个工作者空闲就开始一个新的试验,而不是等待整批完成。
- 适用处: 对随机搜索来说是平凡的,因为样本是独立的;使用过去观测的方法需要额外的工作。
- 多保真度超参数优化
- 在不同的预算 r 下评估配置,只把完整训练花在看起来好的那些上。
- 适用处: 假定误差随 r 下降而代价随 r 上升,并且早期的曲线虽有噪声却有信息。
另外 4 个概念
- 逐次减半
- 把 N 个配置运行 r_min 个轮次,保留最好的 1/eta,把幸存者再训练 eta 倍的时间,重复。
- 适用处: 当 N = eta^K 时,只有一个试验到达完整的预算 r_max。
- 异步逐次减半(ASHA)
- 逐次减半的一个版本,一旦某个档位上有 eta 个结果,就把一个配置晋升一档,这样没有工作者需要等待一个完整的档位。
- 适用处: 晋升的决定在早期可能是错的,因为档位在开始时人数稀少。
- 档位层面的同步
- 同步的 SH 必须先收齐某个档位上的每个观测才能晋升,这迫使工作者等待最慢的试验。
- 适用处: 只有当训练时间各异、或档位的名额不是工作者数量的倍数时才是问题。
- 暂停与恢复调度
- 与其停掉弱的试验,每个晋升的试验不如从头重新开始,除非每个轮次之后都对训练状态做检查点。
- 适用处: 只有带检查点时才高效;本章的 ASHA 运行通过提早停止试验避免了它。
第 19 章划线与批注AI 陪读
“超参数往往是用试错的方式设定的,或者有时被实践者留作默认值,导致泛化欠佳”
“hyperparameters are often set in a trial-and-error manner or sometimes left to their default values by practitioners, leading to suboptimal generalization”
查看原文 →一个安静而有杀伤力的开头:该领域最常见的做法被点名为猜测。整章的存在,是因为默认值是一种坦白,而不是一个选择。
“超参数优化是嵌套的,其中每次迭代都需要训练并验证一个机器学习模型”
“hyperparameter optimization is a nested one, where each iteration requires training and validating a machine learning model”
查看原文 →这是本章真正的成本中心,在一个分句里说完。后面每一个聪明的招数,都只是试图绕开这种嵌套。
“我们不能简单地通过最小化训练损失来调整这些超参数,因为那会导致过拟合”
“we cannot simply adjust these hyperparameters by minimizing the training loss, because this would lead to overfitting”
查看原文 →漂亮:HPO 需要一个单独的目标的理由,与正则化存在的理由相同。把暂退率设为零是完美的例证——有助于泛化的旋钮,总是损害训练损失。
另外 14 条批注
“即使只是顺序地试十个超参数配置,这也已经要花我们大约一天。”
“Even just trying ten hyperparameter configurations in sequence, this would already take us roughly one day.”
查看原文 →具体的数字在这里比任何理论更有说服力。并且注意这个算术意味着什么:十次抽取对一个连续空间来说是可笑的稀薄样本,却已经要花一天。
“现有的方法没有一个能与最先进的竞争,我们在这里不讨论它们”
“none of the existing approaches are competitive with the state-of-the-art yet, and we will not discuss them here”
查看原文 →对一条死路很老实——在教科书里罕见。对训练过程求微分是显而易见的想法,而后面的习题让你恰恰感受到它为什么行不通。
“我们通常试图快速找出一小组表现良好的超参数配置,而不是精确地命中全局最优”
“we usually try to identify a small set of well performing hyperparameter configurations quickly, instead of hitting the global optima exactly”
查看原文 →目标悄悄地从 argmin 降级为“够好就行,要快”。值得注意,有噪声的目标使精确优化不仅昂贵,而且毫无意义。
“没有哪个算法能找到配置空间中不包含的东西”
“no algorithms can find something that is not included in the configuration space”
查看原文 →搜索空间本身就是一个手工选定的超参数——所以自动化没有消除人的判断,只是把它搬到了高一层。
“采样到表现差的配置,与采样到表现较好的配置,是同样可能的”
“it is equally likely to sample a poorly performing configuration than a better performing configuration”
查看原文 →对随机搜索老实的控诉:无记忆。它从不从它刚刚烧掉的一天算力中学习。
“随机搜索在一定程度上缓解了维数灾难,并且可能比网格搜索高效得多”
“Random search somewhat mitigates the curse of dimensionality (Bellman, 1966), and can be far more efficient than grid search”
查看原文 →被低估的要点:网格搜索把预算浪费在重复采样那个要紧的超参数的相同取值上,而随机搜索在每次试验中给每个维度不同的取值。
“用原始的 FashionMNIST 训练集(60000 个样本)训练,用原始的测试集(10000 个样本)验证”
“the original FashionMNIST training set (60000 examples) for training, and the original test set (10000 examples) for validation”
查看原文 →本章在一道习题里栽下了它自己的方法论之罪。在测试集上调参,恰恰就是它所警告的那种泄漏——用有意的坏榜样来教学。
“把每个实验运行几次并报告统计量,至关重要”
“it is crucial to run each experiment several times and report statistics”
查看原文 →两层随机性意味着,单条 HPO 曲线几乎没有信息量。大多数论文漂亮的比较图,熬不过这一段话。
“随机搜索和贝叶斯优化在大约 1000 秒之前表现大致相同,但贝叶斯优化可以利用过去的观测”
“random search and Bayesian optimization perform roughly the same up to ~1000 seconds, but Bayesian optimization can make use of the past observation”
查看原文 →交叉点就是全部故事:只有在你买到足够多的观测来建模之后,建模才有回报。在小预算下,精巧什么也买不到。
“几个轮次之后,我们已经能够目测区分表现良好和欠佳的配置。然而,学习曲线是有噪声的”
“After a few epochs we are already able to visually distinguish between well-performing and suboptimal configurations. However, the learning curves are noisy”
查看原文 →整个多保真度的赌注,被表述为一种张力而不是一个定理:早期的信号是真实的,却不可靠。此后的一切,只是你愿意在它上面押多大的注。
“我们假定误差 $f(\mathbf{x}, r)$ 随 $r$ 下降”
“We assume that the error \(f(\mathbf{x}, r)\) decreases with \(r”
查看原文 →悄悄假设掉了过拟合。许多配置随着轮次增多反而变差,而这恰恰是廉价代理会误导你的地方。
“只有一个试验会被训练到完整的预算 $r_{max}$”
“only a single trial will be trained to the full budget \(r_{max”
查看原文 →所以一轮减半的赢家几乎完全是在低保真度下决定的——全预算的运行是加冕,而不是比较。
“只要收集到至少 $\eta$ 个观测,就把配置晋升到下一个档位”
“promote configurations to the next rung level as soon as we collected at least \(\eta\) observations”
查看原文 →两个数据点作为晋升委员会。大胆——而其理由是统计上的耐心:档位之后会填满,并悄悄纠正你早期的错误。
“档位随时间增长,并且越来越好地反映这个层级上指标值的分布”
“rungs grow over time and reflect the distribution of metric values at this level better and better”
查看原文 →ASHA 真正的论证:比较的阈值是一个滚动的估计,所以算法越往后越准确。错误是前置的,也是廉价的。
读后感AI 陪读
每一种超参数技术都留下一张账单,下一种必须处理
这一章读起来与其说是一项技术的教程,不如说是对不去猜测的代价的老实核算。它一开篇就点出该领域的默认做法——试错,或者干脆沿用默认值——是泛化欠佳的来源,然后用余下的篇幅表明,为什么显而易见的修补代价高昂,而聪明的修补全都是折中。弧线很紧凑:把 HPO 定义为一个嵌套的全局优化,以验证误差为目标(之所以嵌套,是因为每次评估都意味着端到端地训练一个模型);确立随机搜索为基线;发现一个你无法可靠度量的基线算不上基线,于是运行重复的随机种子并报告统计量;异步地并行化,以阻止工作者在落后者身上空等;然后,当并行化原来买到的是墙钟时间而不是算力时,引入资源维度 r,开始廉价地评估配置——逐次减半,然后是 ASHA,去掉减半重新引入的同步屏障。每一节的存在,都是因为前一节留下了一笔具体的未付账单,这在教科书里是罕见的结构上的老实。
细读之下我看穿的是:本章几乎每一个进展,都是用一个被削弱的保证买来的,而文本多半承认这一点,而不是把它藏起来。目标早早地就从 argmin 降级为“一小组表现良好的配置,要快”——理由不仅是代价,还有噪声,因为在一个随机的目标里,精确最优的点并不是一个有意义的目标。随机搜索在并行下完美的线性加速,是对无记忆的一种奖励;它之所以扩展得毫无瑕疵,恰恰因为它什么也没学到,而与贝叶斯优化的比较给出了互补的要点——只有当你买到足够多的观测来建模之后,建模才有回报,所以在小预算下,精巧是浪费钱。多保真度是最大的赌注,而本章把它表述为一种张力,而不是一个定理:早期的学习曲线明显地把好坏的配置区分开来,但它们是有噪声的。误差随 r 下降这一假设,悄悄地假设掉了过拟合,而这恰恰是廉价代理会误导的体制。逐次减半意味着赢家基本上是在低保真度下选出来的,而全预算的运行是加冕而不是比较;ASHA 走得更远,让两个观测构成一个晋升委员会。它真正的辩护不是早期的决定是正确的,而是它们便宜且前置,而档位会随时间填满,比较的阈值会成为对指标分布越来越好的滚动估计——算法一路上自我纠正。
继续阅读
我最尖锐的判断是关于人的判断究竟去了哪里。自动化没有去掉它;它把它搬到了高一层,搬进了配置空间,因为没有哪个算法能找到空间里不包含的东西。这也使本章自己的习题——在 FashionMNIST 的训练集上训练,在它的测试集上验证——成了正文里最有教益的时刻,一次对本章所警告的那种泄漏的有意演示。对读者说:认真对待算术(十个顺序的配置,大约一天,而十次抽取对一个连续空间来说是可笑的稀薄样本),在相信任何曲线之前,每个比较都用多个随机种子运行,并记住本章对基于梯度的 HPO 并不具有竞争力这一点的坦率,是如何持有所有这些方法的榜样——把它们当作有已知失败模式的、由代价塑造的赌注,而不是解决方案。
在 FeedLitra 里读第 19 章,每段旁边都有这些卡片。
开始读书第 20 章:生成对抗网络
是否存在一个均衡,使判别器再也无法区分这两个分布?
第 20 章是怎样展开的AI 辅助
开篇:从判别转向生成。 本章一开头回顾了本书的其余部分,它们讲的都是预测——把数据映射到标签,区分猫与狗,回归和分类。它承认由反向传播训练的网络做这件事做得多么出色,然后打开了一扇门:机器学习也可以瞄准对数据本身建模,把一个分布学得足够简洁,从而可以从中抽取新的样本。照片般真实的合成被点名为直到不久前还没有好方法的目标。文本所搭的桥梁是历史性的和概念性的:判别式的网络变得如此强大,以至于人们开始把它们挪作根本不是监督式的问题之用(RNN 语言模型是被引用的先例)。这就把 2014 年的 GAN 想法设定为那种趋势的一个具体实例——借用分类器的力量,并把它用作训练信号。
展开:双样本检验被变得具有建设性,然后被形式化。 核心直觉被框定为统计的:如果没有任何检验能把一个生成器的样本与真实样本区分开来,它就是好的,这就是经典的双样本检验。文本的关键论断是,GAN 与统计学的不同不在想法,而在用法——不只是报告“这些看起来不同”,检验的裁决被作为梯度反馈回去,以改进生成器。从这里开始,阐述转向机制:生成器/判别器的配对,每一次适应都激起对方的竞争循环,然后是数学。判别器是一个 sigmoid 输出、最小化交叉熵的二分类器;生成器把隐噪声 $\mathbf z$ 通过 $G$ 映射,并希望 $D(G(\mathbf z))\approx 1$。在这里,本章做了一个值得注意的老实的技术绕道:最大化 $-\log(1-D(G(\mathbf z)))$ 这个“自然”的目标会产生梯度消失,所以实践中改为最小化 $-\log D(G(\mathbf z))$——同样的前向传播,只是把标签翻成 $y=1$。只有在那之后,极小极大的目标才作为总结被陈述出来。理论随后有意落得很低:不是图像,第一个演示是“世界上最没效率的高斯参数估计量”——线性变换过的二维正态数据,单个线性层的生成器,三层 MLP 的判别器,以及成对的 update_D/update_G 函数,其唯一的不对称是标签,以及那个让生成器置身于判别器梯度之外的 detach()。
转折:从玩具到照片般真实。 第 20.2 节明确宣布了转变——二维高斯“把意思讲到了”,但“不是特别令人兴奋”——并换成了在宝可梦精灵数据集上的 DCGAN。论证的结构没有变;两个网络的实质变了。在判别式视觉上被证明过的卷积机制被整个引进来,并为生成器反过来运行:G_block 堆叠转置卷积、批量归一化和 ReLU,算术被写明,以显示每个块都让空间尺寸翻倍,所以四个块加上最后一层,把一个 $1\times1\times100$ 的隐向量带到 $3\times64\times64$,用 tanh 匹配数据归一化所选择产生的 $[-1,1]$ 范围。判别器随后被呈现为字面上的镜像——D_block 在每一步让分辨率减半,一直降到单个标量——只有一处实质的改变,并以它自己的理由作动机:leaky ReLU,分段定义,并在 $\alpha$ 上作图,引入它是为了治愈 ReLU 死亡的问题,让梯度继续流动。训练只改变了两个调过的细节,都以对抗的设定来辩护:共用一个学习率,因为这两个网络现在彼此相像,以及 Adam 的 $\beta_1$ 从 0.9 降到 0.5,以减少快速变化的梯度下的动量平滑。
收尾:一个保持在架构层面的总结,以及重新打开问题的习题。 本章结束时没有宣称问题已解决。它的总结重述了 min/max 这一对,并罗列了 DCGAN 的层数和设计选择,而没有评估样本质量,它还公开指出,演示运行的轮次太少,得不到好的结果。习题随后恰恰反驳了文本抹平的那些地方:是否存在一个均衡,使生成器在有限样本上真正获胜(极小极大的表述提出却没有回答的稳定性问题);如果用朴素的 ReLU 取代 leaky ReLU 会坏掉什么(检验那个有动机的偏离);以及 DCGAN 在 Fashion-MNIST 各类别上表现如何(探测这个方法是否均匀地泛化)。因此,整体的形状是:直觉 → 带着实践纠正的形式体系 → 极小的玩具验证 → 卷积的放大 → 有意没写完的收尾。
关键论点,以及支撑它们的原文
GAN 真正的新意,是建设性地使用双样本检验,而不只是把它当作一个裁决。
接着前一点,作者把统计学的论文——它们止步于宣布两个数据集看起来不同——与 GAN 作对比,后者把同一个比较转化为训练信号,不断改进生成器,直到它的样本类似真实数据。
“总之,$D$ 和 $G$ 在玩一个“极小极大”博弈,其综合的目标函数是:”
“To sum up, \(D\) and \(G\) are playing a “minimax” game with the comprehensive objective function:”
§20.1 Generative Adversarial Networks查看原文 →
整个设置可以写成关于单个交叉熵目标的一个极小极大博弈。
作者把两个独立的更新折叠成一个表达式,其中判别器最小化、生成器最大化在真实数据和噪声样本上取的期望交叉熵,明确了这两个网络是朝相反的方向优化同一个量。
“总之,$D$ 和 $G$ 在玩一个“极小极大”博弈,其综合的目标函数是:”
“To sum up, \(D\) and \(G\) are playing a “minimax” game with the comprehensive objective function:”
§20.1 Generative Adversarial Networks查看原文 →
在实践中,这个干净的目标中属于生成器的那一半,必须被替换才能让训练管用。
在陈述了优雅的极小极大形式之后,作者紧接着指出它的弱点:一个成功的生成器把原来那一项的值推到接近零,梯度也接近零,所以转而最小化 -log D(G(z)),办法是用真实数据的标签传入假样本。对称性被牺牲,换来可用的梯度。
“如果生成器做得完美,那么 $D(\mathbf x')\approx 1$,于是上面的损失接近 0,这导致梯度太小,无法让判别器取得良好的进展。”
“If the generator does a perfect job, then \(D(\mathbf x')\approx 1\), so the above loss is near 0, which results in the gradients that are too small to make good progress for the discriminator.”
§20.1 Generative Adversarial Networks查看原文 →
另外 1 个论点
在识别任务上证明了自己的卷积设计,可以被反过来用来合成图像。
作者指出,判别式的网络此前已经被挪作他用过(一个预测字符的语言模型兼作文本生成器),然后通过镜像一个标准的卷积网络来构建 DCGAN:四个转置卷积块把一个 100 维的噪声向量从 1x1 扩展到 32x32,同时让通道减半,最后一个转置卷积到达 3x64x64,而 tanh 把输出压进 (-1,1),以匹配以同样方式归一化的宝可梦图像。
“我们将借用在判别式计算机视觉问题上被证明如此成功的卷积架构,并展示如何借助 GAN,利用它们来生成照片般真实的图像。”
“We will borrow the convolutional architecture that have proven so successful for discriminative computer vision problems and show how via GANs, they can be leveraged to generate photorealistic images.”
§20.2 Deep Convolutional Generative Adversarial Networks查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
竞争把评判变成了训练
判别器被训练成给真实数据标 1、给生成的数据标 0,而它的裁决成为生成器的学习信号。每当生成器学会骗过它,判别器就重新适应新的假货,而那种更敏锐的判断被反馈回去,推动生成器走得更远,所以两者靠相互追逐而改进。
机制 2
重新标注假货,让梯度保持存活
如果生成器要最大化 -log(1-D(G(z))),那么一旦它成功、D(G(z)) 接近 1,损失就停在接近零的地方,梯度缩小到几乎没有,使进展停滞。补救办法是把生成的样本喂给判别器,却谎称标签是 1,并最小化 -log D(G(z)),这推动的是同一个方向,却仍然产生可用的梯度。
机制 3
为什么有一个漏出的负斜率会有帮助
朴素的 ReLU 在输入为负的地方梯度为零,所以一个持续产生负的预激活的单元得不到梯度,永远无法恢复。Leaky ReLU 则让负输入的一小部分 alpha 通过,这样梯度继续流过这样的单元,它们在训练中仍可以移动。
常见误读
把生成器的目标从最大化 -log(1-D(G(z))) 换成最小化 -log D(G(z)),只是代数上的整理,因为两者都奖励骗过判别器。
两者在方向上一致,但在梯度大小上不一致:随着生成器开始成功、D(G(z)) 趋近于 1,第一种形式会变平,值接近零、梯度也接近零,所以学习恰恰在该继续的时候停滞了。把假样本重新标成真、并最小化 -log D(G(z)),恰恰在那个体制下保持梯度很大,这就是作者称之为常见选择的原因。
“如果生成器做得完美,那么 $D(\mathbf x')\approx 1$,于是上面的损失接近 0,这导致梯度太小,无法让判别器取得良好的进展。”
“If the generator does a perfect job, then \(D(\mathbf x')\approx 1\), so the above loss is near 0, which results in the gradients that are too small to make good progress for the discriminator.”
§20.1 Generative Adversarial Networks查看原文 →
既然 leaky ReLU 的帮助在于让负输入通过,那么更大的 alpha 就应该严格更好。
有用的范围是 alpha 严格在 0 和 1 之间:在 alpha=0 时这个函数是朴素的 ReLU,而在 alpha=1 时它变成恒等映射,一个纯粹线性的映射,没有留下任何非线性可供网络利用。判别器各块中使用的默认值是 0.2 的小小漏出,足以让梯度继续流动,而又不放弃非线性。
“Leaky ReLU 是一个非线性函数,对负的输入给出非零的输出。”
“leaky ReLU is a nonlinear function that give a non-zero output for a negative input.”
§20.2 Deep Convolutional Generative Adversarial Networks查看原文 →
第 20 章的核心概念
- 生成对抗网络(GAN)
- 两个相互对抗地训练的网络:一个造假数据,一个评判它。
- 适用处: 需要一个足够强的判别器来给出有用的信号;训练是不稳定的,因为双方都在移动。
- 生成式建模
- 把一个数据分布学得足够好,从而可以采样出看起来像训练数据的新样本。
- 适用处: 与分类不同,它不需要标签,但成功很难用数字来打分。
- 隐变量
- 生成器把它变换成一个样本的随机噪声向量。
- 适用处: 从一个固定的简单来源抽取,比如正态分布,不是学出来的。
- leaky ReLU
- ReLU 的一个变体,对负的输入漏出一个小小的斜率,这样梯度永远不会完全死掉。
- 适用处: 在 alpha=0 时等于朴素的 ReLU,在 alpha=1 时是恒等映射;只有 alpha 在 (0,1) 之间才有用。
另外 0 个概念
第 20 章划线与批注AI 陪读
“GAN 依赖这样的想法:如果我们无法把假数据与真数据区分开,数据生成器就是好的”
“GANs rely on the idea that a data generator is good if we cannot tell fake data apart from real data”
查看原文 →整个领域在一句话里——并且注意那个安静的障眼法:“我们”被换成了“一个容量固定的神经网络”。对一个 CNN 来说不可区分,并不是不可区分。
“而不只是训练一个模型来说“嘿,这两个数据集看起来不像来自同一个分布”
“rather than just training a model to say “hey, these two datasets do not look like they came from the same distribution”
查看原文 →真正的动作:把检验统计量变成梯度。统计学问的是是否;GAN 问的是朝哪个方向走。值得停下来想想,这种转换有多罕见。
“如果生成器做得完美,那么 $D(\mathbf x')\approx 1$,于是上面的损失接近 0,这导致梯度太小,无法让判别器取得良好的进展。”
“If the generator does a perfect job, then \(D(\mathbf x')\approx 1\), so the above loss is near 0, which results in the gradients that are too small to make good progress for the discriminator.”
查看原文 →这段是混乱的。梯度消失的问题,咬的是生成器差(D≈0)的时候,而不是完美的时候,而且它让生成器断粮,而不是判别器。给出的修法是对的;这里印出来的理由是倒着的。
另外 11 条批注
“min_D \max_G \{ -E_{x \sim \textrm{Data}} \log D(\mathbf x) - E_{z \sim \textrm{Noise}} \log(1 - D(G(\mathbf z”
查看原文 →相对于 Goodfellow 的目标,min 和 max 被调换了:D 应当最大化这个量的负值,也就是最小化损失,而 G 则最大化它。照现在这么写,角色是颠倒的——而 min-max 对 max-min 不是表面上的顺序,它改变谁得到内层的最优。
“世界上最没效率的高斯参数估计量”
“the world’s most inefficient estimator of parameters for a Gaussian”
查看原文 →老实又好笑,而且在教学上是正确的选择:用一个你知道闭式答案的玩具,这样当 GAN 摇摆时,你知道是方法的问题,而不是数据的问题。
“它字面上只需要学会参数,就能完美地造假”
“it literally only needs to learn the parameters to fake things perfectly”
查看原文 →罕见的奢侈:生成器的假设类恰好包含真值。你将来调试的每一个真实的 GAN 失败,都发生在这个条件之外,所以别让演示的成功教你乐观。
“我们将使用一个 3 层的 MLP,让事情更有趣一点”
“we will use an MLP with 3 layers to make things a bit more interesting”
查看原文 →这个不对称才是真正的教训,被淡化成了一个玩笑。一个线性的 G 对一个非线性的 D——容量不匹配,是 GAN 实践者一辈子都在转的那个旋钮。
“# 需要重新计算 fake_Y,因为 net_D 已经改变”
“Recomputing `fake_Y` is needed since `net_D` is changed”
查看原文 →两条注释,两个相反的教训:重用 fake_X(廉价,有效),重新计算 fake_Y(D 动了)。这恰恰是人们因为多缓存了一行而悄悄破坏交替优化的地方。
“是否存在一个均衡,使生成器获胜,即判别器最终在有限样本上无法区分这两个分布?”
“Does an equilibrium exist where the generator wins, i.e. the discriminator ends up unable to distinguish the two distributions on finite samples?”
查看原文 →一个比看上去更尖锐的问题。在有限样本上,是的,平凡——把训练集背下来,D 就无计可施。这揭示出这个标准自己无法区分生成与抄写。
“4 + 2 \times (16-1)- 2 \times 1] \times [(4 + 2 \times (16-1)- 2 \times 1]\\ &= 32 \times 32”
查看原文 →算术检查:4+30−2 = 32。✓。但公式写得不必要地繁复——转置卷积的输出就是 s(n−1)+k−2p;第一行就是这个恒等式的伪装。
“输出的宽和高将分别增加 3”
“the output will have its width and height increased by 3 respectively”
查看原文 →“增加 3”——从 1×1 到 4×4,所以技术上是真的,也最让人困惑。老实的说法是 k−2p = 4,也就是说,步幅为 1、不带填充的转置卷积,把一个点投影成一个 k×k 的块。
“它降低了动量——对过去梯度的指数加权滑动平均——的平滑程度,以应对因生成器和判别器相互搏斗而快速变化的梯度”
“It decreases the smoothness of the momentum, the exponentially weighted moving average of past gradients, to take care of the rapid changing gradients because the generator and the discriminator fight”
查看原文 →DCGAN 一节里最好的一句话。β₁=0.5 不是论文里的魔数——而是承认损失地形在构造上就是非平稳的,所以长记忆的动量,是在对一个已经变了的对手取平均。
“判别器是 4 层带步幅的卷积,带批量归一化(输入层除外)”
“The Discriminator is a 4-layer strided convolutions with batch normalization (except its input layer)”
查看原文 →总结声称有这个例外;代码没有实现它——第一个 D_block(n_D) 带了 BatchNorm。DCGAN 的论文明确在 D 的输入层省略 BN。总结与代码不一致。
“如果我们使用标准的 ReLU 激活而不是 leaky ReLU,会发生什么?”
“What will happen if we use standard ReLU activation rather than leaky ReLU?”
查看原文 →有意思的答案不是“神经元死亡”,而是梯度路径:D 的梯度是生成器唯一的老师。把它的一半置零,你不是在拖慢 D,而是在切断 G 的监督信号。
读后感AI 陪读
把统计检验重新框定为梯度很漂亮,数学的阐述却很草率
一章教得漂亮的想法,却教得草率的数学。概念的脊梁真正出色:把双样本检验重新框定为可微的训练信号,是现代机器学习中最了不起的动作之一,而作者们用一段话就把它传达了。玩具高斯分布是选得好的教学:闭式的真值,一个其假设类恰好包含它的生成器,所以每一次失败都可以归因。而 β₁=0.5 的解释,是书解释一个超参数而不是背诵它的罕见例子:动量假设平稳性,对抗训练破坏平稳性,所以缩短记忆。但形式化的段落需要一份勘误。非饱和损失的理由是倒着说的——梯度消失折磨的是一个失败的生成器,让 G 断粮,而不是一个完美的生成器让 D 断粮——而极小极大的目标把 min 和 max 贴在了错误的参与者身上。DCGAN 的总结断言判别器的输入层没有批量归一化,而代码却用了它。转置卷积的代数是正确的,但写成了一种藏起底下那个简单恒等式 s(n−1)+k−2p 的形式。还有两个更深的遗漏困扰着我。第一,本章从没说对抗博弈实际上在最小化什么——最优 D 下的詹森—香农散度——所以模式坍缩、不收敛,以及整条 Wasserstein 的工作线,都没有地方可以挂靠;读者带走的是一份食谱,没有诊断的词汇。第二,唯一的一道习题偶然暴露了这个框架的软肋:在有限样本上,一个把训练集背下来的生成器直接获胜。不可区分性这个标准,自己无法区分生成与抄写。这种张力值得本章的关注,而不是留给它的习题。
在 FeedLitra 里读第 20 章,每段旁边都有这些卡片。
开始读书第 21 章:推荐系统
矩阵分解如何把协同过滤变成一个可训练的模型?
第 21 章是怎样展开的AI 辅助
开篇:问题与词汇。 本章一开头就把推荐系统框定为信息过滤器——把一个压倒性的目录削减到某个人大概想要的东西的工具。作者论证,回报是双向的:用户在搜索上花的功夫更少,而企业赚得更多,亚马逊、Netflix 和 YouTube 被作为证据,说明推荐位于这些服务的核心,而不是装点它们的边缘。从这里开始,本章摆出了它的工作词汇:记忆式、模型式和混合形式的协同过滤,以及显式反馈(一次有意的星级评分)与隐式反馈(点击、购买、浏览历史,免费地积累起来)之间的区别。一个关键的机制性要点在这里被埋下。记忆式的协同过滤通过数两个用户共有的物品来度量相似性,所以在一个稀疏而巨大的交互矩阵上,两个用户很少有足够的重叠使这种相似性有意义——这恰恰是为什么模型式的方法,学习紧凑的隐因子而不是数重叠,会成为主流,以及为什么它们自然地延伸到神经网络。作者也承认了隐式信号的代价:看过一部电影并不意味着观众喜欢它。
展开与第一个转折:从预测评分到排序。 确立了大多数已部署的系统运行在隐式反馈上之后,本章转而反对它刚刚引入的模型。像矩阵分解和 AutoRec 这样的评分预测器,直接丢弃没有观测的用户—物品对,所以它们无法区分一个被观测的对和一个未被观测的对——而因为缺失的并不是随机缺失,拟合出来的模型对排序的目的而言是有偏的。补救办法是优化相对的顺序,而不是绝对的得分。本章综述了逐点、成对和列表式的目标,然后落在成对的家族上:合页排序损失,把一个采样的负例以一个安全间隔推离正例,在精神上被视为与贝叶斯个性化排序可互换,因为两者都只关注正例与负例之间的差距,而这正是一个排好序的列表实际需要的。列表式的方法更直接地瞄准排序指标,却被标明计算量大得多。这一节也是本章一贯的警告所在:缺失的交互混合了真正的不喜欢,和用户干脆从未见过的物品,所以缺失不是负面看法的证据——因此要采样负例,而不是假定它们。在架构上,展开继续到 NeuMF,它融合了一条广义矩阵分解的分支和一条 MLP 的分支,以及 Caser,它把交互历史当作序列,使短期和长期的兴趣被分别建模。
第二个转折:转向富特征的 CTR 预测和因子分解机。 本章随后再次改变场景,从只有用户—物品标识符,转到对富类别特征的点击率预测。在为 CTR 数据准备了一个数据集包装器之后,它引入了因子分解机,而为它辩护的论证是计算上的。枚举每一个特征对,代价是特征数的二次方时间;作者把交互项改写成经嵌入加权的特征之和的平方的一半,减去它们平方之和,这样一遍就够了,而由于只有非零项有贡献,代价降到特征数的线性。这是广告数据的决定性性质,那里独热编码的特征既是高维的,又绝大多数为零。作者还展示了 FM 如何吸纳熟悉的模型:它的前两项就是普通的线性回归,而如果一个特征索引用户、另一个索引物品,那么交互项恰恰就是矩阵分解的点积。
收尾:翻转赞美,以及 DeepFM。 本章以和它早先转而反对评分预测同样的方式转而反对 FM 来收尾。FM 的二阶双线性形式,无论多么廉价,对真实数据中出现的复杂非线性交叉来说都过于僵硬。显而易见的扩展——数三元组和四元组的三阶或四阶 FM——被承认在理论上可行,在实践中则因数值不稳定和昂贵而被否决。DeepFM 是本章转而给出的回答:一个 MLP 与 FM 块并行运行,在同一个共享的嵌入表之上,它们的输出在 sigmoid 之前相加。因为来自两个分支的梯度流回同样的嵌入,二阶交叉和深层非线性组合是被联合拟合的,而不是分成两个独立的阶段——作者把这归功于所报告的结果:DeepFM,带一个三层 30-20-10 的 MLP,其余的超参数与 FM 保持一致,在一个在线广告数据集上,收敛得比 FM 更快,得分更好。最后的说明为这条弧线收尾:与 Wide & Deep 不同,DeepFM 自动发现特征组合,省去了那种做法所要求的手工特征工程。
关键论点,以及支撑它们的原文
推荐系统在两边都有回报:用户找东西花的功夫更少,而企业赚得更多。
作者指向亚马逊、Netflix 和 YouTube,在那里推荐位于服务的核心而不是边缘,以此作为证据,说明过滤一个压倒性的目录在商业上是核心的,而不是一个单纯的便利功能。
“采用推荐系统的好处是双重的:一方面,它可以大大减少用户找东西的功夫,并缓解信息过载的问题。”
“The benefits of employing recommender systems are two-folds: On the one hand, it can largely reduce users’ effort in finding items and alleviate the issue of information overload.”
§21.1 Overview of Recommender Systems查看原文 →
大多数推荐系统都建立在隐式反馈上,它虽然有噪声,却很丰富。
作者对比了两种信号类型:在 IMDb 上打一个星级评分,需要用户特意去做,而点击、购买和浏览历史则免费地从普通使用中积累起来。所述的代价是不可靠——作者指出,看过一部电影实际上并不意味着观众喜欢它。
“因此,许多推荐系统以隐式反馈为中心,它通过观察用户行为间接地反映用户的看法。”
“As such, many recommender systems are centered on implicit feedback which indirectly reflects user’s opinion through observing user behavior.”
§21.1 Overview of Recommender Systems查看原文 →
基于转向隐式信号这一点,被训练来预测显式评分的模型,是个性化排序的错误工具。
作者的推理是,矩阵分解和 AutoRec 干脆丢弃没有观测的用户—物品对,所以它们无法区分一个被观测的对和一个未被观测的对;由于缺失的并不是随机缺失,由此得到的模型对排序的目的而言是有偏的。
“显然,这些模型无法区分被观测的对和未被观测的对,通常不适合个性化排序的任务。”
“Clearly, these models are incapable of distinguishing between observed and non-observed pairs and are usually not suitable for personalized ranking tasks.”
§21.5 Personalized Ranking for Recommender Systems查看原文 →
另外 3 个论点
补救办法是优化相对的顺序,而不是绝对的得分,这正是成对目标所做的。
作者展示了合页排序损失,把负例以一个安全间隔推离正例,并视之为与贝叶斯个性化排序可互换:两者都只关注正例和一个采样的负例之间的差距,而这恰恰是一个排好序的列表所需要的。所述的取舍是,列表式的方法更直接地瞄准排序指标,但计算量大得多。
“与 BPR 类似,它旨在优化正样本和负样本之间的相对距离,而不是绝对的输出,使它非常适合推荐系统。”
“Similar to BPR, it aims to optimize for relevant distance between positive and negative samples instead of absolute outputs, making it well suited to recommender systems.”
§21.5 Personalized Ranking for Recommender Systems查看原文 →
转到富特征的 CTR 预测,因子分解机很有吸引力,因为它们的交互项可以被重新组织成线性时间的形式。
作者推导了改写后的成对项,并指出只需要计算非零的元素,把代价从特征数的二次方降到线性——这是点击预测的决定性性质,那里独热编码的广告特征既是高维的,又大多为零。作者还展示了 FM 涵盖熟悉的模型:它的前两项就是普通的线性回归,而如果一个特征索引物品、另一个索引用户,那么交互项恰恰就是矩阵分解的点积。
“为了解决这个低效问题,我们可以重新组织 FM 的第三项,这可以大大降低计算成本,得到线性的时间复杂度($\mathcal{O}(kd)$)。”
“To solve this inefficiency problem, we can reorganize the third term of FM which could greatly reduce the computation cost, leading to a linear time complexity (\(\mathcal{O}(kd)”
§21.9 Factorization Machines查看原文 →
翻转早先对 FM 的赞美,它的二阶双线性形式对真实的特征交叉来说过于僵硬,所以在它旁边硬加上一个深度网络。
作者论证,真实世界中的交叉是复杂而非线性的,然后报告了一个具体的比较:DeepFM,带一个三层 30-20-10 的 MLP,FM 的其余超参数保持不变,在一个在线广告数据集上,收敛得比 FM 更快,得分更好。作者也指出,高阶 FM 在纸面上是可能的,却因为数值不稳定和昂贵而被避开,而 DeepFM 对组合的自动发现,省去了 Wide & Deep 所要求的手工特征工作。
“给因子分解机加上非线性变换层,使它有能力同时对低阶特征组合和高阶特征组合建模。”
“Adding nonlinear transformation layers to factorization machines gives it the capability to model both low-order feature combinations and high-order feature combinations.”
§21.10 Deep Factorization Machines查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么记忆式协同过滤在稀疏数据上失败
记忆式的协同过滤根据用户或物品共有的物品来给相似性打分,所以当交互矩阵稀疏而巨大时,两个用户很少有足够的重叠使相似性有意义。作者用这一点来解释,为什么模型式的方法——学习紧凑的隐因子而不是数重叠——成为主流,并自然地延伸到神经网络。
机制 2
FM 如何廉价地得到成对项
直接数每个特征对,代价正比于特征数的平方。作者把交互项改写成经嵌入加权的特征之和的平方的一半,减去它们平方之和,这样一遍就够了;由于只有非零项有贡献,代价降到特征数的线性,这就是 FM 在高维稀疏的广告数据上实用的原因。
机制 3
DeepFM 如何同时学习低阶和高阶
DeepFM 把 FM 块和一个 MLP 并排放在同一个共享的嵌入表之上,并在 sigmoid 之前把它们的输出相加。因为来自两个分支的梯度流入同样的嵌入,二阶交叉和深层非线性组合是被联合拟合的,而不是分成两个独立的阶段,作者把更快的收敛归功于此。
常见误读
如果一个用户从未点击或购买过某个物品,这就算是他们不喜欢它的证据,所以把这些对当作负例是安全的。
缺失的交互混合了真正的不喜欢,和用户干脆还没遇到的物品,所以缺失不是负面看法的证据。这就是为什么作者把评分模型中被丢弃的未观测对当作偏差问题——数据是非随机缺失的——也是为什么排序损失要采样负例,而不是假定它们。
“未观测的用户—物品对是真正的负反馈(用户对这些物品不感兴趣)和缺失值(用户将来可能与这些物品交互)的混合。”
“Non-observed user-item pairs are a mixture of real negative feedback (users are not interested in the items) and missing values (the user might interact with the items in the future).”
§21.5 Personalized Ranking for Recommender Systems查看原文 →
既然 FM 只捕捉成对的,那么自然的升级就是三阶或四阶的 FM,去数特征的三元组和四元组。
作者指出,更高阶的 FM 在理论上可行,但在实践中不被使用,因为它在数值上不稳定且昂贵;本章转而给出的回答,是在同样的嵌入之上并行运行一个多层网络,让深度分支吸收高阶的非线性组合,而 FM 保留二阶的。
“因子分解机(FM),由 Rendle(2010)提出,是一种监督算法,可用于分类、回归和排序任务。”
“Factorization machines (FM), proposed by Rendle (2010), is a supervised algorithm that can be used for classification, regression, and ranking tasks.”
§21.9 Factorization Machines查看原文 →
第 21 章的核心概念
- 推荐系统
- 一个过滤巨大目录、把某个用户可能喜欢的物品呈现出来的系统。
- 适用处: 当物品目录很大、且存在用户偏好数据时有用;它补充而不是完全取代显式搜索。
- 协同过滤
- 借助许多用户、智能体和数据源之间的模式来预测一个用户的偏好。
- 适用处: 一般只使用用户—物品的交互数据;内容或上下文信号需要其他类型的模型。
- 显式反馈
- 用户有意给出的偏好信号,比如星级评分或点赞与点踩。
- 适用处: 往往稀缺,因为许多用户不会给产品打分。
- 隐式反馈
- 从观察到的行为,如点击、购买、浏览或观看,推断出的偏好。 像点击、购买和观看这样、无需显式评分就能揭示偏好的信号。
- 适用处: 本质上有噪声:观察到的行为并不可靠地揭示真实的动机。 未观测的对混合了真正的负例和未来的交互,所以缺失不是不喜欢的证据。
- 个性化排序
- 训练一个模型为每个用户给物品排序,而不是预测绝对的得分。
- 适用处: 成对的损失很适合排序;列表式的直接优化指标,但计算量大得多。
- 贝叶斯个性化排序损失
- 一种来自最大后验估计量的成对损失,假定用户喜欢被观测的物品胜过未被观测的。
- 适用处: 需要采样的负例;在排序上与合页损失可互换。
另外 7 个概念
- NeuMF
- 一种模型,把广义矩阵分解通路和 MLP 通路拼接起来,给用户—物品对打分。
- 适用处: MLP 有意不与 GMF 共享嵌入,这提高了参数数量。
- 感知序列的推荐
- 使用用户过去行为的按时间排序的列表,来预测下一个物品。
- 适用处: 水平滤波器捕捉联合层面的模式,垂直滤波器捕捉点层面的模式;L 限定所用历史的长度。
- 点击率预测
- 使用富类别特征,估计一个展示的物品或广告被点击的可能性。
- 适用处: 当仅有交互数据稀疏或有噪声时有用;依赖于辅助信息的质量。
- 因子分解机
- 一种模型,在线性回归之上,通过特征嵌入的点积,加上学出来的成对特征交互。
- 适用处: 通常限于二阶;更高的阶在理论上可能,但数值上不稳定。
- 特征工程
- 手工设计模型看到哪些特征组合;FM 通过从数据中学习隐藏的交互来减少这一点。
- 适用处: 当专家设计的交互易于理解时,它们仍然有帮助;大多数交互隐藏在数据里。
- 深度因子分解机
- FM 和一个 MLP 在共享的嵌入上并行运行,它们的输出相加,再经过 sigmoid。
- 适用处: 不是把深度网络与 FM 合并的唯一办法;非线性层也可以放在交互之上。
- 独热编码
- 每个类别字段的值,被存为其独热项的索引,这正是 CTR 数据集字段所持有的。
- 适用处: Criteo 有实值特征,所以同样的包装器需要改代码。
第 21 章划线与批注AI 陪读
“推荐系统通过减少主动搜索的功夫,取代了搜索引擎”
“Recommender systems are replacements of search engines by reducing the efforts in proactive searches”
查看原文 →说过头了——搜索回答的是一个明说出来的需求,推荐猜的是一个没说出来的需求。它们共存;一个并不取代另一个。教科书的营销腔调漏进了技术行文。
“用他们从未搜索过的东西给用户惊喜”
“surprising users with offers they never searched for”
查看原文 →被纯粹框定为愉悦。这里只字未提这种惊喜服务于谁的利益——本章仅有的明言的目标是用户体验和“增量收入”,而它从未问过这两者何时分歧。
“人们协作,互相帮助执行过滤的过程”
“people collaborate to help one another perform the filtering process”
查看原文 →可爱的来历:协作曾是字面上的,人帮助人。现代的协同过滤保留了这个词,但协作如今是非自愿的——你的点击为从未同意帮忙的陌生人做过滤。
另外 17 条批注
“一个用户看了一部电影,并不一定表明对这部电影的正面看法。”
“A user watched a movie does not necessarily indicate a positive view of that movie.”
查看原文 →概览里最老实的一句话。这个领域转向隐式反馈,是因为它廉价,然后花了几十年修补它所买来的噪声。是可得性推动了方法,而不是有效性。
“这些隐因子可能度量的是那些例子里提到的显而易见的维度,也可能是完全无法解释的。”
“These latent factors might measure obvious dimensions as mentioned in those examples or are completely uninterpretable.”
查看原文 →顺带说出,却是隐模型的整个交易:类型的故事是一个教学上的虚构,数学并不欠我们任何意义。令人耳目一新的是,他们没有假装并非如此。
“正如预期的,它看起来是正态分布,大多数评分集中在 3-4。”
“As expected, it appears to be a normal distribution, with most ratings centered at 3-4.”
查看原文 →它不是正态的——它是有界的、离散的、左偏的,而那个 J 形是关于谁会费心去打分的著名人造产物。说“正如预期”,跳过了评分数据最有趣的东西。
“评分不是随机缺失的,而是因为用户的偏好”
“ratings are not missing at random but because of users’ preferences”
查看原文 →这是早先直方图的评论径直走过的那个偏差,现在承重了。非随机缺失才是 MF/AutoRec 是错误工具的真正原因,比“线性模型”更深。
“证实了神经网络在评分预测任务上的有效性”
“confirming the effectiveness of neural networks in the rating prediction task”
查看原文 →在一个 100K 的数据集上跑一次,没有方差,没有调好的基线——而用的词是“证实”。经典的深度学习时代的过度宣称;后来的复现工作发现,调好的 MF 往往与这些模型相当。
“它假定用户喜欢正例胜过所有其他未观测的物品。”
“It assumes that the user prefers the positive item over all other non-observed items.”
查看原文 →BPR 的整台引擎是一个文本刚承认为假的假设——未观测是不喜欢和尚未见过的混合。有用的虚构,但请注意,这是同一个噪声问题被重新标成了先验。
“这两个损失在推荐中的个性化排序上是可互换的。”
“These two losses are interchangeable for personalized ranking in recommendation.”
查看原文 →两段话里断言了两次,从未论证。BPR 是平滑的对数 sigmoid 概率模型;合页则在间隔处截断。一旦间隔被满足,它们表现不同——一个继续推,一个不再在乎。
“MLP 子网络不与 GMF 共享用户和物品的嵌入”
“the MLP subnetwork does not share user and item embeddings with GMF”
查看原文 →这个设计安静的代价:在本来就稀疏的数据上,嵌入参数翻倍。灵活性,是用推荐系统永远没有的那一种资源买来的。
“同时买牛奶和黄油,比只买其中一样,导致买面粉的概率更高”
“buying both milk and butter together leads to higher probability of buying flour than just buying one of them”
查看原文 →终于有一句话里带着厨房了。联合层面对点层面的模式,在烘焙出现之前是抽象的——而这个例子也偷偷带进了真正的论断:在这里,顺序没有共现那么要紧。
“我们可以把输入矩阵 $\mathbf{E}^{(u, t)}$ 看作一幅图像”
“We can view the input matrix \(\mathbf{E}^{(u, t)}\) as an image”
查看原文 →整个 Caser 的招数就是这个类比,而它比听上去更不牢靠——图像的像素在两个轴上都有空间局部性,嵌入的维度则没有。这恰恰是为什么垂直滤波器跨越全部 L 行,而水平滤波器跨越全部 k 列:没人敢在嵌入轴内部做卷积。
“由于匿名化和隐私的考虑,特征的真实语义没有公开”
“The real semantics of the features are undisclosed due to anonymization and privacy concern”
查看原文 →一整套教学建立在 34 个无名的列上。你可以学会拟合这些数据,却永远无法对它们做推理——令人不安地,这正是工业 CTR 工作的实际处境。
“有些特征交互容易理解,所以可以由专家来设计。然而,大多数其他特征交互都隐藏在数据里”
“Some feature interactions can be easily understood so they can be designed by experts. However, most other feature interactions are hidden in data”
查看原文 →这是 FM 真正的卖点,埋在段落中间:它不是关于准确率,而是关于炒掉特征工程师。经济上的论证,披着建模的外衣。
“然而,数值稳定性可能会削弱泛化。”
“Nevertheless, the numerical stability might weaken the generalization.”
查看原文 →在两节里被说了三次,作为放弃高阶 FM 的理由,却一次也没有给出数字或机制。该领域说“它没管用,我们往前走了”的标准方式。
“它通过自动识别特征组合,减少了手工特征工程的功夫”
“it reduces the effort of hand-crafted feature engineering by identifying feature combinations automatically”
查看原文 →老实的论断比听上去窄:DeepFM 自动化了 FM 本来已经处理的二阶交叉,而把其余的交给一个没人能检查的 MLP。Wide & Deep 手工制作的特征至少是可读的。
“这两个组件共享同样的输入/嵌入,它们的输出被加起来作为最终的预测。”
“These two components share the same inputs/embeddings and their outputs are summed up as the final prediction.”
查看原文 →共享嵌入才是这里真正的设计决策,被安静地陈述。这意味着 FM 的梯度和 MLP 的梯度在为同样的向量争夺——取决于你的心情,这要么是优雅的联合训练,要么是一场拔河。
“给因子分解机加上非线性变换层,使它有能力同时对低阶特征组合和高阶特征组合建模。”
“Adding nonlinear transformation layers to factorization machines gives it the capability to model both low-order feature combinations and high-order feature combinations.”
查看原文 →“有能力建模”承担了重担。一个深度网络有能力对几乎任何东西建模;它能否从稀疏的点击数据里找到高阶交互,是一个这句话绕开了的经验问题。
“我们还可以在特征交互之上添加非线性层。”
“We can also add nonlinear layers over the feature interactions”
查看原文 →一行旁白,打开了整整一个模型家族(NFM、xDeepFM)。并行对堆叠的组合,是路上一个真正的岔口,而文本在路过时朝它挥了挥手。
读后感AI 陪读
该领域不断给噪声改名,而不是去解决它
本章的弧线从框架干净地走向机制:先是推荐系统是什么、为什么重要,然后是显式评分模型(MF、AutoRec),然后转向隐式反馈和排序损失(BPR、合页),再是神经融合(NeuMF)、序列模型(Caser),最后是从 FM 到 DeepFM 的富特征 CTR 一线。当作一个整体来读,整件事的底下有两条线,两条都从未被点名。第一条是噪声的交易。本章早早就直白地说,看一部电影不等于背书——然后把此后每一个模型都建立在恰恰这个信号上,因为它廉价而丰富。BPR 的核心假设,即未观测意味着不喜欢,是同一个噪声问题被重新标成了先验;后面关于非随机缺失的评论,是同一个问题再来一遍,如今承重到足以为放弃 MF 辩护。该领域没有解决它;它一直在给它改名,并往上移一层。第二条线是用能力悄悄顶替证据。隐因子“可能无法解释”——被承认了,又被放下。在一个 100K 的数据集上跑一次,就“证实”了神经网络的有效性。高阶 FM 因为“数值稳定性”而失败,被断言了三次,没有一个数字。DeepFM“给了建模高阶组合的能力”——对任何足够深的网络都是真的,对这样的组合是否能在稀疏的点击数据里被找到却什么也没说。我最尖锐的判断:FM 和 DeepFM 真正的卖点是经济上的,而不是统计上的。它们炒了特征工程师的鱿鱼。这是正当且巨大的胜利,但本章把它装扮成准确率的论证,而后来的复现工作对准确率的论断并不客气。与此并列的是,本章对平台之外的利益出奇地不好奇——“让用户惊喜”和“增量收入”被呈现为同一个目标,而它们何时分歧的问题从未被问起;也没有问起这样一个事实:现代协同过滤从一个人们真的自愿合作的情境里,继承了“协同”这个词。对读者说:把这一章当作架构的地图来用,它画得好,实现得干净,而对它的动词保持不信任。把“证实”“可互换”“减少了功夫”和“给了能力”读作假设,而不是结果。留意文本匆匆带过的旁白——DeepFM 之后并行对堆叠的岔路,共享嵌入的拔河,以及在 Caser 中没人敢在嵌入轴内部做卷积,因为图像的类比只有一半成立。那些顺带的话,才是真正的设计决策所在。并请注意,你将学会拟合 34 个匿名的列,却永远无法对它们做推理——本章把这呈现为数据的局限,其实它是这份工作老实的预览。
在 FeedLitra 里读第 21 章,每段旁边都有这些卡片。
开始读书第 22 章:附录:深度学习的数学
秩如何形式化一个矩阵对空间压缩了多少?
第 22 章是怎样展开的AI 辅助
开篇:一个变成论证的让步。 附录一开头就承认了读者可能已经怀疑的事——没有深奥的数学,你也能做很多深度学习。但这个让步是个铺垫。作者立刻点出了实践者无论如何都会遇到的情形:没有底层的形式体系,你说不出熵实际上度量什么,也读不懂每字符比特数的得分。要点不是数学是构建模型的先修条件,而是架构、损失和指标带着内置的假设,只有数学才能让这些假设可见——让模型自己的报告变得可解释。从这里开始,本章预告了它的五个乐章(线性代数、微积分、概率、统计、信息论),并从可得的最具体的对象开始:一个向量,既可以读作点,也可以读作方向。点积给出夹角,夹角给出余弦相似度,而本章第一个真正的论证,通过一幅被调暗到 10% 亮度的图像到来:按直线距离,它离原图很远,但它与原图的夹角为零。在长度不携带意义的地方,角度是尊重我们想要的不变性的那种度量——作者小心地陈述了这个限定,而不让这个例子越界。
线性代数朝着单一的问题发展。 超平面、线性变换、线性相关和秩随之而来,而秩是这条线索收紧的地方:它数的是列的最大线性无关集的大小,而满秩恰恰是可逆的条件。行列式随后把同一个事实几何地重新描述。因为一个矩阵只能均匀地倾斜、旋转和缩放网格,它破坏信息的唯一办法,是把空间压扁到更少的维度——而压扁使单位正方形的有向面积变为零。因此,消失的行列式不是伴随着不可逆性的一个巧合;它是它的标志,因为丢失的维度无法恢复。张量缩并和爱因斯坦记法给这一切一个共同的记法,而特征分解交付了回报:写成 $W\Sigma W^{-1}$,一个矩阵就揭示了它自己的作用。玩具模型 $A^N v$ 使这一点具体——反复相乘变成特征值的反复相乘,所以经过许多层之后,最大的特征值占主导,并确定一个稳定的拉伸速率。除以它,随机向量的范数就会稳定下来,而不是爆炸或消失。这就是本章第一次抵达一个实际的关切:随机矩阵的特征值,是权重初始化这样运作的原因。
微积分重复同一个动作——局部线性——并抵达反向传播。 放大使一个函数看起来是线性的,这把导数定义为一个缩放因子,并几乎机械地产生了和、积、链式法则。二阶导数加上曲率;用多项式匹配导数得到二次近似,然后是泰勒级数。转到多元,产生偏导数和梯度,而在这里,作者是论证梯度下降,而不是断言它:把沿一个方向的损失变化写成梯度的长度乘以它们夹角的余弦,那么下降量恰恰在余弦取到 $-1$ 的地方最大——负梯度。本章随后把链式法则倒过来。把 $\partial f$ 保持在分子上,把计算重新组织成一遍记录值和单步偏导的前向传播,和一遍重用它们、一次产生每个梯度的反向扫描。这个对比是历史性的,也很尖锐:有限差分对每个参数需要两次损失评估,所以几千个参数就意味着对数据过几千遍——这就是这个问题为什么等到 1986 年的反向传播。海森矩阵为这一节收尾,把二阶导数收集成最佳的局部二次型,并注明矩阵的导数往往呼应它们的单变量形式。
转向概率是通过积分来的。 曲线下的面积,用矩形来近似;微积分基本定理,把求面积变成求导的逆运算;变量替换、有向面积、带富比尼定理的累次积分,以及雅可比行列式——而那个雅可比是铰链,因为正是它让积分成为密度的语言。连续随机变量得到积分为一的概率密度函数,以及直接读出概率的累积分布函数,而作者用这个区别纠正一个自然的错误:密度是每单位长度的概率,而不是概率。任何确切的点概率为零,因为每多一位精度,它的机会就缩小;只要足够窄,密度可以超过十。汇总统计量随之而来,用例子做出了第二个论证——赚十美元上下浮动一美元,与十美元上下浮动十美元完全不同,而在三点的例子里,均值纹丝不动,而方差在动,所以均值干脆看不见分散。切比雪夫不等式随后使标准差对任何分布都是可解释的,而作者表明这个界在一个参数值上恰好取到:在最坏情形下是尖锐的,这就是为什么它对性质良好的数据往往是松的。联合密度、边缘化和协方差把图景扩展到相关的变量,而柯西分布以一个警告为这一节收尾:它的密度积分为一,然而它的方差发散,它的均值塌缩成 $\log\infty$。不是每个分布都有这两个数——而所提供的安抚是狭义的,即机器学习的模型通常被构建得使这样的尾部不会出现,而不是它们不可能出现。
概率巩固,然后成为实践。 协方差归一化为相关系数,没有单位,界在 $[-1,1]$,并可读作一个余弦——这悄悄地接回了本章开篇的几何。极大似然随后到来:选择使 $P(X\mid\theta)$ 最大的 $\theta$,但转而优化负对数似然,有三个明说的理由——十亿个接近二分之一的概率的乘积会下溢机器精度,而它的对数舒舒服服地待在 32 位浮点数里;对乘积求导花的是二次方的时间,而对数的形式只需要 $n$ 次除法和 $n-1$ 次加法;而对数的形式,把目标与信息论联系起来,这个承诺本章在结尾兑现。随后是常见分布的巡礼——离散和连续均匀、二项、泊松、高斯,每个都有质量或密度、累积分布函数、均值、方差和采样代码——由极限统一,然后被指数族涵盖。MNIST 上的朴素贝叶斯把这一切变成一个可用的分类器:靠计数来训练,拉普拉斯平滑,对下溢的对数空间补救,以及对独立性假设要付出什么的老实核算。
统计和信息论为这条弧线收尾。 估计量带来 MSE、偏差、方差和偏差—方差分解;假设检验带来显著性、功效、样本量、检验统计量、$p$ 值、单侧对双侧检验,和一个五步的流程;置信区间得到一个定义、正确的频率派读法、三个点了名的谬误,以及 95% 的高斯/$t$ 公式。然后是信息论,这是本章从负对数似然起就一直朝着的方向:联合熵和条件熵,带逐点形式和性质的互信息,KL 散度及其非对称性,最后是作为多类目标的交叉熵——被表明与极大似然等价,这闭合了早先承诺的循环。习题强化的恰恰是这种读法:把一个语言模型的词困惑度转换成每字符的随机性比特数,既凭直觉又作为对联合分布的期望来论证 $I(X,Y) = H(X) - H(X\mid Y)$,以及推导两个高斯之间的 KL 散度。本章结束在实践者每天的损失函数所在的地方,花了五十页,挣得了解释它的权利。
关键论点,以及支撑它们的原文
即使是动手的实践者也需要数学,因为内置在架构、损失和指标里的选择带着隐藏的假设,只有数学才能暴露它们。
作者一开头就点出了实践者无论如何都会遇到的具体情形:没有底层的数学,你说不出熵实际上度量什么,也读不懂每字符比特数的得分,所以形式体系使模型自己的报告变得可解释。
“在实践中,你有时需要理解架构的选择如何影响梯度流,或者你通过用某种损失函数训练所做的隐含假设。”
“In practice, you will sometimes need to understand how architectural choices influence gradient flow, or the implicit assumptions you make by training with a certain loss function.”
Chapter 22. Appendix: Mathematics for Deep Learning查看原文 →
当数据向量的长度不携带意义时,是角度而不是距离,捕捉了我们想要从表示中得到的尺度不变性。
一幅被调暗到 10% 亮度的图像的副本,按直线距离度量,离得很远,却与原图成零夹角,所以角度把更暗的图片当作同一个东西。作者指出,这只在长度确实不携带信息的地方才成立。
“夹角认为更暗的图像是相同的。”
“The angle considers the darker image identical.”
§22.1 Geometry and Linear Algebraic Operations查看原文 →
把导数建立为局部的缩放因子之后,作者论证,下坡最陡的方式是负梯度,这恰恰为梯度下降的更新提供了依据。
把沿选定方向的损失变化写成梯度的长度乘以它们夹角的余弦,表明下降量恰恰在方向与梯度相反时最大,因为那是余弦取到负一的地方。
“这把我们带到机器学习中最重要的数学概念之一:最陡下降的方向指向 $-\nabla_{\mathbf{w}}L(\mathbf{w})$ 的方向。”
“This brings us to one of the most important mathematical concepts in machine learning: the direction of steepest decent points in the direction of \(-\nabla_{\mathbf{w}}L(\mathbf{w”
§22.4 Multivariable Calculus查看原文 →
另外 3 个论点
手工计算的有限差分从来不是训练网络的可行办法,这个问题直到 1986 年才由反向传播解决。
通过差分估计一个导数,要求对每个参数评估两次损失,所以即使几千个参数,也需要对整个数据集扫过几千遍——作者把这个代价与反向传播所需的两遍作了对比。
“直到 1986 年才得到解决,Rumelhart 等人(1988)引入的反向传播算法,提供了一种办法,能在与网络对数据集做一次预测相同的计算时间内,算出所有权重一起的任何改变会如何改变损失。”
“It was not solved until 1986 that the backpropagation algorithm introduced in Rumelhart et al. (1988) provided a way to calculate how any change of the weights together would change the loss in the same computation time as a single prediction of the network over the dataset.”
§22.3 Single Variable Calculus查看原文 →
光有均值不能描述一个随机量;还必须报告分散程度,而标准差是可解释的,因为切比雪夫不等式把它变成了一个普遍的保证。
赚十美元上下浮动一美元,与赚十美元上下浮动十美元完全不同,而在作者的三点例子里,均值保持固定,而方差随参数移动,所以均值根本看不见分散。切比雪夫随后对任何分布界住了样本偏离标准差的某个倍数之外的频率,而作者表明这个界在一个参数值上恰好取到——意味着它在最坏情形下是尖锐的,因此对温和的分布往往是松的。
“每笔销售赚 $\$10 \pm \$1$ 的利润,与每笔销售赚 $\$10 \pm \$15$ 非常不同,尽管平均值相同。”
“Making a profit of \(\$10 \pm \$1\) per sale is very different from making \(\$10 \pm \$15\) per sale despite having the same average value.”
§22.6 Random Variables查看原文 →
确立了极大似然之后,作者建议转而优化似然的负对数,而不是似然本身。
给出了三个理由:十亿个接近二分之一的概率的乘积会下溢机器精度,而它的对数舒舒服服地放进 32 位浮点数里;直接对乘积求导要花二次方的时间,而对数的形式只需要 n 次除法和 n-1 次加法;而对数的形式把目标与信息论联系起来。
“人们常常转而使用负对数似然,原因多种多样:数值稳定性、把乘积转换成求和(以及由此带来的梯度计算的简化),以及与信息论的理论联系。”
“Often people work with the negative log-likelihood instead for a variety of reasons: numerical stability, conversion of products to sums (and the resulting simplification of gradient computations), and theoretical ties to information theory.”
§22.7 Maximum Likelihood查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么行列式为零意味着没有逆
一个矩阵只能均匀地倾斜、旋转和缩放整个网格,所以它丢失信息的唯一办法,是把空间压扁到更少的维度。压扁使单位正方形的有向面积趋于零,而那个丢失的维度永远无法恢复,所以零行列式恰恰是不可逆映射的标志。
机制 2
最大的特征值设定增长速率
把一个矩阵写成它的特征分解,把反复相乘变成仅仅是特征值的反复相乘,所以经过许多层之后,最大的特征值占主导,并确定一个稳定的拉伸比。把矩阵除以这个值,使随机向量的范数稳定下来,而不是爆炸或消失,这就是特征值支配初始化的原因。
机制 3
反向传播如何用两遍得到所有梯度
把一个复合函数完全展开,会一遍又一遍地重复同样的子项,所以导数必须逐步求取。把链式法则重新排序,使损失保持在分子上,让一遍前向传播记录值和单步的偏导数,之后单独一遍反向扫描重用它们,一次交付对每个输入的导数。
常见误读
一个点处的密度值告诉你那个值的概率,所以大于 1 的密度一定是个错误。
密度是每单位长度的概率,只有它在一个区间上的积分才是概率——对一个连续的量,任何确切的点概率为零,因为每多一位精度,机会都进一步缩小。只要在足够窄的区域上,密度可以超过十,这就是作者指向累积分布函数,作为直接读出概率的对象的原因。
“这意味着,从本质上讲,我们要求的每多一位精度,都应该使匹配的概率降低为原来的 $10$ 分之一。”
“What this means is that in essence each additional digit of accuracy we require should decrease probability of matching by a factor of \(10”
§22.6 Random Variables查看原文 →
每个概率分布都有均值和方差,所以你总可以用这两个数来概括它。
有些完全合法的分布两者都没有。柯西密度积分为一,然而它的方差积分发散,它的均值归结为无穷大的对数,所以这两个量干脆都不存在。作者的安抚比看上去要窄:机器学习的模型通常被构建得使这样的重尾不会出现,而不是它们不可能出现。
“机器学习科学家们定义他们的模型,使我们最常不必处理这些问题,而且在绝大多数情形下,处理的是具有良好定义的均值和方差的随机变量。”
“Machine learning scientists define their models so that we most often do not need to deal with these issues, and will in the vast majority of cases deal with random variables with well-defined means and variances.”
§22.6 Random Variables查看原文 →
第 22 章的核心概念
- 点积
- 两个向量按元素相乘之和;它的值也编码了它们之间的夹角。
- 适用处: 夹角公式需要范数非零;与维数无关。
- 余弦相似度
- 归一化的点积,度量方向的一致程度,同时忽略向量的长度。
- 适用处: 在高维空间中,随机向量的余弦接近 0;它丢弃了幅值的信息。
- 超平面
- 一个平坦的 d-1 维曲面,把 d 维空间切成两个半空间。
- 适用处: 只有线性可分;非线性的边界需要先做嵌入。
- 线性相关
- 这些向量的某个非零的加权组合等于零,所以其中一个是冗余的。
- 适用处: 一个矩阵的列之间的相关,标志着对空间不可逆的压缩。
- 矩阵的秩
- 线性无关的列的最大组的大小。
- 适用处: 通过检查子集来定义,这是列数的指数级,所以它是一个定义,而不是一个实用的算法。
- 逆矩阵
- 第二个矩阵,恰好撤销第一个矩阵对数据所做的事。
- 适用处: 只对满秩方阵存在,即便如此,数值上也通常避免使用。
另外 49 个概念
- 行列式
- 一个矩阵缩放面积或体积的有符号因子。
- 适用处: 当图形被翻转时可以为负,而对大矩阵计算起来很费力。
- 张量缩并
- 对张量的乘积在选定的共有下标上求和,推广了矩阵乘法。
- 适用处: 需要明确指定求和的下标;对张量没有唯一的普遍选择。
- 特征分解
- 把一个矩阵写成沿着它不旋转的特殊方向的拉伸。
- 适用处: 需要一整组线性无关的特征向量;对称矩阵有保证。
- 主特征值
- 绝对值最大的特征值;它的特征向量,是一个被反复相乘的随机向量最终指向的方向。
- 适用处: 适用于同一个固定矩阵对一个一般随机向量的反复作用,忽略非线性。
- 幂迭代
- 反复把一个向量乘以一个矩阵,以收敛到它最大的特征值和特征向量。
- 适用处: 需要起始向量在主特征向量方向上有一些分量。
- 线性近似
- 在一点附近,函数的行为像一条穿过该点、斜率等于导数的直线。
- 适用处: 只在足够小的范围内、对熟悉的可微函数有效。
- 链式法则
- 复合函数的导数,等于内部值处的外层导数乘以内层导数。 要得到穿过复合函数的导数,沿每条路径相乘,再把所有路径加起来。 导数沿着计算路径相乘;你嵌套它们的顺序,决定了你能廉价得到哪些偏导数。
- 适用处: 这里只在 epsilon 的高阶项以内得到证明。 朴素的展开会重复工作;反向传播重用单步的偏导数。 把 ∂w 保持在分母上,给出一个输入的影响;把 ∂f 保持在分子上,则一次给出所有输入的影响。
- 高阶项
- 带有 epsilon 的平方或更高次的项;随着 epsilon 缩小到零而可以忽略。
- 适用处: 对一阶导数可以忽略,但对后面的展开则要紧。
- 泰勒级数
- 由一个函数在某一点的导数构造的多项式,在该点附近近似这个函数。
- 适用处: 只有对性质良好的(实解析的)函数,才在无穷极限下精确地重现这个函数。
- 梯度
- 所有偏导数的向量,说明一个多元函数在任何微小的输入扰动下如何变化。
- 适用处: 只对小的扰动有效;高阶的交叉项被丢弃。
- 反向传播
- 从输出反向算到输入来计算导数,通过一遍前向传播加一遍反向传播。
- 适用处: 它是链式法则的一种记账顺序,而不是一条新的求导规则。
- 海森矩阵
- 多变量函数所有二阶偏导数构成的矩阵。
- 适用处: 有 n^2 个元素,但混合偏导数在存在且连续时是对称的。
- 分母布局的矩阵导数
- 把偏导数排成与分母中那个东西相同的形状。
- 适用处: 这个形状的约定,是转置出现在矩阵导数结果里的原因。
- 微积分基本定理
- 滚动面积函数的导数等于被积函数,所以积分就意味着逆转一个导数。
- 适用处: 只能把 F 确定到相差一个加性常数,对定积分来说它抵消了。
- 变量替换
- 代入一个新变量,按这个代入把坐标轴拉伸了多少,来重新缩放被积函数。
- 适用处: 在 n 维中,需要一个单射的重新参数化,以及雅可比行列式的绝对值。
- 有向面积
- 面积带有符号:负的被积函数或从右到左的积分限给出负值。
- 适用处: 两次翻转抵消,回到正的面积。
- 富比尼定理
- 一个二重积分可以通过按任一顺序迭代单变量积分来计算。
- 适用处: 并不总是成立;对一些不够连续的函数会失效,尽管对机器学习的连续函数是安全的。
- 概率密度函数
- 一个非负函数,其值乘以一个微小的区间宽度,给出落在该区间内的概率。 一个总积分为一的非负函数;你在一个区间上对它积分,得到一个概率,所以它自己的值不是概率。
- 适用处: 在整条实数线上必须积分为一;点的概率为零。 只针对连续随机变量;密度值可能超过 1,也没有直接的概率含义。
- 雅可比矩阵
- 给出多变量映射的最佳线性近似的偏导数矩阵。
- 适用处: 它的行列式的绝对值,是局部的体积缩放因子。
- 累积分布函数
- F(x) 是变量至多为 x 的概率,所以它本身是一个概率,对离散、连续和混合的变量同样适用。
- 适用处: 只有当变量是连续时才是没有跳跃的连续函数;离散变量给出阶梯函数。
- 方差
- 与均值的平均平方距离,度量一个变量波动得有多宽;它的单位是原单位的平方。
- 适用处: 只对常数为零;对像柯西分布这样的重尾变量没有定义。
- 标准差
- 方差的平方根,恢复了原来的单位,所以它描述变化的典型范围。
- 适用处: 可以通过切比雪夫不等式解释为一个范围,该不等式是松的,却在最坏情形下是尖锐的。
- 联合密度函数
- 一个函数 p(x,y),其在一个区域上的积分给出这对变量落在那里的概率,使相关的变量可以一起建模。
- 适用处: 需要多重积分;推广到 p(x_1,...,x_n),带有同样的非负性和单位积分的规则。
- 边缘分布
- 单独一个变量的分布,通过把联合密度对你不关心的变量积分而得到。
- 适用处: 丢弃了关于与被积掉的变量相关性的所有信息。
- 协方差
- 关于两个变量一起波动程度的汇总统计量:一起上升时为正,朝相反方向变动时为负,无关时为零。 对两个随机变量如何一起变动的度量;它带着它们单位的乘积。
- 适用处: 只捕捉线性关系;即使一个变量是另一个的确定性函数,也可能为零。 独立蕴含协方差为零,但协方差为零并不蕴含独立;单位使它难以解释。
- 相关系数
- 协方差除以两个标准差,给出一个介于 -1 和 1 之间、没有单位的数。
- 适用处: 只捕捉线性关系的方向和强度,不捕捉尺度或非线性的依赖。
- 极大似然
- 选择使观测到的数据概率最高的参数。
- 适用处: 只在无信息先验下,才等价于贝叶斯后验的众数。
- 负对数似然
- 似然的对数的负值,用作要被最小化的损失。
- 适用处: 因为对数是递增的,与似然有相同的最优点;因数值、微积分和信息论而更受青睐。
- 熵
- 平均的负对数概率,度量一个来源的随机性。 对一个信号携带多少信息或随机性的度量;当结果均匀分布时它最大。 平均的随机性,这里度量为从一个模型的预测观察到的每字符比特数。
- 适用处: 把 NLL 与信息论联系起来;数据集上的平均 NLL 是熵的近亲。 对连续变量,故事需要有界的支撑集,均匀分布才成为最大熵的选择。 在这些习题中,熵是从一个困惑度的数字读出来的,而不是从一个已知的分布。
- 伯努利
- 最简单的随机变量:以概率 p 取 1,以概率 1-p 取 0。
- 适用处: 均值为 p,方差为 p(1-p);抛硬币式模型的构件。
- 泊松随机变量
- 把一个时间窗口切成无穷多个微小的伯努利试验时得到的极限;它数的是罕见的到达,均值和方差都等于速率。
- 适用处: 需要到达概率随细分的增加而缩小;否则二项分布不会稳定下来。
- 高斯分布
- 许多独立片段的标准化和的极限;也是一旦均值和方差固定,最随机(最大熵)的分布。
- 适用处: 需要额外的条件,比如有限的四阶矩,而它的累积分布函数没有用初等函数表示的闭式。
- 指数族
- 一种模板,其中一个基测度被自然参数与充分统计量的点积的指数重新加权,由一个累积量函数归一化。
- 适用处: 要紧的只是密度可以写成这种形式;对各项的确切划分有些任意。
- 检测的条件独立性
- 朴素贝叶斯假定,一旦数字标签已知,每个像素都与其他像素独立,把一个乘积链坍缩成简单的逐特征因子。
- 适用处: 这个假设在真实图像中通常是错的,却买来了归纳偏置和可处理性。
- 中心极限定理
- 减去均值,再除以大量独立同分布变量之和的标准差,结果看起来是高斯的,而不管原来的分布是什么。
- 适用处: 适用于许多小的独立贡献之和,附带矩条件。
- 拉普拉斯平滑
- 加上伪计数,使从未观测到的像素值不会强迫出现零概率。
- 适用处: 这里 +1/+2 的形式适合二值像素;贝叶斯的依据是 Beta-二项模型。
- softmax 中的数值上溢与下溢
- 把几百个很小的概率相乘,在计算机上会舍入为零;对对数求和则避免了这一点。
- 适用处: 之所以管用,是因为对数是递增的,所以 argmax 不变。
- 估计量与一致性
- 用来猜测总体真实参数的样本的函数。
- 适用处: 这里假定针对的是一个标量的真实参数 theta。
- 偏差—方差权衡
- MSE 分解为平方偏差、方差和不可约误差。
- 适用处: 高偏差意味着欠拟合;高方差意味着过拟合;最后一项是 theta 本身的噪声。
- 假设检验
- 一种权衡证据以反对关于总体的默认陈述的程序。 一个检验检测到至少某一大小的真实差异的机会,等于 1 减去第二类错误率。
- 适用处: 显著性控制对真的 H0 的错误拒绝;功效控制对假的 H0 的未能拒绝。 只有相对于一个陈述出来的效应大小和显著性水平才有意义。
- 检验统计量
- 一个概括样本的单个数,这样可以区分不同的分布。
- 适用处: 不同的选择给出功效差别很大的检验。
- 置信区间
- 一个由样本算出来的随机区间,以至少 1 减 alpha 的概率覆盖真实参数。
- 适用处: 随机性在区间上,而不在固定的参数上。
- 联合熵
- 一对变量放在一起的总随机性。
- 适用处: 下界是两者各自熵中的较大者,上界是它们的和;只有在独立时才等于和。
- 条件熵
- 一旦 X 已知,Y 中还剩下多少信息。
- 适用处: 它是熵的差,而不是概率,所以即使 Y 在无条件下仍是随机的,它也可以为零。
- 互信息
- 两个变量共享的信息,超出线性相关。
- 适用处: 对称且非负;恰在独立时为零,而当一个变量是另一个的可逆函数时,等于完整的熵。
- 逐点互信息
- 一对具体的结果,比变量相互独立时更可能或更不可能多少。
- 适用处: 它是逐个结果的,所以可以很大,而平均的互信息仍然很小。
- KL 散度
- 对一个估计的分布离真实分布有多远的度量。
- 适用处: 不是距离:它是非对称的,当 q 在 p 并非如此的地方赋予零质量时,它变成无穷大。
- 交叉熵损失
- 在估计的分布之下,真实分布的期望惊异度;标准的分类损失。
- 适用处: 与最小化 KL 散度的等价性,只在真实数据的熵 H(P) 为常数时才成立。
- 字符困惑度
- 一个模型在一个词内部赋予各字符的概率的几何平均的倒数。
- 适用处: 这里按长度为 l 的词来定义;把它转换成每字符的比特数,需要词的长度,例如所述的 4.5 个字母。
第 22 章划线与批注AI 陪读
“但我们还没到那一步。”
“But, we are not quite there yet.”
查看原文 →一个五个字的段落,做了全部的修辞工作——前面的安慰是个铺垫,而这一句把椅子抽走了。对这个领域的半成熟很老实。
“我们可以开始抽象地把任务看作空间中点的集合,并把这个任务想象成发现如何分开两个不同的点簇”
“we can start considering tasks abstractly as collections of points in space and picturing the task as discovering how to separate two distinct clusters of points”
查看原文 →这是机器学习整个意识形态的动作,一口气说完:猫和狗溶解成了点云。极其强大,也恰恰是语义丢失的地方。
“然而,如果我们考虑夹角,就不难看出,对任何向量 $\mathbf{v}$,$\mathbf{v}$ 与 $0.1\cdot\mathbf{v}$ 之间的夹角为零。”
“However, if we consider the angle, it is not hard to see that for any vector \(\mathbf{v}\), the angle between \(\mathbf{v}\) and \(0.1\cdot\mathbf{v}\) is zero.”
查看原文 →好的动机:度量应当编码你所相信的不变性。但请注意拟合的方向——我们选择角度,是因为我们本来就知道亮度不该要紧。数学并没有发现不变性,它只是认可它。
另外 17 条批注
“注意,如果高维向量的分量是随机采样的、均值为 $0$,它们的余弦几乎总是接近 $0$。”
“Note that if the components of high-dimensional vectors are sampled randomly with mean \(0\), their cosine will nearly always be close to \(0”
查看原文 →像脚注一样顺带放下,却是这一节里最举足轻重的一句话:在高维空间中,一切都几乎是正交的,所以 0.3 的余弦可能是惊人的,而不是微弱的。测度集中,被放在括号里偷渡进来。
“在这种情况下,我只是凭肉眼,手工估计了一个在训练数据上看起来不错的阈值。”
“In this case, I simply eyeballed a threshold that looked good on the training data by hand.”
查看原文 →突然冒出的第一人称很迷人,而老实就是教学——一个均值差向量加一个猜出来的阈值,就能得到像样的准确率,这悄悄地说明了这个问题有多少已经是线性的。
“矩阵无法对空间的某些部分比对另一些部分扭曲得更多。”
“Matrices are incapable of distorting some parts of space differently than others.”
查看原文 →我读过的对线性的极限最干净的陈述,它解释了激活函数存在的全部理由。深度网络是一堆无法弯曲空间的东西的堆叠,由一些能弯曲空间的东西粘在一起。
“它是 $[1,1]^\top$ 还是 $[0, -1]^\top$?”
“was it \([1,1]^\top\) or \([0, -1]^\top”
查看原文 →信息的破坏,被一个没人能回答的问题具体化了。秩、可逆性和行列式,都由这一个无法挽回的事实而来。
“这需要查看给定矩阵的列的每一个子集,因此可能是列数的指数级。”
“It requires looking at every subset of the columns of our given matrix, and thus is potentially exponential in the number of columns.”
查看原文 →一个在数学上干净、在计算上荒谬的定义——值得注意,书承认了这个差距,而不是把它糊过去。定义和算法是不同的动物。
“接近低秩的矩阵的求逆也是如此”
“so can inversion of a matrix which is close to having low rank”
查看原文 →对上面一切的关键纠正:秩在理论上是二值的,在浮点数里是连续的。“近乎相关”的列才是真实世界的情形,而它们悄悄地惩罚你。
“逆矩阵通常几乎每个元素都是非负的,要求我们存储全部 $1\textrm{M}^2$ 个元素”
“the inverse will typically have almost every entry non-negative, requiring us to store all \(1\textrm{M}^2\) entries”
查看原文 →“非负”是“非零”的笔误——全部要点在于稠密,而不是符号。小失误,但搞浑了承载论证的那一句话。
“一般来说,在实践中避免求逆是个好的经验法则”
“generally avoiding inversion in practice is a good rule of thumb”
查看原文 →这一节里最实用的一句话,却是作为顺带的话说出来的。解方程组,不要构造逆。
“torch.det(torch.tensor([[1, -1], [2, 3]], dtype=torch.float32))”
查看原文 →代码悄悄地把正文里的矩阵转置了。行列式在转置下保持不变,所以检查通过了,没人注意到——一个碰巧的不变量,盖住了草率。
“我们可以把那个图形分解成一堆小方块,这样图形的面积本质上就是方块的数量”
“we can decompose that figure into a collection of little squares so that the area of the figure is in essence just the number of squares”
查看原文 →“像计算机科学家那样思考”是个漂亮的躲闪——这就是黎曼积分,而那个含糊其辞的挥手,恰恰是真正的证明所在之处。
“对于要对什么求和,没有一种情形可以被普遍选定”
“there is no one case of what to sum over that can be universally chosen”
查看原文 →这才是 einsum 存在的老实理由:矩阵有一个规范的缩并,张量没有,所以记法必须携带这个选择。
“求和针对的恰恰是表达式中出现多于一次的那些下标”
“the sum is over exactly those indices that occur more than once in the expression”
查看原文 →被陈述成一个观察,其实是个有牙齿的约定——如果你的意思是不求和,它对 v_i v_i 就是错的,而 einsum 的箭头语法之所以存在,恰恰因为这条规则对意图是不确定的。
“# PyTorch 不支持这种记法。”
“PyTorch does not support this type of notation.”
查看原文 →本该是代码单元的地方有一条注释,然后是“两种记法都允许……”——文本承诺了框架交付不了的两个选项。多框架的源文件渗了出来。
“$(\mathbf{A} - \lambda \mathbf{I})$ 必须把某个方向压缩到零,因此它不可逆”
“mathbf{A} - \lambda \mathbf{I})\) must compress some direction down to zero, hence it is not invertible”
查看原文 →在这里,几何的行列式工作挣到了它的位置:特征方程不是一个代数技巧,而是“这个映射必须压扁某样东西”。
“0 = (2-\lambda)(3-\lambda)-2 = (4-\lambda)(1-\lambda”
查看原文 →检查:(2−λ)(3−λ)−2 = λ²−5λ+4 = (4−λ)(1−λ)。符号对得上,因为两次符号翻转相互抵消。没问题,但用朴素方式去验证的读者会短暂地被吓到。
“无论 $\mathbf{W}$ 做了什么拉伸,$W^{-1}$ 都会撤销它,所以最终发生的唯一拉伸,是乘以那个对角矩阵”
“whatever stretching \(\mathbf{W}\) does, \(W^{-1}\) undoes it, so in the end the only stretching that happens is by multiplication by the diagonal matrix”
查看原文 →本章最干净的论证——把行列式当作体积因子,使 det(W)det(W⁻¹)=1 几乎不需要言语。
“秩与 $\mathbf{A}$ 的非零特征值的数目相同”
“the rank is the same as the number of non-zero eigenvalues of \(\mathbf{A”
查看原文 →只对可对角化的矩阵才成立,而这一节刚刚承认了并非总是如此。两段之后的 [[1,1],[0,1]] 例子,悄悄地驳倒了一般的读法。
读后感AI 陪读
附录是这本书一直悄悄倚靠的东西
这个附录,是书的其余部分一直悄悄倚靠的那一章,从头读到尾,感觉就像在大楼已经住满人之后,被带去看脚手架。它以一个承诺开篇,随后又收回了它——深度学习可以在没有多少数学的情况下实践,但梯度流、损失的假设和熵,没有数学就无法理解——而那个五个字的段落“但我们还没到那一步”,比好几页对冲做了更多老实的工作。这句话为此后的一切设定了调子:一次真正有用、偶尔草率、而且恰恰在承认自身局限的地方最有意思的巡礼。
弧线选得好。线性代数排在最前,而且是几何地来的:向量作为点或方向,点积作为夹角,余弦相似度,超平面作为决策边界。整个领域的意识形态动作,被一口气说了出来——任务成为点的集合,学习成为分开簇——这极其强大,也恰恰是“猫”和“狗”的语义蒸发的地方。留意亮度例子里拟合的方向:我们去拿角度,是因为我们本来就相信尺度不应该要紧。数学并没有发现这个不变性,它认可的是我们先做出的一个选择。而这一节中最举足轻重的一句话,被放在括号里顺带放下——高维的随机向量几乎总是近乎正交的——所以 0.3 的余弦可能是惊人的,而不是微弱的。测度集中,作为脚注偷渡进来。MNIST 上凭肉眼估计的阈值,用第一人称读来迷人,其含义却是毁灭性的:一个均值差向量加一次猜测,就能得到像样的准确率,这说明这个问题有多少本来已经是线性的。
继续阅读
从这里开始,线索很紧:线性变换无法对空间的某些部分比对另一些部分扭曲得更多——这是书里对线性的极限最干净的陈述,也是激活函数的全部理由。深度网络是一堆无法弯曲空间的东西的堆叠,由一些能弯曲空间的东西粘在一起。信息的破坏被具体化(“是 [1,1] 还是 [0,−1]?”),一下子产生了秩、可逆性和行列式,而行列式作为体积的读法,后来回本了两次:det(W)det(W⁻¹)=1 几乎不需要言语,而特征方程不再是一个代数技巧,成了“这个映射必须压扁某样东西”。数值方面的旁白是这里最好的实用内容——秩在理论上是二值的,在浮点数里是连续的,近乎相关的列会悄悄地惩罚你,稀疏矩阵的逆是稠密的,而“实践中避免求逆”作为顺带的一句话到来,它本该是一条框起来的规则。解方程组;不要构造逆。特征值的回报——反复相乘以最大特征值的速率增长,通过重新缩放来稳定,随机矩阵联系到初始化——是抽象终于兑现成你真会在代码里改的东西的地方。
微积分的一半建立在一个在每个尺度上重复的想法之上:放大看,一切都像是线性的。导数作为缩放因子,二阶导数作为曲率,泰勒级数作为用多项式匹配导数,梯度作为最陡的上升,海森矩阵作为最佳的局部二次型——然后是真正有启发的重新框定:反向传播不过是把链式法则写成保持 ∂f 在分子上,这样一遍局部偏导的前向传播和一遍反向的扫描就产生每一个梯度。这是附录里唯一最好的解释时刻。积分随后把同样的动作反过来运行:曲线下的矩形,微积分基本定理把求面积变成求导的逆运算,变量替换和雅可比行列式联系回第一节的体积缩放的故事。这一章在架构上比看上去更连贯。
概率和统计的处理出奇地坦率。密度和累积分布函数,因切比雪夫而变得可解释的均值和方差,通过积分积掉的边缘化,归一化成可读作余弦的相关系数的协方差——几何,有意地回来了。柯西分布被收进来,恰恰是为了打破汇总统计量总是存在这一舒适的假设。极大似然得到了很好的动机,然后立刻通过负对数似然被重新框定,以获得数值稳定性和线性时间的梯度,这才是你实际会实现的版本。分布的目录是参考材料,但最后指数族的统一,把一份清单变成了一个结构。朴素贝叶斯是老实的压轴戏:计数、拉普拉斯平滑、对数空间以躲开下溢,以及一个公然错误的独立性假设,却照样管用。然后是估计量、偏差、方差、偏差—方差分解、带五个步骤的假设检验、功效与样本量、p 值,以及把三个谬误明确点名的置信区间——频率派的区间是关于过程的陈述,而不是关于这个区间包含参数。明确教授这些误读,是比大多数统计学教科书做得更好的教学。
信息论闭合了循环,也闭合了书自己的论证:联合熵和条件熵、互信息、标出了非对称性的 KL 散度,以及交叉熵被揭示为与极大似然从另一边看是同一个对象。习题被选来迫使这种统一——从困惑度得到每字符的比特数,I(X,Y)=H(X)−H(X|Y) 既凭直觉又作为期望来论证,手工推导两个高斯之间的 KL。
最尖锐的判断:这一章在几何时最强,在百科时最弱,而它的瑕疵聚集在仓促的接缝处。在该说“非零”的地方说成“非负”,搞浑了承载稀疏性论证的那一句话。一个行列式的代码单元悄悄地转置了正文里的矩阵,只因为行列式在转置下保持不变这一巧合才得救。一条 PyTorch 的注释坐在本该是代码单元的地方,承诺了框架并不会交付的记法——多框架源文件渗了出来。爱因斯坦求和被呈现为一条被观察到的规则,而它其实是一个有牙齿的约定,不确定到 einsum 的箭头语法为了修补它才存在。而秩等于非零特征值的数目这一论断,只对可对角化的矩阵成立,两段之后被剪切的例子悄悄驳倒。这些都很小,但一个细心的读者会在每一个上绊一跤。
我会这样告诉读者:别把它当作一个要完成的章节。慢慢读几何的各节,把目录式的各节当作查阅。抓住四样东西——矩阵无法弯曲空间,所以非线性不是装饰;一切在局部都是线性的,这就是梯度居然管用的原因;精确的数学与有限精度的算术会分道扬镳,而秩是你最先感受到它的地方;极大似然、交叉熵和 KL 散度是一个想法穿着三件外衣。自己去验证算术,因为文本的失误是真实的,而悄悄溜过去的那些是最有教益的。最重要的是,注意这个附录从未大声说出来的反复出现的模式:几乎在每个转折,数学并没有告诉我们世界是什么样的,它编码的是我们自己带来的一个假设——关于尺度的、关于独立性的、关于线性的——然后以完美的忠实度跟随它。形式体系的严谨是真的;它的前提是我们的。知道哪个是哪个,才是读这样一章真正的理由。
在 FeedLitra 里读第 22 章,每段旁边都有这些卡片。
开始读书第 23 章:附录:深度学习工具
竞价实例比按需 GPU 实例便宜多少?
第 23 章是怎样展开的AI 辅助
开场:活儿开干之前先摆好工作台
本章不从理论讲起,而是从后勤讲起,前提是:跑不了代码的读者,就没法真正从代码里学东西。第一步,是在读者自己的机器上用 Jupyter 把本书的 notebook 打开并跑起来。紧接着是一个不那么显眼的改进:读者不直接用 Jupyter 原生的 .ipynb 文件,而是被引导去编辑本书的 markdown 源文件,由 notedown 搭桥,让 markdown 能像 notebook 一样被打开和运行。理由在版本控制。.ipynb 文件把执行元数据和正文存在一起,所以改一个词也会产生一份塞满无关机器输出的 diff,Git 分不清真正的修改和噪声。编辑 markdown,diff 就只剩改动的那些字——这一点要到章节很后面、直接谈贡献的时候才见回报,但在这里就埋下了。
展开:从笔记本电脑往外走
从本地配置出发,这一章朝着一个一致的方向展开:自己的机器不够用怎么办。先是 SSH 端口转发,这个技巧能让远程服务器上跑的 notebook 出现在本地浏览器里,让远程算力用起来像本地算力。再是真正的云——SageMaker、EC2、Colab——带着一条这一章特意单独拎出来的实用警告。因为按时间计费,闲置的实例应该关掉;但停止不等于删除。停止的实例不再产生计算费用,但还会为保留的磁盘收一点小钱,而且可以重新启动。终止(terminate)则会把挂在上面的一切连磁盘一起抹掉,没东西可重启。如果想丢掉一个实例但保留环境,该做的是先保存一个镜像。这个区别很容易混为一谈,混了代价不小。
转折:从软件到硅片
这一章的枢纽,是从怎么用算力转到怎么买算力。硬件指南以整台服务器的视角开场,并给出一条排序原则:GPU 才是重点,机器其余部分是为了喂饱它们而存在。反直觉的 CPU 建议正是由此而来。因为 Python 的全局解释器锁意味着,给四到八块加速器派活的那个进程实际上跑在一个线程上,所以单线程速度才是瓶颈,于是 6 核 4 GHz 的 CPU 胜过 8 核 3.5 GHz 的——PCIe 通道也要紧,因为它们是把数据送到每块卡上的通道。随之而来的还有一个提醒:没有驱动、CUDA 和支持 GPU 的框架,这些硬件一点加速都带不来。
展开(续):挑卡
聚焦到 GPU 本身,这一章给出三层嵌套的建议。买 NVIDIA,因为它最先进入深度学习,而且 CUDA 的框架支持更好。在 NVIDIA 里面,实验室或中小型团队应该买消费级 RTX,而不是 Tesla:算力大体相当,Tesla 多出来的东西——ECC 内存、被动散热——要到 100 台服务器的规模或者在云上,才值那大约十倍的价钱。到了十台以上服务器,务实的路是买预配置的 Supermicro 或华硕机箱,里面装四到八块 RTX。同一系列内的选择看三个参数——算力、显存大小、带宽——以及从性价比数据里看出的一个规律:同一代内,价格和性能大致成正比,所以真正的收益在代际跃升。对比 980 Ti 和 1080 Ti,GTX 1000 系列的性价比大约是两倍。RTX 2000 系列则让这一点复杂起来,书里对此很诚实:它的优势出现在低精度运算上,而不是普通 32 位性价比上,张量核心和 FP16/INT8/INT4 运算正是在这里见效——并带有两点明说的保留:低精度训练当时还不普及,价格来自写作时的维基百科。第二张图显示能耗几乎随计算量线性上升,新一代更省电。
收尾:回馈贡献,以及工具箱
这一章最后回到由 markdown 建议引出的“读者即贡献者”这条线。论点是:在这里改进真的可行——印刷书为改一个错别字要等好几年下一次印刷,而版本控制加持续集成把这本书的周转缩短到几小时或几天。具体流程随后给出——fork、clone、编辑、git status、add、commit、push、开 pull request——琐碎的错别字可以直接在 GitHub 上改,于是一次修正就是一份小而好审的提交。最后一段盘点可复用的 d2l 工具:绘图、损失、下载与解压、分词、梯度裁剪,然后是机器翻译的部分。其中带掩码的损失值得一提,因为它解释的是一个机制,而不只是提供一个工具:成批的翻译句子被填充到等长,所以原始的逐词元损失会把没有真实目标的位置也算进去,而由每个样本有效长度造出的权重张量会在求平均之前把这些位置清零,只留真正的词元去塑造梯度。seq2seq 的训练和预测函数收在清单末尾,它们标出了一条值得分清的界线——喂真实的前一个词元,只属于训练。预测时模型进入评估模式,每一步的输入是模型自己判断最可能的词元,取自己输出的 argmax,一路回喂直到出现结束符——这正是生成译文早期的一个错误会把整句带偏的原因。这一章以按字母排序的 d2l API 文档收尾,那是让这一切都可检索的索引。
关键论点,以及支撑它们的原文
贡献者应该编辑本书的 markdown 源文件,而不是 notebook 文件。
作者指出,.ipynb 文件带着大量辅助的执行信息,会让 Git 糊涂,使贡献很难审阅;notedown 的配置让你可以直接在 Jupyter 里打开和运行 markdown 源文件,既有 notebook 的体验,又没有脏 diff。
“前者之所以重要,是因为 Jupyter 原生的 ipynb 格式存了大量与内容无关的辅助数据,主要与代码怎么运行、在哪运行有关。”
“The former matters since Jupyter’s native ipynb format stores a lot of auxiliary data that is irrelevant to the content, mostly related to how and where the code is run.”
§23.1 Using Jupyter Notebooks查看原文 →
自己的机器 GPU 算力不够时,就去云上租——但用完要关实例,而且要知道关机不等于删除。
因为云服务按使用时间计费,作者让读者把不用的实例关掉,同时指出一个陷阱:已停止的实例仍会为保留的磁盘收一小笔费用。与之对照的是终止,它会抹掉挂在实例上的一切,包括磁盘,因此无法重启;先保存镜像可以保住环境。远程工作靠通过 SSH 转发服务器的 Jupyter 端口才好用,这样 notebook 看起来就像在本地跑。
“由于云服务按使用时间计费,你应该关掉不用的实例。”
“As cloud services are billed by the time of use, you should close instances that are not being used.”
§23.3 Using AWS EC2 Instances查看原文 →
给多 GPU 服务器挑 CPU,要看主频和 PCIe 通道,不要看核心数。
作者拿 6 核 4 GHz 的芯片和 8 核 3.5 GHz 的芯片比,倾向前者,因为一个进程要同时喂饱四到八块 GPU 时,Python 的全局解释器锁让单线程性能成为瓶颈。这是把 GPU 当作机器其余部分都要为之服务的对象所得出的结论——同时还需要驱动、CUDA 和支持 GPU 的框架,没有它们,硬件一点加速也没有。
“例如,在 6 核 4 GHz 和 8 核 3.5 GHz 的 CPU 之间选,前者要好得多,尽管它的总体速度更低。”
“For example, when choosing between a 6-core 4 GHz and an 8-core 3.5 GHz CPU, the former is much preferable, even though its aggregate speed is less.”
§23.5 Selecting Servers and GPUs查看原文 →
另外 3 个论点
买 NVIDIA;实验室或中小团队买消费级 RTX 系列,别买数据中心卡。
NVIDIA 最先进入深度学习,它的 CUDA 栈有更好的框架支持,所以作者说大多数买家选它。在此基础上,他指出消费级卡和 Tesla 算力大体相近,Tesla 多出 ECC 内存和被动散热,价格约贵十倍——主要在 100 台以上服务器的规模或云上才值。10 台以上服务器时,他描述的务实路径是预配置的 Supermicro 或华硕机箱,装 4-8 块 RTX。
“NVIDIA 最早进入深度学习领域,并通过 CUDA 为深度学习框架提供更好的支持。”
“NVIDIA was the first to enter the deep learning field and provides better support for deep learning frameworks via CUDA.”
§23.5 Selecting Servers and GPUs查看原文 →
每一代新 GPU 的性价比都更高,不过 RTX 2000 系列的收益体现在低精度运算上,而不是普通 32 位性价比上。
对比 980 Ti 和 1080 Ti,作者发现 GTX 1000 系列性价比大约是两倍,而在任何一个系列内,价格和性能大致成正比,所以收益在代际跃升。第二张图显示能耗几乎随计算量线性上升,新一代更省电,张量核心让曲线弯曲——这就是为什么 FP16、INT8 和 INT4 运算是最新卡见效的地方,同时要注意:低精度训练方法当时还不普及,价格取自写作时的维基百科。
“GTX 1000 系列的性价比大约是 900 系列的两倍。”
“The performance-to-cost ratio of the GTX 1000 series is about two times greater than the 900 series.”
§23.5 Selecting Servers and GPUs查看原文 →
读者真的可以改进这本书,因为版本控制和自动化测试让修正能快速落地。
作者拿印刷书对比:印刷书的错别字要等好几年下一次印刷才能改,而本书靠版本控制和持续集成,周转是几小时到几天。然后他走了一遍具体流程——fork、clone、编辑、git status、add、commit、push、开 pull request——展示一次错别字修正如何变成一份小而好审的提交,琐碎的错别字可以直接在 GitHub 上改。
“这一切都得益于版本控制和持续集成(CI)测试。”
“This is all possible due to version control and continuous integration (CI) testing.”
§23.6 Contributing to This Book查看原文 →
它是怎样运作的
本章论证所依靠的 3 个机制。
机制 1
为什么 notebook 文件会让 Git diff 没法读
Jupyter 原生的 .ipynb 文件把执行元数据和文本存在一起,所以哪怕只改一个词,diff 里也满是无关的机器输出。Git 分不清真正的修改和噪声,评审就很痛苦;在 Jupyter 里编辑 markdown 源文件,diff 就只剩真正改动的字。
机制 2
为什么 CPU 主频比核心数重要
Python 的全局解释器锁意味着给 GPU 喂数据的进程实际上跑在一个线程上,所以更快的单核比更多更慢的核更能给 4-8 块加速器派活。这就是为什么 6 核 4 GHz 的 CPU 可能比 8 核 3.5 GHz 的更值得买,而 PCIe 通道也要紧,因为它们把数据送到每块卡上。
机制 3
掩码如何把填充从损失中去掉
成批的翻译句子被填充到等长,所以原始的逐词元损失包含了没有真实目标的位置。由每个样本有效长度造出的权重张量,会在求平均之前把这些位置清零,于是只有真正的词元去塑造梯度。
常见误读
停止云实例和终止它基本是一回事,反正你都不用再付钱了。
停止只是暂停计算的计费,保留的磁盘还要付一点钱,而且实例以后可以再启动;终止则会删除与它相关的一切,磁盘也不例外,没东西可以重启。想丢掉实例但保留配置的话,先给它创建一个镜像。
“由于云服务按使用时间计费,你应该关掉不用的实例。”
“As cloud services are billed by the time of use, you should close instances that are not being used.”
§23.3 Using AWS EC2 Instances查看原文 →
既然解码器训练时读的是真实的前一个目标词元,那预测时也该给它正确的词元。
喂真实的前一个词元只属于训练。预测时模型被切到评估模式,每一步的输入是模型自己判断最可能的词元,也就是取自己输出的 argmax,一路回喂直到出现结束符——这正是生成译文早期的一个错误会把后面整句带偏的原因。
“# 我们用预测概率最高的词元作为输入”
“We use the token with the highest prediction likelihood as input”
§23.7 Utility Functions and Classes查看原文 →
第 23 章的核心概念
- 用 notedown 编辑 markdown 源文件
- 直接在 Jupyter 里编辑本书的 .md 源文件,而不是 .ipynb,这样 Git diff 保持可读。
- 适用处: 只在贡献内容时才用得上;本地跑代码并不需要它。
- 用于 Jupyter 的 SSH 端口转发
- 把远程服务器的 Jupyter 端口隧道转发到你自己的机器,让你像在本地一样浏览它。
- 适用处: 需要有 SSH 访问权限;在 Windows 上需要 PuTTY 之类的第三方软件。
- 对 GPU 的需求
- GPU 是深度学习实用的加速器,需要配套的驱动、CUDA 和支持 GPU 的框架。
- 适用处: 没有合适的驱动和支持 GPU 的框架,GPU 实例带不来任何加速。
- GPU 性能参数
- 购买时要比较的三样东西:算力、显存大小和显存带宽。
- 适用处: 对大多数用户来说只看算力就够了;带宽主要在 GDDR6 时才要紧。
- 消费级与企业级 GPU
- 个人用 GTX/RTX,数据中心用 Tesla;算力相近,但 Tesla 多了 ECC 内存、被动散热,价格贵十倍。
- 适用处: Tesla 主要在 100 台以上服务器的规模或云上才划算。
- 低精度加速
- 用 FP16、INT8 或 INT4 运算,每块钱、每瓦电换来更高的吞吐。
- 适用处: 写作时,低精度的训练算法还不普及。
另外 4 个概念
- 通过 pull request 贡献
- fork、clone、本地编辑、commit、push,然后开一个 pull request,由作者审阅并合并。
- 适用处: 小的错别字可以不用 fork,直接在 GitHub 上改。
- d2l 包
- 一个存放已保存的函数和类的共享库,让各章可以复用代码,而不用重新定义。
- 适用处: 它是教学上的方便,不是生产级的深度学习框架。
- 损失中的序列掩码
- 填充位置的权重设为零,所以它们不会参与训练损失。
- 适用处: 需要每个样本的有效长度;序列本来就等长时没用。
- 教师强制
- 训练时,解码器读取真实的前一个目标词元,而不是它自己的预测。
- 适用处: 只适用于训练时;预测时回喂的是模型自己的 argmax 词元。
第 23 章划线与批注AI 陪读
“这对 Git 来说很麻烦,使审阅贡献变得非常困难。”
“This is confusing for Git, making reviewing contributions very difficult.”
查看原文 →这个附录里唯一有真正论点的一句——文件格式是社会问题,不是技术问题。笔记本不适合协作,所以这本书悄悄改用 markdown 来写。
“最好也设置详细的账单和支出提醒,以免遇到任何意外”
“It is also a good idea to set up detailed billing and spending alerts to avoid any surprise”
查看原文 →藏在注册第一步里:云 GPU 真正的风险不是配置错,而是忘了。注意这一章有多少次回到“停掉实例”。
“只需用下面的命令丢弃你所有的本地改动”
“simply discard all your local changes with the following commands”
查看原文 →给初学者的 git reset --hard,前面只有一句缓冲的话。对笔记存在那些 notebook 里的读者,这是附录里破坏力最大的一行。
另外 16 条批注
“回想一下,在第 23.2 节我们讨论了如何使用 Amazon SageMaker,而自己搭建实例在 AWS 上成本更低。”
“Recall that in Section 23.2 we discussed how to use Amazon SageMaker, while building an instance by yourself costs less on AWS.”
查看原文 →通向同一块 GPU 的三条路,价格递减、人力递增。这个附录其实是在教你怎么买算力,不是教 Jupyter。
“前者要好得多,尽管它的总体速度更低”
“the former is much preferable, even though its aggregate speed is less”
查看原文 →漂亮的反转:GIL 是语言设计上的一个意外,却把你的硬件采购往主频倾斜,而不是核心数。Python 的限制一路伸到了主板上。
“这台服务器大概会又吵又烫。你不会想把它放在桌子底下。”
“This server will probably run loud and hot. You do not want it under your desk.”
查看原文 →语气终于脱掉了手册腔。四块 GPU 不再是一份配置清单,而成了和你同处一室的东西。
“正如一位合著者痛苦地发现的”
“as one of the coauthors painfully discovered”
查看原文 →一句旁白,比整张规格表更让人信任——这里的知识是拿一根装不进去的线缆换来的。
“通常比消费级 GPU 贵十倍”
“usually cost ten times more than consumer GPUs”
查看原文 →同样的算力贵十倍,买的是 ECC 和散热。诚实的读法:你付钱买的是可靠性和机构层面的许可,不是速度。
“然而,这是 TensorCore 造成的,它们耗费的能量不成比例地多。”
“However, this is a consequence of the TensorCores that draw disproportionately much energy.”
查看原文 →两段之内,RTX 的反常两次被同一个退路解释掉。方便——但照现在这么写无法证伪,因为没有给出按 FP16 归一化的图。
“用 FP16 或更低精度来获得高效率。”
“Use FP16 or lower precision for high efficiency.”
查看原文 →说得像是纯上升空间。一个字没提降低精度到底在哪里会出问题——损失缩放、收敛、数值调试。
“印刷之间的间隔(也就是勘误之间的间隔)可能以年计,而这里通常只需几小时到几天”
“the delay between print runs (and thus between typo corrections) can be measured in years, it typically takes hours to days”
查看原文 →这一节的真正论点:这本书在夸自己的新陈代谢,不是在教 Git。从几年到几小时,就是这个媒介的全部卖点。
“当你的 pull request 被作者合并进代码仓库,你就成为贡献者了。”
“When your pull request is merged into the code repository by the authors, you will become a contributor.”
查看原文 →巧妙的激励设计——奖励是身份,不是金钱。一本用归属感付酬的教科书。
“尽量不要提交巨大的 pull request,因为这会让它们难以理解和合入。最好发几个小的。”
“Try not to submit huge pull requests since this makes them hard to understand and incorporate. Better send several smaller ones.”
查看原文 →这里唯一真有手艺智慧的一句,却埋在一条总结要点里。把可审阅性当作一等设计约束,适用范围远不止这个仓库。
“一堆将被弃用的函数:”
“A bunch of functions that will be deprecated:”
查看原文 →对教科书来说坦率得惊人。整整一个附录的代码,作者已经不认账,却删不掉,因为前面的章节还靠着它们。活的书露出疤痕的接缝。
“raise ValueError("%s env is not supported in this Notebook")”
查看原文 →这个格式串没有参数——报错会原样打印 %s。一个小 bug,就坐在邀请读者提 pull request 的这一章里面。简直太完美了。
“frame = inspect.currentframe().f_back”
查看原文 →伸进调用者的栈帧,把每个参数自动赋成属性。教学上是魔法,当习惯则很可怕——读者学到一招,却还看不到它的代价。
“show_Q_function_progress(env_desc, V_all, pi_all)”
查看原文 →几乎逐字重复上面的函数,只是采样哪些迭代不同。一本呼吁优雅代码的书,刚复制粘贴了六十行。
“X[~mask] = value”
查看原文 →一个原地写入,藏在读起来像纯函数的工具里。谁传进来一个还要用的张量,就会被悄悄覆盖——这里没事,只因为 weights 是新建的。
“weighted_loss = (unweighted_loss * weights).mean(dim=1)”
查看原文 →注意这是对所有 num_steps 取 mean,而不是对有效词元——所以在填充很长的批次里,短句子的损失被冲淡了。随后训练又除以 Y_valid_len.sum(),混用了两种归一化。
读后感AI 陪读
JSON diff 毁掉了评审,让笔记本格式成了社会问题
附录把自己说成是杂务——装 Jupyter、租 GPU、提 pull request、这里有些工具函数——而这份谦逊恰恰是最容易误导人的地方。从头读下来,它其实是裹在风衣里的三个论点,而且这一章最诚实的地方,正是它最不像教科书的时候。
第一个论点关于格式与协作。那句 notebook “对 Git 来说很麻烦,使审阅贡献变得非常困难”,是开头几页里唯一有真正思想分量的话:这本书用 markdown 来写,不是为了优雅,而是因为 JSON diff 会毁掉评审。这是社会层面的诊断,不是技术层面的,而且和很后面埋在总结要点里的手艺建议呼应——多发几个小 pull request,别发一个巨大的。把可审阅性当成一等约束,才是 Git 一节真正的教训,比周围那些 git 命令值钱得多。顺带说一句,这些命令里有附录里最危险的一行:给初学者的 git reset --hard,只配了一句提醒,而这一章的读者恰恰把笔记存在那些要被丢弃的 notebook 里。
继续阅读
第二个论点关于买算力,而这一章从没承认这一点。本地 Jupyter、SSH 隧道、SageMaker、自己搭的 EC2、Colab,再到桌边一台四卡服务器——三四条路通向同一批张量核心,按价格递减、人力递增排列。反复出现的隐患从来不是配置错,而是忘记。“设置账单提醒”“把实例停掉”,像念经一样重复,因为云 GPU 的失败模式就是疏忽。硬件指南写得最好的时候,是手册腔裂开的时候:四卡机器会“又吵又烫”,你不会想把它放在桌子底下;一位合著者“痛苦地发现”一根线缆装不进去。这些旁白比规格表更能让人信任,因为只有在这些地方,知识才明显是花了代价换来的。还有一个真正漂亮的观察几乎没被点破——Python 的 GIL 逼着你选主频而不是核心数。一个语言设计上的意外,竟然伸手到你买主板的决定里,这种跨层洞见,这一章其余部分都没去尝试。
硬件一节变弱的地方,是它开始为结论辩护的时候。RTX 的能耗异常两次都用同一个 TensorCore 的退路来解释,却没给出按 FP16 归一化的图来检验——这很方便,但照现在的写法无法证伪。Tesla 卡“贵十倍”说得很直白,但诚实的读法是:你买的是 ECC、散热和机构层面的许可,不是速度。而“用 FP16 或更低精度以获得高效率”纯属只说好处,没提损失缩放、收敛不稳,也没提数值调试会难多少。读到这些地方,要一手放在刹车上。
第三个论点关于媒介本身。从几年到几小时——印刷勘误对比合并 pull request——才是贡献一节真正的卖点;它更像在夸这本书的新陈代谢,而不是在教版本控制。而且它用身份而不是金钱回报贡献者:合并一个修正,你就成了贡献者。对一本同时也是代码仓库的教科书来说,这是个巧妙的激励设计。
然后是工具函数附录,活的书在这里露出疤痕,我会先把持怀疑态度的读者送到这里。“一堆将被弃用的函数”坦率得惊人——作者已经不认账、却删不掉的代码,因为前面的章节还靠着它们。一个格式串没有参数的 ValueError,会原样打印出 %s。inspect.currentframe().f_back 伸进调用者的栈去自动给属性赋值,作为教学是魔法,作为习惯是坏习惯,而学习者还算不出它的代价。两个几乎一样的六十行绘图函数紧挨着,只在采样哪些迭代上不同,出现在一本别处鼓吹优雅的书里。X[~mask] = value 在一个读起来像纯函数的函数里原地写入——这里安全,只因为 weights 是新建的,而这种巧合一旦被复制到别处就不再安全。还有,带掩码的损失是对所有 num_steps 求平均,而不是对有效词元求平均,在填充很长的批次里把短句子的损失冲淡了,随后训练又除以 Y_valid_len.sum()——两种归一化在同一个循环里混用。
整章最尖锐的一行是 dec_input = concat([bos, Y[:, :-1]], 1) # Teacher forcing。整个暴露偏差问题——拿真值训练,推理时却靠自己的猜测——被压缩成两个词的注释,好像只是个格式细节。附录里没有任何地方指出这是结构性的不匹配;章末那份按字母排序的 API 文档当然也没有。
我会这样告诉读者:这个附录不是可有可无的填充,但它是作者最放松警惕的一章,这把双刃剑两面都割。把旁白和弃用说明当作诚实的部分——它们告诉你这活实际要花多少代价。把那些干净利落的祈使句——“用 FP16”“reset --hard”、悄悄改你张量的辅助函数——当作需要再看一眼的论断。最重要的是,别把那些工具函数清单当成定型的参考代码。它们是一本仍在修订的书的工作快照,里面有真实的 bug 和真实的接缝——而读者能在几小时内发现一个坏掉的格式串并提交 pull request,按本章自己的论证,这正是要点所在。
在 FeedLitra 里读第 23 章,每段旁边都有这些卡片。
开始读书论证在哪里吃力
不是反驳,而是细心的读者会想追问的地方。
- 本书一边敦促通过运行代码来建立直觉,一边又坚持有原则的推导,比如对平方损失的极大似然依据;它没有解决的是,在没有理论的情况下,读者该多信任经验性的调整。
“由此可见,最小化均方误差,等价于在加性高斯噪声的假设下对线性模型做极大似然估计。”
“It follows that minimizing the mean squared error is equivalent to the maximum likelihood estimation of a linear model under the assumption of additive Gaussian noise.”
§3.1 Linear Regression查看原文 → - 闭式解被斥为一个走运的特例,然而线性回归——它恰好有解析解——却被奉为几乎包含了深度学习所有组成部分的模型。
“虽然解析解允许漂亮的数学分析,但要求有解析解的限制太严苛,会把深度学习几乎所有激动人心的方面都排除在外。”
“Although analytic solutions allow for nice mathematical analysis, the requirement of an analytic solution is so restrictive that it would exclude almost all exciting aspects of deep learning.”
§3.1 Linear Regression查看原文 → - 即时讲授与前置的预备知识、符号和安装章节相冲突,这些章节在任何任务需要之前就讲了这些材料。
“例如,“$x$:一个标量”的意思是小写字母通常表示标量值,而“$\mathbb{Z}$:整数集”则专指符号 $\mathbb{Z}$。”
“For example, “\(x\): a scalar” means that lowercased letters generally represent scalar values, but “\(\mathbb{Z}\): the set of integers” refers specifically to the symbol \(\mathbb{Z”
Notation查看原文 → - 读者被告知 CPU 就够了,而工程论证却强调模型有几百兆字节的参数,每秒要更新好多次,并且 GPU 加速是偏爱张量的一个理由。
“如果你的机器里没有任何 GPU,暂时不用担心。”
“If your machine does not house any GPU, there is no need to worry just yet.”
Installation查看原文 →
另外 2 处张力,以及 8 条证据上的局限
- 先从零实现一切,然后又为了高层 API 把它丢掉,使人不清楚实践者到底该在哪一层抽象上思考。
“在第 3.4 节中,我们只依赖于:(i)用于数据存储和线性代数的张量;(ii)用于计算梯度的自动微分。”
“In Section 3.4, we relied only on (i) tensors for data storage and linear algebra; and (ii) automatic differentiation for calculating gradients.”
§3.5 Concise Implementation of Linear Regression查看原文 → - 在一堆固定的数据上做离线学习,与“学习系统通过积累与环境的交互而改进”这一说法并不协调。
“由于所有的学习都发生在算法与环境断开连接之后,这有时被称为离线学习。”
“Because all the learning takes place after the algorithm is disconnected from the environment, this is sometimes called offline learning.”
Chapter 1. Introduction查看原文 →
证据上的局限
- “只有 CPU 的机器就足以开始”这一说法只是断言,没有任何基准测试。
“如果你的机器里没有任何 GPU,暂时不用担心。”
“If your machine does not house any GPU, there is no need to worry just yet.”
Installation查看原文 → - 向量化的加速论证,只靠对 10,000 维向量做一次按元素运算的单个微基准。
“向量化代码常常能带来数量级的加速。”
“Vectorizing code often yields order-of-magnitude speedups.”
§3.1 Linear Regression查看原文 → - 闭式的最小二乘解只适用于线性最小二乘,且只在相关矩阵可逆时才适用,所以由它得出的结论不能推广到一般的模型。
“虽然解析解允许漂亮的数学分析,但要求有解析解的限制太严苛,会把深度学习几乎所有激动人心的方面都排除在外。”
“Although analytic solutions allow for nice mathematical analysis, the requirement of an analytic solution is so restrictive that it would exclude almost all exciting aspects of deep learning.”
§3.1 Linear Regression查看原文 → - 对线性回归直观的账单示例,只有在假定的两个特征能解释目标的全部变化时才成立。
“如果你跟上了这些,那你已经理解了线性回归背后的高层思想。”
“If you followed that much, then you already understand the high-level idea behind linear regression.”
Chapter 1. Introduction查看原文 → - 作者们承认,他们自建的出版系统并不完美,所以所宣称的相对现有资源的优势,有一部分只是期许。
- 对形式化理论为什么落后的解释——数学困难、数据性质定义不清、严肃探究起步太晚——是推理而不是证据,所以“靠调整代码来学习”这一处方没有经过经验验证。
- 机器学习的四部分分解,只用目标函数的例子(如平方误差和错误率)来说明,其余三个部分没有得到佐证。
“一个目标函数,用来量化模型做得有多好(或有多差)。”
“An objective function that quantifies how well (or badly) the model is doing.”
Chapter 1. Introduction查看原文 → - 预处理的指导只在一个小小的房屋数据集上演示,在这个规模上,插补和哑变量编码的选择几乎无关紧要。
“然而,要把深度学习应用到真实世界,我们必须提取以任意格式存储的杂乱数据,并对它做预处理,使之适合我们的需要。”
“However, to apply deep learning in the wild we must extract messy data stored in arbitrary formats, and preprocess it to suit our needs.”
§2.2 Data Preprocessing查看原文 →
全书概念导图
5 组概念:通俗的叫法、一句话解释,以及原书自己的用语。
1 · 边运行代码边学习
- 每个想法都恰好在任务需要它的时候到来
- 恰好在某个实际任务需要时才引入每个概念,而不是把理论放在前面。原书用语: Just-in-time teaching
- 先手工搭一遍,再看一行代码的库版本
- 本书反复使用的教学法:先手工实现一个组件,再用此后一直使用的简洁框架版本重做一遍。原书用语: From scratch plus high-level API
- 每个示例都是你可以随意改动的独立 notebook
- 每个自成一体的示例放在自己的 notebook 里,让读者可以复制并修改它。原书用语: One working example, one notebook
- 一套固定的、隔离的环境,在笔记本电脑的 CPU 上就跑得很好
- 一个隔离的 Miniconda Python 3.9 环境,必须在每个新的 shell 中激活,只有更大的模型才在乎有没有 GPU。原书用语: Reproducible runtime environment
2 · 当规则无法写下来的时候
- 见到的数据越多就越好的程序
- 性能随着数据或交互的积累而提高的算法,用在规则无法手工写出的地方。原书用语: Machine learning
- 从已经带着答案的样本中学习
- 利用带标签的样本,基于已知的输入去预测一个指定的未知标签;它的子类型按输出的形式来组织。原书用语: Supervised learning
- 挑出一个样本属于哪个类别
- 预测一个样本属于一组离散类别中的哪一个,当类别同时出现时,扩展为多标签预测。原书用语: Classification and its variants
- 处理以序列形式到来的输入或答案
- 输入或输出是变长序列、需要上下文的任务。原书用语: Sequence learning
3 · 每种方法里的四个部分
- 一组参数设置是一个模型;全部设置,是一个族
- 参数设置固定的程序是一个模型;所有可以达到的设置构成它的族,也就是学习算法所搜索的空间。原书用语: Model and model family
- 从数据中挑选参数的例程
- 利用数据集来挑选参数值的元程序,在本书中主要体现为小批量随机梯度下降。原书用语: Learning algorithm
- 在一堆固定的数据上训练,而不是在一个活的环境里
- 与环境断开、利用一堆固定的数据进行的学习,与把观测映射到动作的策略形成对照。原书用语: Offline learning and policy
4 · 数学与数据的管道
- 任意形状网格里的数字——唯一的数据接口
- 一个有任意多条轴的数字数组——本书的核心数据接口——加上自动微分和 GPU 加速,以广播机制和原地操作为关键机制。原书用语: Tensor (n-dimensional array)
- 把向量从一个空间映射到另一个空间的矩阵运算
- 转置、对称性、哈达玛积和点积,以及沿轴的降维——书写层计算所用的词汇。原书用语: Linear algebra operations
- 把杂乱的真实表格变成干净的张量送进去
- 把杂乱的真实数据变成张量——用插补或删除,以及哑变量编码来处理缺失值——然后把加载、打乱和分批包起来,让学习算法永远不用接触原始存储。原书用语: Data preprocessing and loading
- 从形状就能看出是数、向量还是矩阵的符号
- 一套统一的符号约定,其中大小写和字体编码了对象的阶——标量、向量、矩阵、一般张量——并把占位符与明确命名的具体对象区分开来,还有专门标记的定义性等式。原书用语: Typographic notation system
5 · 线性回归作为缩影
- 预测一个普通的数,比如价格
- 预测一个可以取任意数值的标签,具体实现为特征的加权和再加一个偏置。原书用语: Regression
- 把平方差当作损失——钟形曲线噪声下的最佳拟合
- 预测与标签之差的平方的一半,对样本取平均;等价于加性高斯噪声下的极大似然。原书用语: Squared error loss
- 度量向量的大小,这正是损失所计算的东西
- 一个把向量送到标量的函数,用来度量它的大小,提供了表述学习目标所用的语言。原书用语: Norm
- 在没见过的数据上表现如何,由你设置的旋钮来引导
- 在没见过的数据上的准确率,由训练循环不更新的设置来控制,并在留出的验证集上评判。原书用语: Generalization and hyperparameters
值得停下来的段落AI 陪读
几处值得停下来的原文,每处附一句它为什么对全书要紧。
“完成这项任务所需的精确步骤超出了我们有意识的理解,尽管我们的潜意识认知过程毫不费力地完成了这项任务”
“the precise steps required to perform the task lie beyond our conscious understanding, even though our subconscious cognitive processes execute the task effortlessly”
查看原文 →放在全书的背景下看,这是奠基性的前提:后面的每一章之所以存在,只是因为人的能力超出了人的解释。
“而当你能设计出 $100\%$ 的时候都管用的解决方案时,你通常不应该去操心机器学习。”
“And when you are able to devise solutions that work \(100\%\) of the time, you typically should not be worrying about machine learning.”
查看原文 →书自己立的边界标记——它告诉你接下来的一千页在哪里不适用,这比它们断言的任何东西都更少见,也更有用。
“我们就是不知道如何手工计算它”
“we simply do not know how to calculate it by hand”
查看原文 →从线性模型到深度网络整条弧线的枢纽:采用深度,不是一种胜利,而是承认手工设计的特征已经用尽。
另外 9 条批注
“瓦尔多长什么样,并不取决于瓦尔多在哪里”
“what Waldo looks like does not depend upon where Waldo is located”
查看原文 →本书最深层的反复出现的模式里最干净的一例——架构是对世界的断言,而数学只是这个断言的下标记法。
“主要归因于可用计算资源的变化”
“primarily attributable to shifts in the available computational resources”
查看原文 →通读全卷,这是令人不安的论点:逐章推进的叙事里,有很大一部分是算力和数据披着架构的外衣。
“然而,这种表面上的强项也是它的阿喀琉斯之踵:通用核心的制造成本非常高。”
“This apparent strength, however, is also its Achilles heel: general-purpose cores are very expensive to build.”
查看原文 →与算力的论证相配,解释了为什么赢的是这些运算——深度学习的数学足够可并行,能搭上别人硬件市场的顺风车。
“第一,张量类支持自动微分。第二,它借助 GPU 来加速数值计算”
“First, the tensor class supports automatic differentiation. Second, it leverages GPUs to accelerate numerical computation”
查看原文 →这个领域两个承重的推动者,结果都是工程,而不是数学——后面的理论章节从未真正正视这一框定。
“即使我们只关心硬性的分配,我们仍然使用做软性分配的模型”
“even when we only care about hard assignments, we still use models that make soft assignments”
查看原文 →塑造了书中几乎每个模型的那个安静的约束:一切都必须可微,所以硬性的决策被软化,是为了梯度的缘故,而不是我们的缘故。
“只有一定程度的噪声,才可能把参数从局部极小值中敲出来。”
“Only some degree of noise might knock the parameter out of the local minimum.”
查看原文 →点出了本书在优化、暂退法和数据增广中同样的招牌动作——噪声从缺陷被重新归类为机制。
“在标准的深度学习中,一个训练好的模型对某个测试数据的预测,并不影响它对未来某个测试数据的预测”
“in standard deep learning the prediction of a trained model on one test datum does not affect the predictions on a future test datum”
查看原文 →对前二十章默默假设了什么的最尖锐的陈述;一旦独立同分布被打破,全书那些让人安心的保证也就随之而去。
“尽管注意力权重究竟意味着什么——即它们应该如何解释,如果真能解释的话——仍然是一个模糊的研究话题”
“although what precisely the attention weights mean—i.e., how, if at all, they should be interpreted remains a hazy research topic”
查看原文 →书在可解释性上最老实的时刻:如今统治这个领域的机制抗拒解释,而“如果真能的话”拒绝假装并非如此。
“如果生成器做得完美,那么 $D(\mathbf x')\approx 1$,于是上面的损失接近 0,这导致梯度太小,无法让判别器取得良好的进展。”
“If the generator does a perfect job, then \(D(\mathbf x')\approx 1\), so the above loss is near 0, which results in the gradients that are too small to make good progress for the discriminator.”
查看原文 →值得留作读者的纪律——这样一本严谨的教科书也会印出一个倒过来的理由,所以相信你能检验的推导,胜过它周围的文字。
读后感AI 陪读
规则失效时,用可搜索的空间取代答案
从头读到尾,《动手学深度学习》不是对各种技术的综述,而是一个在每个尺度上反复出现的论证:当一项任务无法归结为你能明说的规则时,就别再规定答案,转而规定一个答案的空间,加上一种搜索它的办法——然后老实地为这一步的代价买单。它的脊梁从前言和符号(知识是一个设计问题;符号即类型)出发,经过预备知识里环环相扣的工具箱,进入线性回归和 softmax 回归,书真正的执念在这里第一次浮现:它把最简单的可用模型搭了两遍,然后立刻攻击这样搭起来所产生的自信,因为训练误差不等于泛化。从这里开始,这个模式换着不同的家具反复出现。MLP 表明,叠加仿射映射如果没有非线性什么也买不到,而决定性的问题变成了数值上的,而不是概念上的——梯度消失、对称性、初始化的方差。深度学习计算这一章揭示出一切之下那个唯一的结构性思想:模块是一个递归的构件,所以层、块和整个模型共用同一个接口。CNN 把关于世界的一个先验(局部性、平移不变性)编码为一种约束,然后用本章余下的篇幅,通过通道、填充和深度,买回约束拿走的东西;现代 CNN 讲述的是一个领域学会停止设计网络、开始设计设计空间。RNN 把可变上下文的问题搬进一个隐状态,而不是躲开它;现代 RNN 用一件武器——穿过时间的加性路径——对付同一个恶棍:梯度消失,同时坦率地把裁剪称为一个权宜之计。注意力随后通过让查找本身变成可学习、可微的,把瓶颈整个化解,而 Transformer 缺乏内置的先验,恰恰因为平滑的幂律缩放而成为优势,使它成了通用的骨干。最后的三分之一,是书转过身来面对自己的账单:在不诚实的地形上的优化,数学变成工程预算、硬件就是物质的计算性能,计算机视觉对前面章节的前提只是权宜之计的缓慢坦白,NLP 预训练那个先承诺免费的表示、再暴露每一种的局限的循环,强化学习用样本低效换来的免模型,高斯过程在函数上的先验,以及超参数优化对不去猜测的代价的核算。它最尖锐的判断是那些令人不安的:根本问题是泛化,而不是拟合;经典的复杂度理论过于悲观,解释不了深度网络;部署出去的模型可以改变它当初训练时所依据的分布;为每个任务量身定做的架构在大规模下不现实,但在资源紧张时仍然是对的;而对于大规模视觉,可扩展性干脆以多数票压过了让 CNN 称霸的归纳偏置。对读者说一句:别从这本书里挖食谱。把各章当作它们本来的样子——论证——来读,把每一段代码都跑一遍并把它弄坏,并把附录——数学和工具——不当作可有可无的卷末附件,而是当作整座大厦一直悄悄倚靠的脚手架。这本书最深的教训是一种习惯,而不是一个结果:说出你的假设,留意它们何时失效,并知道你接受的每一层抽象的价格。
网络书评怎么说
豆瓣上的中文读者评价很高,称赞它动手的代码、开源可得、作者的回应,以及配套的视频课程;批评者则说中文译本笨拙,对底层原理的讲解单薄,后面关于 CNN 和 RNN 的章节对真正的初学者来说太陡。deeplearning.ai 论坛上的一位发帖人主要把它当作一本参考书来推荐。
综合已发表书评的看法;不展示评分,完整书评请点来源链接。
来源与授权
CC BY-SA 4.0原书
- 《动手学深度学习》(Dive into Deep Learning),作者 Aston Zhang、Zachary C. Lipton、Mu Li(李沐)、Alexander J. Smola(剑桥大学出版社,2023;在线版 d2l.ai)。Copyright 2019 Amazon.com, Inc. or its affiliates。正文采用知识共享 署名-相同方式共享 4.0 国际许可协议(CC BY-SA 4.0),示例代码采用修改版 MIT 许可。免费阅读原书 · 许可证
- 本页由 FeedLitra 撰写的文字(摘要、批注、读后感)按 CC BY-SA 4.0 授权。
- 本页的引文中文译文属于原作的改编作品,按同一协议(CC BY-SA 4.0)授权。
- 摘要、论点、批注和读后感由 FeedLitra 根据全书原文 AI 辅助生成,引文已对照原文核对。最近更新:2026 年 10 月 21 日。
在 FeedLitra 里一边读《动手学深度学习》,一边看这些卡片。
开始读书