深度学习简介
在前一章中,我们学习了如何使用现代机器学习模型解决时间序列预测。现在,让我们将注意力转向机器学习的一个子领域,该领域在过去几年中显示出了巨大的潜力——深度学习。我们将尝试揭开深度学习的神秘面纱,并探讨它为何在当今如此流行。我们还将把深度学习分解为主要组成部分,并了解深度学习背后的主力——梯度下降。
本章涵盖以下主要主题:
- 什么是深度学习,为什么是现在?
- 深度学习系统的组成部分
- 表示学习
- 线性层和激活函数
- 梯度下降
技术要求
你需要按照本书《前言》中的说明设置Anaconda环境,以获取运行本书代码所需的所有库和数据集的可用环境。任何额外的库将在运行笔记本时安装。
本章的相关代码可以在https://github.com/PacktPublishing/Modern-Time-Series-Forecasting-with-Python-2E/tree/main/notebooks/Chapter11找到。
什么是深度学习,为什么是现在?
在第5章《时间序列预测作为回归》中,我们讨论了机器学习,并借用了Arthur Samuel的定义:“机器学习是一个研究领域,赋予计算机无需显式编程就能学习的能力。”并且我们进一步了解了如何通过机器学习从数据中学习有用的函数。深度学习是这个研究领域的一个子领域。深度学习的目标也是从数据中学习有用的函数,但在如何实现这一点上有一些特定的规范。
在我们讨论深度学习有什么特别之处之前,先回答另一个问题。为什么我们要将机器学习的这个子领域作为一个单独的话题来讨论?答案在于深度学习方法在无数应用中令人难以置信的有效性。深度学习席卷了机器学习世界,推翻了图像、视频、文本等数据类型的最新系统。如果你还记得十年前手机上的语音识别系统,它们更像是梗而不是真正有用。但今天,你可以说“Hey Google, play Pink Floyd”,然后《Comfortably Numb》就会在你的手机或扬声器上开始播放。多个深度学习系统使得这一过程得以流畅实现。你手机上的语音助手、自动驾驶汽车、网络搜索、语言翻译——深度学习在我们日常生活中的应用列表不断增长。
现在,你可能在想这种叫做深度学习的新技术到底是什么,对吧?深度学习不是一项新技术。深度学习的起源可以追溯到20世纪40年代末和50年代初。它之所以看起来新,只是因为近年来该领域突然流行起来。
让我们快速看看为什么深度学习突然流行起来。
为什么是现在?
深度学习在过去二十年里取得巨大进展有两个主要原因:
- 计算可用性的提升
- 数据可用性的提升
让我们在接下来的章节中详细讨论上面几点。
计算可用性的提升
早在1960年,Frank Rosenblatt撰写了一篇关于三层神经网络的论文(参考文献5),并指出它在展示神经网络作为模式识别设备的能力方面取得了长足的进步。但在同一篇论文中,他提到,随着连接数量的增加,对(1960年代的)数字计算机的负担过大。然而,在随后的几十年里,计算机硬件性能提升了近50,000倍,这极大地推动了神经网络和深度学习的发展。然而,这仍然不够,因为神经网络仍被认为不足以应对大规模应用。
就在这时,一种最初为游戏开发的特定硬件——GPU——挺身而出。目前尚不完全清楚是谁开始将GPU用于深度学习。Kyoung-Su Oh和Keechul Jung在2004年发表了一篇题为《GPU implementation of neural networks》的论文,这似乎是第一篇展示使用GPU进行深度学习获得巨大加速的论文。关于这个主题的最早且更受欢迎的研究论文之一来自Rajat Raina、Anand Madhavan和Andrew Ng,他们在2009年发表了一篇题为《Large-scale deep unsupervised learning using graphics processors》的论文。该论文展示了GPU对深度学习的有效性。
尽管LeCun、Schmidhuber、Bengio等人领导的许多团队都在尝试使用GPU,但转折点出现在Alex Krizhevsky、Ilya Sutskever和Geoffrey E. Hinton使用基于GPU的深度学习系统,在名为ImageNet Large Scale Visual Recognition Challenge 2012的图像识别竞赛中击败了所有其他竞争技术。
GPU的引入为深度学习的广泛应用提供了急需的推动力,并加速了该领域的进展。
参考文献核实:
研究论文《GPU implementation of neural networks》、《Large-scale deep unsupervised learning using graphics processors》和《ImageNet Classification with Deep Convolutional Neural Networks》分别被引用在参考文献部分的1、2和3中。
数据可用性的提升
除了计算能力的飞速提升,助力深度学习的另一个主要因素是数据的急剧增加。随着世界日益数字化,我们生成的数据量急剧增加。曾经只有几百上千行的表,如今膨胀到数百万乃至数十亿行,而存储成本的持续下降也助长了这种数据收集的爆炸式增长。
那么,数据可用性的提升为何有助于深度学习?这源于深度学习的工作方式。深度学习非常依赖数据,需要大量数据来学习良好的模型。因此,如果我们不断增加提供给深度学习模型的数据量,模型就能学习到越来越好的函数。然而,传统机器学习模型并非如此。让我们通过一张图表来巩固这一认识,这张图表由世界知名的机器学习教育者、斯坦福大学兼职教授Andrew Ng在他著名的机器学习课程——Coursera上的《Machine Learning by Stanford University》(https://www.coursera.org/specializations/machine-learning-introduction)中推广开来(图11.1)。

图11.1:随着数据量增加,深度学习与传统机器学习的对比
在图11.1中,该图由吴恩达推广,我们可以看到随着数据规模增大,传统机器学习会达到平台期且不再提升。
经验上已经证明,深度学习模型的过参数化有显著益处。过参数化意味着模型中的参数数量多于可用于训练的数据点数量。在经典统计学中,这是一个大忌,因为在这种情况下,模型必然过拟合。但深度学习似乎轻松地无视了这一规则。过参数化的一个例子是当前最先进的图像识别系统NoisyStudent。它有4.8亿个参数,但它是用120万数据点的ImageNet训练的。
有人认为深度学习模型的训练方式(随机梯度下降,我们很快会解释)是关键,因为它具有正则化效果。在一篇题为《深度学习的计算极限》的研究论文中,Niel C. Thompson等人试图通过一个简单的实验来阐明这一点。他们设置了一个包含1000个特征的数据集,但其中只有10个特征有信号。然后,他们尝试基于该数据集使用不同大小的数据集来学习四个模型:
- Oracle模型:一个仅使用有信号的10个参数的模型。
- 专家模型:一个使用10个重要参数中的9个的模型。
- 灵活模型:一个使用全部1000个参数的模型。
- 正则化模型:一个使用全部1000个参数,但现在是正则化(lasso)模型。(我们在第8章《使用机器学习模型进行时间序列预测》中介绍过正则化。)
让我们看看研究论文中的图11.2:

图11.2:图表展示了不同模型在不同数据规模下的表现
图表的x轴上使用了数据点的数量,
专家模型达到了平台期,因为它明显缺乏信息,无法获取十个重要特征中的一个。灵活模型(使用全部1000个特征)需要大量数据点才能开始识别重要特征,但随着数据规模增大,它仍然不断接近Oracle的性能。正则化模型(作为深度学习模型的代理)随着我们给模型提供越来越多的数据而不断改进。该模型使用正则化来确定这1000个特征中哪些与问题相关,并在更少的数据点下开始利用它们,性能随着数据点增加而持续提升。这再次强化了吴恩达推广的概念——随着数据增多,深度学习开始超越传统机器学习。
除了计算能力和数据可用性之外,还有很多因素促进了深度学习的成功。Sara Hooker 在她的文章《硬件彩票》(参考文献9)中谈到,一个想法之所以胜出,未必是因为它优于其他想法,而是因为它适合当时可用的软件和硬件。而一旦一个研究方向中了彩票,它就会像滚雪球一样发展,因为更多的资金和大型研究机构会支持这个想法,最终它成为想法空间中最突出的想法。
我们已经讨论了一段时间的深度学习,但还没有理解它是什么。现在我们来理解一下。
什么是深度学习?
深度学习没有单一的定义,因为不同的人对它有不同的理解。然而,绝大多数人都同意一件事:当一个模型涉及从原始数据中自动学习特征时,它就被称为深度学习。正如 Yoshua Bengio(图灵奖得主,人工智能的教父之一)在他2021年题为《面向无监督和迁移学习的表示深度学习》的论文中所解释的那样:
“深度学习算法试图利用输入分布中的未知结构来发现好的表示,通常是在多个层次上,高层学习到的特征由低层特征定义。”
在2016年的一次题为《深度学习与可理解性对比软件工程与验证》的演讲中,Google 研究总监 Peter Norvig 给出了类似但更简单的定义:
“一种学习方式,其中你形成的表示具有(原文如此)几个层次的抽象,而不是从输入直接到输出。”
深度学习另一个很多人认同的关键特征是组合性。Yann LeCun,图灵奖得主,人工智能的另一位教父,对深度学习有一个更复杂但更精确的定义(来自@ylecun 2020年1月9日的推文):
“DL 是一种方法论:通过将参数化模块组装成(可能是动态的)图来构建模型,并使用基于梯度的方法对其进行优化。”
我们在此想强调的要点如下:
- 组装参数化模块:这指的是深度学习的组合性。深度学习系统,正如我们很快将看到的,由少数几个子模块组成,这些子模块带有一些参数(有些没有),并被组装成类似图的结构。
- 使用基于梯度的方法进行优化:尽管将基于梯度的学习作为深度学习的充分条件并未被广泛接受,但我们仍然可以从经验中看到,当今最成功的深度学习系统大多使用基于梯度的方法进行训练。(如果你不了解基于梯度的优化方法是什么,别担心。我们很快就会在本章中介绍它。)
如果你之前读过任何关于深度学习的内容,你可能见过神经网络和深度学习被一起或互换使用。但直到现在,我们还没有讨论过神经网络。在讨论之前,让我们先看看任何神经网络的基本单元。
感知机,第一个神经网络
我们称之为深度学习和神经网络的很多东西都深受人脑及其内部运作的影响。尽管最近的研究表明人脑和人工神经网络之间的相似性很小,但这个想法的种子却是受人类生物学启发的。人类创造像自己一样智能存在的愿望早在希腊神话中(伽拉忒亚和潘多拉)就已显现。出于这种愿望,人类多年来一直研究并从人体解剖学中寻找灵感。人体中被深入研究的一个器官是大脑,因为它是智力、创造力以及其他一切使人成为人的中心。
尽管我们仍然对大脑知之甚少,但我们确实知道一点,并利用这一点点信息来设计人工系统。人脑的基本单元就是我们所说的神经元,如下图所示:

图11.3:生物神经元
你们中的许多人可能在生物学或机器学习的背景下已经遇到过这个。但无论如何,让我们回顾一下。生物神经元具有以下部分:
- 树突是神经细胞的分支延伸,用于收集来自周围细胞或其他神经元的输入。
- 胞体,即细胞体,收集这些输入,将它们合并,然后传递下去。
- 轴丘连接胞体和轴突,并控制神经元的放电。如果信号强度超过阈值,轴丘就会通过轴突发射电信号。
- 轴突是连接胞体与神经末梢的纤维。轴突的职责是将电信号传递到末梢。
- 突触是神经细胞的末端,负责将信号传递给其他神经细胞。
McCulloch和Pitts(1943)首次为生物神经元设计了数学模型。然而,McCulloch-Pitts模型存在一些局限性:
- 它只接受二元变量。
- 它认为所有输入变量同等重要。
- 只有一个参数,即阈值,且该参数不可学习。
1957年,Frank Rosenblatt推广了McCulloch-Pitts模型,使其成为一个参数可学习的完整模型。现代深度学习网络与人脑的相似性到此为止。开启这一研究路线的基本学习单元受启发于人类生物学,但也是对其相当拙劣的模仿。
参考文献核实:
Frank Rosenblatt的感知机的原始研究论文被引用在参考文献中引用在5下下..
让我们详细理解感知机,因为它是所有神经网络的基本构建块:

图11.4: 感知机
正如我们从图11.4中看到的,感知机,感知机具有以下组成部分:
- 输入:这些是输入到感知机的实数值输入。这就像神经元中收集输入的树突
- 加权和:每个输入乘以相应的权重并求和。权重决定了每个输入在结果中的重要性。
- 非线性:加权和经过一个非线性函数。对于原始感知机,它是一个带有阈值激活的阶跃函数。输出根据加权和与单元的阈值为正或负。现代感知机和神经网络使用不同类型的激活函数,但我们稍后会看到。
我们可以从数学形式写出感知机如下:

图11.5:感知机的数学视角
如图11.5所示,感知机输出由输入的加权和定义,该加权和通过一个非线性函数传递。现在,我们也可以用线性代数来思考这个问题。这是一个重要的视角,原因有二:
- 线性代数的视角将帮助你更快地理解神经网络。
- 它还会使整个事情变得可行,因为矩阵乘法是现代计算机和GPU非常擅长的。没有线性代数,将这些输入与相应权重相乘需要我们对输入进行循环,很快就变得不可行。
线性代数直觉回顾
让我们看几个概念作为复习。如果你已经了解向量、向量空间和矩阵乘法,可以跳过。
向量和向量空间
在表面层面上,向量是一个数字数组。然而,在线性代数中,向量是一个既有大小又有方向的实体。我们举个例子来说明:
$A = \begin{bmatrix} 5 \\ 0 \end{bmatrix}$
我们可以看到这是一个数字数组。但如果我们在二维坐标空间中绘制这个点,我们得到一个点。如果我们从原点画一条线到这个点,我们会得到一个有方向和大小的实体。这就是一个向量。
二维坐标空间称为向量空间。非正式地说,二维向量空间是所有可能的具有两个分量的向量。扩展到n维,一个n维向量空间是所有可能的具有n个分量的向量。
我想留给你的最后直觉是:向量是n维向量空间中的一个点。
矩阵与变换
同样,在表面层面上,矩阵是一个数字的矩形排列,如下所示:
$M = \begin{bmatrix} 1 & 0 \\ 0 & 0 \end{bmatrix}$
矩阵有很多用途,但与我们最相关的一个直觉是,矩阵指定了其所在向量空间的线性变换。当我们用一个向量乘以一个矩阵时,我们实际上是在变换该向量,矩阵的值和维度定义了发生的变换类型。根据矩阵的内容,它执行旋转、反射、缩放、剪切等操作。
我们在
Chapter11文件夹中提供了一个名为01-Linear_Algebra_Intuition.ipynb的笔记本,其中探讨了矩阵乘法作为一种变换。我们还将这些变换矩阵应用于向量空间,以建立关于矩阵乘法如何旋转和扭曲向量空间的直觉。我强烈建议前往扩展阅读部分,那里我们提供了一些资源,以便开始学习并巩固必要的直觉。
如果我们将输入视为特征空间(具有m维的向量空间)中的向量,那么项 $\sum_{i=1}^{m} x_i w_i$ 只不过是一个输入向量的线性组合。我们可以将方程重写为如下向量形式:
$$\hat{y} = g(\mathbb{X}^T \mathbb{W})$$
其中,$\mathbb{X} = \begin{bmatrix} 1 \\ x_1 \\ ... \\ x_m \end{bmatrix}, \ \mathbb{W} = \begin{bmatrix} w_0 \\ w_1 \\ ... \\ w_m \end{bmatrix}$
偏置也作为一个固定值为1的哑输入包含在这里,并将$w_0$ 添加到 $\mathbb{W}$ 向量中。
现在我们已经对深度学习有了初步了解,让我们回顾一下之前讨论的深度学习的一个方面——组合性——并在下一节中更深入地探讨它。
深度学习系统的组成部分
让我们回顾一下杨立昆(Yann LeCun)对深度学习的定义:
“深度学习是一种方法学:通过将参数化的模块组装成(可能是动态的)图,并使用基于梯度的方法对其进行优化来构建模型。”
这里的核心思想是,深度学习是一个极度模块化的系统。深度学习不仅仅是一个模型,而是一种语言,可以用少数具有特定属性的参数化模块来表达任何模型:
- 它应能通过一系列计算从给定输入产生输出。
- 如果给出了期望输出,它应能向其输入传递关于如何改变以到达期望输出的信息。例如,如果输出低于期望值,该模块应能告诉其输入向某个方向改变,以使输出更接近期望值。
数学功底较强的读者可能已经看出了与第二点区别的联系。你是对的。为了优化这类系统,我们主要使用基于梯度的优化方法。因此,将这两个属性合并为一个,我们可以说这些参数化模块应该是可微函数。
让我们借助一张图来帮助进一步讨论。

图11.6:一个深度学习系统
如图图11.6所示,深度学习可以被视为一个系统,它通过一系列线性和非线性变换接收原始输入数据,并为我们提供输出。它还可以通过调整内部参数,使输出尽可能接近期望输出。为了使示意图更简单,我们选择了一种适合大多数流行深度学习系统的范式。一切都从原始输入数据开始。原始输入数据经过N个进行表示学习的线性和非线性函数块。让我们详细探讨这些块。
表示学习
表示学习,通俗地说,学习最好的特征,通过这些特征我们可以使问题线性可分。线性可分意味着我们可以用一条直线将不同类别(在分类问题中)分开(图11.7):

图11.7: 使用函数将非线性可分数据转换为线性可分数据,$\phi$
图11.6中的表示学习块可能包含多个堆叠的线性和非线性函数,该块的总体功能是学习一个函数$\phi$,该函数将原始输入转换为使问题线性可分的良好特征。
另一种视角是通过线性代数来看待。正如我们在本章前面探讨的,矩阵乘法可以看作向量的线性变换。如果我们将这种直觉扩展到向量空间,可以看到矩阵乘法以某种方式扭曲了向量空间。当我们将多个线性和非线性变换堆叠在一起时,我们本质上是在将输入向量空间(带有特征)扭曲、扭转和压缩成另一个空间。当我们让一个参数化系统以执行特定任务(例如区分狗和猫的分类)的方式扭曲输入空间(图像像素)时,表示学习块会学习正确的变换,从而使任务(区分猫和狗)变得更容易。
我制作了一个视频来说明这一点,因为没有什么比动态视频更能建立直觉。我选取了一个非线性可分的样本数据集,训练一个神经网络对其进行分类,然后可视化模型如何将输入空间转换为线性可分的表示。你可以在以下链接找到视频:https://www.youtube.com/watch?v=5xYEa9PPDTE。
现在,让我们看看表示学习块的内部。我们可以看到有一个线性变换和一个非线性激活。
线性变换
线性变换只是应用于向量空间的变换。当我们在神经网络上下文中提到线性变换时,实际上指的是仿射变换。
线性变换在应用变换时固定原点,但仿射变换则不。旋转、反射、缩放等是纯粹的线性变换,因为原点在做这些变换时不会改变。但像平移这样的操作,会移动向量空间,则是仿射变换。因此,A**XT 是线性变换,但 A**XT + b 是仿射变换。
所以,线性变换只是对输入向量空间进行矩阵乘法,这是当今任何神经网络或深度学习系统的核心。
如果我们在线性变换之上堆叠线性变换会发生什么?例如,我们首先将输入X与变换矩阵A相乘,然后将结果与另一个变换矩阵B相乘:
$$T = B \cdot (A \cdot X)$$
根据结合律(同样适用于线性代数),我们可以将等式重写如下:
$$T = (B \cdot A) \cdot X$$
将其推广到由 N 个变换矩阵组成的堆栈,可以发现所有矩阵最终合并为单一的线性变换。这在一定程度上违背了堆叠 N 层的初衷,不是吗?
这正是非线性变得至关重要的地方,我们通过使用非线性函数(称为激活函数)来引入非线性。
激活函数
激活函数 是非线性可微函数。在生物神经元中,轴丘根据输入决定是否发射信号。激活函数起类似作用,是神经网络能够建模非线性数据的关键。换句话说,非正式地讲,激活函数的关键在于将输入向量空间(线性不可分)变换为线性可分的向量空间。为了 展开 空间,使线性不可分的点变得线性可分,我们需要进行非线性变换。
我们重复了上一节中的实验,可视化了神经网络在输入向量空间上的训练后变换,但这次没有使用任何非线性。生成的视频可在此处查看:https://www.youtube.com/watch?v=z-nV8oBpH2w。模型学到的最佳变换仍然不足,点依旧线性不可分。
理论上,激活函数可以是任何非线性可微(确切地说,是几乎处处可微)函数。然而,随着时间推移,有几种非线性函数被广泛用作激活函数。让我们来看其中几种。
Sigmoid
Sigmoid 是最常见的激活函数之一,可能也是最古老的之一。它也被称为 logistic 函数。当讨论感知机时,我们提到阶跃函数(文献中也称为 Heaviside 函数)作为激活函数。阶跃函数不是连续函数,因此不是处处可微。一个非常接近的替代是 sigmoid 函数。
其定义如下:
$$g(x) = \frac{1}{1 + e^{-x}}$$
其中 g 是 Sigmoid 函数,x 是输入值。
Sigmoid 是一个连续函数,因此处处可微。其导数计算也更为简单。由于这些特性,Sigmoid 在深度学习早期被广泛采用作为标准激活函数。
让我们看看 Sigmoid 函数的形状以及它如何变换向量空间:

图11.8:Sigmoid 激活函数(左)以及原始与激活后的向量空间(中、右)
Sigmoid 函数将输入压缩到 0 和 1 之间,如图11.8(左)所示。我们可以在向量空间中观察到相同现象。Sigmoid 函数的缺点之一是,在函数的平坦部分梯度趋于零。当神经元接近函数中的这个区域时,它接收和传播的梯度变得可以忽略不计,单元停止学习。我们称之为激活饱和。因此,如今 Sigmoid 通常不在深度学习中使用,除了输出层(我们很快就会讨论这个用途)。
双曲正切(tanh)
双曲正切是另一种流行的激活函数。它们可以简单定义如下:
$$\tanh(x) = \frac{\sinh(x)}{\cosh(x)}$$
它与 Sigmoid 非常相似。实际上,我们可以将 tanh 表示为 Sigmoid 的函数。让我们看看这个激活函数的形状:

图11.9:Tanh激活函数(左)以及原始和激活后的向量空间(中、右)
我们可以看到,其形状与sigmoid相似,但略为尖锐。但关键区别在于,tanh函数输出介于-1到1之间的值。而且由于尖锐度,我们还可以看到向量空间被推向边缘。函数输出关于原点(0)对称,这一特性有利于网络优化,因此tanh比sigmoid更受青睐。但由于tanh函数也是一种饱和函数,同样存在梯度极小阻碍梯度流动进而影响学习的问题,这同样困扰着tanh激活函数。
修正线性单元及其变体
随着神经科学对人脑的了解不断加深,研究人员发现大脑中只有1%到4%的神经元在任何时刻被激活。但对于所有激活函数,如sigmoid 或 tanh,网络中几乎一半的神经元都被激活。2010年,Vinod Nair和Geoffrey Hinton在开创性论文Rectified Linear Units Improve Restricted Boltzmann Machines中提出了修正线性单元(ReLUs)。自此,ReLUs成为深度神经网络的事实激活函数。
ReLU
ReLU的定义如下:定义如下:
g((x) = ) = max((x, 0), 0)
它只是一个线性函数,但在零点处有一个转折。所有大于零的值保持不变,但所有小于零的值被压缩到零。输出范围从0到$\infty$。让我们看看它的视觉效果:

图11.10:ReLU激活函数(左)以及原始和激活后的向量空间(中、右)
我们可以看到,左象限和底象限的点都被推到了坐标轴线上。这种压缩正是激活函数具有非线性的原因。由于激活函数急剧变为零,而不像sigmoid或tanh那样趋近于零,因此ReLU是非饱和的。
参考文献核实:
提出ReLU的研究论文在参考文献中引用为参考文献7。
使用ReLU有几个优点:
- 激活函数及其梯度的计算非常廉价。
- 训练收敛速度远快于使用饱和激活函数的网络。
- ReLU有助于在网络中引入稀疏性(通过将激活设为0,可以关闭网络中大部分神经元),并且类似于生物神经元的工作方式。
但ReLU并非没有问题:
- 当x < 0时,梯度变为零。这意味着输出小于0的神经元的梯度为零,因此该单元将不再学习。这被称为死亡ReLU。
- 另一个缺点是ReLU单元的平均输出为正,当我们堆叠多层时,这可能导致输出中的正偏置。
让我们看看几种试图解决我们讨论的ReLU问题的变体。
Leaky ReLU和参数化ReLU
Leaky ReLU是标准ReLU的一种变体,它解决了死亡ReLU问题。它由Maas等人在2013年提出。Leaky ReLU可以定义如下:
$$g(x) = \begin{cases} x, & \text{if } x \geq 0 \\ \alpha x, & \text{if } x \lt 0 \end{cases}$$
这里,$\alpha$ 是斜率参数(通常设为非常小的值,如0.001),被视为超参数。这确保了当 x < 0 时梯度不为零,从而确保没有死亡ReLU。但ReLU提供的稀疏性在此丢失,因为没有完全关闭单元的零输出。让我们可视化这个激活函数:

图11.11: Leaky ReLU激活函数(左)和原始及激活后的向量空间(中、右)
2015年,K. He等人对leaky ReLU提出了另一个小修改,称为参数化ReLU。在参数化ReLU中,他们没有将$\alpha$视为超参数,而是将其视为可学习参数。
参考文献检查:
提出leaky ReLU的研究论文在参考文献中引用为文献8,参数化ReLU引用为文献9。
还有许多其他不太常用的激活函数,但它们仍有足够的用例,被包含在PyTorch中。你可以在这里找到它们的列表:https://pytorch.org/docs/stable/nn.html#non-linear-activations-weighted-sum-nonlinearity。我们建议你使用名为02-Activation_Functions.ipynb的笔记本(位于Chapter 11文件夹中),尝试不同的激活函数,观察它们如何扭曲向量空间。
至此,我们了解了图11.6中第一个模块(表示学习)的组成部分。下一个模块是线性分类器,它包含一个线性变换和一个输出激活函数。我们已经知道线性变换是什么,但什么是输出激活函数?
输出激活函数
输出激活函数是那些对网络输出施加一些期望属性的函数。
扩展阅读:
这些函数与最大似然估计(MLE)以及所选损失函数有更深层的联系,但我们不会深入讨论,因为这超出了本书的范围。我们在深入阅读部分提供了由Ian Goodfellow、Yoshua Bengio和Aaron Courville所著的《深度学习》一书。如果你对深度学习的更深入理解感兴趣,我们建议你阅读该书。
如果我们希望神经网络在回归情况下预测连续数值,只需使用线性激活函数(这相当于没有激活函数)。网络的原始输出被视为预测值,并传入损失函数。
但在分类情况下,期望输出是所有可能类别中的一个类别。如果只有两个类别,我们可以使用老朋友——sigmoid函数,其输出在0和1之间。我们也可以使用tanh函数,因为它的输出在-1和1之间。sigmoid函数更受欢迎,因为它具有直观的概率解释性。值越接近1,网络对该预测越有信心。
现在,sigmoid适用于二分类。那么多分类(可能类别超过两个)呢?
Softmax
Softmax是一种函数,它将一个K个实数值的向量转换为另一个K个正实数值的向量,这些值之和为1。Softmax定义如下:
$$Softmax(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{K} e^{x_j}}$$
这个函数将网络的原始输出转换为类似于K个类别概率的东西。这与sigmoid有很强的关联——当K=2时,sigmoid是softmax的特例。在下图中,我们看看一个大小为3的随机向量如何被转换为总和为1的概率:

图11.12: 原始输出与softmax输出对比
如果我们仔细观察,可以看到除了将实数值转换为类似于概率的东西外,它还增大了最大值与其他值之间的相对差距。这种激活函数是多分类问题的标准输出激活函数。
现在,图中(图11.6)只剩下一个主要组件——损失函数。
损失函数
我们在第5章《时间序列预测作为回归》中提到的损失函数,很好地迁移到了深度学习。在深度学习中,损失函数也是衡量模型预测好坏的一种方式。如果预测与目标相差甚远,损失函数就会更高;随着我们接近真实值,它会变得更小。在深度学习范式中,我们对损失函数有一个额外的要求——它必须是可微的。
经典的机器学习中常见的损失函数,例如均方误差或平均绝对误差,在深度学习中同样有效。实际上,在回归任务中,它们是实践者默认的选择。对于分类任务,我们采用一个从信息论中借来的概念,称为交叉熵损失。然而,由于深度学习是一个非常灵活的框架,我们可以使用任何损失函数,只要它是可微的。有很多损失函数已经被人尝试过并发现能在许多情况下工作。其中很多也是PyTorch API的一部分。你可以在这里找到它们:https://pytorch.org/docs/stable/nn.html#loss-functions。
既然我们已经涵盖了深度学习系统的所有组件,让我们也简要看一下如何训练整个系统。
前向传播和反向传播
在图11.6中,我们可以看到两组箭头:一组从输入指向期望输出,标记为正向计算;另一组从期望输出反向指向输入,标记为反向计算。这两个步骤是学习深度学习系统的核心。在正向计算中,通常称为前向传播,我们使用在层中定义的一系列计算,将输入一直传播到网络以得到输出。得到输出后,我们会使用损失函数来评估我们与期望输出的接近程度。这个信息现在用于反向计算,通常称为反向传播,以计算所有参数的梯度。
那么,什么是梯度,为什么我们需要它?在高中数学中,我们可能以另一种形式遇到梯度或导数,即斜率。它是当变量改变一个单位时,量的变化率。导数告诉我们标量函数的局部斜率。虽然导数总是针对单个变量,但梯度是导数在多变量函数中的推广。直观上,梯度和导数都告诉我们函数的局部斜率。有了损失函数的梯度,我们可以使用数学优化中的一种技术,称为梯度下降,来优化我们的损失函数。
让我们通过一个例子来看看。
梯度下降
任何机器学习或深度学习模型都可以视为一个函数,它将输入 x 转换为输出 $\hat{y}$,使用一些参数 $\theta$。这里,$\theta$ 可以是我们在整个网络中对输入进行的所有矩阵变换的集合。但为了简化示例,我们假设只有两个参数 a 和 b。如果我们稍加思考学习的过程,会发现在保持输入和期望输出相同的情况下,改变损失的方式就是改变模型的参数。因此,我们可以将损失函数视为由参数(这里是 a 和 b)参数化的。
笔记本提示:
要跟随完整代码,请使用 03-Gradient_Descent.ipynb 文件夹中的笔记本 03-Gradient_Descent.ipynb 以及 Chapter11 文件夹中的代码和 src 文件夹中的代码。
让我们假设损失函数采用以下形式:
$$\mathcal{L}(a, b) = (a - 8)^2 + (b - 2)^2$$
让我们看看这个函数是什么样子的。我们可以使用三维图来可视化具有两个参数的函数,如图11.13所示。两个维度用于表示两个参数,在该二维网格的每个点处,我们可以在第三维中绘制损失值。
这种损失函数的图也称为损失曲线(单变量情况)或损失曲面(多变量情况)。

图11.13: 损失曲面图
三维形状中较亮的部分是损失函数较小的区域,当我们远离那里时,损失会增大。
在机器学习中,我们的目标是最小化损失函数,换句话说,找到使我们的预测输出尽可能接近真实值的参数。这属于数学优化的范畴,有一种特殊的技术非常适合这种方法——梯度下降。
梯度下降是一种数学优化算法,通过迭代地沿最陡下降方向移动来最小化代价函数。在单变量函数中,导数(或斜率)给出了最陡上升的方向(和幅度)。例如,如果我们知道一个函数的斜率为1,那么向右移动时我们是在上坡,向左移动时则是下坡。类似地,在多变量情况下,函数在任意点的梯度给出了最陡上升的方向(和幅度)。由于我们关注的是最小化损失函数,我们将使用负梯度,它指向最陡下降的方向。
那么,让我们为损失函数定义梯度。我们使用高中微积分知识,但即使你不熟悉,也无需担心:
$$\nabla f(a, b) = \begin{bmatrix} \frac{df}{da} \\ \frac{df}{db} \end{bmatrix} = \begin{bmatrix} 2(a - 8) \\ 2(b - 2) \end{bmatrix}$$
现在,算法是如何工作的?非常简单,步骤如下:
- 将参数初始化为随机值。
- 计算该点的梯度。
- 沿梯度相反方向迈一步。
- 重复步骤2和3,直到收敛或达到最大迭代次数。
还有一个方面需要更明确:每次迭代中我们迈多大步?
理想情况下,梯度的幅值告诉我们函数在该方向的变化速度,我们应该迈出等于梯度大小的步长。但梯度的某个属性使得这样做并不明智。梯度仅定义了当前点无穷小邻域内最陡上升的方向和幅值,而对更远的情况视而不见。因此,我们使用一个超参数,通常称为学习率,来调节每次迭代的步长。因此,我们不迈出等于梯度的步长,而是迈出等于学习率乘以梯度的步长。
数学上,如果$\theta$是参数向量,则在每次迭代中,我们使用以下公式更新参数:
$$\theta = \theta - \eta \times \Delta f(a, b)$$
这里,$\eta$是学习率,并且$\Delta f$是该点的梯度。
让我们看一个非常简单的梯度下降实现(参见GitHub仓库中的notebook以获取完整的定义和工作代码)。首先,我们定义一个返回任意点梯度的函数:
def gradient(a, b):
return 2*(a-8), 2*(b-2)
现在我们定义几个初始参数,如最大迭代次数、学习率和a与b的初始值:
# maximum number of iterations that can be done
maximum_iterations = 500
# current iteration
current_iteration = 0
# Learning Rate
learning_rate = 0.01
#Initial value of a, b
current_a_value = 28
current_b_value = 27
Now, all that is left is the actual process of gradient descent:
while current_iteration < maximum_iterations:
previous_a_value = current_a_value
previous_b_value = current_b_value
# Calculating the gradients at current values
gradient_a, gradient_b = gradient(previous_a_value, previous_b_value)
# Adjusting the parameters using the gradients
current_a_value = current_a_value - learning_rate * gradient_a * (previous_a_value)
current_b_value = current_b_value - learning_rate * gradient_b * (previous_b_value)
current_iteration = current_iteration + 1
我们知道该函数的最小值在a = 8和b = 2处,因为这样会使损失函数为零。而梯度下降找到了一个相当精确的解——a = 8.000000000000005和b = 2.000000002230101。我们还可以绘制它到达最小值所走的路径,如图11.14所示:

图11.14:损失曲面上的梯度下降优化
我们可以看到,即使我们将参数初始化得远离实际原点,优化算法也会直接路径走向最优点。在每一点,算法查看该点的梯度,沿相反方向移动,最终收敛到最优点。
当梯度下降被应用于学习任务时,需要注意一些细节。假设我们有一个包含N个样本的数据集。在机器学习中有三种常用的梯度下降变体,它们各有优缺点。
批量梯度下降
我们将所有N个样本通过网络,并计算所有N个实例的平均损失。然后使用这个损失来计算梯度,沿正确方向迈出一步,然后重复。
优点如下:
- 优化路径是直接的。
- 优化路径有收敛保证。
缺点如下:
- 单步需要评估整个数据集,计算代价高昂。对于大型数据集,每步的计算量变得过高。
- 每步优化所需时间长,因此收敛也会慢。
随机梯度下降(SGD)
在SGD中,我们从N个样本中随机抽取一个样本,计算损失和梯度,然后更新参数。
优点如下:
- 由于我们只使用单个实例进行优化步骤,每个优化步骤的计算量非常低。
- 每个优化步骤所需的时间也更快。
- 随机抽样还起到正则化作用,有助于避免过拟合。
缺点如下:
- 梯度估计是有噪声的,因为我们只基于一个实例进行步骤。因此,通往最优的路径将是颠簸且嘈杂的。
- 仅仅因为每次优化所需的时间低,并不意味着收敛更快。由于梯度估计有噪声,我们可能多次未能迈出正确的步长。
小批量梯度下降
小批量梯度下降是一种介于批量梯度下降和SGD之间的技术。在这种变体中,我们有一个称为小批量大小(或简称批量大小)的参数b。在每个优化步骤中,我们从N个样本中随机抽取b个实例,并计算所有b个实例的平均损失上的梯度。当b = N时,我们得到批量梯度下降;当b = 1时,我们得到随机梯度下降。这是当今神经网络训练最流行的方法。通过改变批量大小,我们可以在两种变体之间切换,并管理每种选择的优缺点。
没有什么比一个可视化游乐场更能培养直觉了,在那里我们可以看到我们讨论的不同组件的效果。Tensorflow Playground是一个极好的资源(参见进一步阅读部分的链接)来实现这一点。我强烈建议您前往那里,使用该工具,直接在浏览器中训练几个神经网络,并实时观察学习过程是如何进行的。
小结
本书新的一部分以深度学习的介绍开始。我们先回顾了一些历史,以理解为什么深度学习如今如此流行,并探索了其在感知机中的简陋起源。我们理解了深度学习的可组合性,并剖析了深度学习的不同组成部分,如表示学习块、线性层、激活函数等。最后,我们通过观察深度学习系统如何利用梯度下降从数据中学习,圆满结束了讨论。有了这些理解,我们现在准备进入下一章,在那里我们将把叙述引向时间序列模型。
参考文献
以下是本章使用的参考文献列表:
- Kyoung-Su Oh and Keechul Jung. (2004), GPU implementation of neural networks. Pattern Recognition, Volume 37, Issue 6, 2004: https://doi.org/10.1016/j.patcog.2004.01.013..
- Rajat Raina, Anand Madhavan, and Andrew Y. Ng. (2009), Large-scale deep unsupervised learning using graphics processors. In Proceedings of the 26th Annual International Conference on Machine Learning (ICML ‘09): https://doi.org/10.1145/1553374.1553486..
- Alex Krizhevsky, Ilya Sutskever, and Geoffrey E. Hinton. (2012), ImageNet Classification with Deep Convolutional Neural Networks. Commun. ACM 60, 6 (June 2017), 84–90: https://doi.org/10.1145/3065386..
- Neil C. Thompson, Kristjan Greenewald, Keeheon Lee, and Gabriel F. Manso. (2020). The Computational Limits of Deep Learning. arXiv:2007.05558v1 [cs.LG]: https://arxiv.org/abs/2007.05558v1..
- Frank Rosenblatt. (1957), The perceptron – A perceiving and recognizing automaton, Technical Report 85-460-1, Cornell Aeronautical Laboratory.
- Charu C. Aggarwal, Alexander Hinneburg, and Daniel A. Keim. (2001). On the Surprising Behavior of Distance Metrics in High Dimensional Spaces. In Proceedings of the 8th International Conference on Database Theory (ICDT ‘01). Springer-Verlag, Berlin, Heidelberg, 420–434:https://dl.acm.org/doi/10.5555/645504.656414..
- Nair, V. and Hinton, G.E. (2010). Rectified Linear Units Improve Restricted Boltzmann Machines. ICML: https://icml.cc/Conferences/2010/papers/432.pdf..
- Andrew L. Maas, Awni Y. Hannun, and Andrew Y. Ng. (2013). Rectifier nonlinearities improve neural network acoustic models. ICML Workshop on Deep Learning for Audio, Speech, and Language Processing: https://ai.stanford.edu/~amaas/papers/relu_hybrid_icml2013_final.pdf..
- Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun (2015). Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification. 2015 IEEE International Conference on Computer Vision (ICCV), 1026-1034: https://ieeexplore.ieee.org/document/7410480..
- Sara Hooker. (2021). 硬件抽奖. Commun. ACM, 第64卷: https://doi.org/10.1145/3467017..
延伸阅读
如果你想进一步了解本章涉及的一些主题,可以查阅以下资料:
- 线性代数课程,来自Gilbert Strang: https://ocw.mit.edu/resources/res-18-010-a-2020-vision-of-linear-algebra-spring-2020/videos/
- 线性代数的本质,来自3Blue1Brown: https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab
- 神经网络——线性代数视角,作者Manu Joseph: https://deep-and-shallow.com/2022/01/15/neural-networks-a-linear-algebra-perspective/
- 深度学习 – Ian Goodfellow, Yoshua Bengio, Aaron Courville:https://deep-and-shallow.com/2022/01/15/neural-networks-a-linear-algebra-perspective/
- Tensorflow Playground: : https://playground.tensorflow.org/