当前位置: 首页 > news >正文

神经网络的数学之旅:从输入到反向传播

目录

    • 神经网络简介
      • 神经元
      • 激活函数
      • 神经网络
    • 神经网络的工作过程
      • 前向传播(forward)
      • 反向传播(backward)
      • 训练神经网络

神经网络简介

神经元

在深度学习中,必须要说的就是神经⽹络,或者说是⼈⼯神经⽹络(artificial neural network)。神经⽹络是⼀种⼈类受到⽣物神经细胞结构启发⽽研究出的算法体系。

神经⽹络这个名字容易让⼈觉得特别神秘,不像我们接触过的程序算法那样直观,在编程的时候我们常⽤到的都是⼀些加减乘除、循环、分⽀、⽐⼤⼩、读写等等,使⽤这些基本步骤就能够完成⼀个明确的⽬标务,然⽽神经⽹络和这种直观的⽅式还真有些不同

在这里插入图片描述

上图⼀个最简单的神经元,有⼀个输⼊,⼀个输出,中间是⼀个参数,然后节点表⽰进⾏某种运算,所以它表达的含义跟⼀个普通函数没什么区别。不过需要注意的是,我们⽬前使⽤的神经元内部的运算通常有两个部分组成,第⼀部分是所谓的线性模型,可以把它理解为一个简单的包含加减乘除的函数,假设为 f ( x ) = 2 x + 1 f(x) = 2x + 1 f(x)=2x+1,它是图 中圆圈内的第一个部分。图中圆圈内运算的另外一部分激活函数,这一部分也不是很复杂,就是将第一部分线性模型的结果再通过一个激活函数计算,这个函数通常是非线性的,例如 f ( x ) = 1 1 + e − 2 x + 1 f(x) = \frac{1}{1+e^{-2x+1}} f(x)=1+e2x+11,其中 2 x + 1 2x + 1 2x+1是第一部分的线性函数。我们可以看出它虽然和普通的函数没什么区别,但这种方式的确是神经网络工作的原理。

在这里插入图片描述

我们接着看上图,输入 x x x 可以是一个一维向量,也可以是三维向量,当然也可以是一个更多的 n n n 维向量。对于 n n n 维向量输入项的神经元 f ( x ) f(x) f(x) 来说,这个函数就是:

f ( x ) = w x + b f(x) = wx + b f(x)=wx+b
其中 x x x 是一个 n × 1 n \times 1 n×1 的矩阵也就是 n n n 维列向量,而 w w w 是一个 1 × n 1 \times n 1×n 的权重矩阵, b b b 是偏置项。这个过程是在计算什么?权重矩阵和偏置项到底是什么?我们举一个例子来说明,假设 x x x 是一个这样的矩阵:

( 1 180 70 ) \begin{pmatrix} 1 \\ 180 \\ 70 \end{pmatrix} 118070

这个特征向量有三个维度,比如说第一行代表性别,数值1代表男生,数值0代表女生,第二行代表身高180cm,第三行代表体重70kg,这是一个多维度的描述,可能是描述人的体重情况。然后根据不同的人有不同的特征向量, w w w 是一个 1 × n 1 \times n 1×n 的矩阵,它表示权重的概念,就是表示每一项的重要程度,例如 [ 0.1 × 0.03 × 0.06 ] [0.1 \times 0.03 \times 0.06] [0.1×0.03×0.06] b b b 是偏置项,它是一个实数值,假设在这里 b b b 就是 1 × 1 1 \times 1 1×1 的矩阵0,整个函数则表示为 w w w x x x 进行内积操作,乘出来是一个实数,然后加上 b b b,即

f ( x ) = 0.1 × 1 + 0.03 × 180 + 0.06 × 70 + 0 = 9.7 f(x) = 0.1 \times 1 + 0.03 \times 180 + 0.06 \times 70 + 0 = 9.7 f(x)=0.1×1+0.03×180+0.06×70+0=9.7
最终的结果是 9.7,那么我们在这定义一个区间 ( 6 , 13 ) (6,13) (6,13),只要结果在这个区间内则体重正常。不在区间的话就通过一些算法计算,进而调整 w w w b b b,使得计算结果尽量落在这个区间,这样做的前提是我们给出的数据都是正常体重的数据,经过大量数据的演算推导,我们就能够获得精确度极高的 w w w b b b 的值,从而确定 f ( x ) f(x) f(x),如此一来,我们就可以使用这个确定的函数 f ( x ) f(x) f(x) 来检验新的体重是否标准了。

在以后训练神经网络的时候,这些 w w w b b b 参数,是我们最终想要得到的最有价值的东西,有这些参数之后我们就可以拿新的输入 x x x,通过计算来预测结果。

通常,我们在训练神经网络的时候,会需要大量的数据样本,这些数据样本里面我们已知的有输入 x x x,然后还会有已经知道的输出 f ( x ) f(x) f(x) y y y,这个输出通常称为标签,例如一张猫的图片,输入就是这张图片的像素矩阵,输出就是图片的名称-猫(当然可以拿数字来代替,计算机并不清楚文字猫和数字 0的区别)。

这里我们引入一个新的概念,叫做损失函数。我们简单解释一下,在训练神经网络的时候,一开始,我们会初始化 w w w b b b 参数,假设定义它们的矩阵里面全是接近 0 的浮点小数,那么输入与其计算后会得到结果 f ′ ( x ) f'(x) f(x),但是这个数据真实的标签却是 f ( x ) f(x) f(x)。我们会定义一个损失函数,它代表了计算输出的标签与真实数据的标签的差距,通常把这个函数写作为 Loss:

L o s s = ∑ i = 1 n ∣ w x i + b − y i ∣ Loss = \sum_{i=1}^{n} |wx_i + b - y_i| Loss=i=1nwxi+byi
上式举了一个损失函数的例子, w x i + b wx_i + b wxi+b 为输入通过线性模型计算得出的 f ′ ( x ) f'(x) f(x)

∣ w x i + b − y i ∣ |wx_i + b - y_i| wxi+byi 代表求 f ′ ( x ) f'(x) f(x) f ( x ) f(x) f(x) 之间差的绝对值, ∑ i = 1 n ∣ w x i + b − y i ∣ \sum_{i=1}^{n} |wx_i + b - y_i| i=1nwxi+byi 代表将从 1 开始到 n 所有差的绝对值加起来。那么这个函数有什么用途呢?我们训练神经网络的最终目的是得到合适的 w w w b b b,那么这个损失函数足够小的情况下,就代表神经网络计算出的结果与真实的结果差距足够小,也就说明我们的 w w w b b b 越可靠。至于怎么通过这个函数去不断的调整 w w w b b b 呢?我们后面部分会讲解。

激活函数

激活函数(activation function),也叫作激励函数。在第一小节神经元中,我们提到过这个名词,也大概说明了一下什么是激活函数,它是在神经元中跟随 f ( x ) = w x + b f(x) = wx + b f(x)=wx+b 之后加入的非线性因素激活函数在神经元线性模型之后使得神经网络能够学习和逼近复杂的函数关系,如下图右半部分部分:

11

那么解释一下什么是非线性,生活中的各种事物抽象为数学模型后几乎都是非线性。举个例子,理想情况下房子越大,价格越贵,这里的面积与价格可以视作线性关系,但是真实情况下,房价不仅受到面积的影响因素,还会受到地理位置、时间、楼层等因素的影响,那么这几种因素与房价就不是线性关系了。通常神经元的串联和并联叠加构成了神经网络,如果都是线性模型的叠加,那最终整个网络也是线性的,也就是矩阵相乘的关系,但是其中加入了激活函数,那么叠加之后的神经网络理论上就可以构成任意复杂的函数从而解决一些复杂问题。下面我们给出神经网络中常用到的三种激活函数:

在这里插入图片描述

可以看到第⼀种 sigmoid 函数,是将线性模型的计算结果投射到 0 到 1 之间,第⼆个 TanH 函数是将线性模型的计算结果投射到-1 到 1 之间,最后⼀个 ReLU 是将线性模型计算结果⼩于 0的部分投射为 0,⼤于等于 0 的部分投射为计算结果本⾝。


激活函数(Activation Function)的作用主要是引入非线性,使得神经网络能够学习和逼近复杂的函数关系。其主要作用包括:
1. 引入非线性
• 线性变换本质上只是输入数据的加权和,即使有多层神经网络,若无激活函数,整个网络仍等效于一个线性变换,无法学习复杂的模式。
• 激活函数如 ReLU、Sigmoid、Tanh 能够引入非线性,使得神经网络能够学习更复杂的映射关系。
2. 特征提取和表示学习
• 在深度神经网络中,不同层的激活函数能够帮助网络提取不同层次的特征,从而提高模型的表达能力。
3. 梯度传播
• 适当的激活函数能够确保梯度的有效传播,避免梯度消失或梯度爆炸问题。例如,ReLU(修正线性单元)可以在正值区域保持梯度不变,而 Sigmoid 在极端值时会导致梯度消失。
4. 增加网络的表达能力
• 通过非线性变换,神经网络可以逼近任何复杂的函数(根据通用逼近定理),使其能够处理更复杂的任务,如图像识别、自然语言处理等。

常见激活函数:
Sigmoid: σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1+e^{-x}} σ(x)=1+ex1
• 优点:输出范围 (0,1),适用于二分类任务。
• 缺点:易导致梯度消失,计算复杂。
Tanh: tanh ⁡ ( x ) = e x − e − x e x + e − x \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} tanh(x)=ex+exexex
• 优点:输出范围 (-1,1),比 Sigmoid 更平衡。
• 缺点:仍有梯度消失问题。
ReLU(Rectified Linear Unit): f ( x ) = max ⁡ ( 0 , x ) f(x) = \max(0, x) f(x)=max(0,x)
• 优点:计算简单,不易发生梯度消失。
• 缺点:可能会出现“死亡 ReLU”(某些神经元可能永远不会被激活)。
Leaky ReLU: f ( x ) = max ⁡ ( α x , x ) f(x) = \max(\alpha x, x) f(x)=max(αx,x)
• 改进:当 x < 0 时,仍然有小的梯度,缓解死亡 ReLU 问题。
Softmax:
• 作用:用于多分类任务,将输出转换为概率分布。


神经网络

神经网络就是神经元首尾相接形成一个类似网络的结构来协同计算,这个算法体系被称为神经网络

在这里插入图片描述

上图是⼀个⾮常简单的神经⽹络结构,在神经⽹络中通常会分为:输⼊层、隐藏层、输出层。输⼊层在整个⽹络最前端,图中为最左侧(也有⾃下⽽上的结构⽰意图),它直接接受输⼊的向量,输⼊层通常不计⼊层数,隐藏层这⼀层可以有多层,在⽐较深的⽹络中,隐藏层能达到数⼗上百层,输出层是最后⼀层,⽤来输出整个⽹络计算后的结果,这⼀层可能是⽐较复杂的类型的值或者向量,根据不同的需求输出层的构造也是不同的。

神经元就是通过这种结构进⾏数据传递,数据经过前⼀个神经元的计算输出给下⼀层的神经元当做输⼊,因为前⼀层的神经元节点连接了下⼀层的所有节点,因此这种前后层相互连接的⽹络也叫作全连接神经⽹络,这是⼀种⾮常常⻅的⽹络结构。

神经网络的工作过程

前向传播(forward)

在前⾯我们接触过了⼀种简单的神经⽹络结构,叫做全连接神经⽹络,同时,这种神经元从输⼊层开始,接受前⼀级输⼊,并输出到后⼀级,直⾄最终输出层,由于数据是⼀层⼀层从输⼊⾄输出传播的,也叫作前馈神经⽹络

在这里插入图片描述

这是一个简单的神经网络结构, i 1 i1 i1 i 2 i2 i2 分别是两个输入,隐藏层有两个神经元节点 h 1 h1 h1 h 2 h2 h2,偏置项 b 1 b1 b1 b 2 b2 b2,输出层也有 2 个神经元节点 o 1 o1 o1 o 2 o2 o2,那么前向传播过程中,隐藏层神经元节点线性部分计算有:

l h 1 = w 1 × i 1 + w 2 × i 2 + b 1 l_{h1} = w1 \times i1 + w2 \times i2 + b1 lh1=w1×i1+w2×i2+b1
假设激活函数为 sigmoid,那么第一个隐藏层节点输出为:

o u t h 1 = 1 1 + e − l h 1 out_{h1} = \frac{1}{1 + e^{-l_{h1}}} outh1=1+elh11

同理:

o u t h 2 = 1 1 + e − l h 2 out_{h2} = \frac{1}{1 + e^{-l_{h2}}} outh2=1+elh21

输出层 o1 节点假设激活函数为 sigmoid(这里使用激活函数的作用往往是根据特定的需求,比如多分类问题需要用到 softmax 函数),那么:

l o 1 = w 5 × o u t h 1 + w 6 × o u t h 2 + b 2 l_{o1} = w5 \times out_{h1} + w6 \times out_{h2} + b2 lo1=w5×outh1+w6×outh2+b2

同理:

l o 2 = w 7 × o u t h 1 + w 8 × o u t h 2 + b 2 l_{o2} = w7 \times out_{h1} + w8 \times out_{h2} + b2 lo2=w7×outh1+w8×outh2+b2

这样整个网络的前向传播输出:

o u t o 1 = 1 1 + e − l o 1 out_{o1} = \frac{1}{1 + e^{-l_{o1}}} outo1=1+elo11

o u t o 2 = 1 1 + e − l o 2 out_{o2} = \frac{1}{1 + e^{-l_{o2}}} outo2=1+elo21

这时如果将我们的参数都赋值为常数带入进去,然后设定一组真实的数据(其中包含输入 i 1 i1 i1 i 2 i2 i2,也包含一个与之对应的输出 out),输入之后会计算得到一个计算结果,然后将计算结果与我们设定的真实结果 out 做比较,会出现差距,那么损失函数我们上一章已经提到了,假设损失函数是:

E t o t a l = 1 n ∑ i = 1 n ( t a r g e t − o u t p u t ) 2 E_{total} = \frac{1}{n} \sum_{i=1}^{n}(target - output)^2 Etotal=n1i=1n(targetoutput)2

其中 t a r g e t target target 代表数据样本的标签,是理论输出的值, o u t p u t output output 代表神经网络计算的输出,那么这两者之间的差值就能代表当前神经网络计算的误差,这里取其平方再加和除 n n n 的意义是,实际输出与我们期望的输出差距越大,代价越高,然后取其均方差,则有:

E o 1 = 1 2 ( t a r g e t − o u t o 1 ) 2 E_{o1} = \frac{1}{2}(target - out_{o1})^2 Eo1=21(targetouto1)2

E o 2 = 1 2 ( t a r g e t − o u t o 2 ) 2 E_{o2} = \frac{1}{2}(target - out_{o2})^2 Eo2=21(targetouto2)2

E t o t a l = E o 1 + E o 2 E_{total} = E_{o1} + E_{o2} Etotal=Eo1+Eo2

有了这个损失函数就可以学习接下来的反向传播了

反向传播(backward)

反向传播,顾名思义,反向传播算法是利⽤损失函数进⽽从输出到输⼊⽅向传播达到调整参数的⽬的,它的存在主要是解决深层(多个隐藏层)神经⽹络的参数更新问题,反向传播算法就是梯度下降应⽤了链式法则,在机器学习中,梯度下降法的作用就是:最小化一个损失函数,链式法则是微积分中的求导法则,⽤于复合函数的求导,在神经⽹络中只要有了隐藏层,那么隐藏层的权重参数与损失函数会构成复合函数,因此使⽤链式法则解决复合函数求导问题达到调整权重参数的⽬的.

我们将上⼀⼩节中的神经⽹络拿过来,并将输⼊、输出、权值、偏置都赋予实数,来演⽰⼀下反向传播的过程,具体实数赋值如下:

在这里插入图片描述

上图中,将输⼊赋值 0.10 与 0.20,隐藏层权重为0.05、0.15、0.10、0.20,偏置为 0.35,输出层权重为 0.25、0.35、0.30、0.40,偏置为0.50,最终赋值输出为 0.85、0.30,注意这个输出是我们预设好的标签
就是我们希望输⼊ 0.10 与 0.20 后,通过神经⽹络计算,最终输出 0.85 与 0.30。 通过上⼀节的前向传播,我们得到了前向传播中各个节点的计算公式,将实数带⼊公式我们可以得到:

隐藏层第一个节点线性部分:
l h 1 = 0.05 × 0.10 + 0.15 × 0.20 + 0.35 = 0.385 l_{h1} = 0.05 \times 0.10 + 0.15 \times 0.20 + 0.35 = 0.385 lh1=0.05×0.10+0.15×0.20+0.35=0.385

隐藏层第二个节点线性部分:
l h 2 = 0.10 × 0.10 + 0.20 × 0.20 + 0.35 = 0.400 l_{h2} = 0.10 \times 0.10 + 0.20 \times 0.20 + 0.35 = 0.400 lh2=0.10×0.10+0.20×0.20+0.35=0.400

隐藏层第一个节点输出:
o u t h 1 = 1 1 + e − 0.385 = 0.595078474 out_{h1} = \frac{1}{1 + e^{-0.385}} = 0.595078474 outh1=1+e0.3851=0.595078474

隐藏层第二个节点输出:
o u t h 2 = 1 1 + e − 0.4 = 0.598687660 out_{h2} = \frac{1}{1 + e^{-0.4}} = 0.598687660 outh2=1+e0.41=0.598687660
同理,输出层线性部分:

l o 1 = 0.25 × 0.595078474 + 0.35 × 0.598687660 + 0.50 = 0.8583102995 l_{o1} = 0.25 \times 0.595078474 + 0.35 \times 0.598687660 + 0.50 = 0.8583102995 lo1=0.25×0.595078474+0.35×0.598687660+0.50=0.8583102995

l o 2 = 0.30 × 0.595078474 + 0.40 × 0.598687660 + 0.50 = 0.9179986062 l_{o2} = 0.30 \times 0.595078474 + 0.40 \times 0.598687660 + 0.50 = 0.9179986062 lo2=0.30×0.595078474+0.40×0.598687660+0.50=0.9179986062

输出层输出:

o u t o 1 = 1 1 + e − 0.8583102995 = 0.702307507 out_{o1} = \frac{1}{1 + e^{-0.8583102995}} = 0.702307507 outo1=1+e0.85831029951=0.702307507

o u t o 2 = 1 1 + e − 0.9179986062 = 0.714634132 out_{o2} = \frac{1}{1 + e^{-0.9179986062}} = 0.714634132 outo2=1+e0.91799860621=0.714634132

损失函数计算结果:

E o 1 = ∑ i = 1 n 1 2 ( 0.85 − 0.702307507 ) 2 = 0.010906536 E_{o1} = \sum_{i=1}^{n} \frac{1}{2} (0.85 - 0.702307507)^2 = 0.010906536 Eo1=i=1n21(0.850.702307507)2=0.010906536

E o 2 = ∑ i = 1 n 1 2 ( 0.30 − 0.714634132 ) 2 = 0.085960731 E_{o2} = \sum_{i=1}^{n} \frac{1}{2} (0.30 - 0.714634132)^2 = 0.085960731 Eo2=i=1n21(0.300.714634132)2=0.085960731

E t o t a l = 0.010906536 + 0.085960731 = 0.096867268 E_{total} = 0.010906536 + 0.085960731 = 0.096867268 Etotal=0.010906536+0.085960731=0.096867268

到这之后可以看到我们的总误差的数值,那么接下来进行反向传播算法,在反向传播算法里面应用了很多导数的知识,我们重点放在过程上。

对于权重参数 w 5 w5 w5 来说,我们想知道它的变化对损失函数的影响有多大,是根据最后的总损失函数反馈到 o u t o 1 out_{o1} outo1,然后由 o u t o 1 out_{o1} outo1 反馈到 l o 1 l_{o1} lo1,最后由 l o 1 l_{o1} lo1 反馈到 w 5 w5 w5,那么我们对其求偏导并且根据链式法则有:

∂ E t o t a l ∂ w 5 = ∂ E t o t a l ∂ o u t o 1 × ∂ o u t o 1 ∂ l o 1 × ∂ l o 1 ∂ w 5 \frac{\partial E_{total}}{\partial w5} = \frac{\partial E_{total}}{\partial out_{o1}} \times \frac{\partial out_{o1}}{\partial l_{o1}} \times \frac{\partial l_{o1}}{\partial w5} w5Etotal=outo1Etotal×lo1outo1×w5lo1
那么:

E t o t a l = 1 2 ( 0.85 − o u t o 1 ) 2 + 1 2 ( 0.3 − o u t o 2 ) 2 E_{total} = \frac{1}{2}(0.85 - out_{o1})^2 + \frac{1}{2}(0.3 - out_{o2})^2 Etotal=21(0.85outo1)2+21(0.3outo2)2
对上述 o u t o 1 out_{o1} outo1 求偏导,根据求导公式得:

∂ E t o t a l ∂ o u t o 1 = 2 × 1 2 ( 0.85 − o u t o 1 ) × − 1 = 0.702307507 − 0.85 = − 0.147692493 \frac{\partial E_{total}}{\partial out_{o1}} = 2 \times \frac{1}{2}(0.85 - out_{o1}) \times -1 = 0.702307507 - 0.85 = -0.147692493 outo1Etotal=2×21(0.85outo1)×1=0.7023075070.85=0.147692493

接着计算 ∂ o u t o 1 ∂ l o 1 \frac{\partial out_{o1}}{\partial l_{o1}} lo1outo1

o u t o 1 = 1 1 + e − l o 1 out_{o1} = \frac{1}{1 + e^{-l_{o1}}} outo1=1+elo11

这是对 sigmod 函数进行求导:

∂ o u t o 1 ∂ l o 1 = o u t o 1 × ( 1 − o u t o 1 ) = 0.702307507 × ( 1 − 0.702307507 ) = 0.209071672 \frac{\partial out_{o1}}{\partial l_{o1}} = out_{o1} \times (1 - out_{o1}) = 0.702307507 \times (1 - 0.702307507) = 0.209071672 lo1outo1=outo1×(1outo1)=0.702307507×(10.702307507)=0.209071672
接着往下计算 ∂ l o 1 ∂ w 5 \frac{\partial l_{o1}}{\partial w5} w5lo1

l o 1 = w 5 × o u t h 1 + w 6 × o u t h 2 + b 2 l_{o1} = w5 \times out_{h1} + w6 \times out_{h2} + b2 lo1=w5×outh1+w6×outh2+b2

∂ l o 1 ∂ w 5 = 1 × o u t h 1 × w 5 1 − 1 + 0 + 0 = 0.595078474 \frac{\partial l_{o1}}{\partial w5} = 1 \times out_{h1} \times w5^{1-1} + 0 + 0 = 0.595078474 w5lo1=1×outh1×w511+0+0=0.595078474

最后三项相乘得出

∂ E t o t a l ∂ w 5 = − 0.147692493 × 0.209071672 × 0.595078474 = − 0.018375021 \frac{\partial E_{total}}{\partial w5} = -0.147692493 \times 0.209071672 \times 0.595078474 = -0.018375021 w5Etotal=0.147692493×0.209071672×0.595078474=0.018375021
到这之后我们可以根据梯度下降的算法来更新 w 5 w5 w5 权重了:
w 5 + = w 5 − η ∂ E t o t a l ∂ w 5 = 0.25 − 1 × ( − 0.018375021 ) = 0.268375021 w_5^+ = w_5 - \eta \frac{\partial E_{total}}{\partial w_5} = 0.25 - 1 \times (-0.018375021) = 0.268375021 w5+=w5ηw5Etotal=0.251×(0.018375021)=0.268375021

上述的式子是梯度下降的算法, η \eta η 是学习率,就是说梯度下降的步幅,是由工程师凭借经验或者测试而确定的数值, w 5 w_5 w5 被更新为 w 5 + w_5^+ w5+。同理我们也可以将 w 6 , w 7 , w 8 w6, w7, w8 w6,w7,w8 更新完成。当我们使用更新完之后的参数再带入神经网络去计算时,会发现最终的输出与真实的输出已经更接近了。这就是梯度下降算法的作用.

对于隐藏层更新权重时,例如更新 w 1 w1 w1,使用的方法基本与前文更新 w 5 w5 w5 是一致的,从 o u t o 1 , l o 1 , w 5 out_{o1}, l_{o1}, w5 outo1,lo1,w5 三处分别求偏导再求其乘积,但有区别.

损失函数对 w 1 w1 w1 权重求偏导:

∂ E t o t a l ∂ w 1 = ∂ E t o t a l ∂ o u t h 1 × ∂ o u t h 1 ∂ l h 1 × ∂ l h 1 ∂ w 1 \frac{\partial E_{total}}{\partial w1} = \frac{\partial E_{total}}{\partial out_{h1}} \times \frac{\partial out_{h1}}{\partial l_{h1}} \times \frac{\partial l_{h1}}{\partial w1} w1Etotal=outh1Etotal×lh1outh1×w1lh1
由图中的传递方式可以看到, o u t h 1 out_{h1} outh1 会接受有 E o 1 E_{o1} Eo1,与 E o 2 E_{o2} Eo2 两个地方传来的误差损失。

那么 ∂ E t o t a l ∂ o u t h 1 \frac{\partial E_{total}}{\partial out_{h1}} outh1Etotal 就可以拆为:

∂ E t o t a l ∂ o u t h 1 = ∂ E o 1 ∂ o u t h 1 + ∂ E o 2 ∂ o u t h 1 \frac{\partial E_{total}}{\partial out_{h1}} = \frac{\partial E_{o1}}{\partial out_{h1}} + \frac{\partial E_{o2}}{\partial out_{h1}} outh1Etotal=outh1Eo1+outh1Eo2
继续往下计算 ∂ E o 1 ∂ o u t h 1 \frac{\partial E_{o1}}{\partial out_{h1}} outh1Eo1,主要是利用链式法则将隐藏层与输出层链接起来计算:

∂ E o 1 ∂ o u t h 1 = ∂ E o 1 ∂ l o 1 × ∂ l o 1 ∂ o u t h 1 \frac{\partial E_{o1}}{\partial out_{h1}} = \frac{\partial E_{o1}}{\partial l_{o1}} \times \frac{\partial l_{o1}}{\partial out_{h1}} outh1Eo1=lo1Eo1×outh1lo1
那么可以利用输出层的计算结果( ∂ E o 1 ∂ o u t o 1 \frac{\partial E_{o1}}{\partial out_{o1}} outo1Eo1 ∂ E t o t a l ∂ o u t o 1 \frac{\partial E_{total}}{\partial out_{o1}} outo1Etotal 结果相等):

∂ E o 1 ∂ l o 1 = ∂ E o 1 ∂ o u t o 1 × ∂ o u t o 1 ∂ l o 1 = − 0.147692493 × 0.209071672 = − 0.030878316 \frac{\partial E_{o1}}{\partial l_{o1}} = \frac{\partial E_{o1}}{\partial out_{o1}} \times \frac{\partial out_{o1}}{\partial l_{o1}} = -0.147692493 \times 0.209071672 = -0.030878316 lo1Eo1=outo1Eo1×lo1outo1=0.147692493×0.209071672=0.030878316
接着:

l o 1 = w 5 × o u t h 1 + w 6 × o u t h 2 + b 2 l_{o1} = w5 \times out_{h1} + w6 \times out_{h2} + b2 lo1=w5×outh1+w6×outh2+b2

∂ l o 1 ∂ o u t h 1 = w 5 = 0.25 \frac{\partial l_{o1}}{\partial out_{h1}} = w5 = 0.25 outh1lo1=w5=0.25

最终:

∂ E o 1 ∂ o u t h 1 = ∂ E o 1 ∂ l o 1 × ∂ l o 1 ∂ o u t h 1 = − 0.030878316 × 0.25 = − 0.007719579 \frac{\partial E_{o1}}{\partial out_{h1}} = \frac{\partial E_{o1}}{\partial l_{o1}} \times \frac{\partial l_{o1}}{\partial out_{h1}} = -0.030878316 \times 0.25 = -0.007719579 outh1Eo1=lo1Eo1×outh1lo1=0.030878316×0.25=0.007719579
同样我们可以计算出:

∂ E o 2 ∂ o u t h 1 = 0.025367174 \frac{\partial E_{o2}}{\partial out_{h1}} = 0.025367174 outh1Eo2=0.025367174
那么:

∂ E t o t a l ∂ o u t h 1 = ∂ E o 1 ∂ o u t h 1 + ∂ E o 2 ∂ o u t h 1 = − 0.007719579 + 0.025367174 = 0.017647595 \frac{\partial E_{total}}{\partial out_{h1}} = \frac{\partial E_{o1}}{\partial out_{h1}} + \frac{\partial E_{o2}}{\partial out_{h1}} = -0.007719579 + 0.025367174 = 0.017647595 outh1Etotal=outh1Eo1+outh1Eo2=0.007719579+0.025367174=0.017647595
在这之后我们计算第二部分 ∂ o u t h 1 ∂ l h 1 \frac{\partial out_{h1}}{\partial l_{h1}} lh1outh1

o u t h 1 = 1 1 + e − l h 1 out_{h1} = \frac{1}{1 + e^{-l_{h1}}} outh1=1+elh11

∂ o u t h 1 ∂ l h 1 = o u t h 1 ( 1 − o u t h 1 ) = 0.595078474 × ( 1 − 0.595078474 ) = 0.240960084 \frac{\partial out_{h1}}{\partial l_{h1}} = out_{h1}(1 - out_{h1}) = 0.595078474 \times (1 - 0.595078474) = 0.240960084 lh1outh1=outh1(1outh1)=0.595078474×(10.595078474)=0.240960084

然后计算第三部分 ∂ l h 1 ∂ w 1 \frac{\partial l_{h1}}{\partial {w1}} w1lh1

l h 1 = w 1 × i 1 + w 2 × i 2 + b 1 l_{h1} = w1 \times i1 + w2 \times i2 + b1 lh1=w1×i1+w2×i2+b1

∂ l h 1 ∂ w 1 = i 1 = 0.1 \frac{\partial l_{h1}}{\partial w1} = i1 = 0.1 w1lh1=i1=0.1

那么三项相乘:
∂ E t o t a l ∂ w 1 = ∂ E t o t a l ∂ o u t h 1 × ∂ o u t h 1 ∂ l h 1 × ∂ l h 1 ∂ w 1 \frac{\partial E_{total}}{\partial w1} = \frac{\partial E_{total}}{\partial out_{h1}} \times \frac{\partial out_{h1}}{\partial l_{h1}} \times \frac{\partial l_{h1}}{\partial w1} w1Etotal=outh1Etotal×lh1outh1×w1lh1

∂ E t o t a l ∂ w 1 = 0.017647595 × 0.240960084 × 0.1 = 0.000425237 \frac{\partial E_{total}}{\partial w1} = 0.017647595 \times 0.240960084 \times 0.1 = 0.000425237 w1Etotal=0.017647595×0.240960084×0.1=0.000425237

最后梯度下降算法更新 w 1 w1 w1

w 1 + = w 1 − η ∂ E t o t a l ∂ w 1 = 0.05 − 1 × 0.000425237 = 0.049574763 w_1^+ = w_1 - \eta \frac{\partial E_{total}}{\partial w1} = 0.05 - 1 \times 0.000425237 = 0.049574763 w1+=w1ηw1Etotal=0.051×0.000425237=0.049574763
同理也可以将 w 2 , w 3 , w 4 w2, w3, w4 w2,w3,w4 更新完成,最后将更新完的所有参数全部带入重新计算,得出新的输出,然后再根据损失函数、反向传播、梯度下降不停的去迭代更新参数,最终理论上输出的结果会无限接近真实结果,那么这一组参数就会变得非常有价值。上文中的理论推导都是基于简单的实数,并且网络结构简单,目的是理解神经网络的工作过程。真实的环境中都是使用矩阵批量计算的,并且已经有很多深度学习工具帮我们实现了计算过程,我们学会调用对应的函数就能便捷的实现计算过程。

训练神经网络

训练神经⽹络,也是使⽤梯度下降⽅法。神经⽹络模型的参数,与其隐藏层数量和神经元数量相关,学习率可以在经验值 1e-3 范围内进⾏探索。 ⼀个合适的学习率能够让我们的损失函数在合适的时间内收敛到局部最⼩值。

损失函数(loss function)是⽤来评估模型的预测结果与真实结果不⼀致程度的函数。学完前⾯内容之后,我们已经知道了神经⽹络的⼯作过程,在前向传播计算完之后会得出⼀个输出,这个输出就是模型的预测值,真实值是在准备数据时就定义好的。

⽐如说 1000 张猫的图⽚,那么图⽚像素矩阵就是我们的输⼊,我们命名这些图为猫 1、猫 2…,这个就是⼿动打上去的标签,但是计算机是不能理解的,这样就需要将名字为猫的图⽚也转化为⼀个输出值矩阵,矩阵中以猫为名字的图⽚我们定义为 1,我们就知道将猫图⽚的像素矩阵输⼊之后经过计算得出的结果我们去和 1 ⽐较,如果计算的预测值和真实值 1 不同,接着进⾏反向传播、梯度下降优化等等训练神经⽹络,这样我们最终会得到⼀个猫图⽚像素矩阵与数字 1 的映射关系。

这个过程中,每次计算的值是预测值,真实值是概率值,通常取值为1(100%)。预测值通常需要softmax函数转换为概率值。然后才是通过损失函数计算预测和真实之间的误差。损失函数⼀个⾮负实值函数,通常会经过绝对值或者平⽅的⽅式让其变为⾮负,因为如果第⼀次计算差距是负数,第⼆次是正数,那么就会抵消了,变为没有误差,那肯定是不合适的。损失函数越⼩,模型就越健壮。

相关文章:

  • 在串口通信中使用共享指针(`std::shared_ptr`)
  • 用 R 语言打造交互式叙事地图:讲述黄河源区生态变化的故事
  • MCP认证难题破解:常见技术难题实战分析与解决方案
  • 额外篇 非递归之美:归并排序与快速排序的创新实现
  • 基于Redis的3种分布式ID生成策略
  • JAVA文件I/O
  • 大数据平台简介
  • 《Operating System Concepts》阅读笔记:p738-p747
  • Java从入门到“放弃”(精通)之旅——数组的定义与使用⑥
  • 批量创建OpenStack实例
  • 【java实现+4种变体完整例子】排序算法中【堆排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
  • doris/clickhouse常用sql
  • C++镌刻数据密码的树之铭文:二叉搜索树
  • 与终端同居日记:Linux指令の进阶撩拨手册
  • 区块链木材业务服务平台:商贸物流新变革
  • 18、TimeDiff论文笔记
  • 【综述】一文读懂卷积神经网络(CNN)
  • 【2025】Datawhale AI春训营-RNA结构预测(AI+创新药)-Task2笔记
  • [dp20_完全背包] 介绍 | 零钱兑换
  • 包含物体obj与相机camera的 代数几何代码解释
  • 寻找“香奈儿”代工厂
  • 国常会:要持续稳定股市,持续推动房地产市场平稳健康发展
  • 上海一季度人民币贷款增4151亿,住户存款增3134亿
  • 习近平会见柬埔寨太后莫尼列
  • 二十届中央第五轮巡视完成进驻
  • 铁路12306开售5月1日车票,目前系统安全平稳运行