前言¶
就在几年前,还没有成群的深度学习科学家在大型公司和初创企业开发智能产品和服务。当我们进入这个领域时,机器学习还没有占据日报的头条。我们的父母不知道什么是机器学习,更不用说我们为什么会选择它而不是医学或法律等职业。机器学习是一门蓝天(blue skies)的学术学科,其工业意义仅限于一小部分现实世界的应用,包括语音识别和计算机视觉。此外,这些应用中的许多都需要大量的领域知识,以至于它们通常被视为完全独立的领域,而机器学习只是其中的一小部分。那时,神经网络——本书关注的深度学习方法的前身——通常被认为是过时的。
然而,在短短几年内,深度学习令世界惊叹,推动了计算机视觉、自然语言处理、自动语音识别、强化学习和生物医学信息学等不同领域的快速发展。此外,深度学习在许多具有实际意义的任务中的成功,甚至催化了理论机器学习和统计学的发展。有了这些进步,我们现在可以制造出比以往任何时候都更具自主性的自动驾驶汽车(尽管自主性比一些公司可能让你相信的要低),通过提出澄清性问题来调试代码的对话系统,以及在围棋等棋盘游戏中击败世界上最好的人类玩家的软件代理——这一壮举曾被认为需要几十年才能实现。这些工具已经对工业和社会产生了越来越广泛的影响,改变了电影的制作方式、疾病的诊断方式,并在基础科学中发挥着越来越大的作用——从天体物理学到气候建模,再到天气预报和生物医学。
关于本书¶
本书是我们为使深度学习易于理解而做出的尝试,旨在教给您*概念*、*背景*和*代码*。
一种结合代码、数学和HTML的媒介¶
任何计算技术要发挥其全部影响力,都必须被充分理解、有完善的文档,并由成熟、维护良好的工具支持。关键思想应被清晰地提炼出来,以最大限度地缩短新从业者入门所需的时间。成熟的库应自动化常见任务,而示例代码应使从业者能够轻松地修改、应用和扩展常见应用以满足他们的需求。
以动态Web应用程序为例。尽管在20世纪90年代,像亚马逊这样的大量公司开发了成功的数据库驱动的Web应用程序,但这项技术帮助富有创造力的企业家的潜力,在很大程度上直到过去十年才得以实现,部分原因是功能强大、文档完善的框架的发展。
测试深度学习的潜力带来了独特的挑战,因为任何一个应用都汇集了不同的学科。应用深度学习需要同时理解 (i) 以特定方式构建问题的动机;(ii) 给定模型的数学形式;(iii) 将模型拟合到数据的优化算法;(iv) 告诉我们何时应期望我们的模型能泛化到未见数据的统计原理,以及验证它们确实已经泛化的实用方法;以及 (v) 高效训练模型所需的工程技术,以驾驭数值计算的陷阱并最大限度地利用可用硬件。在一个地方教授制定问题所需的批判性思维技能、解决问题的数学知识以及实现这些解决方案的软件工具,这带来了巨大的挑战。我们在本书中的目标是提供一个统一的资源,以帮助潜在的从业者快速上手。
当我们开始这个图书项目时,还没有任何资源能够同时 (i) 保持最新;(ii) 以足够的技术深度涵盖现代机器学习实践的广度;以及 (iii) 将人们期望从教科书中得到的优质阐述与人们期望从动手教程中得到的干净可运行代码交织在一起。我们发现大量代码示例,说明如何使用给定的深度学习框架(例如,如何在TensorFlow中进行基本的矩阵数值计算)或实现特定技术(例如,LeNet、AlexNet、ResNet等的代码片段)散布在各种博客文章和GitHub仓库中。然而,这些示例通常侧重于*如何*实现给定的方法,而忽略了*为什么*做出某些算法决策的讨论。虽然有一些互动资源零星地出现以解决特定主题,例如,在网站 Distill 上发布的引人入胜的博客文章,或个人博客,但它们只涵盖了深度学习中的选定主题,并且通常缺少相关代码。另一方面,虽然已经出现了几本深度学习教科书——例如,Goodfellow 等人 (2016),它对深度学习的基础知识进行了全面的调查——但这些资源没有将描述与代码实现相结合,有时让读者对如何实现它们一无所知。此外,太多的资源被隐藏在商业课程提供商的付费墙后面。
我们着手创建一个资源,该资源能够 (i) 免费提供给所有人;(ii) 提供足够的技术深度,为成为一名应用机器学习科学家的道路提供起点;(iii) 包含可运行的代码,向读者展示*如何*在实践中解决问题;(iv) 允许我们和整个社区快速更新;以及 (v) 辅以一个论坛,用于互动讨论技术细节和回答问题。
这些目标常常相互冲突。方程、定理和引文最好用LaTeX管理和排版。代码最好用Python描述。而网页原生于HTML和JavaScript。此外,我们希望内容既可以作为可执行代码、实体书、可下载的PDF,也可以作为网站在互联网上访问。似乎没有工作流程适合这些要求,所以我们决定组建自己的工作流程(23.6节)。我们决定使用GitHub来共享源代码并促进社区贡献;使用Jupyter notebooks来混合代码、方程和文本;使用Sphinx作为渲染引擎;以及使用Discourse作为讨论平台。虽然我们的系统并不完美,但这些选择在相互竞争的关注点之间取得了折衷。我们相信,*《动手学深度学习》*可能是第一本使用这种集成工作流程出版的书籍。
在实践中学习¶
许多教科书按顺序呈现概念,对每个概念进行详尽的介绍。例如,Bishop (2006) 的优秀教科书对每个主题的讲解都非常透彻,以至于要读到线性回归这一章都需要进行大量的准备工作。虽然专家们正是因为其透彻性而喜爱这本书,但对于真正的初学者来说,这一特性限制了它作为入门教材的用处。
在本书中,我们*即时*教授大多数概念。换句话说,你将在需要这些概念来完成某些实际目标的那一刻学习它们。虽然我们在一开始会花一些时间教授一些基本预备知识,如线性代数和概率论,但我们希望你在担心更深奥的概念之前,能尝到训练第一个模型的满足感。
除了一些提供基本数学背景速成课程的初步笔记本外,后续的每一章都介绍了一定数量的新概念,并提供了几个使用真实数据集的独立工作示例。这带来了一个组织上的挑战。一些模型可能在逻辑上可以归入一个笔记本中。而一些想法可能最好通过连续执行几个模型来教授。相比之下,坚持*一个工作示例,一个笔记本*的策略有一个很大的优势:这使你尽可能容易地通过利用我们的代码来开始自己的研究项目。只需复制一个笔记本并开始修改它。
在全书中,我们根据需要将可运行的代码与背景材料交织在一起。总的来说,我们倾向于在完全解释工具之前就提供它们(通常稍后补充背景知识)。例如,我们可能会在解释为什么*随机梯度下降*有用或为其工作原理提供一些直觉之前就使用它。这有助于为从业者提供快速解决问题的必要弹药,但代价是要求读者在某些策展决策上信任我们。
本书从零开始教授深度学习概念。有时,我们会深入探讨模型的细节,而这些细节通常会被现代深度学习框架向用户隐藏。这在基础教程中尤其常见,我们希望你理解给定层或优化器中发生的一切。在这些情况下,我们通常会提供两个版本的示例:一个是我们从头开始实现所有内容,只依赖于类似NumPy的功能和自动微分;另一个是更实用的示例,我们使用深度学习框架的高级API编写简洁的代码。在解释了某个组件的工作原理后,我们会在后续的教程中依赖高级API。
内容和结构¶
本书大致可分为三部分,涉及预备知识、深度学习技术以及专注于实际系统和应用的高级主题(图 1)。
图 1 本书结构。¶
第一部分:基础与预备知识。 第1节 是深度学习的介绍。然后,在 第2节,我们快速让你掌握动手实践深度学习所需的先决条件,例如如何存储和操作数据,以及如何应用基于线性代数、微积分和概率论基本概念的各种数值运算。 第3节 和 第5节 涵盖了深度学习中最基本的概念和技术,包括回归和分类、线性模型、多层感知机以及过拟合和正则化。
第二部分:现代深度学习技术。 第6节 描述了深度学习系统的关键计算组件,并为我们后续实现更复杂的模型奠定了基础。接下来,第7节 和 第8节 介绍了卷积神经网络(CNNs),这是构成大多数现代计算机视觉系统骨干的强大工具。类似地,第9节 和 第10节 介绍了循环神经网络(RNNs),这些模型利用数据中的顺序(例如,时间)结构,常用于自然语言处理和时间序列预测。在 第11节,我们描述了一类相对较新的模型,基于所谓的*注意力机制*,它已经取代RNNs成为大多数自然语言处理任务的主导架构。这些章节将让你快速了解深度学习从业者广泛使用的最强大和最通用的工具。
第三部分:可扩展性、效率和应用(可在线获取)。在第12章中,我们讨论了用于训练深度学习模型的几种常见优化算法。接下来,在第13章中,我们研究了影响深度学习代码计算性能的几个关键因素。然后,在第14章中,我们阐述了深度学习在计算机视觉中的主要应用。最后,在第15章和第16章中,我们演示了如何预训练语言表示模型并将其应用于自然语言处理任务。
代码¶
本书的大多数章节都包含可执行代码。我们相信,有些直觉最好通过试错法来培养,即通过微调代码并观察结果。理想情况下,一个优雅的数学理论可能会精确地告诉我们如何调整代码以达到预期的结果。然而,今天的深度学习从业者常常不得不在没有可靠理论指导的地方摸索。尽管我们尽了最大努力,但对于各种技术有效性的正式解释仍然缺乏,原因多种多样:描述这些模型的数学可能非常困难;解释可能依赖于目前缺乏明确定义的数据属性;以及对这些主题的认真研究直到最近才开始升温。我们希望,随着深度学习理论的进步,本书的每个未来版本都将提供超越现有版本的见解。
为了避免不必要的重复,我们将一些最常导入和使用的函数和类捕获到 d2l
包中。在全书中,我们用 #@save
标记代码块(例如函数、类或导入语句集合),以表示它们稍后将通过 d2l
包进行访问。我们在 23.8节 中提供了对这些类和函数的详细概述。 d2l
包是轻量级的,只需要以下依赖项。
#@save
import collections
import hashlib
import inspect
import math
import os
import random
import re
import shutil
import sys
import tarfile
import time
import zipfile
from collections import defaultdict
import pandas as pd
import requests
from IPython import display
from matplotlib import pyplot as plt
from matplotlib_inline import backend_inline
d2l = sys.modules[__name__]
本书中的大部分代码基于PyTorch,这是一个流行的开源框架,受到了深度学习研究社区的热情拥抱。本书中的所有代码都已在最新稳定版的PyTorch下通过测试。然而,由于深度学习的快速发展,*印刷版中*的某些代码在未来版本的PyTorch中可能无法正常工作。我们计划保持在线版本为最新。如果您遇到任何问题,请查阅安装来更新您的代码和运行时环境。下面列出了我们PyTorch实现中的依赖项。
#@save
import numpy as np
import torch
import torchvision
from PIL import Image
from scipy.spatial import distance_matrix
from torch import nn
from torch.nn import functional as F
from torchvision import transforms
#@save
import collections
import hashlib
import inspect
import math
import os
import random
import re
import shutil
import sys
import tarfile
import time
import zipfile
from collections import defaultdict
import pandas as pd
import requests
from IPython import display
from matplotlib import pyplot as plt
from matplotlib_inline import backend_inline
d2l = sys.modules[__name__]
本书中的大部分代码基于Apache MXNet,这是一个用于深度学习的开源框架,是AWS(亚马逊网络服务)以及许多大学和公司的首选。本书中的所有代码都已在最新的MXNet版本下通过测试。然而,由于深度学习的快速发展,*印刷版中*的某些代码在未来版本的MXNet中可能无法正常工作。我们计划保持在线版本为最新。如果您遇到任何问题,请查阅安装来更新您的代码和运行时环境。下面列出了我们MXNet实现中的依赖项。
#@save
from mxnet import autograd, context, gluon, image, init, np, npx
from mxnet.gluon import nn, rnn
#@save
import collections
import hashlib
import inspect
import math
import os
import random
import re
import shutil
import sys
import tarfile
import time
import zipfile
from collections import defaultdict
import pandas as pd
import requests
from IPython import display
from matplotlib import pyplot as plt
from matplotlib_inline import backend_inline
d2l = sys.modules[__name__]
本书中的大部分代码基于Jax,这是一个开源框架,可以对任意Python和NumPy函数进行可组合的函数转换,例如微分,以及JIT编译、向量化等等!它在机器学习研究领域正变得越来越受欢迎,并且拥有一个易于学习的类似NumPy的API。实际上,JAX试图与NumPy实现1:1的对等,因此切换您的代码可能就像更改一个导入语句一样简单!然而,由于深度学习的快速发展,*印刷版中*的某些代码在未来版本的Jax中可能无法正常工作。我们计划保持在线版本为最新。如果您遇到任何问题,请查阅安装来更新您的代码和运行时环境。下面列出了我们JAX实现中的依赖项。
#@save
from dataclasses import field
from functools import partial
from types import FunctionType
from typing import Any
import flax
import jax
import numpy as np
import optax
import tensorflow as tf
import tensorflow_datasets as tfds
from flax import linen as nn
from flax.training import train_state
from jax import grad
from jax import numpy as jnp
from jax import vmap
#@save
import collections
import hashlib
import inspect
import math
import os
import random
import re
import shutil
import sys
import tarfile
import time
import zipfile
from collections import defaultdict
import pandas as pd
import requests
from IPython import display
from matplotlib import pyplot as plt
from matplotlib_inline import backend_inline
d2l = sys.modules[__name__]
本书中的大部分代码基于TensorFlow,这是一个用于深度学习的开源框架,在工业界被广泛采用,并受到研究人员的欢迎。本书中的所有代码都已在最新稳定版的TensorFlow下通过测试。然而,由于深度学习的快速发展,*印刷版中*的某些代码在未来版本的TensorFlow中可能无法正常工作。我们计划保持在线版本为最新。如果您遇到任何问题,请查阅安装来更新您的代码和运行时环境。下面列出了我们TensorFlow实现中的依赖项。
#@save
import numpy as np
import tensorflow as tf
目标读者¶
本书面向寻求扎实掌握深度学习实践技术的学生(本科生或研究生)、工程师和研究人员。因为我们从零开始解释每一个概念,所以不需要任何深度学习或机器学习的先前背景。要完全解释深度学习的方法需要一些数学和编程知识,但我们只假设你具备一些基础知识,包括适量的线性代数、微积分、概率论和Python编程。万一你忘记了什么,在线附录提供了本书中你会发现的大部分数学知识的复习。通常,我们会优先考虑直觉和思想,而不是数学的严谨性。如果你想在理解本书的先决条件之上扩展这些基础,我们很高兴推荐一些其他很棒的资源:《线性分析》(Linear Analysis)by Bollobás (1999) 深入地涵盖了线性代数和泛函分析。《统计学大全》(All of Statistics)(Wasserman, 2013) 对统计学进行了精彩的介绍。Joe Blitzstein 关于概率和推断的书籍和课程是教学上的瑰宝。如果你以前没有用过Python,你可能想浏览一下这个Python教程。
Jupyter笔记本、网站、GitHub和论坛¶
我们所有的笔记本都可以在 D2L.ai网站 和 GitHub 上下载。与本书相关,我们推出了一个讨论论坛,地址在 discuss.d2l.ai。每当你对本书的任何章节有疑问时,你都可以在每个笔记本的末尾找到指向相关讨论页面的链接。
致谢¶
我们对英文和中文草稿的数百名贡献者深表感谢。他们帮助改进了内容并提供了宝贵的反馈。本书最初以MXNet为主要框架实现。我们感谢Anirudh Dagar和Yuan Tang分别将早期MXNet代码的大部分改编为PyTorch和TensorFlow实现。自2021年7月起,我们用PyTorch、MXNet和TensorFlow重新设计并实现了本书,选择PyTorch作为主要框架。我们感谢Anirudh Dagar将大部分较新的PyTorch代码改编为JAX实现。我们感谢百度的Gaosheng Wu、Liujun Hu、Ge Zhang和Jiehang Xie将大部分较新的PyTorch代码改编为中文草稿中的PaddlePaddle实现。我们感谢Shuai Zhang将出版社的LaTeX样式整合到PDF构建中。
在GitHub上,我们感谢这份英文草稿的每一位贡献者,他们让它变得对每个人都更好。他们的GitHub ID或名字是(排名不分先后):alxnorden, avinashingit, bowen0701, brettkoonce, Chaitanya Prakash Bapat, cryptonaut, Davide Fiocco, edgarroman, gkutiel, John Mitro, Liang Pu, Rahul Agarwal, Mohamed Ali Jamaoui, Michael (Stu) Stewart, Mike Müller, NRauschmayr, Prakhar Srivastav, sad-, sfermigier, Sheng Zha, sundeepteki, topecongiro, tpdi, vermicelli, Vishaal Kapoor, Vishwesh Ravi Shrimali, YaYaB, Yuhong Chen, Evgeniy Smirnov, lgov, Simon Corston-Oliver, Igor Dzreyev, Ha Nguyen, pmuens, Andrei Lukovenko, senorcinco, vfdev-5, dsweet, Mohammad Mahdi Rahimi, Abhishek Gupta, uwsd, DomKM, Lisa Oakley, Bowen Li, Aarush Ahuja, Prasanth Buddareddygari, brianhendee, mani2106, mtn, lkevinzc, caojilin, Lakshya, Fiete Lüer, Surbhi Vijayvargeeya, Muhyun Kim, dennismalmgren, adursun, Anirudh Dagar, liqingnz, Pedro Larroy, lgov, ati-ozgur, Jun Wu, Matthias Blume, Lin Yuan, geogunow, Josh Gardner, Maximilian Böther, Rakib Islam, Leonard Lausen, Abhinav Upadhyay, rongruosong, Steve Sedlmeyer, Ruslan Baratov, Rafael Schlatter, liusy182, Giannis Pappas, ati-ozgur, qbaza, dchoi77, Adam Gerson, Phuc Le, Mark Atwood, christabella, vn09, Haibin Lin, jjangga0214, RichyChen, noelo, hansent, Giel Dops, dvincent1337, WhiteD3vil, Peter Kulits, codypenta, joseppinilla, ahmaurya, karolszk, heytitle, Peter Goetz, rigtorp, Tiep Vu, sfilip, mlxd, Kale-ab Tessera, Sanjar Adilov, MatteoFerrara, hsneto, Katarzyna Biesialska, Gregory Bruss, Duy–Thanh Doan, paulaurel, graytowne, Duc Pham, sl7423, Jaedong Hwang, Yida Wang, cys4, clhm, Jean Kaddour, austinmw, trebeljahr, tbaums, Cuong V. Nguyen, pavelkomarov, vzlamal, NotAnotherSystem, J-Arun-Mani, jancio, eldarkurtic, the-great-shazbot, doctorcolossus, gducharme, cclauss, Daniel-Mietchen, hoonose, biagiom, abhinavsp0730, jonathanhrandall, ysraell, Nodar Okroshiashvili, UgurKap, Jiyang Kang, StevenJokes, Tomer Kaftan, liweiwp, netyster, ypandya, NishantTharani, heiligerl, SportsTHU, Hoa Nguyen, manuel-arno-korfmann-webentwicklung, aterzis-personal, nxby, Xiaoting He, Josiah Yoder, mathresearch, mzz2017, jroberayalas, iluu, ghejc, BSharmi, vkramdev, simonwardjones, LakshKD, TalNeoran, djliden, Nikhil95, Oren Barkan, guoweis, haozhu233, pratikhack, Yue Ying, tayfununal, steinsag, charleybeller, Andrew Lumsdaine, Jiekui Zhang, Deepak Pathak, Florian Donhauser, Tim Gates, Adriaan Tijsseling, Ron Medina, Gaurav Saha, Murat Semerci, Lei Mao, Levi McClenny, Joshua Broyde, jake221, jonbally, zyhazwraith, Brian Pulfer, Nick Tomasino, Lefan Zhang, Hongshen Yang, Vinney Cavallo, yuntai, Yuanxiang Zhu, amarazov, pasricha, Ben Greenawald, Shivam Upadhyay, Quanshangze Du, Biswajit Sahoo, Parthe Pandit, Ishan Kumar, HomunculusK, Lane Schwartz, varadgunjal, Jason Wiener, Armin Gholampoor, Shreshtha13, eigen-arnav, Hyeonggyu Kim, EmilyOng, Bálint Mucsányi, Chase DuBois, Juntian Tao, Wenxiang Xu, Lifu Huang, filevich, quake2005, nils-werner, Yiming Li, Marsel Khisamutdinov, Francesco “Fuma” Fumagalli, Peilin Sun, Vincent Gurgul, qingfengtommy, Janmey Shukla, Mo Shan, Kaan Sancak, regob, AlexSauer, Gopalakrishna Ramachandra, Tobias Uelwer, Chao Wang, Tian Cao, Nicolas Corthorn, akash5474, kxxt, zxydi1992, Jacob Britton, Shuangchi He, zhmou, krahets, Jie-Han Chen, Atishay Garg, Marcel Flygare, adtygan, Nik Vaessen, bolded, Louis Schlessinger, Balaji Varatharajan, atgctg, Kaixin Li, Victor Barbaros, Riccardo Musto, Elizabeth Ho, azimjonn, Guilherme Miotto, Alessandro Finamore, Joji Joseph, Anthony Biel, Zeming Zhao, shjustinbaek, gab-chen, nantekoto, Yutaro Nishiyama, Oren Amsalem, Tian-MaoMao, Amin Allahyar, Gijs van Tulder, Mikhail Berkov, iamorphen, Matthew Caseres, Andrew Walsh, pggPL, RohanKarthikeyan, Ryan Choi, and Likun Lei.
我们感谢亚马逊云服务(Amazon Web Services),特别是叶文铭、George Karypis、Swami Sivasubramanian、Peter DeSantis、Adam Selipsky和Andrew Jassy,感谢他们对本书写作的慷慨支持。没有可用的时间、资源、与同事的讨论以及持续的鼓励,这本书就不会问世。在本书准备出版期间,剑桥大学出版社提供了出色的支持。我们感谢我们的责任编辑David Tranah的帮助和专业精神。
小结¶
深度学习已经彻底改变了模式识别,引入的技术现已为计算机视觉、自然语言处理和自动语音识别等众多领域的技术提供动力。要成功应用深度学习,你必须了解如何构建问题、建模的基本数学知识、将模型拟合到数据的算法以及实现这一切的工程技术。本书提供了一个全面的资源,包括文字、图表、数学和代码,全部集中在一处。