大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
个人主页-Sonhhxg_柒的博客_CSDN博客
欢迎各位→点赞 + 收藏⭐️ + 留言
系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟
文章目录
神经网络的基本要素
神经网络的数学装置
线性代数
向量和矩阵运算
概率导论
概率和集合
条件概率和贝叶斯规则
随机变量和概率分布
概率分布
信息论
微积分
神经网络的简短介绍
神经元
层作为操作
神经网络
激活函数
普遍逼近定理
训练神经网络
梯度下降
成本函数
反向传播
权重初始化
SGD 改进
概括
本节将讨论一些核心深度学习( DL ) 概念:DL 到底是什么,DL 算法的数学基础,以及使快速开发 DL 算法成为可能的库和工具。
在本章中,我们将讨论神经网络 (NN) 的一些复杂性——深度学习( DL )的基石。我们将讨论他们的数学仪器、结构和训练。我们的主要目标是让您系统地了解NN。通常,我们从计算机科学的角度来处理它们——作为机器学习(ML) 算法(甚至是特殊实体)由许多不同的步骤/组件组成。我们通过从神经元、层等方面进行思考来获得直觉(至少我在第一次了解这个领域时是这样做的)。这是一种完全有效的做事方式,我们仍然可以在这种理解水平上做出令人印象深刻的事情。不过,也许这不是正确的方法。
NN 具有扎实的数学基础,如果我们从这个角度来处理它们,我们将能够以更基本和更优雅的方式来定义和理解它们。因此,在本章中,我们将尝试从数学和计算机科学的角度强调 NN 之间的类比。如果您已经熟悉这些主题,则可以跳过本章。尽管如此,我还是希望你能找到一些你还不知道的有趣的东西(我们将尽最大努力让本章保持有趣!)。
在本章中,我们将介绍以下主题:
在接下来的几节中,我们将讨论与 NN 相关的数学分支。完成此操作后,我们会将它们连接到 NN 本身。
线性代数处理线性方程,例如线性变换(或线性函数)及其表示,例如矩阵和向量。
线性代数识别以下数学对象:
我们可以将一个n维向量直观地表示为n维欧几里得空间中一个点的坐标(相当于一个坐标系)。在这种情况下,向量被称为欧几里得,每个向量分量代表沿相应轴的坐标,如下图所示:
然而,欧几里得向量不仅仅是一个点,我们还可以用以下两个属性来表示它:
我们可以将向量表示为单列n×1矩阵(称为列矩阵)或单列1×n矩阵(称为行矩阵)。
TensorFlow 和 PyTorch 等当代 DL 库使用张量作为其主要数据结构。
现在我们已经介绍了线性代数中的对象类型,在下一节中,我们将讨论一些可以应用于它们的操作。
在本节中,我们将讨论与 NN 相关的向量和矩阵运算。开始吧:
在这里,| 一个| 和 | 乙| 是矢量幅度,θ 是两个矢量之间的角度。让我们假设这两个向量是n维的,并且它们的分量是a 1、b 1、a 2、b 2等等。这里,前面的公式等价于:
点积作为两个向量之间的一种相似性度量——如果两个向量之间的夹角 θ 很小(向量具有相似的方向),则它们的点积会更高,因为.
下图显示了两个二维向量之间的叉积示例:
正如我们之前提到的,输出向量垂直于输入向量,这也意味着向量垂直于包含它们的平面。输出向量的大小等于边的向量a和b的平行四边形的面积(如上图所示)。
我们可以将矩阵的每一行视为一个单独的n维向量。这里,输出向量的每个元素是对应矩阵行和x之间的点积。下面是一个数值示例:
如果我们将两个向量视为行矩阵,我们可以将向量点积表示为矩阵乘法,即。
我们对线性代数的介绍到此结束。在下一节中,我们将介绍概率论。
在本节中,我们将讨论与 NN 相关的概率和统计的一些方面。
让我们从引入统计实验的概念开始,它具有以下属性:
统计实验的一个例子是抛硬币,它有两种可能的结果——正面或反面。另一个例子是掷骰子,有六种可能的结果:1、2、3、4、5 和 6。
我们将概率定义为某个事件 e发生的可能性,我们将用 P(e)来表示它。概率是 [0, 1] 范围内的数字,其中 0 表示事件不会发生,1 表示它总是会发生。如果P(e) = 0.5,则事件发生的可能性为 50-50,依此类推。
有两种方法可以接近概率:
为了理解这一点,让我们使用抛硬币的例子,它有两种可能的结果。每个可能结果的理论概率是 P(heads) = P(tails) = 1/2。掷骰子每一面的理论概率为 1/6。
实验的结果可能表明这些事件的可能性不同。例如,假设我们抛硬币 100 次,观察正面 56 次。这里,正面的经验概率是 P(heads) = 56 / 100 = 0.56。试验次数越多,计算出的概率就越准确(这就是所谓的大数定律)。
在下一节中,我们将讨论集合上下文中的概率。
实验的所有可能结果(事件)的集合称为样本空间。我们可以将样本空间视为一个数学集。它通常用大写字母表示,我们可以用 {} 列出所有集合结果(与 Python 集合相同)。例如,抛硬币事件的样本空间是 S c = {heads, tails},而对于骰子行,它是 S d = {1, 2, 3, 4, 5, 6}。集合的单个结果(例如正面)称为样本点。事件是样本空间的一个结果(样本点)或结果的组合(子集)。组合事件的一个示例是骰子落在偶数上,即 {2, 4, 6}。
假设我们有一个样本空间 S = {1, 2, 3, 4, 5} 和两个子集(事件)A = {1, 2, 3} 和 B = {3, 4, 5}。在这里,我们可以对它们进行以下操作:
交集为空集 {} 的集合是不相交的。
以下维恩图说明了这些不同的集合关系:
我们可以将集合属性传递给事件及其概率。我们将假设事件是独立的——一个事件的发生不会影响另一个事件发生的概率。例如,不同抛硬币的结果是相互独立的。话虽如此,让我们学习如何翻译事件域中的集合操作:
假设我们要计算一张牌是红色(红心或方块)和杰克的概率。红色的概率是P(red) = 26/52 = 1/2。获得杰克的概率是P(Jack) = 4/52 = 1/13。因此,联合概率为P(red, Jack) = (1/2) * (1/13) = 1/26。在这个例子中,我们假设这两个事件是独立的。然而,这两个事件同时发生(我们抽一张牌)。如果它们连续发生,例如,两张牌,一张是杰克,另一张是红色,我们将进入条件概率领域。这种联合概率也表示为 P(A, B) 或 P(AB)。
单个事件发生的概率 P(A) 也称为边际概率(与联合概率相反)。
如果我们同时只有两个不相交且共同穷举的事件,则这些事件是互补的。例如,奇数和偶数掷骰子事件是互补的。
到目前为止,我们已经讨论了独立事件。在下一节中,我们将重点关注依赖项。
如果事件A的发生改变了事件B发生的概率,其中A发生在B之前,那么两者是相关的。为了说明这个概念,让我们假设我们从一副牌中依次抽出多张牌。当牌堆满时,抽到红心的概率是P(hearts) = 13/52 = 0.25。但是一旦我们抽到了第一张牌,第二回合选红心的概率就会改变。现在,我们只有 51 张牌,少了一颗心。我们将第二次抽奖的概率称为条件概率,并用 P(B|A) 表示。假设事件 A 已经发生(第一次平局),这是事件B (第二次平局)的概率。继续我们的例子,第二次抽红心的概率变为P(hearts 2|心1 ) = 12/51 = 0.235。
接下来,我们可以根据相关事件扩展联合概率公式(在上一节中介绍)。公式如下:
但是,前面的等式只是两个事件的特例。我们可以将其进一步扩展到多个事件 A 1、 A 2、...、A n。这个新的通用公式被称为概率链规则:
例如,三个事件的链式规则如下:
我们还可以推导出条件概率本身的公式:
这个公式是有意义的,原因如下:
使用这个等式,我们可以将条件概率公式中的P(A ∩B) 的值替换为:
如果我们知道相反的条件概率 P(B|A),前面的公式使我们能够计算条件概率P(B|A)。这个方程被称为贝叶斯规则,经常在机器学习中使用。在贝叶斯统计的上下文中,P(A) 和 P(B|A) 分别称为先验概率和后验概率。
贝叶斯规则可以在医学测试领域进行说明。假设我们要确定患者是否患有特定疾病。我们进行了体检,结果呈阳性。但这并不一定意味着患者患有这种疾病。大多数测试都有一个可靠性值,即对患有特定疾病的人进行测试时呈阳性的百分比。使用他的信息,我们将应用贝叶斯规则来计算患者患病的实际概率,假设测试是阳性的。我们得到以下信息:
这里,P(has disease)是没有任何先验条件的疾病的一般概率。将此视为一般人群中疾病的概率。
接下来,让我们对疾病和测试的准确性做一些假设:
我们可以问以下问题:如果一项测试对癌症的准确率为 98%,如果一个 45 岁的人接受了测试,结果是阳性,那么他们患上这种疾病的概率是多少?使用前面的公式,我们可以计算以下内容:
在下一节中,我们将超越概率,我们将讨论随机变量和概率分布。
在统计学中,我们将变量定义为描述给定实体的属性。属性的值可能因实体而异。例如,我们可以用一个变量来描述一个人的身高,这对于不同的人来说会有所不同。但是假设我们多次测量同一个人的身高。由于一些随机因素,例如人的姿势或我们自己的测量不准确,我们可以期望每次获得稍微不同的值。因此,尽管我们测量的是同一事物,但变量高度的值会有所不同。为了解释这些变化,我们将引入随机变量。这些变量的值由一些随机事件决定。与常规变量不同,
有两种类型的随机变量:
Discrete,可以采用不同的单独值。例如,足球比赛中的进球数是一个离散变量。
Continuous,可以在给定间隔内取任何值。例如,高度测量是一个连续变量。
随机变量用大写字母表示,随机变量X的某个值x的概率用P(X = x)或p(x)表示。随机变量的每个可能值的概率集合称为概率分布。根据变量类型,我们有两种概率分布:
PMF 仅针对随机变量的可能值定义。PMF 的所有值都是非负的,它们的和为 1。也就是说,PMF 的事件是互斥的,并且是共同穷举的。我们将用 P(X) 表示 PMF,其中 X 是随机变量。
在 PDF 中,概率是针对一个值区间计算的,并由曲线下的表面积给出,由该区间包围(这是上图中的标记区域)。曲线下的总面积为 1。我们将用f X表示 PDF ,其中 X 是随机变量。
接下来,让我们关注随机变量的一些性质:
让我们以前面的离散变量示例为例,其中我们定义了一个具有六个可能值(0、1、2、3、4、5)及其各自概率(0.1、0.2、0.3、0.2、0.1、0.1)的随机变量)。这里,平均值为μ = 0*0.1 + 1*0.2 + 2*0.3 + 3*0.2 + 4*0.1 + 5*0.1 = 2.3。
连续变量的均值定义如下:
虽然使用离散变量,我们可以将 PMF 视为查找表,但 PDF 可能更复杂(实际函数或方程),这就是为什么两者之间存在不同符号的原因。我们不会进一步详细介绍连续变量的均值。
换句话说,方差衡量随机变量的值与其平均值的差异。
离散随机变量的方差如下:
让我们使用前面的示例,我们计算的平均值为 2.3。新的方差将为Var(X) = (0 - 2.3) 2 * 0 + (1 - 2.3) 2 * 1 + ... + (5- 2.3) 2 * 5 = 2.01。
连续变量的方差定义如下:
我们还可以根据标准差定义方差:
标准差和方差的区别在于,标准差用与平均值相同的单位表示,而方差用平方单位。
在本节中,我们定义了什么是概率分布。接下来,让我们讨论不同类型的概率分布。
我们将从二项式实验中离散变量的二项式分布开始。二项式实验只有两种可能的结果:成功或失败。它还满足以下要求:
二项式实验的一个例子是掷硬币实验。
现在,让我们假设实验由n次试验组成。其中x是成功的,而每次试验的成功概率为p。变量 X 的二项式 PMF 的公式(不要与x混淆)如下:
这里,是二项式系数。这是x次成功试验的组合数,我们可以从n次总试验中选择。如果n=1,那么我们有一个二项分布的特殊情况,称为伯努利分布。
接下来,让我们讨论连续变量的正态(或高斯)分布,它非常接近许多自然过程。正态分布用以下指数 PDF 公式定义,称为正态方程(最流行的符号之一):
这里,x是随机变量的值,μ是均值,σ是标准差,σ 2是方差。上述等式产生了一条钟形曲线,如下图所示:
正态分布
让我们讨论正态分布的一些属性,没有特别的顺序:
具有不同μ和σ值的正态分布示例
在下一节中,我们将介绍信息论的多学科领域,这将有助于我们在 NN 的上下文中使用概率论。
信息论试图确定一个事件所具有的信息量。信息量遵循以下原则:
我们将定义事件x的信息量(或自我信息量)如下:
这里,log是自然对数。例如,如果事件的概率是P(x) = 0.8,那么I(x) = 0.22。或者,如果P(x) = 0.2,则I(x) = 1.61。我们可以看到,事件信息内容与事件概率是相反的。自我信息量 I(x) 以自然信息单位 ( nat ) 衡量。我们还可以使用以 2 为底的对数来计算 I(x) ,在这种情况下,我们以位为单位进行测量。两个版本之间没有主要区别。出于本书的目的,我们将坚持使用自然对数版本。
让我们讨论一下为什么我们在前面的公式中使用对数,即使负概率也会满足自我信息和概率之间的互易性。主要原因是对数的乘积和除法规则:
这里,x 1和x 2是标量值。无需过多详细说明,请注意,这些属性使我们能够轻松地在网络训练期间最小化误差函数。
到目前为止,我们已经定义了单个结果的信息内容。但是其他结果呢?为了测量它们,我们必须测量随机变量概率分布的信息量。让我们用 I( X ) 来表示它,其中X是一个随机离散变量(我们将在这里关注离散变量)。回想一下,在随机变量和概率分布部分,我们将离散随机变量的平均值(或期望值)定义为所有可能值的加权和乘以它们的概率。我们将在这里做类似的事情,但我们将每个事件的信息内容乘以该事件的概率。
该度量称为香农熵(或仅称为熵),定义如下:
这里,x i代表离散变量值。与低概率事件相比,概率较高的事件将具有更大的权重。我们可以将熵视为有关概率分布的事件(结果)的预期(平均)信息量。为了理解这一点,让我们尝试计算熟悉的抛硬币实验的熵。我们将计算两个例子:
我们可以看到,当结果的可能性相同时,熵最高,而当一个结果变得普遍时,熵会降低。从某种意义上说,我们可以将熵视为对不确定性或混沌的度量。下图显示了一个二元事件(例如抛硬币)上的熵H (X)的图表,取决于两个结果的概率分布:
左:自然对数的熵;右:以 2 为底的对数的熵
接下来,让我们假设我们有一个离散随机变量X和两个不同的概率分布。这通常是 NN 产生一些输出概率分布Q ( X ) 并且我们在训练期间将其与目标分布P ( X ) 进行比较的场景。我们可以用交叉熵来衡量这两个分布之间的差异,交叉熵定义如下:
例如,让我们计算前面抛硬币场景的两个概率分布之间的交叉熵。我们已经预测分布Q(heads) = 0.2, Q(tails) = 0.8和目标(或真实)分布P(heads) = 0.5, P(tails) = 0.5。交叉熵如下:
衡量两个概率分布之间差异的另一种方法是Kullback-Leibler 散度(KL 散度):
对数的乘积规则帮助我们将第一行公式转换为第二行更直观的形式。更容易看出 KL 散度衡量了目标和预测对数概率之间的差异。如果我们进一步推导出方程,我们还可以看到熵、交叉熵和 KL 散度之间的关系。
在下一节中,我们将讨论微积分领域,这将有助于我们训练神经网络。
在 ML 中,我们经常对如何通过调整 ML 算法的参数来逼近某个目标函数感兴趣。如果我们将 ML 算法本身视为一个数学函数(NN 就是这种情况),我们想知道当我们改变它的一些参数(权重)时,该函数的输出是如何变化的。值得庆幸的是,微积分处理函数相对于函数所依赖的变量的变化率。以下是对衍生品的(非常)简短的介绍。
假设我们有一个函数f(x),它有一个参数x,它具有以下图形:
f(x)和斜率的图形(红色点划线)
通过计算函数在该点的斜率,我们可以得到关于f(x)在任意 x 值处如何相对于x变化的相对概念。如果斜率为正,则函数增加。相反,如果它是负数,它会减少。我们可以使用以下等式计算斜率:
这里的想法很简单——我们计算f在x和x+Δx 处的两个值之间的差:Δy = f(x + Δx) - f(x)。然后,我们计算Δy和Δx的比值,得到斜率。但是如果Δx太大,则测量不会很准确,因为x和x+Δx之间的函数图部分可能会发生剧烈变化。我们可以使用更小的Δx来最小化这个误差;在这里,我们可以专注于图表的一小部分。如果Δx接近 0,我们可以假设斜率反映了图形的单个点。在这种情况下,我们将斜率称为f(x)的一阶导数。我们可以通过以下等式用数学术语表达这一点:
这里,f'(x)和dy / dx分别是拉格朗日和莱布尼茨的导数符号。是极限的数学概念——我们可以认为它是Δx接近 0。求f导数的过程称为微分。下图显示了不同x值的斜率:
我们可以看到f的局部最小值和局部最大值处的斜率为0——在这些点(称为鞍点),随着x的变化, f既不会增加也不会减少。
接下来,假设我们有一个多参数的函数,。f对任何参数x i的导数称为偏导数,记为。在计算偏导数时,我们假设所有其他参数, 是常数。我们将用 表示向量的分量的偏导数。
最后,让我们提一些有用的区分规则:
神经网络和神经网络本身的数学工具形成了一种知识层次。如果我们将实现神经网络视为建造房屋,那么数学装置就像搅拌混凝土。我们可以学习如何独立于如何建造房屋来混合混凝土。事实上,除了建造房屋的特定目标之外,我们还可以将混凝土用于多种目的。但是,我们需要知道如何在建造房屋之前搅拌混凝土。继续我们的类比,现在我们知道如何混合混凝土(数学仪器),我们将专注于实际建造房屋(NN)。
NN 是一个试图逼近另一个目标函数g的函数(我们用f表示) 。我们可以用以下等式来描述这种关系:
这里,x是输入数据,θ是 NN 参数(权重)。目标是找到具有最佳近似值g的此类θ参数。这个通用定义适用于回归(近似g的确切值)和分类(将输入分配给多个可能的类之一)任务。或者,NN 函数可以表示为。
我们将从 NN 的最小构建块——神经元开始讨论。
前面的定义是 NN 的鸟瞰图。现在,让我们讨论 NN 的基本构建块,即神经元(或单元)。单位是可以定义如下的数学函数:
在这里,我们有以下内容:
或者,我们可以用它们的向量表示替换x i和w i,其中和。在这里,公式将使用两个向量的点积:
左:一个单位及其等效公式;右:感知器的几何表示。
如果x• w = 0 ,则输入向量x将垂直于权重向量w 。因此,x• w = 0处的所有向量x在向量空间 中定义了一个超平面,其中n是x的维数。在二维输入(x 1 , x 2 )的情况下,我们可以将超平面表示为一条线。这可以用感知器(或二元分类器)来说明——使用阈值激活函数
将其输入分类为两个类之一。 具有两个输入(x 1 , x 2 ) 的感知器的几何表示是分隔这两个类的一条线(或决策边界)(在上图中的右侧)。这对神经元造成了严重的限制,因为它不能对线性不可分的问题进行分类——即使是简单的问题,例如 XOR。
具有恒等激活函数 ( f(x) = x ) 的单元等效于多元线性回归,而具有 sigmoid 激活函数的单元等效于逻辑回归。
接下来,让我们学习如何分层组织神经元。
NN 组织结构的下一层是单元层,我们将多个单元的标量输出组合在一个输出向量中。层中的单元不相互连接。这种组织结构之所以有意义,原因如下:
在经典 NN(即 DL 之前的 NN,当时它们只是众多 ML 算法之一)中,层的主要类型是全连接( FC ) 层。在这一层中,每个单元接收来自输入向量x的所有分量的加权输入。假设输入向量的大小是m,FC 层有n 个单元和一个激活函数f,对于所有单元都是相同的。n 个单元中的每一个都将具有m个权重:m个输入中的每一个都有一个权重。以下是我们可以用于单个单元j的输出的公式一个 FC 层。它与我们在神经元部分定义的公式相同,但我们将在此处包含单位索引:
这里,w ij是第 j 层单元和第 i 个输入分量之间的权重。我们可以将连接输入向量和单位的权重表示为m × n矩阵W。每个矩阵列代表一个层单元的所有输入的权重向量。在这种情况下,层的输出向量是矩阵向量相乘的结果。然而,我们也可以在一个输入矩阵(或批次)X中组合多个输入样本x i, 这将同时通过图层。在这种情况下,我们有矩阵-矩阵乘法,层输出也是一个矩阵。下图展示了一个 FC 层的示例,以及它在批处理和单个示例场景中的等效公式:
我们已经明确分离了偏差和输入权重矩阵,但在实践中,底层实现可能使用共享权重矩阵并将额外的 1 行附加到输入数据。
当代 DL 不限于 FC 层。我们还有很多其他的类型,比如卷积、池化等等。一些层具有可训练的权重(FC、卷积),而另一些则没有(池化)。我们还可以将术语功能或操作与层互换使用。例如,在 TensorFlow 和 PyTorch 中,我们刚刚描述的 FC 层是两个顺序操作的组合。首先,我们对权重和输入进行加权求和,然后将结果作为输入提供给激活函数操作。在实践中(即使用 DL 库时),NN 的基本构建块不是单元,而是将一个或多个张量作为输入并输出一个或多个张量的操作:
接下来,让我们讨论如何在 NN 中组合层操作。
在神经元部分,我们证明了一个神经元(也适用于一层)只能对线性可分的类进行分类。为了克服这个限制,我们必须在 NN 中组合多个层。我们将 NN 定义为操作(或层)的有向图。图节点是操作,它们之间的边决定了数据流。如果两个操作相连,那么第一个的输出张量将作为第二个的输入,这由边缘方向决定。一个 NN 可以有多个输入和输出——输入节点只有输出边,而输出只有输入边。
基于这个定义,我们可以识别出两种主要类型的 NN:
以下是这两种网络的示例:
假设,当一个操作从多个操作接收输入时,我们使用逐元素和来组合多个输入张量。然后,我们可以将 NN 表示为一系列嵌套的函数/操作。我们将用 表示 NN 操作,其中i是一些索引,可帮助我们区分多个操作。例如,左边前馈网络的等价公式如下:
右侧RNN的公式如下:
我们还将使用与操作本身相同的索引来表示操作的参数(权重)。让我们看一个索引为 l 的 FC 网络层,它从索引为l-1的前一层获取输入。以下是具有层索引的单个单元和矢量/矩阵层表示的层公式:
现在我们已经熟悉了完整的 NN 架构,让我们讨论不同类型的激活函数。
让我们从经典开始讨论不同类型的激活函数:
Sigmoid 激活函数
双曲正切激活函数
接下来,让我们关注新的孩子—— *LU(LU代表线性单位)函数族。我们将从2011 年首次成功使用的整流线性单元 ( ReLU ) 开始(深度稀疏整流器神经网络,http ://proceedings.mlr.press/v15/glorot11a/glorot11a.pdf )。下图显示了 ReLU 公式、其导数及其图表:
ReLU 激活函数
正如我们所见,ReLU 在x > 0时重复其输入,否则保持为 0。与 sigmoid 和 tanh 相比,这种激活有几个重要的优势:
连续的 sigmoid 激活“挤压”数据
ReLU 的幂等性使得理论上可以创建与 sigmoid 相比具有更多层的网络。
然而,在训练过程中,网络权重可以以这样的方式更新,即一层中的某些 ReLU 单元将始终接收小于 0 的输入,这反过来又会导致它们也永久输出 0。这种现象被称为垂死的 ReLU。为了解决这个问题,已经提出了许多 ReLU 修改。以下是非详尽列表:
ELU 激活函数
最后,我们会提到softmax,它是分类问题中输出层的激活函数。假设最终网络层的输出是一个向量 ,其中n 个分量中的每一个表示输入数据属于n 个可能类别之一的概率。这里,每个向量分量的 softmax 输出如下:
此公式中的分母充当规范化器。softmax 输出有一些重要的属性:
换句话说,我们可以将 softmax 输出解释为离散随机变量的概率分布。然而,它还有一个更微妙的属性。在我们对数据进行归一化之前,我们用 对每个向量分量进行指数变换。让我们假设两个向量分量是z 1 = 1和z 2 = 2。在这里,我们将有exp(1) = 2.7和exp(2) = 7.39。正如我们所看到的,转换前后的分量之间的比率非常不同——分别为 0.5 和 0.36。实际上,与较低的分数相比,softmax 增加了较高分数的概率。
在下一节中,我们将把注意力从 NN 的构建块转移到它的整体上。更具体地说,我们将演示神经网络如何逼近任何函数。
1989 年首次证明了具有 sigmoid 激活函数的 NN 的通用逼近定理,然后在 1991 年证明了具有任意非线性激活函数的 NN。它指出,紧凑子集上的任何连续函数 都可以通过具有至少一个具有有限数量单元和非线性激活的隐藏层的前馈 NN 逼近到任意准确度。尽管具有单个隐藏层的 NN 在许多任务中表现不佳,但该定理仍然告诉我们,就 NN 而言,没有理论上无法克服的限制。定理的形式证明太复杂,无法在此解释,但我们将尝试使用一些基本数学来提供直观的解释。
我们将实现一个近似于 boxcar 函数(如下图右侧所示)的 NN,这是一种简单的阶跃函数。由于一系列阶跃函数可以逼近R的紧凑子集上的任何连续函数,这将使我们了解为什么通用逼近定理成立:
为了理解这种近似是如何工作的,我们将从具有单个标量输入x和 sigmoid 激活的单个单元开始。以下是单位及其等效公式的可视化:
在下图中,我们可以看到[-10: 10] 范围内输入的不同b和w值的公式图:
在仔细检查公式和图表后,我们可以看到 sigmoid 函数的陡度由权重w决定。此外,函数沿x轴的平移由公式t = -b/w确定。让我们讨论上图中的不同场景:
我们可以直观地看到,前面的图包含了 box 函数的所有成分。我们可以借助具有一个隐藏层的 NN 组合不同的场景,该隐藏层包含上述两个单元。下图显示了网络架构,以及单元的权重和偏差,以及网络生成的框函数:
以下是它的工作原理:
该网络的输出不是 0,而是仅在 (-5, 5) 区间内。因此,我们可以通过以类似方式向隐藏层添加更多单元来近似附加框。
现在我们已经熟悉了 NN 的结构,让我们专注于训练过程。
在本节中,我们将训练 NN 定义为以最小化成本函数J(θ)的方式调整其参数s(权重)θ i的过程。成本函数是对由多个样本组成的训练集的一些性能测量,表示为向量。每个向量都有一个相关的标签(监督学习)。最常见的是,成本函数测量网络输出和标签之间的差异。
我们将从对梯度下降优化算法的简短回顾开始本节。如果你已经熟悉它,你可以跳过这个。
出于本节的目的,我们将使用具有单个回归输出和均方误差( MSE ) 成本函数的 NN,其定义如下:
在这里,我们有以下内容:
首先,梯度下降计算J(θ)关于所有网络权重的导数(梯度)。梯度为我们提供了J(θ)相对于每个权重如何变化的指示。然后,该算法使用此信息来更新权重,以在将来出现相同的输入/目标对时最小化J(θ) 。目标是逐步达到成本函数的全局最小值。以下是 MSE 和具有单个权重的 NN 的梯度下降的可视化:
让我们看一下梯度下降的逐步执行:
这里,η 是学习率。
梯度下降 通过累积所有训练样本的误差来更新权重。在实践中,我们将使用它的两个修改:
接下来,让我们讨论一下我们可以与 SGD 一起使用的不同成本函数。
除了 MSE,还有一些其他的损失函数常用于回归问题。以下是非详尽列表:
MAE 优于 MSE 的一个优点是它可以更好地处理异常样本。使用 MSE,如果样本的差异为,它会呈指数增长(因为平方)。与其他样本相比,我们会得到这个样本的超大重量,这可能会扭曲结果。使用 MAE,差异不是指数级的,而且这个问题不太明显。
另一方面,MAE梯度将具有相同的值,直到我们达到最小值,它会立即变为 0 。这使得算法更难预测成本函数最小值的接近程度。将此与 MSE 进行比较,当我们接近成本最小值时,斜率逐渐减小。这使得 MSE 更容易优化。总之,除非训练数据被异常值破坏,否则通常建议使用 MSE 而不是 MAE。
接下来,让我们关注分类问题的成本函数。以下是非详尽列表:
这里,x (i) /t (i)是第i个输入/标签训练对。
现在我们已经了解了不同的成本函数,让我们专注于使用反向传播通过网络传播误差梯度。
在本节中,我们将讨论如何更新网络权重以最小化成本函数。正如我们在梯度下降部分所展示的,这意味着找到成本函数J(θ)相对于每个网络权重的导数。在链式法则的帮助下,我们已经朝着这个方向迈出了一步:
这里,f(θ)是网络输出,θ j是第j个网络权重。在本节中,我们将进一步推动信封,我们将学习如何为所有网络权重推导 NN 函数本身(提示:链式法则)。我们将通过网络向后传播误差梯度来做到这一点(因此得名)。让我们从几个假设开始:
下图显示了我们引入的所有符号:
这里,第 l 层代表输入,第 l+1 层代表输出,w ij将第 l 层中的y i (l)激活连接到第 l+1 层的第 j 个神经元的输入
有了这些丰富的知识,让我们开始吧:
1.首先,我们假设l和l+1分别是倒数第二和最后一个(输出)网络层。知道了这一点,J 对w ij的导数如下:
2.让我们专注于。在这里,我们计算层l的输出的加权和相对于其中一个权重w ij的偏导数。正如我们在微积分部分所讨论的,在偏导数中,我们将考虑除w ij常数之外的所有函数参数。当我们导出j (l+1)时,它们都变为 0,我们只剩下。因此,我们得到以下信息:
3.第 1 点的公式适用于网络的任意两个连续隐藏层l和l+1。我们知道,我们也知道这是激活函数的导数,我们可以计算(参见激活函数部分)。我们需要做的就是计算导数(回想一下,这里l+1是某个隐藏层)。请注意,这是关于第l+1层激活函数的误差的导数。我们现在可以计算所有导数,从最后一层开始向后移动,因为以下适用:
j的和反映了这样一个事实,即在网络的前馈部分,输出被馈送到第l+1层中的所有神经元。因此,当误差向后传播时,它们都对y i (l)有贡献。
再次,我们可以计算。按照我们在步骤 3中遵循的相同逻辑,我们可以计算它。因此,一旦我们知道,我们就可以计算。由于我们可以计算最后一层,我们可以向后移动并计算任何层,因此也可以计算任何层。
5.总而言之,假设我们有一系列适用于以下内容的层:
在这里,我们有以下基本方程:
6.如果我们设置,则δ j (l+1)表示成本相对于激活值的变化,我们可以将 δ j (l+1) 视为神经元y j (l+1)处的误差。我们可以将这些方程改写如下:
在此之后,我们可以写出以下等式:
这两个方程为我们提供了反向传播的另一种观点,因为成本相对于激活值存在变化。一旦我们知道下一层l+1的变化,它们为我们提供了一种计算任何层l变化的方法。
现在我们熟悉了反向传播,让我们讨论训练过程的另一个组成部分:权重初始化。
训练深度网络的一个关键组成部分是随机权重初始化。这很重要,因为一些激活函数,例如 sigmoid 和 ReLU,如果它们的输入在一定范围内,就会产生有意义的输出和梯度。
一个著名的例子是梯度消失问题。为了理解它,让我们以 sigmoid 激活的 FC 层为例(这个例子对 tanh 也有效)。我们在激活函数部分看到了 sigmoid 的图(蓝色)及其导数(绿色) 。如果输入的加权和大致落在(-5, 5)范围之外,则 sigmoid 激活将有效地为 0 或 1。本质上,它会饱和。这在我们推导出 sigmoid 的反向传递中是可见的(公式是σ' = σ(1 - σ)). 我们可以看到,在输入的相同 (-5, 5) 范围内,导数大于 0。因此,无论我们尝试将错误传播回前几层,如果激活不在此范围内(因此得名),它将消失。
解决此问题的一种方法是使用 *LU 激活。但即便如此,使用更好的权重初始化仍然是有意义的,因为它可以加快训练过程。一种流行的技术是 Xavier/ Glorot 初始化程序(通常以两个名称之一找到:http: //proceedings.mlr.press/v9/glorot10a/glorot10a.pdf)。简而言之,该技术考虑了单元的输入和输出连接数。有两种变体:
这里,n in和n out分别是输入和输出的数量(即,将其输出发送到当前单元的单元数和当前单元将其输出发送到的单元数)。
建议对 sigmoid 或 tanh 激活函数使用 Xavier/Glorot 初始化。论文深入研究整流器:在 ImageNet 分类上超越人类水平的性能( https://arxiv.org/abs/1502.01852 ) 提出了一种更适合 ReLU 激活的类似技术。同样,有两种变体:
当输入为负时,ReLU 输出始终为 0。如果我们假设 ReLU 单元的初始输入以 0 为中心,那么其中一半将产生 0 输出。与 Xavier 初始化相比,He 初始化器通过将方差增加两倍来补偿这一点。
在下一节中,我们将讨论对标准 SGD 的权重更新规则的一些改进。
我们将从 动量开始,它通过使用先前权重更新的值调整当前权重更新来扩展普通 SGD。也就是说,如果步骤 t-1的权重更新 很大,它也会增加步骤 t的权重更新。我们可以用一个类比来解释动量。将损失函数表面想象成一座小山的表面。现在,假设我们在山顶(最大)拿着一个球。如果我们放下球,由于地球的重力,它会开始向山脚滚动(最小)。它行进的距离越远,它的速度就会增加得越多。换句话说,它将获得动力(因此得名优化)。
现在,让我们看看如何在权重更新规则中实现动量。回想一下我们在梯度下降部分介绍的更新规则,即。假设我们处于训练过程的第t步:
1.首先,我们将计算当前权重更新值v t通过还包括先前更新的速度v t-1:
这里,μ 是[0:1] 范围内的超参数,称为动量率。v t在第一次迭代期间被初始化为 0。
然后,我们执行实际的权重更新:
对基本动量的改进是Nesterov 动量。它依赖于观察到步骤t-1的动量可能无法反映步骤t的条件。例如,假设t-1处的梯度很陡,因此动量很高。然而,在t-1 权重更新之后,我们实际上达到了成本函数最小值,并且只需要在t处进行较小的权重更新。尽管如此,我们仍然会从t-1获得很大的动量,这可能会导致调整后的权重超过最小值。Nesterov 动量建议改变我们计算权重更新速度的方式。我们将计算v t基于由权重θ j的潜在未来值计算的成本函数的梯度。以下是更新后的速度公式:
如果t-1处的动量相对于t不正确,则修改后的梯度将在同一更新步骤中补偿此误差。
接下来,我们来讨论一下 Adam 自适应学习率算法(Adam: A Method for Stochastic Optimization,https://arxiv.org/abs/1412.6980)。它根据之前的权重更新(动量)计算每个权重的个体和自适应学习率。让我们看看它是如何工作的:
1.首先,我们需要计算梯度的一阶矩(或均值)和二阶矩(或方差):
这里,β 1和 β 2是超参数,默认值分别为 0.9 和 0.999。m t和v t充当梯度的移动平均值,有点类似于动量。在第一次迭代期间,它们被初始化为 0。
2.由于m t和v t以 0 开始,因此在训练的初始阶段它们会偏向 0。例如,假设在t=1 时,β1 = 0.9和= 10。这里,m1 = 0.9 * 0 + (1 - 0.9) * 10 = 1,这比 10 的实际梯度要小很多。补偿这种偏差,我们将计算m t和v t的偏差校正版本:
3.最后,我们需要使用以下公式执行权重更新:
这里,η 是学习率,ε 是一些小的值,以防止除以 0。
本章的开头是关于构成 NN 基础的数学工具的教程。然后,我们回顾了 NN 及其架构。在此过程中,我们试图明确地将数学概念与 NN 的各个组件联系起来。我们特别关注了各种类型的激活函数。最后,我们全面了解了 NN 训练过程。我们讨论了梯度下降、成本函数、反向传播、权重初始化和 SGD 优化技术。