《DEEP LEARNING with Python, 3rd Ed.》读书笔记

2024年初就从图书馆借阅过《DEEP LEARNING with Python》第二版的中文版。

在技术更迭日新月异的今天,计算机类书籍的生命周期往往很短,所以自己也极少购买纸质书。但阅读此书后,竟然毫不犹豫地入手了一本纸质正版书(2022 年 8 月版,其英文版出版日期是2021-12)。当时就是觉得它是一本值得收藏的好书,后来也没再次翻阅过 ;),也甚是惭愧。

如今,《DEEP LEARNING with Python, 3rd Ed.》的英文版已于 2025 年 11 月正式面世。作者在https://deeplearningwithpython.io/上面发布了在线阅读版。就像作者所说,“The third edition is available here for anyone to read online, free of charge.” 全书完全在网络免费开放阅读。借助Google的AI在线翻译,不同国度的读者都可以第一时间无障碍的阅读本书。

这就是时代的红利。

想当年,那会刚毕业,为了第一时间阅读当年最经典《Thinking in Java》这本书,一边阅读,一边拿着一本厚字典查单词,那种痛苦,历历在目。

言归正传,这套书带给我最大的感触是,其宏观的视野与对本质的洞察。作者不仅能将深度学习和相关AI的核心概念梳理得极其清晰,更能通过深入浅出的语言或形象的比喻,一针见血地揭示事物背后的逻辑和本质。我始终相信,概念与定义是事物的本质,也是一切知识体系的基础与核心。

此外,作者对 AI 的优势、局限及未来发展的论述客观且务实,不故弄玄虚,这种实事求是的态度在当下的技术浪潮中显得尤为珍贵。

以下是本书的一些重要摘录。

其中关于流形假设这段话太牛了:“流形假说认为所有自然数据都位于其编码所在的高维空间中的一个低维流形上。这可以说是对宇宙信息结构的一种非常强有力的论断。就我们目前所知,它是准确的,也是深度学习能够奏效的原因。它不仅适用于MNIST数字,也适用于人脸、树木形态、人声,甚至自然语言。”所以只要模型能找到这个流形子空间,所有的东西都可以通过插值来处理。

关于Transformer模型,注意力机制为Transformer提供了两个关键特性:

  • 它们学习到的嵌入空间在语义上是连续的——也就是说,在嵌入空间中移动一个位,只会改变相应词元的人类可理解含义一个位。Word2Vec空间也展现了这一特性。
  • 它们学习到的嵌入空间是语义插值的——也就是说,在嵌入空间中取两个点之间的中间点,就能得到一个代表对应词元之间“中间含义”的点。这是因为每个新的嵌入空间都是通过对前一个空间中的向量进行插值构建的。

插值是深度神经网络学习的基础。深度神经网络本质上就是插值机器;它们将复杂的现实世界概率分布映射到低维流形上。即使对于像人类语言这样复杂的输入和像自然图像这样复杂的输出,我们也能利用这一特性。

你可以把Transformer看作类似于数据库:它存储着你可以通过传入的令牌检索的信息。但是Transformer和数据库之间有两个重要的区别。

  • 首先,Transformer 是一种连续的、可插值的数据库。它并非将数据存储为一组离散的条目,而是将其存储为一个向量空间——一条曲线。你可以在这条曲线上移动(正如我们之前讨论的,它在语义上是连续的),探索附近相关的点。你还可以对不同数据点进行插值,找到它们的中间状态。这意味着你可以从数据库中检索到比输入更多的信息——尽管并非所有信息都准确或有意义。插值可以带来泛化能力,但也可能导致“幻觉”——这是当今训练的生成式语言模型面临的一个重大问题。

  • 第二个区别在于,Transformer 模型不仅仅包含数据。对于像 RoBERTa 这样的模型来说,它基于从互联网抓取的数十万份文档进行训练,因此包含大量数据:事实、地点、人物、日期、事物和关系。但它同时也是一个程序数据库——或许它最重要的功能就是程序。

第一章 什么是深度学习?

  • 简而言之,人工智能可以被描述为 自动化通常由人类执行的智力任务的努力(the effort to automate intellectual tasks normally performed by humans.)。
  • 衡量算法性能是否良好的方法  ——这对于确定算法当前输出与其预期输出之间的差距至关重要。该测量结果用作反馈信号,以调整算法的运行方式。我们称这种调整步骤为“学习”(This adjustment step is what we call learning)。
  • 机器学习和深度学习的核心问题在于如何有效地转换数据:换句话说,就是学习当前输入数据的有用表示——这些表示能够帮助我们更接近预期的输出(to learn useful representations of the input data at hand—representations that get us closer to the expected output)。
  • 从本质上讲,表示是一种不同的数据呈现方式,用于表示或编码数据。
  • 在机器学习的语境下,“学习”指的是在反馈信号的引导下,自动搜索能够生成有用数据表示的数据转换过程——这些表示能够用更简单的规则来解决当前任务。
  • 简而言之,这就是机器学习:在预定义的可能性空间内,利用反馈信号的指导,寻找输入数据的有效表示和规则。
  • 就我们的目的而言,深度学习是一个用于从数据中学习表征的数学框架。
  • 您可以将深度网络视为一个多阶段的信息提炼过程,信息经过一系列过滤器的过滤,最终得到越来越纯净的信息(即,对于特定任务而言非常有用的信息)。
  • 智能是面对未知、适应未知并从中学习的能力。即使是最好的自动化系统,也只能处理它经过训练或预先编程的情况。

第二章 神经网络的数学基础

  • 搭建深度学习环境来运行这些笔记本最简单的方法是使用Google Colaboratory(简称 Colab),它是一个托管的 Jupyter Notebook 环境,已成为机器学习从业者的行业标准。
  • NumPy 是一个非常流行的 Python 数值计算库。在你的机器学习学习过程中,你会经常看到它的身影。由于缺乏 GPU 和自动微分支持,它很少用于实现现代机器学习算法,但 NumPy 数组经常被用作数值数据交换格式。
  • 张量(模型中存储数据的对象)、张量运算(构成模型的层)以及梯度下降(使模型能够从训练样本中学习)。
  • 不要把五维向量和五维张量混淆!五维向量只有一个轴,沿该轴有五个维度,而五维张量有五个轴(每个轴的维度数可以任意)。 维度可以表示特定轴上的元素个数(如我们的五维向量),也可以表示张量的轴数(例如五维张量),这有时会让人感到困惑。
  • 张量由三个关键属性定义:轴数(秩)Number of axes (rank) ——例如,秩为 3 的张量有三个轴,而矩阵有两个轴。形状 Shape——这是一个整数元组,用于描述张量在每个轴上的维度数。例如,前面的矩阵示例的形状为(3, 5),而秩为 3 的张量示例的形状为(3, 3, 5)数据类型
  • 选择张量中的特定元素称为 张量切片(tensor slicing)。
  • 使数据张量的概念更加具体。你将要处理的数据几乎总是属于以下几类之一:
    • 向量数据(Vector data)——形状为 的秩 2 张量(samples, features),其中每个样本都是一个数值属性(“特征”)的向量
    • 时间序列数据或序列数据(Timeseries data or sequence data) ——形状为 的秩 3 张量(samples, timesteps, features),其中每个样本都是一个(长度为timesteps)特征向量序列。
    • 图像(Images)——形状为 的 4 阶张量(samples, height, width, channels),其中每个样本都是一个二维像素网格,每个像素由一个值向量(“通道”)表示。
    • 视频(Video)——形状为 的 5 阶张量(samples, frames, height, width, channels),其中每个样本都是一个(长度为frames)的图像序列。
  • 当在 GPU 上运行 JAX/TensorFlow/PyTorch 代码时,逐元素操作是通过完全向量化的 CUDA 实现来执行的,这样可以最大限度地利用高度并行的 GPU 芯片架构。
  • 线性变换——任意矩阵的乘积即可实现线性变换。请注意,前面提到的缩放和旋转,根据定义,都是线性变换。仿射变换——仿射变换(见图 2.12)是线性变换(通过矩阵乘法实现)和平移(通过向量加法实现)的组合。正如你可能已经意识到的,这正是y = W @ x + bDense层实现的计算!Dense没有激活函数的层就是仿射层。关于仿射变换的一个重要观察结果是,即使重复应用多个仿射变换,最终得到的仍然是仿射变换(所以一开始只需应用一个仿射变换即可)借助激活函数,Dense我们可以构建一个层链来实现非常复杂的非线性几何变换,从而为深度神经网络提供非常丰富的假设空间。
  • 你可以通过张量运算 (例如加法、张量积或逐元素乘法)来操作数值张量,这些运算可以解释为编码几何变换。总的来说,深度学习中的一切都可以进行几何解释。
  • 学习是指找到一组模型权重值,使得给定一组训练数据样本及其对应目标的损失函数最小化。

第三章 TensorFlow、PyTorch、JAX 和 Keras 简介

  • Keras、TensorFlow、PyTorch 和 JAX 的功能集并不完全相同,也不能互相替代。它们之间存在一些重叠,但在很大程度上,它们针对不同的应用场景扮演着不同的角色。最大的区别在于 Keras 与其他三者之间。Keras 是一个高级框架,而其他三者则属于底层框架。想象一下建造房屋。Keras 就像一套预制建筑组件:它提供了一个简化的接口,用于设置和训练神经网络。相比之下,TensorFlow、PyTorch 和 JAX 则像是建造房屋所使用的原材料。
  • TensorFlow、PyTorch 和 JAX 是三种流行的底层数值计算和自动微分框架。它们各有各的实现方式、优势和劣势。Keras 是一个用于构建和训练神经网络的高级 API。它可以与 TensorFlow、PyTorch 或 JAX 一起使用——只需选择你最喜欢的后端即可。
  • 需要注意的是,TensorFlow 不仅仅是一个库,它实际上是一个平台,拥有庞大的组件生态系统,其中一些由 Google 开发,一些由第三方开发。例如,TFX 用于工业级机器学习工作流管理,TF-Serving 用于生产环境部署,TF Optimization Toolkit 用于模型量化和剪枝,以及 TFLite 和 MediaPipe 用于移动应用部署。......它的生产部署生态系统是所有框架中最成熟的,尤其是在移动设备或浏览器部署方面。
  • NumPy 数组和 TensorFlow 张量的一个显著区别在于,TensorFlow 张量不可赋值:它们是常量。
  • PyTorch 是一个基于 Python 的开源机器学习框架,主要由 Meta(前身为 Facebook)开发。......PyTorch 在机器学习研究领域得到了广泛应用。.....广受欢迎的预训练模型共享平台 Hugging Face 对 PyTorch 提供了顶级的支持,这意味着你想要使用的任何模型都可能在 PyTorch 版本中可用。这正是如今 PyTorch 被广泛采用的主要原因。
  • JAX 是一个用于可微分计算的开源库,主要由谷歌开发。自 2018 年发布以来,JAX 迅速在研究界获得广泛关注,尤其因其能够大规模利用谷歌的 TPU 而备受青睐。如今,JAX 已被生成式人工智能领域的大多数顶尖公司所采用,例如 DeepMind、苹果、Midjourney、Anthropic 和 Cohere 等。......JAX 在现代机器学习框架中独树一帜的主要特点在于其函数式、无状态的设计理念。虽然这种理念乍看之下可能会带来一些不便,但它恰恰释放了 JAX 的强大功能——能够编译成速度极快的代码,并可扩展到任意规模的模型和任意数量的设备。......它速度很快。对于大多数模型而言,它是你目前为止见过的所有框架中最快的。
  • Keras 目前的默认后端是 TensorFlow.
  • 模型的拓扑结构定义了一个假设空间。你可能还记得,在第一章中,我们将机器学习描述为“在预定义的 可能性空间内,利用反馈信号的指导,寻找输入数据的有用表示”。通过选择网络拓扑结构,你可以将可能性空间(假设空间)限制在一系列特定的张量运算范围内,从而将输入数据映射到输出数据。接下来,你需要寻找的是一组合适的权重张量值,这些权重张量用于这些张量运算。
  • 假设空间它编码了你对问题的假设,也就是模型初始所依赖的先验知识。......选择合适的网络架构与其说是一门科学,不如说是一门艺术。虽然有一些最佳实践和原则可以借鉴,但只有实践才能帮助你成为一名合格的神经网络架构师。
  • 为合适的问题选择合适的损失函数至关重要:你的神经网络会不惜一切代价来最小化损失

第四章 分类与回归

  • 拥有 16 个单元意味着权重矩阵的W形状为 (input_dimension, 16):与的点积W会将输入数据投影到 16 维表示空间(然后加上偏置向量b并应用运算relu)。你可以直观地理解表示空间的维度,即“你允许模型在学习内部表示时拥有多大的自由度”。拥有更多单元(更高维度的表示空间)可以让模型学习更复杂的表示,但这会增加模型的计算成本,并可能导致学习到不必要的模式(这些模式可以提高训练数据上的性能,但对测试数据没有帮助)。

  • 利用验证集上的结果来指导下一步的训练决策——例如,选择合适的模型大小或训练轮数。

  • 每个 epoch 结束时,模型会稍作停顿,以便计算其在 10,000 个验证样本上的损失和准确率。

  • 令人困惑的是,逻辑回归并不是回归算法,而是一种分类算法。

  • 请注意,用于归一化测试数据的量是使用训练数据计算的。即使是数据归一化这样简单的操作,您也绝不应该在工作流程中使用任何基于测试数据计算的量。

    此外,我们还应该调整目标值。我们归一化的输入值范围很小,接近于 0,而模型的权重初始化为较小的随机值。这意味着在训练开始时,模型的预测值也会很小。如果目标值在 60,000 到 500,000 之间,模型就需要非常大的权重值才能输出这些值。如果学习率很小,则需要很长时间才能达到这个目标值。最简单的解决方法是将所有目标值除以 100,000,这样最小的目标值就变为 0.6,最大的目标值就变为 5。然后,我们可以将模型的预测值乘以 100,000,从而将其转换回美元值。

  • 一般来说,训练数据越少,过拟合就越严重,而使用小型模型是缓解过拟合的一种方法。

  • 该模型(回归模型)以一个单元结束,且没有激活函数:它将是一个线性层。这是标量回归的典型设置——标量回归旨在预测一个连续值。应用激活函数会限制输出的范围;

  • 从这个标量回归示例中,你应该记住以下几点:

    • 回归分析使用的损失函数与分类分析使用的损失函数不同。均方误差(MSE)是回归分析中常用的损失函数。
    • 同样,回归分析所用的评估指标与分类分析所用的评估指标不同;显然,准确率的概念并不适用于回归分析。常用的回归评估指标是平均绝对误差(MAE)。
    • 当输入数据中的特征值处于不同范围内时,应在预处理步骤中对每个特征进行独立缩放。
    • 当数据较少时,使用 K 折交叉验证是可靠评估模型的好方法。
    • 当训练数据较少时,最好使用中间层较少的较小模型(通常只有一到两层),以避免严重的过拟合。
  • 当数据量较少时,K折交叉验证可以帮助可靠地评估模型。

第五章 机器学习基础

  • 机器学习的核心问题在于优化与泛化之间的矛盾。优化指的是调整模型以使其在训练数据上获得最佳性能的过程(即机器学习中的“学习”),而泛化指的是训练好的模型在从未见过的数据上的表现。当然,最终目标是获得良好的泛化能力,但泛化能力并非完全可控;你只能让模型更好地拟合训练数据。如果拟合过度,就会出现过拟合,从而影响泛化能力。

  • 深度学习模型的一个显著特点是,只要具有足够的表征能力,它们就可以被训练来适应任何事物。

  • 事实证明,深度学习中的泛化能力与深度学习模型本身关系不大,而与现实世界的信息结构关系密切。

  • 流形假设(The manifold hypothesis)有效子空间中的所有样本都通过贯穿该子空间的平滑路径连接起来。......流形假说认为所有自然数据都位于其编码所在的高维空间中的一个低维流形上。这可以说是对宇宙信息结构的一种非常强有力的论断。就我们目前所知,它是准确的,也是深度学习能够奏效的原因。它不仅适用于MNIST数字,也适用于人脸、树木形态、人声,甚至自然语言。

  • 流形假设意味着:

    • 机器学习模型只需要在其潜在输入空间(潜在流形)内拟合相对简单、低维、高度结构化的子空间。
    • 在这些流形中的一个内,总是可以在两个输入之间进行插值 ——也就是说,通过一条连续路径将一个输入变形为另一个输入,该路径上的所有点都落在流形上。
  • 如果你处理的数据点可以进行插值,你就可以通过将它们与流形上相邻的其他点联系起来,来理解那些你以前从未见过的点。换句话说,你只需使用空间的一个样本就能理解整个空间。你可以使用插值来填补空白。

  • 人类具备极强的概括能力,这得益于除插值之外的其他认知机制——抽象、世界的符号模型、推理、逻辑、常识、关于世界的先验认知——我们通常称之为理性,而非直觉和模式识别。后者本质上很大程度上是插值性的,而前者则不是。

  • 虽然深度学习确实非常适合流形学习,但模型的泛化能力更多地取决于数据的自然结构,而非模型本身的任何属性。只有当数据构成一个可以插值的流形时,模型才能实现泛化。特征信息量越大、噪声越小,模型的泛化能力就越强,因为输入空间会更简单、结构更清晰。数据整理和特征工程对于提高泛化能力至关重要。

  • 您应该始终牢记,提升深度学习模型的最佳方法是使用更多或更高质量的数据进行训练

  • 当无法获取更多数据时,次优方案是调整模型允许存储的信息量,或者对模型曲线的平滑度施加约束。如果网络只能记忆少量模式或非常规则的模式,优化过程会迫使它专注于最突出的模式,这些模式更有可能具有良好的泛化能力。这种防止过拟合的方法称为正则化。

  • 三种经典的评估方法:简单的留出验证法、K折交叉验证法和带随机打乱的迭代K折交叉验证法。

  • 在选择评估方案时,请注意以下几点:

    • 数据代表性  ——你需要确保训练集和测试集都能代表当前数据。例如,如果你要对数字图像进行分类,并且初始样本数组已按类别排序,那么将数组的前 80% 作为训练集,剩余的 20% 作为测试集,会导致训练集只包含类别 0-7,而测试集只包含类别 8-9。这看似荒谬的错误,但却非常常见。因此,通常应该在将数据拆分为训练集和测试集之前,先对数据进行随机打乱。
    • 时间之箭  ——如果你试图根据过去预测未来(例如,预测明天的天气、股票走势等等),那么在拆分数据之前不应该随意打乱数据顺序,因为这样做会造成时间泄漏:你的模型实际上会使用来自未来的数据进行训练。在这种情况下,你应该始终确保测试集中的所有数据都于训练集中的数据。
    • 数据冗余  ——如果你的数据中某些数据点出现了两次(这在实际数据中相当常见),那么对数据进行打乱并将其拆分为训练集和验证集会导致训练集和验证集之间出现冗余。实际上,你将使用部分训练数据进行测试,这是最糟糕的做法!请确保你的训练集和验证集互不相交。
  • 机器学习项目的第一个重大里程碑:获得一个具有一定泛化能力(可以胜过一个简单的基线)并且能够过拟合的模型。

  • 提高模型拟合度

    • 训练没有开始:你的训练损失不会随着时间推移而减少。

      降低或提高学习率。学习率过高可能导致更新幅度过大,严重偏离正确拟合值,就像前面的例子一样;而学习率过低则可能导致训练速度过慢,甚至停滞不前。

      增加批次大小。批次样本越多,得到的梯度信息越丰富,噪声越小(方差越低)。

    • 训练开始得很顺利,但是你的模型无法有效地泛化:你无法超越你设定的常识性基准。

      这或许是你在机器学习中可能遇到的最糟糕的情况。这表明你的方法存在根本性的问题,而且可能很难确定问题出在哪里。以下是一些建议。

      首先,可能是你使用的输入数据本身包含的信息不足以预测目标值:问题本身无法解决。之前我们尝试拟合一个标签被打乱的 MNIST 模型时就遇到了这种情况:模型可以正常训练,但验证准确率始终停留在 10%,因为这样的数据集显然无法进行泛化。

      也可能是你使用的模型类型不适合当前问题。例如,在第 13 章中,你会看到一个时间序列预测问题的例子,其中密集连接架构无法超越一个简单的基线模型,而更合适的循环架构却能很好地泛化。使用对问题做出正确假设的模型对于实现泛化至关重要:你应该使用正确的架构先验信息。

    • 训练损失和验证损失都会随着时间的推移而下降,你可以超越你的基线,但你似乎无法过拟合,这表明你仍然处于欠拟合状态。 如果你始终无法实现过拟合,那很可能是模型表征能力的问题:你需要一个更大的模型,一个容量更大的模型——也就是说,一个能够存储更多信息的模型。你可以通过增加层数、使用更大的层(参数更多的层)或者使用更适合当前问题的层类型(更好的架构先验)来提高表征能力。 但模型的记忆容量过大也是有可能 的。如果模型立即出现过拟合现象,则说明模型规模过大。

  • 提高泛化能力

    • 数据集整理

      投入更多精力和资金进行数据收集几乎总是比投入同样的资金开发更好的模型带来更大的投资回报:

      • 确保你拥有足够的数据。记住,你需要 对输入-输出空间进行密集采样。更多的数据会带来更好的模型。有时,一些看似无法解决的问题,随着数据集的增大,反而能够迎刃而解。
      • 尽量减少标签错误——可视化您的输入以检查异常情况,并校对您的标签。
      • 清理数据并处理缺失值(我们将在下一章中介绍)。
      • 如果你有很多功能,但不确定哪些功能真正有用,那就进行功能选择。
    • 特征工程 特征工程是指利用你对数据和当前机器学习算法(在本例中为神经网络)的了解,通过在数据输入模型之前对其应用硬编码(非学习)的转换,来优化算法性能的过程。在许多情况下,期望机器学习模型能够从完全任意的数据中学习是不合理的。数据需要以一种能够简化模型工作的方式呈现给模型。

      幸运的是,现代深度学习消除了大部分特征工程的需求,因为神经网络能够自动从原始数据中提取有用特征。这是否意味着只要使用深度神经网络就无需担心特征工程?并非如此,原因有二:

      • 优秀的功能仍然能够让你以更优雅的方式解决问题,同时减少资源消耗。例如,用卷积神经网络来解决读取钟面时间的问题就显得非常荒谬。
      • 好的特征能让你用更少的数据解决问题。深度学习模型自主学习特征的能力依赖于大量的训练数据;如果只有少量样本,那么特征的信息价值就至关重要。
    • 提前停车 你也可以在每个轮次结束时保存模型,然后在找到最佳轮次后,重用之前保存的最近一个模型。在 Keras 中,通常使用EarlyStopping回调函数来实现这一点。回调函数会在验证指标不再提升时中断训练,同时记住最佳模型状态。

    • 对模型进行正则化 正则化技术是一系列最佳实践,旨在主动限制模型完美拟合训练数据的能力,从而提升模型在验证阶段的表现。之所以称之为“正则化”,是因为它往往能使模型更简洁、更“正则化”,曲线更平滑、更“通用”——从而降低模型对训练集的依赖性,使其能够通过更精确地逼近数据的潜在流形而更好地泛化。请记住,“正则化”模型是一个需要始终遵循精确评估流程的过程。

      • 缩小网络规模 寻找合适模型大小的一般流程是:从相对较少的层数和参数开始,然后增加层的大小或添加新层,直到验证损失不再增加为止。

      • 添加权重正则化 与复杂的模型相比,简单的模型更不容易过拟合。

        简单模型指的是参数值分布熵较小的模型(或者如上一节所述,参数较少的模型)。因此,缓解过拟合的常用方法是限制模型的复杂度,强制其权重只能取较小的值,从而使权重值的分布更加规则。这称为权重正则化,其实现方式是在模型的损失函数中添加一个与大权重相关的代价。该代价有两种形式(请注意,由于此惩罚项*仅在训练时添加*,因此该模型在训练时的损失将远高于测试时的损失。):

        • L1 正则化——增加的成本与权重系数的绝对值(权重的L1 范数)  成正比。
        • L2 正则化——增加的代价与权重系数的平方成正比(权重的L2 范数)。在神经网络中,L2 正则化也称为权重衰减。不要被不同的名称所迷惑:权重衰减在数学上与 L2 正则化是相同的。
      • 添加 Dropout

        权重正则化通常用于较小的深度学习模型。大型深度学习模型往往参数过多,因此对权重值施加约束对模型容量和泛化能力的影响不大。在这种情况下,更推荐使用另一种正则化技术:dropout。 Dropout 应用于神经网络层时,会在训练过程中随机丢弃(置零)该层的部分输出特征。 核心思想是,在层的输出值中引入噪声可以打破不重要的偶然模式(Hinton 称之为*阴谋*),如果没有噪声,模型就会开始记住这些模式。

第六章 机器学习的通用工作流程

  • 你不是从数据集开始,而是从问题开始。
  • 机器学习的通用工作流程大致分为三个部分:
    • 明确任务——理解问题领域以及客户需求背后的业务逻辑。收集数据集,了解数据的含义,并选择衡量任务成功与否的方法。 并非所有问题都能用机器学习解决;即使你收集了输入 X 和目标 Y 的示例,也不意味着 X 包含足够的信息来预测 Y。例如,如果你试图根据股票近期的价格历史来预测其在股市上的走势,你不太可能成功,因为价格历史本身并不包含太多预测信息。
    • 开发模型——准备数据以便机器学习模型可以处理它,选择模型评估协议和要超越的简单基线,训练一个具有泛化能力但可能过拟合的第一个模型,然后对模型进行正则化和调整,直到获得最佳的泛化性能。
    • 部署模型— 向利益相关者展示您的工作成果,将模型部署到 Web 服务器、移动应用程序、网页或嵌入式设备,监控模型在实际应用中的性能,并开始收集构建下一代模型所需的数据。
  • 技术从来都不是中立的。如果你的工作对世界产生任何影响,那么这种影响就带有道德指向:技术选择也是伦理选择。
  • 一个好的数据集是一项值得精心维护和投入的宝贵资产。如果你有额外的50个小时可以投入到一个项目中,那么最有效的分配方式很可能是收集更多的数据,而不是寻求模型的渐进式改进。
  • 请记住,机器学习只能用于记忆训练数据中存在的模式。它只能识别你以前见过的事物。使用基于历史数据训练的机器学习模型来预测未来,就等于假设未来会像过去一样发展。但事实往往并非如此。
  • 将数据集视为黑箱是一种糟糕的做法。在开始训练模型之前,您应该探索并可视化您的数据,以深入了解其预测能力——这将指导特征工程——并筛查潜在问题。
  • 事实上,模型开发只是机器学习工作流程中的一个步骤,而且在我看来,它并不是最难的。机器学习中最难的是定义问题以及收集、标注和清洗数据。
  • 度学习模型通常不直接处理原始数据。数据预处理旨在使手头的原始数据更适合神经网络。这包括向量化、归一化或处理缺失值。许多预处理技术都具有领域特定性(Many preprocessing techniques are domain specific)(例如,特定于文本数据或图像数据);
  • 现阶段,你应该重点关注以下三件事:
    • 特征工程——过滤掉无信息特征(特征选择),并利用你对问题的了解来开发可能有用的新特征。
    • 选择合适的架构先验——您将使用哪种模型架构?密集连接网络、卷积神经网络、循环神经网络还是Transformer?深度学习是否适合这项任务,还是应该使用其他方法?
    • 选择合适的训练配置——应该使用哪种损失函数?批次大小和学习率应该是多少? 通常情况下,我们无法直接优化衡量问题成功与否的指标。有时,将指标转化为损失函数并非易事;毕竟,损失函数需要能够在仅使用少量数据的情况下计算(理想情况下,损失函数甚至只需一个数据点即可计算),并且必须是可微的(否则,就无法使用反向传播来训练网络)。例如,广泛使用的分类指标 ROC AUC 就无法直接优化。因此,在分类任务中,通常会优化 ROC AUC 的替代指标,例如交叉熵。一般来说,交叉熵越低,ROC AUC 值就越高。
  • 将模型转化为产品最简单的方法或许是通过 REST API 在线提供服务。

第七章 深入了解 Keras

  • 大多数深度学习模型看起来不像列表,而更像图。

  • compile 是告诉模型“规则是什么”,而 fit 是让模型“开始练习”。

  • 内置fit()工作流程仅专注于监督学习:在这种设置下,输入数据关联着已知的目标(也称为标签标注),并且损失是根据这些目标和模型的预测结果计算得出的。然而,并非所有形式的机器学习都属于这一范畴。还有一些设置中不存在明确的目标,例如生成式学习(我们将在第 16 章介绍)、 自监督学习(目标从输入中获取)或强化学习(学习由偶尔的“奖励”驱动——很像训练狗)

  • Keras 回调提供了一种简单的方法,可以在调用期间监视模型fit() ,并根据模型的状态自动采取操作。

  • 使用 Keras 对大型数据集进行数十个 epoch 的训练,model.fit() 有点像放飞纸飞机:除了最初的弹射之外,你无法控制它的轨迹或落点。为了避免糟糕的结果(从而避免浪费纸飞机),更明智的做法不是使用纸飞机,而是使用能够感知环境、将数据发送回操作员并根据当前状态自动做出转向决策的无人机。Keras回调API 可以帮助你将对 Keras 的调用model.fit()从纸飞机转变为能够自我评估并动态采取行动的智能自主无人机。

    以下是一些使用回调函数的示例:

    • 模型检查点 ——在训练过程中不同阶段保存模型的当前状态。
    • 提前停止Early stopping) ——当验证损失不再改善时中断训练(当然,还要保存训练期间获得的最佳模型)。
    • 在训练过程中动态调整某些参数的值 ——例如优化器的学习率。
    • 在训练过程中记录训练和验证指标,或者在模型学习到的表示更新时将其可视化 ——fit()您熟悉的进度条实际上是一个回调!

第八章 图像分类

  • 全连接层和卷积层之间的根本区别在于:全连接Dense层学习输入特征空间中的全局模式(例如,对于 MNIST 数字,学习涉及所有像素的模式),而卷积层学习局部模式(参见图 8.1)
  • 这一关键特性赋予卷积神经网络两个有趣的属性:
    • 它们学习到的模式具有平移不变性。卷积神经网络(ConvNet)在学习了图片右下角的某个模式后,就能识别出它出现在图片的任何位置,例如左上角。而如果模式出现在新的位置,全连接模型则需要重新学习。这使得卷积神经网络在处理图像时数据效率很高——因为视觉世界本质上是平移不变的。它们只需要更少的训练样本就能学习到具有泛化能力的表征。
    • 它们可以学习模式的空间层级结构(见图 8.2)。第一层卷积层学习诸如边缘之类的小局部模式,第二层卷积层学习由第一层特征构成的大模式,依此类推。这使得卷积神经网络能够高效地学习日益复杂和抽象的视觉概念——因为视觉世界本质上是空间层级结构的
  • 深度轴上的每个维度都是一个特征(或滤波器)
  • 最大池化是指从输入特征图中提取窗口,并输出每个通道的最大值。它在概念上类似于卷积,区别在于最大池化不是通过学习到的线性变换(卷积核)来变换局部图像块,而是通过硬编码的max张量运算来变换。与卷积的一个显著区别是,最大池化通常使用 2×2 的窗口和步长 2,将特征图下采样(downsample) 2 倍。而卷积通常使用 3×3 的窗口,步长为 1。
  • 简而言之,使用下采样的原因是减小特征图的大小,使它们所包含的信息空间分布越来越少,越来越集中在通道中,同时通过使连续的卷积层“查看”越来越大的窗口(就它们覆盖的原始输入图像的比例而言),来诱导空间滤波器层次结构。
  • 请注意,最大池化并非实现这种下采样的唯一方法。如您所知,您也可以在之前的卷积层中使用步长。此外,您还可以使用平均池化代替最大池化,其中每个局部输入块的变换方式是取该块内每个通道的平均值,而不是最大值。但最大池化通常比这些替代方案效果更好。简而言之,原因在于特征倾向于编码某种模式或概念在特征图不同图块上的空间存在性(因此称为特征图),而观察不同特征的最大存在性比观察它们的平均存在性更有意义。因此,最合理的下采样策略是首先生成密集特征图(通过无步长卷积),然后观察小块上特征的最大激活值,而不是观察输入的稀疏窗口(通过有步长卷积)或对输入块进行平均,后者可能会导致您丢失或稀释特征存在性信息。
  • 数据增强(data augmentation),这是一种在计算机视觉中缓解过拟合的强大技术。 数据增强的方法是通过对现有训练样本进行一系列随机变换,生成更多训练数据,最终得到看起来逼真的图像。其目标是确保在训练过程中,模型永远不会看到完全相同的图像两次。这有助于模型接触到更多数据特征,从而提升泛化能力。 请注意,我们使用未经增强的图像进行评估——数据增强通常只在训练阶段进行,因为它是一种正则化技术。
  • 由于卷积神经网络学习的是局部的、平移不变的特征,因此它们在感知问题上的数据效率非常高。
  • 深度学习模型本质上具有高度可重用性:例如,你可以将一个在大规模数据集上训练的图像分类或语音转文本模型,稍作修改后,就能将其应用于截然不同的问题。具体来说,在计算机视觉领域,许多预训练的分类模型都可以公开下载,并可用于仅使用少量数据构建强大的视觉模型。这正是深度学习最大的优势之一:特征重用。 如果原始数据集足够大且足够通用,那么预训练模型学习到的空间特征层次结构可以有效地作为视觉世界的通用模型,因此其特征可以应用于许多不同的计算机视觉问题,即使这些新问题涉及的类别与原始任务完全不同。例如,您可以在 ImageNet 数据集(其中类别主要为动物和日常物品)上训练一个模型,然后将该训练好的模型用于识别图像中的家具等看似毫不相关的任务。这种学习特征在不同问题之间的可移植性是深度学习相对于许多较旧的浅层学习方法的关键优势,也使得深度学习在处理小数据问题时非常有效。 请注意,特定卷积层提取的特征表示的通用性(以及由此而来的可重用性)取决于该层在模型中的深度。模型中较靠前的层提取的是局部的、高度通用的特征图(例如视觉边缘、颜色和纹理),而较靠上的层则提取更抽象的概念(例如“猫耳朵”或“狗眼睛”)。因此,如果您的新数据集与训练原始模型的数据集差异很大,那么最好只使用模型的前几层进行特征提取,而不是使用整个卷积层。
  • 模型中特征图的深度逐渐增加(从 32 层到 512 层),而特征图的尺寸则逐渐减小(从 180 × 180 减小到 7 × 7)。这几乎是所有卷积神经网络的共同特征。
  • 我们使用的模型名称中的“41”是什么意思?按照惯例,预训练的卷积神经网络通常以其“深度”命名。在这个例子中,“41”表示我们的 Xception 模型有 41 个可训练层(卷积层和全连接层),层层堆叠。
  • 网络微调(Fine-tuning)的步骤如下:
    1. 在已训练好的基础网络之上添加您的自定义网络。
    2. 冻结基础网络。
    3. 训练你新增的那部分。
    4. 解冻基础网络。
    5. 将这两层以及你添加的部分一起进行联合训练。
  • Partial fine-tuning 在处理大型预训练模型时,有时可能只会解冻卷积基的部分顶层,而保持底层冻结。

第九章 卷积神经网络架构模式

  • ConvNet architecture patterns 模型的“架构”是创建该模型时所有选择的总和:使用哪些层、如何配置它们、以及如何连接它们。这些选择定义了模型的假设空间:梯度下降可以搜索的可能函数空间,由模型的权重参数化。与特征工程类似,一个好的假设空间编码了你对当前问题及其解决方案的先验知识 。例如,使用卷积层意味着你预先知道输入图像中存在的相关模式是平移不变的。为了有效地从数据中学习,你需要对你要寻找的内容做出假设。

  • 模型架构的核心在于 简化梯度下降算法的求解过程——要知道,梯度下降本身就是一个相当简单的搜索过程,因此它需要尽可能多的辅助手段。

  • 模型架构与其说是一门科学,不如说是一门艺术。经验丰富的机器学习工程师往往能够凭直觉在第一次尝试时就构建出高性能模型,而初学者却常常连一个能训练的模型都难以创建。这里的关键词是“凭直觉”(intuitively):没有人能清晰地解释什么有效什么无效。专家们依靠模式匹配,而这种能力是通过大量的实践经验获得的。

  • Modularity, hierarchy, and reuse

    如果你想简化一个复杂的系统,有一个通用的方法:只需将你那团杂乱无章的复杂性结构化为模块,将这些模块组织成一个层级结构,然后根据需要在多个地方复用相同的模块(“复用”是抽象的另一种说法)。这就是模块化-层级-复用(MHR)公式。

  • 更深的层级结构本质上是有益的,因为它们鼓励特征重用,从而实现抽象。一般来说,由较深的窄层堆叠而成的模型比由较浅的宽层堆叠而成的模型性能更好。然而,层级堆叠的深度是有限的:梯度消失问题。这就引出了我们第一个重要的模型架构模式:残差连接。

  • 而探究因果关系的方法非常简便: 消融研究(ablation studies)。消融研究是指系统地移除系统的部分组件——也就是简化系统——从而确定系统性能的真正来源。如果你发现 X + Y + Z 组合能带来良好的结果,那么不妨也尝试 X、Y、Z、X + Y、X + Z、Y + Z 的组合,看看会发生什么。 始终要问自己:有没有更简单的解释?

  • 残差连接(Residual connections)“残差”在统计学和数学中通常指:观测值与真实值之间的差。将输入直接加到输出上,迫使卷积层只去拟合“差额”的结构,就被命名为残差连接

  • 批量归一化的主要作用在于它有助于梯度传播——类似于残差连接——从而允许构建更深的网络。对中间激活值进行归一化是否有帮助呢?BatchNormalization批量归一化正是实现这一功能。

  • 深度可分离卷积(Depthwise separable convolutions)首先对输入的每个通道独立地执行空间卷积,然后再通过逐点卷积(1×1 卷积)混合输出通道。

  • 简而言之,Transformer 架构是为处理文本而开发的——它本质上是一种序列处理架构。

第十章 解读卷积神经网络的学习成果

  • 人们常说深度学习模型是“黑箱”:它们学习到的表征难以提取并以人类可读的形式呈现。虽然这种说法对某些类型的深度学习模型部分正确,但对卷积神经网络(ConvNets)而言则完全不成立。卷积神经网络学习到的表征非常易于可视化,这很大程度上是因为它们是 对视觉概念的表征(representations of visual concepts)。

    重点介绍其中三种最易于理解和使用的方法:

    • 可视化卷积神经网络的中间输出(中间激活值) ——有助于理解连续的卷积神经网络层如何转换其输入,并初步了解各个卷积神经网络滤波器的含义。
    • 可视化卷积神经网络的滤波器——有助于精确理解卷积神经网络中每个滤波器所响应的视觉模式或概念。
    • 可视化图像中类别激活的热图——有助于了解图像中哪些部分被识别为属于特定类别,从而帮助您定位图像中的对象。
  • 可视化中间激活(Visualizing intermediate activations)

    • 第一层充当各种边缘检测器的集合。在这个阶段,激活值几乎保留了初始图像中的所有信息。
    • 随着层级的提升,激活模式变得越来越抽象,视觉可解释性也越来越低。它们开始编码更高层次的概念,例如“猫耳朵”和“猫眼睛”。更高层次的表征包含的关于图像视觉内容的信息越来越少,而关于图像类别的信息越来越多。
    • 随着层数的增加,激活值的稀疏性也随之增加:在第一层,所有滤波器都会被输入图像激活;但在后续层中,越来越多的滤波器处于空白状态。这意味着滤波器编码的模式在输入图像中并不存在。
  • 我们刚刚观察到深度神经网络学习到的表征的一个重要普遍特征:随着层数的增加,每一层提取的特征都变得越来越抽象。更高层的激活值包含的关于特定输入的信息越来越少,而关于目标(在本例中是图像的类别:猫或狗)的信息越来越多。深度神经网络实际上充当着信息提炼管道(information distillation pipeline)的角色,原始数据(在本例中是RGB图像)输入后,会经过反复转换,从而过滤掉无关信息(例如图像的具体视觉外观),并放大和提炼有用的信息(例如图像的类别)。

    这与人类和动物感知世界的方式类似:观察一个场景几秒钟后,人类可以记住场景中存在哪些抽象物体(例如自行车、树),但却记不住这些物体的具体外观。事实上,如果你试图凭记忆画出一辆普通的自行车,你很可能根本画不出来,即使你一生中见过成千上万辆自行车(例如,参见图 10.4)。现在就试试:这种现象绝对真实存在。你的大脑已经学会了完全抽象化视觉输入——将其转化为高级视觉概念,同时过滤掉无关的视觉细节——这使得我们很难记住周围事物的本来面目。

  • 可视化卷积神经网络滤波器(Visualizing ConvNet filters) 检查卷积神经网络(ConvNet)学习到的滤波器的另一种简便方法是显示每个滤波器应该响应的视觉模式。这可以通过输入空间中的梯度上升来实现,即对卷积神经网络的输入图像的值应用梯度下降,从而最大化特定滤波器的响应,初始输入图像为空白图像。最终得到的输入图像将是所选滤波器响应最强的图像。

  • 这些滤波器可视化图可以让你深入了解卷积神经网络(ConvNet)各层如何感知世界:卷积神经网络中的每一层都会学习一组滤波器,使得它们的输入可以表示为这些滤波器的组合。这类似于傅里叶变换将信号分解为一组余弦函数。随着模型层数的增加,这些卷积神经网络滤波器组中的滤波器会变得越来越复杂和精细:

    • 模型第一层的滤波器对简单的方向性边缘和颜色(或在某些情况下对彩色边缘)进行编码。
    • 堆栈上层一些的滤镜,例如block4_sepconv1,对由边缘和颜色组合而成的简单纹理进行编码。
    • 更高层级的滤镜开始呈现出类似自然图像中的纹理:羽毛、眼睛、树叶等等。
  • 可视化类别激活热图(Visualizing heatmaps of class activation)

    最后介绍一种可视化技术——它有助于理解给定图像的哪些部分引导卷积神经网络(ConvNet)做出最终分类决策。这对于“调试”卷积神经网络的决策过程非常有帮助,尤其是在出现分类错误的情况下(这属于模型可解释性问题)。它还可以帮助你定位图像中的特定对象。 这类技术被称为类激活图(CAM)可视化,其原理是生成输入图像的类激活热图。类激活热图是一个二维网格,网格上显示了与特定输出类别相关的分数,这些分数针对任何输入图像中的每个位置计算,表明每个位置相对于所考虑类别的重要性。例如,给定一张输入到“狗与猫”卷积神经网络的图像,CAM 可视化可以生成“猫”类别的热图,指示图像中不同部分与猫的相似程度;还可以生成“狗”类别的热图,指示图像中不同部分与狗的相似程度。 可视化热图 (CAM/Grad-CAM):是在问“对于这张特定的图片,模型是因为看到了哪个区域才判断它是‘狗’的?”

  • 核心原理:特征图的加权求和 在深层卷积神经网络(如 ResNet 或 VGG)中,最后一层卷积层输出的特征图(Feature Maps) 包含了最丰富的语义信息。 每个特征图可以看作是某种特征的“探测器”。例如: 通道 1 探测到了“毛茸茸的耳朵”。 通道 2 探测到了“湿润的鼻子”。 通道 3 探测到了“草地”。 当模型判定这张图是“狗”时,它会给“耳朵”和“鼻子”通道分配极高的权重,而给“草地”分配极低的权重。将这些特征图按照权重叠加在一起,就能得到一张反映“狗”特征分布的地图。

第十一章 图像分割

  • 计算机视觉的不同分支包括:图像分类、图像分割和目标检测。 除了图像分类、图像分割和目标检测这三者之外,深度学习在计算机视觉领域还涵盖了一些更为细分的任务,例如图像相似度评分(评估两幅图像的视觉相似程度)、关键点检测(精确定位图像中感兴趣的属性,例如面部特征)、姿态估计、3D网格估计、深度估计等等。但首先,图像分类、图像分割和目标检测是每位机器学习工程师都应该熟悉的基础。几乎所有计算机视觉应用最终都可以归结为这三者之一。

  • 三种不同的图像分割方法:

    • 语义分割,其中每个像素都被独立地分类到一个语义类别,例如“猫”。如果图像中有两只猫,则对应的像素都映射到同一个通用的“猫”类别(见图 11.2)。
    • 实例分割旨在解析出单个对象实例。在一张包含两只猫的图像中,实例分割会区分属于“猫 1”的像素和属于“猫 2”的像素(见图 11.2)。
    • 全景分割结合了语义分割和实例分割,它为图像中的每个像素分配一个语义标签(例如“猫”)和一个实例标签(例如“猫2”)。这是三种分割类型中信息量最大的。
  • 为了评估模型,我们将使用 交并比( Intersection over Union)(IoU) 指标。它衡量的是真实分割掩码和预测掩码之间的匹配程度。可以分别计算每个类别的 IoU,也可以对多个类别取平均值。其工作原理如下:

    1. 计算掩码之间的交集,即预测结果与真实值重叠的区域。
    2. 计算两个掩码的并集,即两个掩码共同覆盖的总面积。这就是我们感兴趣的整个空间——目标对象以及模型可能错误包含的任何额外部分。
    3. 将交集面积除以并集面积即可得到交并比 (IoU)。IoU 是一个介于 0 和 1 之间的数字,其中 1 表示完全匹配,0 表示完全不匹配。
  • Segment Anything 的工作原理(How Segment Anything works)

    在尝试使用该模型进行分割之前,我们先来详细了解一下SAM的工作原理。该模型的强大功能很大程度上源于其预训练数据集的规模。Meta公司在开发模型的同时还开发了SA-1B数据集,其中部分训练好的模型被用于辅助数据标注过程。也就是说,数据集和模型是在一个反馈循环中共同开发的。

第十二章 目标检测

  • 目标检测的核心在于绘制边界框(也称为边界框)(drawing boxes (called bounding boxes)),将图像中感兴趣的物体框起来(见图 12.1)。这不仅能让你知道图像中有哪些物体,还能让你知道它们的位置。它的一些最常见应用包括:

    • 计数——找出图像中某个物体的出现次数。
    • 跟踪——通过对电影的每一帧执行对象检测,跟踪场景中物体随时间推移的运动情况。
    • 裁剪——识别图像中包含感兴趣对象的区域,将其裁剪出来,并将图像块的更高分辨率版本发送到分类器或光学字符识别 (OCR) 模型。
  • 实际上,分割是检测的严格超集。它不仅返回检测模型能够返回的所有信息,而且还包含更多信息。这种信息量的增加带来了显著的计算成本:一个优秀的目标检测模型通常比图像分割模型运行速度快得多。此外,它还增加了数据标注成本:训练分割模型需要收集像素级精确的掩码,这比目标检测模型所需的简单边界框的生成要耗时得多。

  • 在早期版本的 R-CNN 中,第一阶段是一个名为 选择性搜索的启发式模型(heuristic model called Selective Search),它利用空间一致性(spatial consistency)的定义来识别类似物体的区域启发式(Heuristic)是机器学习领域一个经常听到的术语——它简单来说就是“一套人为设定的硬编码规则”。它通常与学习模型(规则是自动生成的)或理论模型相对立。

  • 目标检测主要有两种方法:

    • 基于区域的卷积神经网络(R-CNN)是一种两阶段模型,它首先提出感兴趣的区域,然后使用卷积神经网络(ConvNet)对其进行分类。
    • 单阶段检测器(例如 RetinaNet 和 YOLO)可以在一步内完成这两项任务。单阶段检测器通常速度更快、效率更高,因此适用于实时应用(例如自动驾驶汽车)。
  • 单阶段检测器的主要系列包括RetinaNet、单次多框检测器(SSD)和You Only Look Once系列(简称YOLO)。没错,就是那个梗。故意这么叫的。

    个人注:

    在计算机视觉领域,它是 You Only Look Once(你只看一次)的缩写,由 Joseph Redmon 在 2015 年提出。但这个名字其实是故意套用了当时社交网络上极其火爆的一个流行语:YOLO —— You Only Live Once(你只活一次)。

  • 如前所述,YOLO模型是一个单阶段检测器。它并非先尝试识别场景中的所有候选对象,然后再对对象区域进行分类,而是一次性生成边界框和对象标签。

  • 大多数图像中的物体并非均匀分布在网格上,为了解决这个问题,模型会为每个方框输出一个置信度分数(confidence score ),如图 12.4 所示。我们希望在检测到物体时置信度较高,而未检测到物体时置信度为零。大多数网格位置都没有物体,因此置信度应接近于零。

  • ResNet 的结构与 Xception 非常相似,但它使用步长卷积而非池化层来对图像进行下采样。正如我们在第 11 章中提到的,当需要关注输入的空间位置时,步长卷积的效果更佳

  • 这个训练示例清晰地展示了流式库的用处tf.data。一次性加载这个大型数据集中的所有图像会耗尽系统内存(请记住,图像张量比压缩后的 JPEG 文件大得多)。使用流式库tf.data,我们可以分批加载图像数据,并在完成后释放内存,只在特定时刻映射数据集中我们需要的部分。调用流prefetch(2)式库会将tf.data两个批次的数据缓冲起来,并在使用前准备就绪,这样我们就无需中断每个批次的训练来加载和调整更多图像的大小。

  • Redmon 等人提出了一些损失函数缩放技巧来提高训练质量:

    • 他们将盒子放置损失放大五倍,使其成为整体训练中更重要的一部分。
    • 由于大多数网格单元都是空的,因此空位置的置信度损失也减半。这样可以防止这些零置信度预测对损失造成过大的影响。
    • 在计算损失之前,他们会对宽度和高度取平方根。这是为了防止大框的影响过大。我们将使用一个sqrt能够保留输入符号的函数,因为我们的模型在训练初期可能会预测出负的宽度和高度。

第十三章 时间序列预测

  • 本章重点讨论预测。但实际上,时间序列还可以用于许多其他用途,例如:

    • 异常检测(Anomaly detection)——检测连续数据流中发生的任何异常情况。企业网络出现异常活动?可能是攻击者。生产线上的读数异常?需要人工检查。异常检测通常采用无监督学习,因为您通常不知道要查找哪种异常,因此无法使用特定的异常示例进行训练。
    • 分类(Classification)——为时间序列分配一个或多个类别标签。例如,给定网站访问者的活动时间序列,判断该访问者是机器人还是真人。
    • 事件检测(Event detection)——识别连续数据流中特定预期事件的发生情况。一个特别有用的应用是“热词检测”,其中模型监控音频流并检测诸如“OK Google”或“Hey Alexa”之类的语音指令。
  • 时间序列数据具有跨多个时间尺度的周期性,这是一个重要且非常常见的特征。

  • 处理时间序列数据时,使用比训练数据更新的验证和测试数据至关重要,因为我们试图根据过去预测未来,而不是反过来,因此验证/测试数据的划分应该反映这种时间顺序。

  • 每个数据集生成一个元组(samples, targets),其中samples是包含 256 个样本的批次,每个样本包含 120 小时的连续输入数据,targets是对应的 256 个目标温度数组。请注意,样本是随机打乱的,因此同一批次中的两个连续序列(例如samples[0]samples[1])在时间上不一定接近。

    个人注:

    在处理时间序列时,初学者往往会陷入一个直觉误区:认为“训练过程的随机化”会破坏“时间维度的连续性”。

    其实,我们需要区分两个完全不同的概念:序列内部的连续性(Temporal Order inside a sample)和样本之间的顺序(Order of samples in a batch)。

    注:完整内容详见译文。

  • 分类问题回归问题在神经网络输出层设计上的本质区别。

    简单来说:激活函数就像是一个“过滤器”或“缩减器”,而回归问题需要的是“真实原值”。

  • 你可能会疑惑,如果存在一个简单且性能良好的模型能够从数据推导出目标值(即常识性的基线模型),为什么你正在训练的模型找不到它并对其进行改进呢?这是因为你寻找解决方案的模型空间——也就是你的假设空间——实际上是所有具有你定义的配置的双层网络的空间。常识性的启发式模型只是这个空间中数百万个模型中的一个。这就像大海捞针。即使一个好的解决方案理论上存在于你的假设空间中,也不意味着你就能通过梯度下降找到它。

    这是机器学习的一个相当重要的局限性:除非学习算法被硬编码为寻找特定类型的简单模型,否则它有时可能无法找到简单问题的简单解决方案。因此,使用良好的特征工程和相关的架构先验至关重要:你需要精确地告诉模型它应该寻找什么。

  • 循环神经网络(Recurrent neural networks)

    在天气预报的案例中,全连接方法和卷积方法的效果都不理想,但这并不意味着机器学习不适用于这个问题。全连接方法首先将时间序列展平,从而消除了输入数据中的时间信息。卷积方法对数据的每个片段都采用相同的处理方式,甚至应用了池化操作,这破坏了顺序信息。我们应该将数据视为一个序列,其中因果关系和顺序至关重要。

    有一类神经网络架构是专门为这种应用场景设计的:循环神经网络。其中,长短期记忆(LSTM)层尤其受欢迎。

  • 我们在全连接网络示例中就是这样做的:我们将五天的数据展平为一个大的向量,并一次性处理完毕。这类网络被称为前馈网络(feedforward networks)。

  • 相比之下,当你阅读当前句子时,你是逐字逐句地处理信息——或者更确切地说,是逐次扫视——同时还要记住前面的内容;这让你能够流畅地理解句子所传达的含义。生物智能则以增量的方式处理信息,同时维护一个基于过往信息构建并随着新信息的到来不断更新的内部模型。

    循环神经网络(RNN)采用相同的原理,尽管形式极其简化:它通过遍历序列元素并维护一个包含当前已处理信息的状态来处理序列。实际上,RNN 是一种具有内部循环的神经网络(参见图 13.6)。

    在处理两个不同的独立序列(例如同一批次中的两个样本)之间,循环神经网络 (RNN) 的状态会被重置,因此您仍然将一个序列视为一个单独的数据点:网络的一个输入。变化之处在于,该数据点不再一次性处理;相反,网络会在内部循环处理序列元素。

  • 因此,构成 RNN 单元的运算组合最好被理解为一组对搜索的约束,而不是工程意义上的设计。

    可以说,选择这些约束条件——也就是如何实现RNN单元——最好交给优化算法(例如遗传算法或强化学习过程)来处理,而不是交给人类工程师。未来,我们将采用这种方式构建模型。总之,你不需要了解LSTM单元的具体架构;作为人类,理解它不应该是你的工作。你只需要记住LSTM单元的作用:允许在稍后重新注入过去的信息,从而解决梯度消失问题。

  • 在循环层之前应用 dropout 会阻碍学习,而不是有助于正则化。2015 年,Yarin Gal 在他的贝叶斯深度学习博士论文中指出,[5]确定了循环神经网络中使用dropout的正确方法:在每个时间步应用相同的dropout掩码(相同的丢弃单元模式),而不是使用随时间步随机变化的dropout掩码。

  • 通常,增加网络容量是通过增加层中的单元数量或添加更多层来实现的。循环层堆叠是构建更强大循环网络的经典方法:例如,不久前谷歌翻译算法就是由七个大型LSTM 层堆叠而成的——这非常强大。

  • 在下面的例子中,我们将尝试两个经过 dropout 正则化的循环层堆叠。为了有所改变,我们将使用GRU层而不是LSTM门控循环单元(Gated Recurrent Unit ) (GRU) 与 LSTM 非常相似——您可以将其视为 LSTM 架构的一个略微简化、精简的版本。

  • 双向循环神经网络( bidirectional RNNs)双向RNN是一种常见的RNN变体,在某些任务上可以比常规RNN提供更优的性能。它常用于自然语言处理——你可以称它为深度学习在自然语言处理领域的瑞士军刀。

  • 双向RNN利用了RNN的顺序敏感性:它由两个常规RNN组成,例如你已经熟悉的R1层GRU和R2LSTM层,每个层分别沿一个方向(按时间顺序和按反时间顺序)处理输入序列,然后合并它们的表示。通过双向处理序列,双向RNN可以捕捉到单向RNN可能忽略的模式。

  • 当您训练与本节第一个实验中相同的基于 LSTM 的模型时,您会发现这种反向顺序的 LSTM 模型甚至远逊于常识基线模型。这表明,在这种情况下,时间顺序处理对于该方法的成功至关重要。这完全合乎情理:底层LSTM通常更擅长记忆近期而非远期数据,而且,自然地,对于该问题而言,较新的天气数据点比较旧的数据点更具预测性(这正是常识基线模型表现相当出色的原因)。因此,按时间顺序处理的 LSTM 层必然优于反向顺序处理的 LSTM 层。

    然而,对于许多其他问题,包括自然语言处理,情况并非如此:直觉上,一个词在理解句子中的重要性并不强烈依赖于它在句子中的位置。对于文本数据,反向处理与按时间顺序处理的效果一样好——你可以倒着读文本,完全没问题(试试看!)。虽然词序在理解语言中确实很重要,但你使用哪种顺序并非关键。

    重要的是,用反向序列训练的循环神经网络(RNN)会学习到与用原始序列训练的RNN不同的表征,这就像现实世界中时间倒流时,你的心智模型也会有所不同——如果你的一生中第一天就去世,最后一天才出生。在机器学习中,不同但有用 的表征总是值得利用的,而且差异越大越好:它们提供了一个新的视角来审视你的数据,捕捉到其他方法遗漏的数据特征,从而有助于提升任务性能。这就是集成学习(ensembling)背后的直觉,我们将在第18章探讨这个概念。

  • 然而,双向循环神经网络非常适合处理文本数据——或者任何其他顺序重要但具体 使用*哪种*顺序无关紧要的数据。事实上,在2016年的一段时间里,双向长短期记忆网络(LSTM)被认为是许多自然语言处理任务中最先进的方法(在Transformer架构兴起之前,您将在第15章中学习到)。

  • 一些读者肯定会想运用我们在此介绍的技术,尝试预测股票市场(或货币汇率等)的未来价格。然而,市场的统计特征与天气模式等自然现象截然不同。就市场而言,过去的表现并不能很好地预测未来的收益——就像开车时总是回头看后视镜一样,毫无益处。另一方面,机器学习则适用于那些过去数据*能够*很好地预测未来的数据集,例如天气、电力消耗或商店客流量。

    请始终记住,所有交易的本质都是信息套利(information arbitrage):利用其他市场参与者所缺乏的数据或洞察来获取优势( gaining an advantage by using data or insights that other market participants are missing. )。试图利用众所周知的机器学习技术和公开数据来战胜市场实际上是一条死路,因为你与其他参与者相比没有任何信息优势。你很可能白白浪费时间和资源,一无所获。

第十四章 文本分类

  • 尽管遭遇了这些挫折,也经历了从兴奋到失望的反复起伏,手工编写的规则在20世纪90年代仍然是主流方法。问题显而易见,但除了用符号规则描述语法之外,别无他法。然而,随着20世纪80年代末计算机速度的提升和海量数据的出现,研究开始朝着新的方向发展。当你发现自己构建的系统充斥着大量临时规则时,作为一名聪明的工程师,你很可能会开始思考:“我能否利用语料库来自动查找这些规则?我能否在某个规则空间中搜索规则,而不是自己去创造它们?” 就这样,你就踏入了机器学习的领域。

  • 过去十年,自然语言处理(NLP)研究人员和从业者发现,学习文本相关统计问题的答案竟能带来惊人的效果。2010年代,研究人员开始将长短期记忆网络(LSTM)模型应用于文本处理,这极大地增加了NLP模型的参数数量以及训练所需的计算资源。结果令人鼓舞——LSTM模型能够比以往的方法更准确地泛化到未见过的样本,但最终也遇到了瓶颈。LSTM难以追踪包含大量句子和段落的长文本链中的依赖关系,而且与计算机视觉模型相比,它们的训练速度慢且操作繁琐。

    在2010年代末期,谷歌的研究人员发现了一种名为Transformer的新架构,它解决了困扰LSTM的诸多可扩展性问题。只要模型及其训练数据规模同时增加,Transformer的性能似乎就会越来越好。更重要的是,即使对于长序列,训练Transformer所需的计算也可以有效地并行化。如果训练机器的数量翻倍,等待结果所需的时间大约可以缩短一半。

  • 然而,有些炒作需要理性看待——它们本质上是模式识别机器。尽管我们人类总是倾向于在“会说话的东西”中寻找智能,但这些模型复制和合成训练数据的方式与人类智能截然不同(而且效率低得多!)。不过,公平地说,从极其简单的“猜词”训练设置中涌现出复杂的行为,是过去十年机器学习领域最令人震惊的实证成果之一。

  • 在开始任何建模之前,我们需要将文字转换为数字张量。与图像相对自然的数值表示不同,文本的数值表示可以通过多种方式构建。

  • 所有文本建模问题都涉及一个预处理步骤,即文本被分解并转换为整数数据,称为分词

  • 分词可以分为三个步骤:标准化拆分索引。标准化对文本进行规范化,拆分将文本分解成词元,索引为每个词元分配一个唯一的整数 ID。

  • 分词主要分为三种类型:字符分词词分词子词分词。对于表达能力足够强且训练数据充足的模型,子词分词通常是最有效的。

  • 自然语言处理模型的主要区别在于处理输入词元的顺序:

    • 集合模型会忽略大部分顺序信息,仅基于输入中词元的有无来学习简单快速的模型。 二元三元模型会考虑两个或三个连续词元的有无。集合模型的训练和部署速度都非常快。
    • 序列模型试图从输入数据中有序的词元序列中进行学习。序列模型需要大量数据才能有效地学习。
  • 嵌入是一种将词元ID转换为可学习的潜在空间的有效方法。词嵌入通常可以使用梯度下降法进行训练。

  • 我们可以将寻找理想的分词器视为寻找理想的输入数据压缩方式。缩短词元长度(个人注:减少文本编码后的词元数量)可以压缩样本的整体长度。较小的词汇表可以减少表示每个词元所需的字节数。如果我们能够同时实现这两点,就能将简短而信息丰富的序列输入到深度学习模型中。

    压缩和分词(compression and tokenization)之间的这种类比并非一直显而易见,但事实证明它非常有效。过去十年自然语言处理研究中发现的最实用有效的技巧之一。

  • 如何表示词序是各种自然语言处理(NLP)架构的核心问题。最简单的做法是忽略词序,将文本视为无序的词集——这样就得到了词袋模型(bag-of-words)。也可以决定严格按照词出现的顺序逐个处理,就像时间序列中的步骤一样——这时就可以使用上一章提到的循环神经网络(RNN)模型。最后,还有一种混合方法:Transformer架构在技术上与词序无关,但它会将词的位置信息注入到处理的表示中,这使得它能够同时处理句子的不同部分(与RNN不同),同时仍然能够感知词序。由于RNN和Transformer都考虑了词序,因此它们都被称为序列模型。

  • 文本预处理的特殊之处在于它必须始终在 CPU 上运行。GPU 严格处理数值输入,因此所有分词都必须在 GPU 的训练步骤之前完成。一种方法是预先计算分词后的输入——分词不依赖于模型权重,因此您可以在开始训练之前对所有输入文本文件进行分词,并将其重新保存为整数序列。

  • 词嵌入 显然,使用独热编码将单词转换为向量(这是我们能做的最简单的事情)并不是一个好主意。还有更好的方法——词嵌入。

    当你使用独热编码对数据进行编码时,你实际上是在进行特征工程决策。你将一个关于特征空间结构的基本假设注入到模型中。这个假设是,你编码的不同词元彼此独立:实际上,独热向量彼此正交。但对于词语而言,这个假设显然是错误的。词语构成了一个结构化的空间:它们彼此共享信息。“movie”(电影)和“film”(影片)在大多数句子中可以互换使用,因此表示“movie”的向量不应该与表示“film”的向量正交——它们应该是同一个向量,或者至少非常接近。

    更抽象地说,两个词向量之间的几何关系应该反映这两个词之间的语义关系。例如,在一个合理的词向量空间中,同义词应该嵌入到相似的词向量中;一般来说,任意两个词向量之间的几何距离(例如余弦距离或L2距离)应该与这两个词之间的“语义距离”相关。含义不同的词应该彼此远离,而相关的词应该彼此靠近。

    词嵌入是词语的向量表示,它正是实现了这一点:将人类语言映射到结构化的几何空间。

    在现实世界的词嵌入空间中,有意义的几何变换的典型例子是“性别”向量和“复数”向量。例如,将“女性”向量添加到“国王”向量中,即可得到向量“女王”。添加“复数”向量,即可得到“国王们”。词嵌入空间通常包含数千个此类可解释且可能有用的向量。

    是否存在一个理想的词嵌入空间,能够完美映射人类语言并适用于任何自然语言处理(NPL)任务?或许存在,但我们尚未计算出这样的空间。此外,也不存在我们可以尝试映射的单一人类语言——语言种类繁多,彼此并不同构,因为语言反映了特定的文化和语境。更实际地说,一个好的词嵌入空间很大程度上取决于你的任务:一个用于英语电影评论情感分析模型的理想词嵌入空间,可能与一个用于英语法律文件分类模型的理想词嵌入空间截然不同,因为某些语义关系的重要性会因任务而异。

    因此,对于每个新任务,学习一个新的嵌入空间是合理的。幸运的是,反向传播使得这一点变得容易,而 Keras 则让这一切变得更加简单。关键在于学习 KerasEmbedding层的权重。

  • 训练词嵌入最直接的方法之一是连续词袋模型(Continuous Bag of Words)(CBOW)。[2]其思路是,在数据集中的所有文本上滑动一个窗口,不断尝试根据缺失单词左右两侧出现的单词来猜测它(图 14.6)。

  • 下一章我们将介绍Transformer模型。该模型在学习较长词序之间的依赖关系方面略胜一筹,但最关键的是,这些模型通常使用大量的英文文本进行训练,包括所有词序信息。这使得模型能够粗略地学习支配语言的语法模式的统计形式。正是这些围绕词序的统计模式,导致我们当前的LSTM模型由于数据限制而无法有效学习。

第十五章 语言模型和Transformer

  • Transformer 是一种用于文本建模问题的强大架构。

  • 沿用整数序列作为文本自然数值表示的概念。

  • 解决这类预测问题的实用方法是构建一个每次只预测单个词元输出的模型。语言模型 最简单的形式是学习一个简单而深刻的概率分布:p(token|past tokens)给定一个包含所有已观测词元的序列,语言模型会尝试输出一个关于所有可能出现的下一个词元的概率分布。一个包含 20,000 个词的词汇表意味着模型只需要预测 20,000 个输出,但通过 反复预测下一个词元,我们就能构建一个可以生成长文本序列的模型。

  • 翻译属于一类建模问题,通常被称为序列到序列建模。

  • 在开发实际的机器翻译系统时,必须更仔细地设计指标。有一些标准指标,例如 BLEU 分数,可以衡量机器翻译文本与一组高质量参考译文的相似度,并且可以容忍轻微的序列错位。

  • RNN方法在序列到序列学习方面存在一些根本性的局限性:

    • 源序列表示必须完全保存在编码器状态向量中,这大大限制了您可以翻译的句子的大小和复杂性。
    • RNN 难以处理非常长的序列,因为它们往往会逐渐忘记过去——当序列达到第 100 个标记时,关于序列的开头几乎没有信息了。
  • 在2010年代中期,循环神经网络(RNN)主导了序列到序列的学习。大约在2017年,谷歌翻译就采用了 LSTM类似我们刚才创建的架构,由七个大型层堆叠而成。然而,RNN的这些局限性最终促使研究人员开发了一种新型的序列模型,称为Transformer。

  • 2017 年,Vaswani 等人在开创性论文《Attention Is All You Need》中引入了 Transformer 架构。[1]作者们当时正在研究类似我们刚刚构建的翻译系统,而关键发现就体现在标题中。事实证明,一种名为注意力机制(mechanism called attention)的简单机制可以用来构建强大的序列模型,而这些模型完全不需要循环层。注意力机制的概念并不新鲜,在他们发表论文时,它已经在自然语言处理系统中应用了几年。但注意力机制如此有效,以至于可以作为传递序列信息的唯一机制,这在当时确实令人惊讶。

  • 注意力机制的核心思想是构建一种机制,使神经网络能够根据当前处理的输入,在上下文上赋予序列的某些部分更高的权重,而降低其他部分的权重(图15.3)

  • 不妨做一个思想实验:想象一下,用这本书来构建一个天气预报模型。如果你时间充裕,或许会通读全书,但当你真正开始实现模型时,你会特别关注时间序列相关的章节。即使在同一个章节内,你也可能会找到一些特定的代码示例和解释,并经常参考。另一方面,在编写代码时,你不会特别在意图像卷积的细节。这本书的总字数超过十万字,远远超过我们以往处理过的任何序列长度,但人类在从文本中提取信息时,往往会根据上下文进行选择理解(selective and contextual )。

  • 什么是Einsum符号?(What is Einsum notation?)

    在机器学习代码库中,你会经常看到类似这样的代码片段:np.einsum('ij,jk->ik', a, b)。这被称为Einsum 符号,即爱因斯坦求和符号的缩写。一旦你学会阅读它们,它们就能成为编写复杂数组运算的清晰方法。因此,你会在 Transformer 代码中经常看到它们。

  • 但是我们应该如何计算这种相关性得分呢?当研究人员最初研究注意力机制时,这个问题曾是一个重要的研究课题。事实证明,最直接的方法之一就是最佳方法。我们可以使用点积来简单地衡量目标向量和源向量之间的距离。如果源向量和目标向量彼此接近,我们就假设源标记与我们的预测相关。在本章末尾,我们将探讨为什么这个假设符合直觉。

  • 我们将使用不同的输入名称将其等效地写成sum(score(query, key) * value)。这种三参数版本更通用——在极少数情况下,您可能不希望使用同一个向量来对源输入进行评分,也不希望使用同一个向量来对源输入求和。

    这些术语源自搜索引擎和推荐系统。想象一下一个用于在数据库中查找照片的搜索工具——“查询”是你的搜索词,“键”是你用来与查询匹配的照片标签,“值”则是照片本身(图 15.6)。我们正在构建的注意力机制与这种查找方式大致类似。

  • 注意力机制能够使模型处理文本中原本GRU难以处理的长程依赖关系。事实上,这确实提升了 RNN 模型的性能,而注意力机制最初就是在 2010 年代中期被应用的。

    然而,《Attention is all you need》的作者们意识到,注意力机制可以更进一步,成为处理模型中所有序列数据的通用机制。虽然到目前为止,我们只将注意力机制视为处理两个序列之间信息传递的一种方式,但你也可以利用注意力机制让序列关注自身

    1
    multi_head_attention(key=source, value=source, query=source)

    这被称为自注意力机制( self-attention ),它非常强大。借助自注意力机制,每个词元可以关注自身序列中的每个词元,包括它自身,从而使模型能够学习到该词在上下文中的表示。

  • 注意力机制负责在序列中传递信息,而前馈网络则负责更新各个序列项的表示。

  • 本节表面上是关于序列模型的。在前一章中,我们看到了词序对语义的重要性。然而,我们刚刚构建的Transformer模型实际上并非序列模型。你注意到了吗?它由密集层和注意力层组成。密集层独立处理序列中的每个词元,而注意力层则将这些词元视为一个集合。你可以改变序列中词元的顺序,得到相同的成对注意力得分和相同的上下文感知表示。即使你完全重排每个英语源句子中的每个词,模型也不会察觉,你仍然会得到相同的准确率。注意力机制是一种集合处理机制,它关注的是序列元素对之间的关系——它并不关心这些元素出现在序列的开头、结尾还是中间。那么,为什么我们说Transformer是一个序列模型呢?如果它不考虑词序,又怎么可能适用于机器翻译呢?

    对于循环神经网络(RNN),我们依赖于层计算来感知顺序。而对于Transformer,我们则直接将位置信息注入到嵌入序列本身。这被称为位置嵌入。让我们来看一下。

  • 《注意力机制》的作者们使用了一种有趣的技巧来编码词的位置:他们在词嵌入中添加了一个向量,[-1, 1]该向量包含的值会根据词的位置循环变化(他们使用余弦函数来实现这一点)。这个技巧提供了一种方法,可以通过一个包含小值的向量来唯一地刻画大范围内的任何整数。这很巧妙,但实际上我们可以做更简单、更有效的事情:我们将以学习词索引嵌入的相同方式来学习位置嵌入向量。然后,我们将位置嵌入添加到相应的词嵌入中,从而得到一个位置感知的词嵌入。这被称为位置嵌入( positional embedding )。

  • 我们能从Transformer模型中学到很多经得起时间考验的东西。在本章末尾,我们将探讨Transformer模型如此高效的原因。但值得注意的是,机器学习领域整体上是经验驱动的。注意力机制源于增强循环神经网络(RNN)的尝试,经过无数人的多年摸索和验证,最终催生了Transformer模型。我们没有理由认为这个过程已经结束。

  • 为了预训练模型,我们取一段文本序列,并将大约 15% 的词元替换为一个特殊[MASK]词元。在训练过程中,模型会尝试预测原始掩码词元的值。经典的语言模型(有时也称为因果语言模型)尝试预测的是原始值,p(token|past tokens)而掩码语言模型则尝试预测的是 原始值p(token|surrounding tokens) While the classic language model, sometimes called a causal language model, attempts to predict p(token|past tokens), the masked language model attempts to predict p(token|surrounding tokens).

    这种训练方式是无监督的。你不需要为输入的文本添加任何标签;对于任何文本序列,你都可以轻松地选择一些随机标记并将其屏蔽掉。这使得作者能够轻松找到训练如此大规模模型所需的大量文本数据。他们主要从维基百科获取数据。

  • 在 KerasHub 中,骨干网络(Backbone)指的是任何尚未针对特定任务进行专门训练的预训练模型。我们刚刚加载的模型接收一个输入序列,并将其嵌入到形状为 的输出序列中(batch_size, sequence_length, 768),但它没有针对特定的损失函数进行设置。你可以将它用于任何下游任务——例如句子分类、识别包含特定信息的文本片段、词性识别等等。 我们将在这个主干系统上添加一个分类头,使其专门用于我们对 IMDb 影评分类的微调。你可以把它想象成给螺丝刀装上不同的刀头:十字头用于一种任务,一字头用于另一种任务。

  • 一种方法是对整个序列进行均值池化或最大池化,计算所有标记向量的平均值。但效果稍好一些的方法是直接使用第一个标记的表示作为池化值。这是因为我们模型中注意力机制的特性——最终编码器层的第一个位置能够关注序列中的所有其他位置并从中提取信息。因此,注意力机制允许我们根据序列的上下文信息进行池化,而不是像取平均值那样使用粗略的方法。

  • 2013年,在谷歌,托马斯·米科洛夫和他的同事们注意到了一些非凡的现象。他们正在构建一个名为“Word2Vec”的预训练词嵌入模型,类似于我们在上一章中构建的连续词袋模型(CBOW)。与我们的CBOW模型类似,他们的训练目标是将词语之间的相关性转化为词嵌入空间中的距离关系:词汇表中的每个词都关联一个向量,并且这些向量经过优化,使得表示频繁共现词的向量之间的点积(余弦邻近度)更接近1,而表示不常共现词的向量之间的点积更接近0。

    他们发现,由此产生的嵌入空间远不止捕捉语义相似性那么简单。它展现了一种涌现式学习(emergent learning)——一种类似“词语算术”的能力。在这个空间中存在一个向量,你可以将它添加到许多男性名词上,从而得到一个接近其女性对应词的点,例如 V(king) - V(man) + V(woman) = V(queen),这是一个性别向量。这相当令人惊讶;该模型并没有针对此进行任何显式训练。似乎存在数十个这样的神奇向量——复数向量、将野生动物名称映射到其最接近的宠物名称的向量等等。

    快进十年——我们现在进入了大型预训练Transformer模型的时代。表面上看,这些模型与原始的Word2Vec模型截然不同。Transformer可以生成流畅自然的语言——这是Word2Vec完全无法做到的。正如我们将在下一章中看到的,这类模型似乎对几乎任何主题都了如指掌。然而,它们实际上与经典的Word2Vec有很多共同之处。

    两种模型都试图将词元(单词或子词)嵌入到向量空间中。它们都基于相同的基本原理来学习这个空间:同时出现的词元在嵌入空间中会彼此靠近。两种模型都使用余弦距离来比较词元。甚至嵌入空间的维度也相似:每个词元都用一个维度在 1000 到 10000 之间的向量来表示。

    此时你可能会插话:Transformer 的训练目的是预测序列中缺失的词,而不是将词元分组到嵌入空间中。语言模型的损失函数与 Word2Vec 最大化共现词元点积的目标有何关系?答案是注意力机制。

    注意力机制无疑是Transformer架构中最关键的组成部分。它通过线性重组先前空间中的词嵌入来学习新的词嵌入空间,并以加权组合的方式赋予彼此“更接近”(即点积更高)的词更大的权重。它会将原本就接近的词的向量聚集在一起,最终形成一个词相关性转化为嵌入邻近性(以余弦距离衡量)的空间。Transformer的工作原理是学习一系列逐步细化的嵌入空间,每个空间都基于对前一个空间元素的重组。

    注意力机制为Transformer提供了两个关键特性:

    • 它们学习到的嵌入空间在语义上是连续的——也就是说,在嵌入空间中移动一个位,只会改变相应词元的人类可理解含义一个位。Word2Vec空间也展现了这一特性。
    • 它们学习到的嵌入空间是语义插值的——也就是说,在嵌入空间中取两个点之间的中间点,就能得到一个代表对应词元之间“中间含义”的点。这是因为每个新的嵌入空间都是通过对前一个空间中的向量进行插值构建的。
  • 你可以把Transformer看作类似于数据库:它存储着你可以通过传入的令牌检索的信息。但是Transformer和数据库之间有两个重要的区别。

    • 首先,Transformer 是一种连续的、可插值的数据库。它并非将数据存储为一组离散的条目,而是将其存储为一个向量空间——一条曲线。你可以在这条曲线上移动(正如我们之前讨论的,它在语义上是连续的),探索附近相关的点。你还可以对不同数据点进行插值,找到它们的中间状态。这意味着你可以从数据库中检索到比输入更多的信息——尽管并非所有信息都准确或有意义。插值可以带来泛化能力,但也可能导致“幻觉”——这是当今训练的生成式语言模型面临的一个重大问题。

    • 第二个区别在于,Transformer 模型不仅仅包含数据。对于像 RoBERTa 这样的模型来说,它基于从互联网抓取的数十万份文档进行训练,因此包含大量数据:事实、地点、人物、日期、事物和关系。但它同时也是一个程序数据库——或许它最重要的功能就是程序。

  • 请注意,它们与您通常接触的程序有所不同。它们不像 Python 程序那样——一系列符号语句逐步处理数据。相反,这些向量程序是高度非线性的函数,它们将潜在嵌入空间映射到自身,类似于 Word2Vec 的“魔法向量”,但要复杂得多。

    在下一章中,我们将把Transformer模型推向一个全新的规模。这些模型将使用数十亿个参数,并在数万亿个单词上进行训练。这些模型的输出常常令人感觉神奇——仿佛有一个智能操作员坐在模型内部,操控着一切。但重要的是要记住,这些模型本质上是插值模型——由于注意力机制的存在,它们学习了一个包含大量英语文本的插值嵌入空间。探索这个嵌入空间可能会带来一些有趣且意想不到的泛化结果,但它无法合成出任何接近真正人类智能的全新事物。

第十六章 文本生成

  • 从实际意义上讲,人工智能远未达到能与人类编剧、画家或作曲家匹敌的程度。但取代人类并非必要,也不应该成为人工智能的目标。在许多领域,尤其是在创意领域,人们会利用人工智能来增强自身能力——与其说是人工智能,不如说是增强智能。( more augmented intelligence than artificial intelligence )

  • 潜在空间采样可以成为艺术家的画笔,增强我们的创造力,并拓展我们的想象空间。它甚至可以消除对技术技巧和练习的需求,使艺术创作更加普及——建立起一种纯粹表达的新媒介,将艺术与技艺区分开来。

    It can even make artistic creation more accessible by eliminating the need for technical skill and practice—setting up a new medium of pure expression, factoring art apart from craft.借助电子计算机,作曲家就像一位领航员:他按下按钮,输入坐标,操控着一艘宇宙飞船在声音的空间中航行,穿越他过去只能在遥远梦境中瞥见的音响星座和星系。

    With the aid of electronic computers the composer becomes a sort of pilot: he presses the buttons, introduces coordinates, and supervises the controls of a cosmic vessel sailing in the space of sound, across sonic constellations and galaxies that he could formerly glimpse only as a distant dream.

  • 作者们证明,这种预训练模型可以进行微调,从而在各种文本分类任务上取得最先进的性能——从衡量两个句子的相似度到回答多项选择题。他们将这种预训练模型命名为GPT,即生成式预训练 Transformer 的缩写( Generative Pretrained Transformer.)。

    GPT并没有带来任何建模或训练方面的改进。有趣的是,这种通用的训练方案在许多任务上都能胜过更复杂的技术。它无需复杂的文本归一化,也无需针对每个基准测试定制模型架构或训练数据,只需要大量的预训练数据和计算资源。

  • 这种设置称为少样本(few-shot learning)学习,它尝试仅使用少量监督示例来教模型解决一个新问题——对于标准梯度下降来说,示例数量太少了。

  • 原始的 GPT 模型简化了我们在上一章看到的序列到序列 Transformer 模型。与我们翻译模型中需要编码器和解码器来处理源序列和目标序列不同,GPT 方法完全摒弃了编码器,只使用解码器。这意味着信息只能在序列中从左到右传递。

    这是GPT开发者的一个有趣尝试。仅解码器模型仍然可以处理序列到序列的问题,例如问答。然而,我们不再将问题和答案作为单独的输入,而是必须将它们合并成一个单一的序列才能输入到模型中。因此,与原始Transformer不同,问题标记和答案标记的处理方式完全相同。所有标记都被嵌入到同一个潜在空间中,并使用相同的参数集。

    这种方法的另一个后果是,即使对于输入序列,信息流也不再是双向的。给定一个输入,例如“法国的首都在哪里?”,学习到的“在哪里”一词的表示无法在注意力层中同时关注“首都”和“法国”这两个词。这限制了模型的表达能力,但在预训练的简易性方面却具有巨大的优势。我们无需精心构建包含成对输入输出的数据集;所有内容都可以是单个序列。我们可以大规模地训练任何在互联网上找到的文本。

  • 幻觉和不可控的输出(Hallucinations and uncontrollable output)是语言模型的根本问题。如果存在万全之策,我们至今尚未找到。然而,一种非常有帮助的方法是,使用你期望的特定类型生成输出的示例来进一步微调模型。

    如果要构建一个能够执行指令的聊天机器人,这种训练方式就叫做指令微调(instruction fine-tuning)。让我们用 Gemma 做一些指令微调,让她作为对话伙伴更加得心应手。 通过使用包含预期响应的示例进行进一步训练,我们实际上是在引导模型的输出朝着我们想要的方向发展。我们在这里不会学习语言的潜在空间;这已经在数万亿个词元的预训练中完成了。我们只是对学习到的表征进行一些微调,以控制输出的语气和内容。

  • 不过,我们仍然可以利用指令调优来取得一些进展。一种常见的技巧是使用大量的指令/响应对来训练模型,其中期望的响应是“是”或"I don't know"“否” "As a language model, I cannot help you with that"。这可以训练模型避免尝试回答某些特定主题,因为在这些主题上它往往会给出质量较差的结果。

  • 本书不会深入探讨强化学习的细节,但请不要被这个术语吓到——它指的是任何一种训练设置,在这种设置中,深度学习模型通过做出预测(称为动作)并获得关于这些预测的反馈(称为 奖励)来学习。简而言之,模型自身的预测就成为了它的训练数据。

  • 将 Transformer 模型扩展到不同模态的方法在概念上很简单。Transformer 并非文本专用模型;它是一种高效的序列数据模式学习模型。如果我们能够找到将其他数据类型强制转换为序列表示的方法,就可以将该序列输入 Transformer 模型并进行训练。

  • 这类模型的总称是基础模型(foundation models)更具体地说,基础模型是指任何基于广泛数据(通常使用大规模自监督)训练的模型,它可以针对各种下游任务进行微调。

  • 这是机器学习漫长发展历程中近期发生的一项重要且引人注目的转变。与其从零开始训练模型来处理你的数据集,通常情况下,使用基础模型来获取输入(无论是图像、文本或其他类型)的丰富表征会更好,然后针对最终的下游任务对该模型进行专门化处理。

  • 检索增强生成(Retrieval Augmented Generation (RAG))

    检索与生成(实际问答)

    1. 用户提问:用户输入问题。
    2. 问题向量化:把用户的问题也转换成一个向量。
    3. 相似度检索 (Retrieval):在数据库里找和问题向量“距离最近”的几个文字块。
    4. 注入上下文 (Augmentation)把找回来的文字块和原始问题拼接在一起,做成一个超长的 Prompt。
    5. 模型输出 (Generation):大模型阅读这些参考资料,给出一个有理有据的回答。
  • “推理”模型(“Reasoning” models) 2023年,谷歌的研究人员发现,如果你用一些数学题的“展示解题步骤”的例子来引导模型——就像做作业一样把解题步骤写出来——模型也会开始模仿。当模型模仿写出中间步骤时,它会更加关注自己的输出,从而更快地找到正确答案。他们将这种方法称为“思维链(chain-of-thought)”引导,这个名称沿用至今。另一组研究人员发现,甚至不需要例子;你只需用“让我们一步一步地思考”这句话来引导模型,就能获得更好的输出。

  • 这种循序渐进的微调方法与RLHF非常相似。首先,我们会用一些监督学习的例子来训练模型,这些例子要求学习者“展示解题步骤”并得出正确答案。接下来,我们会给模型一个新的数学题,并检查模型是否给出了正确的答案。最后,我们会利用这些新生成的输出来进一步调整模型的权重。

  • 我们可能无法盲目地扩展这些模型,还有另一个原因:预训练数据开始告罄!科技公司越来越难以找到更多高质量、公开的、由人类撰写的内容用于预训练。模型甚至开始“自相矛盾”,大量使用其他语言学习模型(LLM)创建的内容进行训练,这又引发了一系列新的问题。这也是强化学习近期备受关注的原因之一。如果你能创建一个具有挑战性的、自包含的环境,为语言学习模型生成新的问题,你就找到了一种利用模型自身输出继续训练的方法——无需再费力地在网络上搜寻更多优质文本素材。

  • LoRA 是一种通过冻结大多数 Transformer 参数并仅更新注意力投影权重的低秩分解来减少内存使用量的技术。

第十七章 图像生成

  • 当今最流行、最成功的创意人工智能应用是图像生成:学习潜在的视觉空间并从中采样,从而创建全新的图像,这些图像是从真实图像中插值而来的——虚构的人物、虚构的地点、虚构的猫狗等等。

  • 图像生成相关的高级概念,以及该领域两种主要技术——变分自编码器variational autoencoders)(VAE)和扩散模型diffusion models)。

  • 图像生成的核心思想是构建一个低维的潜在表征空间(与深度学习中的其他一切一样,它是一个向量空间),其中任何一点都可以映射到一幅“有效”图像:一幅看起来像真实物体的图像。能够实现这种映射的模块,以潜在点作为输入并输出图像(像素网格),通常被称为生成器,有时也称为解码器。一旦学习到这样的潜在空间,就可以从中采样点,并通过将它们映射回图像空间,生成以前从未见过的图像(参见图 17.1)——即训练图像的中间状态。

  • 此外,文本条件化使得将自然语言提示空间映射到潜在空间成为可能(见图17.2),从而可以进行 语言引导的图像生成——生成与文本描述相对应的图片。这类模型被称为文本到图像模型。

    Further, text-conditioning makes it possible to map a space of prompts in natural language to the latent space (see figure 17.2), making it possible to do language-guided image generation—generating pictures that correspond to a text description. This category of models is called text-to-image models.

    通过对潜在空间中大量训练图像进行插值,这类模型能够生成无限多种视觉概念组合,其中许多组合甚至是前所未有的。

  • 图像去噪领域的早期成功让研究人员产生了一个引人注目的想法:既然可以使用自编码器去除图像中的少量噪声,那么肯定可以通过循环多次重复该过程来去除大量噪声。最终,我们能否对完全由噪声组成的图像进行去噪呢?

    事实证明,确实可以。通过这种方式,你可以凭空创造出全新的图像,如图 17.7 所示。这就是扩散模型背后的关键原理,更准确地说,应该称之为反向扩散模型,因为“扩散”指的是逐渐向图像添加噪声,直到图像最终消失的过程。 扩散模型本质上是一个循环的去噪自编码器,能够将纯噪声转化为清晰逼真的图像。你或许听过米开朗基罗的这句名言:“每一块石头里都藏着一座雕像,雕塑家的任务就是把它发现出来(Every block of stone has a statue inside it and it is the task of the sculptor to discover it)”——同样,每一块白噪声里都藏着一幅图像,扩散模型的任务就是把它发现出来。

  • 这比我们之前训练的花朵去噪器更胜一筹。模型不再学习如何在没有任何额外信息的情况下去除图像噪声,而是可以利用最终图像的文本表示来指导去噪过程。

    训练完成后,事情就变得更有趣了。因为我们已经训练了一个模型,它能够根据文本的矢量表示将纯噪声映射到图像,所以现在我们可以输入纯噪声和一个从未见过的提示信息,并将其去噪后得到提示信息对应的图像。

    在使用扩散模型时,有些问题是不可避免的。例如,要真正画出一个穿着宇航服的人坐在纸做的大象上,需要一定的解剖学和物理学知识,而我们的模型恰恰缺乏这些知识。模型会尽力根据训练数据插值生成输出,但它对试图表示的物体本身并没有真正的理解。

  • VAE能够生成高度结构化、连续的潜在空间表征。因此,它们非常适合在潜在空间中进行各种图像编辑:例如换脸、将皱眉的脸变成微笑的脸等等。

  • 此类文本到图像扩散模型学习到的视觉潜在空间本质上是插值的。这一点可以通过对用作扩散过程输入的文本嵌入进行插值,并在输出图像之间实现平滑插值来验证。

第十八章 现实世界的最佳实践

  • 超参数优化(Hyperparameter optimization)

    而更新超参数则面临着独特的挑战。请考虑以下几点:

    • 超参数空间通常由离散决策构成,因此它既不连续也不可微。所以,你通常无法在超参数空间中使用梯度下降法。相反,你必须依赖无梯度优化技术,而这些技术的效率自然远低于梯度下降法。
    • 计算此优化过程的反馈信号(这组超参数是否能使模型在此任务上表现优异?)可能非常昂贵:它需要从头开始在您的数据集上创建和训练一个新模型。
    • 反馈信号可能存在噪声:如果一次训练运行的性能提高了 0.2%,是因为模型配置更好,还是因为初始权重值比较理想?
  • 有了自动调优,你不再是一个‘调参工人’(天天纠结该选 128 还是 256),而变成了一个‘架构设计师’(思考模型的骨架该怎么搭)。那些细微的数字交给算法去跑,你来决定模型的大方向。

  • 模型集成(Model ensembling) 集成学习成功的关键在于分类器集合的多样性(diversity)。多样性就是力量。如果所有盲人摸象都只摸到象鼻,他们就会认为大象像蛇,永远无法了解大象的真相。多样性正是集成学习成功的关键。用机器学习的术语来说,如果所有模型都存在相同的偏差,那么集成模型也会保留这种偏差。如果模型存在 不同的偏差,这些偏差就会相互抵消,集成模型就会更加稳健、更加准确。

  • 随机森林(Random Forest)和梯度提升树(Gradient Boosting Decision Tree, GBDT)是机器学习中表现最稳健的两大“集成学习”算法。虽然它们都由决策树组成,但它们的底层哲学完全不同。

  • 随机森林的核心思想是“并行集成(Bagging)”。它的目标是通过“群体智慧”来降低单个模型的误差(方差)。

    核心逻辑

    1. 随机采样(Bootstrap):从原始数据中有放回地抽取多份不同的子集。
    2. 特征随机:在构建每一棵决策树时,只随机选取一部分特征(属性),而不是全部特征。
    3. 独立生长:让成百上千棵决策树互不干扰地生长。
    4. 多数表决:对于分类任务,每棵树投一票,得票最多的类别为最终结果。
  • 梯度提升树的核心思想是“串行集成(Boosting)”。它的目标是通过“不断迭代”来减少模型与真实值之间的差距(偏差)。

    核心逻辑

    1. 起步:先建立第一棵非常简单的树(通常表现很差)。
    2. 计算残差(Residual):计算这棵树的预测值与真实值之间的差距(即“错误在哪里”)。
    3. 针对性改进:建立第二棵树,这棵树不负责预测原始目标,而是专门负责预测第一棵树留下的残差
    4. 累加迭代:将新树的结果加到旧模型上,再计算新的残差,循环往复。
  • 了解浮点精度(Understanding floating-point precision)精度之于数字,正如分辨率之于图像。

  • 关于浮点数的一个反直觉的事实是,可表示的数字并非均匀分布。较大的数字精度较低:There’s the same number of representable values between 2 ** N and 2 ** (N + 1) as there is between 1 and 2, for any N.

  • 因此,将数字转换为浮点表示时产生的数值误差会因所考虑的具体值而异,并且对于绝对值较大的数字,误差往往会更大。

    理解浮点数分辨率的方法是,看它能安全处理的两个任意数字之间的最小距离。单精度浮点数的最小距离约为 1e-7,双精度浮点数约为 1e-16,而半精度浮点数的最小距离仅为 1e-3。

第十九章 人工智能的未来

  • 深度学习的局限性

    • 大语言模型难以适应新事物。 大语言学习模型解决特定问题的能力与问题的复杂性无关,而与熟悉程度(familiarity)密切相关——任何足够新颖的问题,无论多么简单,它们都会束手无策。
    • 大语言模型对措辞和其他干扰因素高度敏感。 高维空间的跨越:在图像的高维空间里,虽然像素只动了一点点,但这个点已经跨越了模型脆弱的分类决策边界。人类视觉也会被攻击。视错觉图:有些精心设计的图案(如著名的“旋转舞者”或“不可能的图形”),本质上就是针对人类大脑视觉系统的“对抗样本”。
    • 大语言模型难以学习可泛化的程序。 大语言模型即使学习了数百万个示例,也无法最终掌握精确的加法算法,原因在于它本质上只是一系列简单的、连续的几何变换,将一个向量空间映射到另一个向量空间。这种模型非常适合感知模式识别,但却不适合编码任何类型的离散逻辑步骤,例如位值或进位等概念。目前的大模型处理数学题的现状可以泛化为:“能借外力(代码)就借外力;不能借外力就靠拆解步骤;实在不行就靠‘死记硬背’加上一点高维插值的运气。” 正如你引用的内容所说,如果只让模型“凭直觉”脱口而出,它们在本质上依然是脆弱的统计模拟器,而非逻辑处理器。
    • 将机器学习模型拟人化的风险。 人类的一个基本特征是 心智理论theory of mind):我们倾向于将意图、信念和知识投射到周围的事物上。例如,在石头上画个笑脸,在我们看来,它就“快乐”了。作为机器学习从业者,务必牢记这一点,切勿陷入“神经网络理解它们所执行的任务”的误区——它们并不理解,至少无法以我们能够理解的方式理解。
  • 自动机与智能体(Automatons vs. intelligent agents)。大语言模型从输入到输出的直接几何变换与人类的思维和学习方式存在根本差异。这不仅仅是因为人类是通过自身体验而非接受明确的训练示例来学习。人脑与可微参数函数相比,完全是两码事。

  • 自动装置和真正的智能体之间究竟有何不同?

    • 局部泛化与极端泛化(Local generalization vs. extreme generalization) 这种运用抽象思维和推理能力来应对我们始料未及的经历的能力,是人类认知能力的本质特征。我称之为 极端泛化( extreme generalization ):一种仅凭少量数据甚至完全没有新数据,就能适应全新、从未经历过的情况的能力。这种能力是人类和高等动物展现智能的关键所在。 然而,深度神经网络的泛化能力仅限于我所说的 局部泛化(local generalization)(见图 19.6):当输入开始偏离网络在训练时所见的内容时,深度神经网络执行的输入到输出的映射很快就会失效。深度神经网络只能泛化到 已知的未知情况,即模型开发过程中预先设想并在训练数据中广泛存在的变异因素,例如宠物照片的不同拍摄角度或光照条件。这是因为深度神经网络通过流形上的插值进行泛化(回顾第五章):输入空间中的任何变异因素都需要被它们学习到的流形所捕捉。因此,基础数据增强对于提升深度神经网络的泛化能力至关重要。与人类不同,这些模型无法在数据匮乏或完全没有数据的情况下进行即兴发挥。
  • 智能的本质 它是一种能够高效利用现有信息,在充满不确定性和瞬息万变的未来中做出成功决策的能力。笛卡尔所谓的“理解”正是这种卓越能力的关键:它能够挖掘过往经验,构建模块化、可复用的抽象概念,并能快速将其应用于应对新情况,实现高度的泛化能力。

  • 如何培养智力(How to build intelligence) 我称之为万花筒假说:我们对世界的体验似乎充满了难以置信的复杂性和永无止境的新奇感,但在这片复杂海洋中,万物又彼此相似。描述你所生活的宇宙所需的独特意义原子数量相对较少,而你周围的一切都是这些原子的重组:几个种子,无穷无尽的变化,就像万花筒内部的运作一样,几颗玻璃珠在镜面系统的反射下,呈现出丰富多彩、看似无穷无尽的图案(见图19.7)。

  • 智能的本质:抽象思维的习得与重组。

    该过程包含两个主要部分:

    • 抽象获取Abstraction acquisition)——从经验流或数据流中高效提取简洁、可重用的抽象概念。这涉及识别底层结构、原则或不变式。
    • 即时重组On-the-fly recombination)——以新颖的方式高效地选择和重组这些抽象概念,以模拟新的问题和情况,即使是与过去经验相去甚远的问题和情况。
  • 经典深度学习范式存在两大主要问题的根源:

    • 这些模型完全缺乏动态重组能力。它们在训练阶段通过梯度下降法能够很好地获取抽象概念,但由于设计上的缺陷,它们在测试阶段完全无法重组已有的信息。它们的行为就像一个静态的抽象数据库,功能仅限于检索。它们缺失了关键信息的一半——而这恰恰是最重要的一半。
    • 它们效率极低。梯度下降法需要海量数据才能提炼出简洁的抽象概念——比人类需要的数据量要多几个数量级。
  • 设定正确目标的重要性。

    那就是捷径法则(shortcut rule):如果你专注于优化某个成功指标,你或许能实现目标,但代价是牺牲系统中所有未被该指标涵盖的部分。最终,你会走上所有可能的捷径。你的创造物是由你给自己设定的激励机制塑造的。

    这种情况在机器学习竞赛中屡见不鲜。2009 年,Netflix 举办了一项挑战赛,承诺向在电影推荐任务中得分最高的团队颁发 100 万美元的奖金。最终,Netflix 从未采用过获胜团队开发的系统,因为它过于复杂且计算量巨大。获胜团队只优化了预测准确率——这也是他们获得奖励的目标——却牺牲了系统的其他所有重要特性:推理成本、可维护性和可解释性。这条捷径法则在大多数 Kaggle 竞赛中也同样适用——Kaggle 获胜团队开发的模型几乎从未被实际应用于生产环境。

  • 测试时自适应(test-time adaptation)(TTA)

    2023年盛行的“规模就是一切”的信条开始让位于“实际上,我们需要的是动态重组”。2024年12月公布的竞赛结果令人瞩目:领先的解决方案并非简单地扩展现有的深度学习架构,而是全部采用了某种形式的测试时自适应(test-time adaptation)(TTA)——无论是测试时搜索还是测试时训练。

    TTA 指的是人工智能系统在测试过程中利用所提供的具体问题信息进行主动推理或学习的方法——这是经典深度学习范式所缺乏的关键组成部分。

  • 实现测试时自适应有多种方法:

    • 测试时训练Test-time training)——该模型根据测试任务中给出的示例,使用梯度下降法调整其一些参数。
    • 搜索方法Search methods)——系统在测试时会搜索许多可能的推理步骤或潜在解决方案,以找到最佳方案。这可以通过自然语言(思维链合成)或在符号化的、可验证的程序空间(程序合成)中完成。
  • 缺失的要素:搜索和符号(The missing ingredients: Search and symbols)

  • 抽象的两极(The two poles of abstraction)

    抽象概念的习得始于对事物的比较。至关重要的是,比较事物有两种截然不同的方式,由此衍生出两种不同的抽象概念和两种思维模式,每一种都更适合解决不同类型的问题。这两种抽象概念共同构成了我们所有思维的基础。

    将事物联系起来的第一种方法是相似性比较,它产生了以价值为中心的类比(value-centric analogies。第二种方法是精确的结构匹配,它产生了以程序为中心的类比(或以结构为中心的类比)(program-centric analogies (or structure-centric analogies))。在这两种情况下,你都从事物的实例出发,并将相关的实例合并在一起,从而生成一个抽象概念,该概念捕捉了底层实例的共同元素。不同之处在于如何判断两个实例之间的关联,以及如何将实例合并成抽象概念。

  • 以价值为中心的类比(Value-centric analogy)

    假设你在后院遇到了许多不同种类的甲虫,它们分属不同的物种。你会注意到它们之间存在相似之处。有些甲虫彼此更相似,有些则不太相似:相似性的概念隐含着一个平滑的连续距离函数,它定义了一个潜在流形,你的甲虫实例就存在于这个流形中。当你观察了足够多的甲虫后,就可以开始将更相似的实例聚类在一起,并将它们合并成一组原型,这些原型捕捉了每个聚类的共同视觉特征(图 19.12)。这些原型是抽象的:它们看起来不像你见过的任何特定实例,尽管它们编码了所有实例共有的属性。当你遇到一只新的甲虫时,你不需要将它与之前见过的每一只甲虫进行比较才能知道该如何处理它。你只需将它与你已有的几个原型进行比较,找到最接近的原型——即这只甲虫所属的类别——并用它来做出有用的预测:这只甲虫有可能咬你吗?它会吃你的苹果吗? 这几乎就是对无监督机器学习(例如 K-means 聚类算法)工作原理的描述。总的来说,所有现代机器学习,无论是否采用无监督方法,其工作原理都是学习描述实例空间的潜在流形,这些实例空间通过原型进行编码。(还记得你在第 10 章中可视化的卷积神经网络特征吗?它们就是可视化的原型。)以值为中心的类比正是大语言模型能够进行局部泛化的关键所在。

  • 以程序为中心的类比(Program-centric analogy)

    至关重要的是,认知远不止于价值中心类比所能实现的那种即时、粗略、直觉式的分类。还有另一种抽象生成机制,它速度较慢、精确且深思熟虑:程序中心(或结构中心)类比( program-centric (or structure-centric) analogy )。

    在软件工程中,你经常会编写一些看似有很多共同点的不同函数或类。当你注意到这些冗余时,你会开始思考:是否存在一个更抽象的函数来执行相同的任务,并且可以重复使用两次?是否存在一个抽象基类,你的两个类都可以继承自它?这里你使用的抽象定义对应于以程序为中心的类比。你并非试图通过比较类和函数的外观相似度(就像通过隐式距离函数比较两张人脸一样)来比较它们。相反,你感兴趣的是它们是否存在结构完全相同的部分。你正在寻找所谓的子图同构(参见图 19.13):程序可以表示为运算符图,而你试图找到在不同程序中完全共享的子图(程序子集)。 这种通过在不同离散结构中建立精确的结构匹配来进行类比的方法,并非计算机科学或数学等专业领域所独有——你其实一直在不知不觉中使用它。它是推理规划以及严谨性(而非直觉)这一概念的 基础。任何时候,当你思考通过离散关系网络(而非连续相似性函数)相互连接的对象时,你就是在运用以程序为中心的类比。

  • 认知是两种抽象思维的结合

  • 我们所做的一切,我们所想的一切,都是这两种抽象方式的结合。你很难找到只涉及其中一种的任务。即使是看似“纯粹感知”的任务,例如识别场景中的物体,也包含相当多的关于你所观察物体之间关系的隐性推理。即使是看似“纯粹推理”的任务,例如证明一个数学定理,也包含大量的直觉。当数学家提笔作答时,他们心中已经对前进的方向有了大致的构想。他们为达成目标而采取的离散推理步骤,是由高层次的直觉引导的。

    这两个极端相辅相成,正是它们的交织融合才使得极端泛化成为可能。任何思维都离不开这两者。

  • 为什么深度学习并不能完全解决抽象生成问题

    深度学习非常擅长编码以价值为中心的抽象概念,但它基本上不具备生成以程序为中心的抽象概念的能力。类人智能是这两种抽象概念紧密交织的产物,因此我们实际上缺失了所需能力的一半——可以说是最重要的一半。 因此,我们不太可能看到一种方法能够将推理问题简化为流形插值,或者将感知问题简化为离散推理。人工智能的未来发展方向是开发一个统一的框架,将这两种 抽象生成方式融合在一起。

  • 人工智能的另一种方法:程序合成

    TTA的一个特别有前景的分支是程序合成——这个领域目前仍然非常小众,但我预计它将在未来几十年内蓬勃发展。这与机器学习非常相似:给定以输入-输出对形式提供的训练数据,我们可以找到一个能够将输入与输出匹配并能泛化到新输入的程序。不同之处在于,我们不是学习硬编码程序(神经网络)中的参数值,而是通过离散搜索过程生成源代码(见表 19.2)。

  • 融合深度学习和程序合成:

    • 将深度学习模块和算法模块集成到混合系统中 对于AlphaGo和自动驾驶汽车这两个系统而言,正是人类编写的离散程序与学习到的连续模型相结合,才使得它们能够达到单独使用任何一种方法都无法企及的性能水平,例如端到端的深度神经网络或不包含机器学习元素的软件。目前,此类混合系统的离散算法元素仍需由人类工程师精心硬编码。但未来,此类系统或许能够完全自主学习,无需任何人为干预。
    • 利用深度学习指导程序搜索 深度学习可以帮助程序合成实现同样的目标:尽管我们想要生成的每个特定程序本质上可能是一个离散对象,执行非插值数据操作,但目前的证据表明,所有有用程序的空间可能非常像一个连续流形。这意味着,经过数百万次成功程序生成案例训练的大语言模型,可能会开始对 程序空间中的搜索路径形成清晰的直觉,从而确定从规范到相应程序的搜索过程——就像软件工程师可能对他们即将编写的脚本的整体架构以及他们应该使用的中间函数和类(作为通往目标的垫脚石)有直接的直觉一样。、
  • 自动代码生成的原理,就是把一个极其复杂的、离散的逻辑搜索问题,转化为了一个在高维连续空间里的路径预测问题。

    模型是一个“高维插值数据库”,现在的代码生成就是在这个数据库里,根据你的注释作为起始坐标,插值出通往运行成功的代码路径。

  • 模块化组件重组和终身学习 为了解决组合泛化问题,我们需要重用健壮的程序组件,例如人类编程语言中的函数和类。这些组件将专门针对新环境中的模块化重用而演化——这与语言学习模型记忆的模式截然不同。我们的人工智能将根据当前任务动态地重新组合这些组件,从而合成新的程序。至关重要的是,这些可重用组件库将基于所有人工智能实例的累积经验构建,并永久供所有人访问。我们的人工智能遇到的任何问题都只需解决一次——这使得它们能够不断自我改进。

第二十章 结论

  • 我对深度学习尤其乐观的原因之一是,即使未来十年我们不再取得任何技术进步,将现有算法应用于所有适用问题也将对大多数行业带来颠覆性的变革。

  • 深度学习最令人惊讶的地方在于它的简单性。十五年前,没人会想到我们能用梯度下降法训练的简单参数模型,在机器感知和自然语言处理问题上取得如此惊人的成果。而现在看来,你只需要足够大的参数模型,并用梯度下降法在足够多的样本上进行训练即可。正如费曼曾经形容宇宙那样:“它并不复杂,只是很大。 ” [1]( As Feynman once said about the universe, “It’s not complicated, it’s just a lot of it.” )

  • 在深度学习中,一切皆向量;也就是说,一切皆几何空间中的一个点。模型输入(文本、图像等)和目标首先被向量化——分别转换为初始输入向量空间和目标向量空间。深度学习模型中的每一层都对其输入的数据执行一个简单的几何变换。模型中的所有层共同构成一个复杂的几何变换,该变换又可分解为一系列简单的变换。这个复杂的变换试图将输入空间逐点映射到目标空间。该变换由各层的权重参数化,权重会根据模型的当前性能进行迭代更新。

  • 将这种复杂的几何变换应用于输入数据的整个过程可以用三维可视化的方式呈现:想象一个人试图展开一个纸团,这个纸团就是模型初始的输入数据流形。人对纸团的每一个动作都类似于对一层数据进行简单的几何变换。完整的展开动作序列就是整个模型的复杂变换。深度学习模型是用于展开高维复杂数据流形的数学机器。

    这就是深度学习的魅力所在——将意义转化为向量,转化为几何空间,然后逐步学习将一个空间映射到另一个空间的复杂几何变换。你只需要足够高维的空间,就能捕捉原始数据中所有关系的全部内涵。

  • 关键网络架构(Key network architectures)

    读完本书后,您应该熟悉的网络架构类型包括:密集连接网络卷积网络循环网络扩散模型Transformer模型。每种模型都针对特定的数据模态:网络架构编码了 关于数据结构的假设——一个假设空间,寻找合适模型的过程就在这个空间中进行。特定架构能否解决特定问题,完全取决于数据结构与网络架构假设的匹配程度。

  • 密集连接的网络(Densely connected networks)

    密集连接网络是由 Dense多层网络堆叠而成,用于处理向量数据(其中每个样本都是一个数值或类别属性的向量)。这类网络不预设输入特征的特定结构:之所以称为 密集连接,是因为每一层的所有单元都Dense与其他所有单元相连。该层试图映射任意两个输入特征之间的关系;这与二维卷积层不同,后者仅关注局部关系。 密集连接网络最常用于分类数据(例如,输入特征为属性列表的数据),例如第 4 章中使用的波士顿房价数据集。它们也常被用作大多数网络的最终分类或回归阶段。例如,第 8 章介绍的卷积神经网络通常以一到两层结束Dense,第 13 章介绍的循环神经网络也是如此。

  • 卷积神经网络(ConvNets) 卷积层通过对输入张量中不同的空间位置(块)应用相同的几何变换来处理空间局部模式。这使得表示具有平移不变性,从而使卷积层具有极高的数据效率和模块化特性。

    卷积神经网络(ConvNets)由卷积层和最大池化层堆叠而成。池化层可以对数据进行空间下采样,这对于在特征数量增长时保持特征图大小合理,以及使后续卷积层能够“看到”更大范围的输入数据至关重要。 构建非常深的卷积神经网络时,通常会添加 批量归一化层以及残差连接 ——这两种架构模式有助于梯度信息在网络中平滑流动。

  • Transformers

    Transformer 最初是为机器翻译设计的,其架构分为两大部分:

    1. Encoder(编码器):负责将源语言(如中文)“转换”为抽象的语义概念。
    2. Decoder(解码器):负责将这些抽象概念“转换”回目标语言(如英文)。

    这种“输入 \(\rightarrow\) 语义 \(\rightarrow\) 输出”的全程转换逻辑,使得 Transformer 就像一个大型的语言信号转换器

  • 循环神经网络(Recurrent neural networks)

蒸馏技术(个人增加)

在 AI 领域,“蒸馏”(Knowledge Distillation)是一个非常形象的比喻:它的核心目标是将一个巨大、复杂模型的“知识”,浓缩到一个轻量、快速的小模型中

简单来说,就是“大老师”教“小初学者”的过程。

  1. 蒸馏的核心角色

在蒸馏过程中,有两个主要角色:

  • 教师模型 (Teacher Model):一个预先训练好的、性能极强但体积巨大的模型(如 BERT-Large 或 GPT-4)。它虽然聪明,但推理速度慢,难以部署在手机端。
  • 学生模型 (Student Model):一个架构更简单、参数更少的轻量级模型(如 DistilBERT)。我们的目标是让它的表现尽可能接近老师。
  1. 蒸馏的核心逻辑:为什么不直接训练学生?

如果只让学生模型学习“标准答案”(Hard Targets,如:这张图是猫还是狗),学生只能学到表面结果。

蒸馏的关键在于让学生学习老师的“软标签” (Soft Targets)

  • 硬标签:[猫: 1, 狗: 0, 猪: 0]
  • 软标签(老师的思考过程):[猫: 0.9, 狗: 0.09, 猪: 0.01]

这个软标签告诉学生:“虽然这是猫,但它长得其实有点像狗,完全不像猪。” 这种类别间的相对关系包含了模型对特征的深刻理解,这就是“知识”。

  1. 蒸馏的具体步骤

第一步:训练教师模型

首先,在大规模数据集上训练出一个高性能的教师模型。这个过程通常耗时耗力,但只需要做一次。

第二步:计算软预测值(温度 T)

为了让“软标签”里的信息更明显,我们会引入一个参数 Temperature (\(T\))

  • \(T=1\) 时,输出概率分布通常很尖锐(猫 0.999,其余几乎为 0)。
  • 调高 \(T\)(如 \(T=5\))后,分布会变得平滑,暴露出老师对“错误选项”的细微评价。

第三步:联合训练学生

学生模型在训练时需要同时看两个东西:

  1. 真实标签(Ground Truth):告诉学生什么是绝对正确的。

  2. 老师的软输出:通过计算 蒸馏损失 (Distillation Loss),强迫学生的输出分布去模仿老师的分布。

  3. 为什么要费劲搞蒸馏?

  • 模型压缩:你可以得到一个体积缩小 40%、速度提升 60%,但性能保留 95% 以上的模型。
  • 低功耗部署:让复杂的 AI 逻辑能在手机、智能手表甚至传感器上流畅运行。
  • 隐私与速度:不需要把所有数据都传回云端大模型处理,在本地小模型上就能完成任务。

总结

蒸馏不是简单的“复制粘贴”,而是知识的迁移。老师把对世界的“精细理解”传授给学生,让学生在保持轻巧的同时,依然拥有不俗的智慧。这也是为什么你现在的手机能流畅运行各种 AI 翻译和图像识别的原因之一。

说 DeepSeek “蒸馏”了 OpenAI(通常指 GPT-4),这在 AI 圈是一个非常专业且具有代表性的技术路径。

需要纠正一个常见的误区:这种蒸馏不是指 DeepSeek 拿到了 OpenAI 的源代码或模型权重,而是通过“黑盒蒸馏”(Black-box Distillation)的方式,学习 GPT-4 的逻辑能力

以下是实现这一过程的具体操作流程:

  1. 核心逻辑:把 GPT-4 当成“数据标注员”

传统的蒸馏需要看到教师模型的内部参数(白盒),但由于 GPT-4 是闭源的,DeepSeek 采用的是基于样本的蒸馏

  • 思路:如果我不知道老师脑子里是怎么想的,那我就给老师出 100 万道难题,看他的解题步骤(Chain of Thought, CoT)
  • 知识迁移:GPT-4 强大的地方不在于最终答案(Yes/No),而在于它推理时的逻辑链条。DeepSeek 记录下这些链条,作为自己训练的“标准教材”。
  1. 具体操作过程(四步走)

第一步:构建高难度指令集(Instruction Construction)

DeepSeek 的团队会编写或收集大量极其复杂的提示词(Prompts),涵盖数学证明、代码逻辑、深度推理等。

  • 这些题目必须足够难,才能把 GPT-4 的真本事逼出来。

第二步:获取教师模型的推理链(Generating CoT Data)

将这些难题输入给 GPT-4,要求它:“请一步步思考并给出详细的推理过程。”

  • 产出:海量的 [问题] -> [详细推理逻辑] -> [最终答案] 数据对。
  • 关键点:这比普通的问答对价值高出百倍,因为它包含了“如何思考”的知识。

第三步:数据清洗与自我对弈(Cleaning & Self-Correction)

GPT-4 也会出错。DeepSeek 会利用自动化工具或更小的模型来剔除那些逻辑不通、格式错误的回复。

  • 甚至会让 DeepSeek 自己的模型尝试模仿,如果模仿得不好,再回头看 GPT-4 是怎么做的。

第四步:有监督微调(SFT)

这是真正的“蒸馏”时刻。DeepSeek 将收集到的这几百万条来自 GPT-4 的高质量推理数据,喂给自己的基座模型(Base Model)进行有监督微调(Supervised Fine-Tuning)

  • 结果:DeepSeek 并没有 GPT-4 那么大的参数量,但通过学习这些“精华数据”,它学会了类似的思维模式。
  1. 为什么 DeepSeek 做得这么成功?

DeepSeek 并不只是单纯的“抄作业”,它还做了两件非常牛的事:

  1. 架构创新 (MoE):DeepSeek 采用了 Mixture of Experts (混合专家架构)。这让它在推理时虽然只激活一小部分参数(省钱、极快),但却能承载从 GPT-4 那里学来的复杂知识。

  2. 强化学习 (RL):在蒸馏完 GPT-4 的数据后,DeepSeek 还会进行大规模的强化学习。它不再看老师怎么做,而是自己跟自己下棋,通过奖励机制(比如数学题做对了给高分)来进一步压榨模型的推理极限。

  3. 这种“蒸馏”合法吗?

这在行业内属于“灰色地带”。

  • OpenAI 的服务条款通常禁止使用其输出数据来训练竞争模型。
  • 但在实际操作中,几乎所有顶尖的国产模型和开源模型(如 Llama 3 的某些指令微调版本)都多多少少使用了合成数据进行蒸馏。

总结

DeepSeek “蒸馏” OpenAI 的过程,本质上是用 GPT-4 生成的高质量思维链数据,来训练一个架构更高效的国产模型

这就像是一个学生通过刷学霸出的“超级模拟卷”和“解题笔记”,最终在考试中拿到了和学霸接近的分数,而他付出的计算成本(学费)却只有学霸的几十分之一。