目录引言

第 1 章 引言Chapter 1 Introduction

1.1 什么是可微编程?1.1 What is differentiable programming?

计算机程序是执行某一任务的一系列基本指令。在传统计算机编程中,程序通常由程序员手工编写。然而,对于某些任务,尤其是涉及复杂模式与复杂决策的任务,例如图像识别或文本生成,手工编写程序极具挑战,甚至可能无法实现。A computer program is a sequence of elementary instructions for performing a task. In traditional computer programming, the program is typically manually written by a programmer. However, for certain tasks, particularly those involving intricate patterns and complex decision-making, such as image recognition or text generation, manually writing a program is extremely challenging, if not impossible.

相比之下,现代神经网络提供了一种不同的途径。它们由参数化的功能模块组合而成,并利用基于梯度的优化直接从数据中训练得到。在这一端到端的训练过程中,网络同时学习特征提取与任务执行,使得神经网络能够处理以往被认为传统手工编码程序无法企及的复杂任务。这一新的编程范式被称为“可微编程”或“软件 2.0”。我们在下文给出一个非正式定义。In contrast, modern neural networks offer a different approach. They are constructed by combining parameterized functional blocks and are trained directly from data using gradient-based optimization. This end-to-end training process, where the network learns both feature extraction and task execution simultaneously, allows neural networks to tackle complex tasks that were previously considered insurmountable for traditional, hand-coded programs. This new programming paradigm has been referred to as “differentiable programming” or “software 2.0”. We give an informal definition below.

定义 1.1.1(可微编程)。Definition 1.1.1 (Differentiable programming).
可微编程是一种编程范式:在该范式下,复杂的计算机程序(包括含有控制流与数据结构的程序)能够被端到端地自动微分,从而可以基于梯度对程序中的参数进行优化。Differentiable programming is a programming paradigm in which complex computer programs (including those with control flows and data structures) can be differentiated end-to-end automatically, enabling gradient-based optimization of parameters in the program.

神经网络作为参数化程序Neural networks as parameterized programs

在可微编程中,与常规计算机编程一样,程序被定义为基本操作的组合,形成一张计算图。关键区别在于,如图 1.1 所示,程序(例如神经网络)包含可从数据中调整的参数,并能够利用自动微分(autodiff)进行端到端求导。通常假定程序定义了一个数学上有效的函数(又称纯函数):该函数对相同参数应返回相同的值,且不应有任何副作用。此外,该函数应具有良定义的导数,以确保其可用于基于梯度的优化算法。因此,可微编程不仅是对程序求导的艺术,也是设计有意义的可微程序的艺术。In differentiable programming, as in regular computer programming, a program is defined as the composition of elementary operations, forming a computation graph. The key difference is that, as illustrated in Fig. 1.1, the program (such as a neural network) contains parameters that can be adjusted from data and can be differentiated end-to-end using automatic differentiation (autodiff). Typically, it is assumed that the program defines a mathematically valid function (a.k.a. pure function): the function should return identical values for identical arguments and should not have any side effects. Moreover, the function should have well-defined derivatives, ensuring that it can be used in a gradient-based optimization algorithm. Therefore, differentiable programming is not only the art of differentiating through programs but also of designing meaningful differentiable programs.

图 1.1:神经网络可被视为参数化程序。Figure 1.1: Neural networks can be seen as parameterized programs.

为什么需要导数?Why do we need derivatives?

机器学习通常归结为优化某个目标函数,该函数是损失函数与模型(网络)函数的组合。无导数优化被称为零阶优化。它只假定我们能够评估希望优化的目标函数。遗憾的是,众所周知它会遭遇维数灾难,即只能扩展到低维问题,例如维度小于 1010 的问题。而基于导数的优化则高效得多,能够扩展到数百万或数十亿个参数。使用一阶与二阶导数的算法分别被称为一阶算法与二阶算法。Machine learning typically boils down to optimizing a certain objective function, which is the composition of a loss function and a model (network) function. Derivative-free optimization is called zero-order optimization. It only assumes that we can evaluate the objective function that we wish to optimize. Unfortunately, it is known to suffer from the curse of dimensionality, i.e., it only scales to low-dimensional problems, such as less than 1010 dimensions. Derivative-based optimization, on the other hand, is much more efficient and can scale to millions or billions of parameters. Algorithms that use first and second derivatives are known as first-order and second-order algorithms, respectively.

为什么自动微分如此有用?Why is autodiff so useful?

在自动微分革命之前,研究人员与从业者需要手工实现他们希望优化的函数的梯度。对于复杂函数,手工推导梯度可能变得非常繁琐。此外,每当函数发生变化(例如尝试一个新想法),梯度就需要重新推导。自动微分之所以是颠覆性的,是因为它让用户能够快速而富有创造性地针对其任务试验各种函数。图 1.2 给出了一个 JAX 代码示例 [34]。Before the autodiff revolution, researchers and practitioners needed to manually implement the gradient of the functions they wished to optimize. Manually deriving gradients can become very tedious for complicated functions. Moreover, every time the function is changed (for example, for trying out a new idea), the gradient needs to be re-derived. Autodiff is a game changer because it allows users to focus on quickly and creatively experimenting with functions for their tasks. An example of JAX code [34] is given in Fig. 1.2.

Refer to caption
图 1.2:得益于自动微分(autodiff),用户可以专注于表达前向计算(模型),从而实现快速实验,并减少对易出错的手工梯度推导的需求。Figure 1.2: Thanks to automatic differentiation (autodiff), the user can focus on expressing the forward computation (model), enabling fast experimentation and alleviating the need for error-prone manual gradient derivation.

可微编程不仅仅是深度学习Differentiable programming is not just deep learning

尽管深度学习与可微编程之间显然存在重叠,但二者关注点不同。深度学习研究由多层构成的人工神经网络,能够学习数据的中间表示。人们已提出具有各种归纳偏置的神经网络架构。例如,卷积神经网络是为图像设计的,而 transformer 是为序列设计的。另一方面,可微编程研究的是设计复杂程序并对其求导的技术。它的用处不止于深度学习:例如在强化学习、概率编程以及一般意义上的科学计算中。While there is clearly overlap between deep learning and differentiable programming, their focus is different. Deep learning studies artificial neural networks composed of multiple layers, able to learn intermediate representations of the data. Neural network architectures have been proposed with various inductive biases. For example, convolutional neural networks are designed for images, and transformers are designed for sequences. On the other hand, differentiable programming studies the techniques for designing complex programs and differentiating through them. It is useful beyond deep learning: for instance in reinforcement learning, probabilistic programming and scientific computing in general.

可微编程不仅仅是自动微分Differentiable programming is not just autodiff

尽管自动微分是可微编程的关键要素,但它并非唯一要素。可微编程还关注有原则的可微操作的设计。事实上,可微编程的许多研究都致力于使经典计算机编程操作与自动微分兼容。正如我们将看到的,许多可微松弛都可以在概率框架中加以解释。本书的一个核心主题是优化、概率与微分之间的相互作用。微分对优化有用,反过来,优化也可用于设计可微算子。While autodiff is a key ingredient of differentiable programming, it is not the only one. Differentiable programming is also concerned with the design of principled differentiable operations. In fact, much research on differentiable programming has been devoted to making classical computer programming operations compatible with autodiff. As we shall see, many differentiable relaxations can be interpreted in a probabilistic framework. A core theme of this book is the interplay between optimization, probability and differentiation. Differentiation is useful for optimization and conversely, optimization can be used to design differentiable operators.

我们对可微编程的愿景Our vision for differentiable programming

计算机编程提供了控制流、数据结构和标准库等强大工具,使用户能够构建复杂程序来解决错综复杂的问题。我们的长期愿景是实现传统编程与可微编程之间的对等,使程序员能够利用他们所熟悉的全套工具,无缝地表达可微程序(例如神经网络)。然而,如前所述,可微编程并不仅仅是将自动微分应用于现有代码。程序的设计必须考虑到可微性。这通常归结为在程序或其组件上诱导出一个概率分布。尽管要完全实现这一雄心勃勃的目标仍有大量工作要做,但我们希望本书能提供一个坚实的基础。Computer programming offers powerful tools like control flows, data structures, and standard libraries, enabling users to construct complex programs for solving intricate problems. Our long-term vision is to achieve parity between traditional and differentiable programming, empowering programmers to seamlessly express differentiable programs (such as neural networks) using the full suite of tools they are accustomed to. However, as discussed earlier, differentiable programming is not simply a matter of applying automatic differentiation to existing code. Programs must be designed with differentiability in mind. This usually comes down to inducing a probability distribution over the program or its components. While significant work remains to fully realize this ambitious goal, we hope this book offers a solid foundation.

“可微编程”从何而来?Where does “differentiable programming” come from?

尽管神经网络与自动微分已存在数十年,“可微编程”这一术语却出现得较晚。[148] 讨论了神经网络架构与函数式编程中高阶函数之间的类比,并将其称为“一种新的编程方式”。[49] 撰写了一篇题为“可微编程”的文章,指出存在一种范式:程序通过微分来学习细节,同时具备函数式编程的表达能力。[156] 在 POPL 2018 上作了题为“微分编程语言的一些原则”的主题演讲。“可微编程”与“软件 2.0”这两个术语由 [117] 和 [104] 等人推广开来。从这个视角看,自动微分框架不应仅仅被视为库,而应被视为嵌入在现有编程语言(如 Python)中的领域特定语言(DSL)。另见 [98] 的综述。While neural networks and autodiff have existed for several decades, the term “differentiable programming” is more recent. [148] discussed analogies between neural network architectures and higher-order functions in functional programming, and referred to it as a “new kind of programming”. [49] wrote an essay titled “differentiable programming”, recognizing a paradigm where programs learn details through differentiation, with the expressiveness of functional programming. [156] gave a keynote talk titled “Some principles of differential programming languages” at POPL 2018. The “differentiable programming” and “software 2.0” terms were popularized, among others, by [117] and [104]. From this perspective, autodiff frameworks can be seen, not merely as libraries, but as domain-specific languages (DSLs) embedded into an existing programming language, such as Python. See also [98] for a review.

1.2 本书目标与范围1.2 Book goals and scope

本书旨在提供可微编程的全面介绍,并着重强调核心数学工具。The present book aims to provide a comprehensive introduction to differentiable programming with an emphasis on core mathematical tools.

  • •

    在第一部分中,我们回顾基础知识:微分与概率学习。In Part I, we review fundamentals: differentiation and probabilistic learning.

  • •

    在第二部分中,我们回顾可微程序。这包括神经网络、序列网络与控制流。In Part II, we review differentiable programs. This includes neural networks, sequence networks and control flows.

  • •

    在第三部分中,我们回顾如何穿越程序进行微分。这包括自动微分,也包括穿越优化与积分(特别是期望)进行微分。In Part III, we review how to differentiate through programs. This includes automatic differentiation, but also differentiating through optimization and integration (in particular, expectations).

  • •

    在第四部分中,我们回顾平滑程序。我们聚焦于两种主要技术:源于优化领域的下确卷积,以及源于积分领域的卷积。我们还力求阐明二者之间的联系。In Part IV, we review smoothing programs. We focus on two main techniques: infimal convolution, which comes from the world of optimization, and convolution, which comes from the world of integration. We also strive to spell out the connections between them.

  • •

    在第五部分中,我们回顾优化程序:基本优化概念、一阶算法、二阶算法与对偶性。In Part V, we review optimizing programs: basic optimization concepts, first-order algorithms, second-order algorithms and duality.

我们的目标是呈现对可微编程有用的基本技术,而非综述这些技术在各种应用中的使用方式。Our goal is to present the fundamental techniques useful for differentiable programming, not to survey how these techniques have been used in various applications.

1.3 目标读者1.3 Intended audience

本书旨在作为可微编程的研究生水平入门读物。我们的教学选择以机器学习社区为考量。对微积分、线性代数、概率论与机器学习有一定熟悉度将有所助益。This book is intended to be a graduate-level introduction to differentiable programming. Our pedagogical choices are made with the machine learning community in mind. Some familiarity with calculus, linear algebra, probability theory and machine learning is beneficial.

1.4 如何阅读本书?1.4 How to read this book?

本书无需逐章线性阅读。在需要时,我们会在章首说明建议作为先修内容阅读的章节。This book does not need to be read linearly chapter by chapter. When needed, we indicate at the beginning of a chapter what chapters are recommended to be read as a prerequisite.

1.5 相关工作1.5 Related work

可微编程建立在多种相互关联的主题之上。我们在本节回顾相关的教科书、教程与软件。Differentiable programming builds upon a variety of connected topics. We review in this section relevant textbooks, tutorials and software.

关于反向传播与自动微分(autodiff)的标准教科书是 [210] 与 [87] 的著作。[16] 提供了一份侧重机器学习的教程。自动微分也在更一般的教科书中得到回顾,例如 [55]、[140](从线性代数视角)以及 [141](从函数式视角;自动微分部分由 Roy Frostig 撰写)的著作。本书也受到 [154] 的数据科学教科书的影响。[86] 回顾了反向模式自动微分的历史。Standard textbooks on backpropagation and automatic differentiation (autodiff) are those of [210] and [87]. A tutorial with a focus on machine learning is provided by [16]. Automatic differentiation is also reviewed as part of more general textbooks, such as those of [55], [140] (from a linear algebra perspective) and [141] (from a functional perspective; autodiff section authored by Roy Frostig). The present book was also influenced by [154]’s textbook on data science. The history of reverse-mode autodiff is reviewed by [86].

关于反向传播不同视角的教程是 Deisenroth 与 Ong 的“There and Back Again: A Tale of Slopes and Expectations”(链接)。关于隐式微分的教程是 Kolter、Duvenaud 与 Johnson 的“Deep Implicit Layers - Neural ODEs, Deep Equilibrium Models, and Beyond”(链接)。A tutorial on different perspectives of backpropagation is “There and Back Again: A Tale of Slopes and Expectations” (link), by Deisenroth and Ong. A tutorial on implicit differentiation is “Deep Implicit Layers - Neural ODEs, Deep Equilibrium Models, and Beyond” (link), by Kolter, Duvenaud, and Johnson.

关于图模型中的推断及其与指数族之间联系的标准参考是 [206] 的著作。可微编程也与概率编程相关;例如参见 [131]。The standard reference on inference in graphical models and its connection with exponential families is that of [206]. Differentiable programming is also related to probabilistic programming; see, e.g., [131].

[19] 提供了从下确卷积视角对平滑的综述。[146] 是关于凸优化的标准教科书。[18] 是关于一阶优化方法的教科书。A review of smoothing from the infimal convolution perspective is provided by [19]. A standard textbook on convex optimization is that of [146]. A textbook on first-order optimization methods is that of [18].

加速了机器学习中自动微分革命的自动微分实现是 Theano [22] 与 Autograd [124]。现代主要的自动微分实现包括 TensorFlow [1]、JAX [34] 与 PyTorch [151]。我们尤其感谢 JAX 团队影响了我们对自动微分的看法。Autodiff implementations that accelerated the autodiff revolution in machine learning are Theano [22] and Autograd [124]. Major modern implementations of autodiff include TensorFlow [1], JAX [34], and PyTorch [151]. We in particular acknowledge the JAX team for influencing our view of autodiff.