深度学习基础
开始深度学习!!
- 深度学习
机器学习包含深度学习 > 因为深度学习就是神经网络的进阶版本!神经网络是众多机器学习中的一种.
传统机器学习人为的进行特征工程,特征的筛选;深度学习 会智能化的提取到最优特征!
深度学习可解释性差,但这样的玄学,在计算机视觉和自然语言处理领域有很好的效果!!
- 导数与偏导
- 某一点处的导数值就是函数f在该点的切线斜率值 / 导数是函数在某一点上的瞬时变化率
- z = x^2 + y^2
[对x求偏导],意味着我们想得知其函数图像上的 [任意某个点] 在x方向的变化率.
[对x求偏导],就是让y等于一个固定的值,此时抛物面就被压扁成一个抛物线了,我们求的就是这个抛物线上任意x的导数.
这与偏函数的精髓相呼应: 单独隔离出x的影响,"暂时忽略"其它变量的变化,把它们当作固定的/当作是常量.
> 该示例中,不管固定y的值是多少,这么多个抛物线上,任意x的导数值都是2x
- 方向导数和梯度
... ...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 基本概述
- AI - 人工智能 > 对人的意识、思维进行模拟
- ML - 机器学习 > 利用 [已有的数据] 进行 [学习] , 获得一个训练好的 [模型/人的经验], 然后可以利用此模型 [预测] 未来的情况.
- ANN - 神经网络 > 神经网络是众多机器学习算法中的其中一个,模仿人类大脑神经结构构建出来的一种算法
- Deep Learning - 深度学习 > 可以简单理解成是神经网络的升级、进阶版本
★ 深度学习其实就是机器学习的一部分!
[传统机器学习] 在进行特征工程的 过程中, 需要 人为的 去处理特征;
[深度学习] 基于相关的神经网络 很智能的 对原始的数据进行处理, 以便提取到对模型最优的特征数据..
在现实的学习和应用中,神经网络可以说是解释性最差的一种算法,类似玄学! 但是确确实实可以实现很好的效果!
深度学习90%的情况下是应用在计算机视觉和自然语言处理中.
- 计算机视觉: 输入数据为图像数据
- 自然语言处理: 输入数据为文本数据
2
3
4
# 必备高数知识
# 线性代数
矩阵、标量、向量、张量、线性空间.
矩阵是由向量组成的,若将一个二乘二的矩阵拆开,就可以得到两个向量.这是两个可以在坐标系中表示的向量!!
通过一对二维基向量的组合,我么可以得到所有的二维向量!
其实不止二维向量,三维向量同样如此!那么这些向量的集合,我们就称之为线性空间!
题外话:
- 其实所谓的矩阵就是对某一个线性空间的基向量进行变换.
- 矩阵所拆分出来的两个向量就是变换后的基向量!!<矩阵本质上是由基向量变换而来>
- (-2,pai)这个向量就是 基向量i(1,0)乘以-2,基向量j(0,1)乘以pai得到的,在上图的几何图像中是有表示的!
(注:这是向量运算,不是矩阵运算哈!
- 再延伸一点 - 原基向量i(1,0) 原基向量j(0,1) > 变换后基向量i(0,1) 变换后基向量j(1,0)
相当于原先两个基向量的位置进行了对调!整个线性空间就做了旋转的操作!
So,我们见到的矩阵就是通过一种非常简单的方式向我们展示了它所代表的线性变换!
矩阵积: A的第i行与B的第j列对应元素逐一相乘后求和.
2
3
4
5
6
7
8
9
10
11
12
13
14
# 导数
# 导数介绍
p和a之间的距离表示为△X.. 根据极限思想, 如果让p点无限接近a点, 即△X无限趋近于0.
则两点间的斜率 (蓝色线斜率) 就可以近似等于红色线斜率了.
任何一个函数 f 在函数曲线上某一点x的斜率值就是该函数f在x点的导数. 记作:f'(x)
即 某一点处的导数值就是函数f在该点的切线斜率值.. 简单记忆 导数值==切线斜率值
.
# 导数与单调性与极值
我们可以根据一个函数的导数, 判断该函数的单调性 (在什么区间单调递增, 在什么区间单调递减)
对f(x)
求导后, 根据求导后f'(x)
的图像. 不难观察到:
在 (-∞, 2) 和 (1,+∞)区间, 导数值为正; 在(-2, -1)区间, 导数值为负. x=-2和x=1这两个点, 导数值为0.
对应f(x)图像, 导数值为正的区间, f(x)的图像单调递增; 导数值为负的区间, f(x)的图像单调递减..
导数值为0的点, 恰好是f(x)图像中单调性发生变化的点. 若单调递增变单调递减, 该点是f(x)图像的极大值, 反之为极小值..
综上: 导数值为正, 原函数单调递增; 导函数为负, 原函数单调递减. 导数值为0, 所对应的点是原函数的极值..
# 极值与最值
对于一个函数图像来讲, 可能会存在多个"极值点". 根据这多个极值点, 就可以找出函数值中的最大值和最小值..
# 偏导数
总的来说, 偏导数和导数都是描述函数变化率的工具, 但它们适用于不同类型的函数.
导数主要用于 一元函数, 而偏导数则用于 多元函数.
通过偏导数, 我们可以更全面地了解函数在不同方向上的变化情况, 这对于理解和分析复杂的多变量问题非常有帮助.
导数是函数在某一点上的变化率, 即曲线在该点的切线斜率; 类似地, 偏导数也是函数在某一点上关于某一变量的变化率.
说函数在某一点的变化率 严谨点指的就是 函数在某一点的瞬时变化率/函数在某一点的导数值/函数在某一点的斜率/
- 线性函数 f(x)=2x,其导数f‘(x)=2 > 无论x是多少,变化率(斜率)都是固定值 3
- 非线性函数 f(x) = x^2,其导数f‘(x)=2x > 变化率(斜率)不是恒定的,而是随着自变量x的变化而变化
2
3
具体来说, 偏导数就是在多元函数里,固定其他变量不变,专门研究某一个变量对函数值的影响.
换个说法, 就是固定某些变量, [只] 让一个变量动起来, 然后看函数是怎么变化的
偏函数其精髓在于(若一个多元函数包含两个变量 x、y): 单独隔离出x的影响,"暂时忽略"其它变量的变化,把它们当作固定的/当作是常量.
这样做,河狸吗? 合理的很,我们可以理解成, 这样做可以帮助我们逐一分析每个变量对结果的贡献.
z = x^2 + y^2
∂(z)/∂(x)即函数z对x变量的偏导 = 2x + 0 = 2x
∂(z)/∂(y)即函数z对y变量的偏导 = 0 + 2y = 2y
z = x^2 + 3xy + y^2
∂(z)/∂(x)即函数z对x变量的偏导 = 2x + 3y + 0 = 2x + 3y
∂(z)/∂(y)即函数z对y变量的偏导 = 0 + 3x + 2y = 3x + 2y
2
3
4
5
6
7
8
9
10
上述的阐述太抽象了, 结合函数的几何图像举个例子.. 以函数 z = x^2 + y^2
为例, 这个函数的几何图像是一个曲面..
需求: 我们在函数z上 [对x求偏导] , 意味着我们想得知其函数图像上的 [任意某个点] 在x方向的变化率.
我们需要固定y变量的值, 若y=1,则 z=x^2+1
; 若y=3,则 z=x^2+3
其对应的导数都是 f‘(z)=2x
可以想象, y=1时, 一个平面从上到下与这个函数曲面切割, 相交得到了一条抛物线, 即 函数z/曲面上 y=1时,那些点的连线..
对这个抛物线上的任意一点都可以求得导数值.. 即求 z=x^2+1
这个一元函数的导数.. y=2,y=3,y=4, 同理..
PS: 还可以理解成, 偏导数是求函数在某一特定方向上(此处是平行于x轴)的变化率.
具体过程 举个栗子. 简单阐述下:
下方图中是一个二元的损失函数在三维坐标系中呈现的曲面图. w轴和b轴是损失函数的两个变量, L轴是损失函数的值.
需求: 求曲面上 (-1,0,4) 这个点 在w方向和b方向上的偏导是多少? (-1,0,4分别是w、b、L的值)
点(-1,0,4)分别是变量 w、b 以及 损失函数loss的值
- 求该损失函数上(-1,0,4)这个点在w变量上的偏导.
> ∂(loss)/∂(w) -- 固定b=0, 对w求偏导就是对 b=0 这个平面和曲线的交线.
求导数 - 在交线上求(-1,4)这个点的导数!! - 即这个点在x方向上的变化率
- 求该损失函数上(-1,0,4)这个点在b变量上的偏导.
> ∂(loss)/∂(b) -- 固定w=-1,对b求偏导就是对 w=-1这个平面和曲线的交线.
求导数 - 在交线上求(0,4)这个点的导数!! 可以发现该点在交线上处于最低点,则导数值为0 - 即这个点在x方向上的变化率
★★ 举一反三:
> z = x^2 + y^2 不管固定y的值是多少,在这么多个抛物线上,任意x的导数值都是2x !!
> z = x^2 + 3xy + y^2 固定y的值,在这么多个曲线上,任意x的导数值都可通过 2x+3y 得到 !!
2
3
4
5
6
7
8
9
10
11
综上, 针对函数 f(x,y)..
[对x求偏导], 就是让y等于一个固定的值,此时抛物面就被压扁成一个抛物线了,我们求的就是这个抛物线的导数.
这与我们前面所说的 偏函数的精髓相呼应: 单独隔离出x的影响,"暂时忽略"其它变量的变化,把它们当作固定的/当作是常量.
对y求偏导,同理,就是让x等于一个固定的值..同样的抛物面也会被压扁成一个抛物线..
# 梯度下降算法
# 损失函数
- 损失函数也可以被称为代价函数, 英文称为 loss function 或 cost function.
有些地方我们会看到使用 loss 表示代价函数的值, 有些地方我们会看到用 cost 表示代价函数的值. - 代价函数并没有准确的定义, 一般我们可以理解为是一个人为定义的函数, 我们可以利用这个函数来优化模型的参数.
最简单常见的一个代价函数是均方差(Mean-Square Error, MSE) 代价函数 - 优化模型的损失或者代价, 通常我们会使用 [梯度下降] 的方式..
梯度下降也是我们在求解机器学习算法的模型参数时最常用的方法之一..
以多元线性回归方程为例: y = W^T*X (其中w0=b,x0=1)
代入均方误差公式,X特征矩阵是已知的,y标签向量是已知的! MSE最后的取值取决于 W 和 b 的值.
梯度下降算法也就是在求 MSE最小时, W和b的值.
2
3
# 方向导数和梯度
我们已经了解了导数、偏导数的概念, 那什么是方向导数, 什么是梯度呢?
方向导数 就是多元函数在某一点处沿 [任意方向] 的变化率..
梯度(gradient), 是多元函数 [全部] 偏导数所构成的向量 - [自变量方向] 的变化率构成的向量.
下图分别是一元函数、三元函数、n元函数, 这些函数的梯度向量都是函数对其变量求偏导后所组成的向量..
☆ 先提一嘴:
梯度的方向指损失函数在某点增长最快的方向..
在该方向上, 函数增长速率的大小 等于 在梯度方向上的方向导数 (即梯度向量的变化率/梯度向量的模长)
不能描述成 在梯度方向上的方向导数的变化率, 因为方向导数本身表示的就是变化率.
# 梯度的性质
★ 函数上的 [某一点] 如果沿着 [函数梯度的方向] 运动, 那么函数增加的最快; 如果沿着函数梯度的 [反方向] 运动, 函数减小的最快.
为什么? 数学推导证明无需探究.. 记住这条结论即可.. 梯度向量的方向是损失函数在某点增长最快的方向
我们可以画几何图, 更直观的理解这条梯度的性质:
图中是二元函数 f(x,y) = x^2 + y^2 的几何图像.
思考一个问题,该图像上的任意一点(比如 1,1,2 这一点),沿着哪个方向运动,能使得函数f(x,y)增大或减少的最快呢?
★ 先需明确一点,梯度向量是在函数的输入空间中定义的!! 所以需要投影!
将函数几何图像上的一点P(1,1,2)标记为红色,P‘是点P在灰色的x-o-y平面上的投影,标记为蓝色.
图中从蓝色点出发,以黑色箭头表示点(1,1)处的梯度向量!! 将(1,1)代入梯度(2x,2y),可得梯度向量(2,2).
对于输入(x,y)=(1,1), 若在灰色的x-0-y平面上可沿着任意方向都移动1个单位的距离,通过比较函数值(具体过程 略),可知:
- 沿着正梯度方向(2,2)运动, 函数值f(x,y)增加的最快;
- 沿着负梯度方向(-2,-2)运动, 函数值f(x,y)减小的最快.
★★★ Q: 那么曲面映射到x-o-y平面上的点,沿着梯度向量的反方向移动0.5个单位,这0.5指的就是 步长吗?
A: 是的!!
沿着梯度向量的反方向移动0.5个单位后的点,该点就是参数值更新后的点.
再映射回曲面上,那个点相较于原来的点,值必定是减少了的!
对梯度向量的解读
- "起点是函数图像上的点"
(1, 1, 2) 是函数图像 f(x,y) = x^2 + y^2 上的一点.
这个点在 x-y 平面上的投影是 (1, 1), 即我们把z轴的高度忽略, 只关心 x, y 坐标.
- "方向是指向(3, 3)的坐标点"
梯度向量是一个箭头, 从(1, 1)指向(3, 3), 这是梯度的方向.
它并不是函数图像上的另一个点, 而是一个几何向量, 表示方向和大小.
- 那意思是 若我想画 点(1,2,5)的梯度向量呢?则在x-o-y平面, 起点是(1,2) 终点是应该是 (1,2)+(1*2,2*2) = (3,6)
- "函数图像上表示梯度向量"
在函数图像上, 比如点(1, 1, 2)所在的图像上,梯度向量的方向指向 x-0-y 平面的(3, 3).
你可以在(1, 1, 2)处画一个箭头, 方向是从 x-0-y 平面上的(1, 1)指向(3, 3), 用来表示增长的方向.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 梯度下降过程
梯度下降法: 一种迭代优化算法, 用于寻找函数的最小值.
在机器学习中, 经常将损失函数作为目标函数, 通过梯度下降法来最小化损失函数, 从而调整模型参数以使其在给定数据上拟合最佳.
梯度下降法核心思想: 通过不断调整参数的值, 使目标函数的值逐渐减小.
其基本步骤如下:
选择初始参数值: 从一个 [随机] 选择的初始化参数值 开始.
计算梯度: 计算目标函数关于参数的梯度, 梯度是目标函数在每个参数维度上的偏导数. 梯度向量表示了函数值增长最快的方向.
更新参数:
- 沿着梯度的 [反方向], 以一定的 [学习率] 调整参数.
沿梯度反方向调整参数是由于梯度指向损失函数值增加最快的方向, 因此, 要想减小函数值, 我们应该向梯度的反方向移动.
这样, 每一步更新都是朝着减少损失函数值的方向进行的. - "学习率" 决定了每次参数更新的 "步长". 通常, 较小的学习率使得优化更稳定, 但需要更多的迭代次数.
而较大的学习率可能导致不稳定的收敛或者振荡.
- 沿着梯度的 [反方向], 以一定的 [学习率] 调整参数.
迭代: 重复步骤2和3, 直到满足停止条件, 如达到一定的迭代次数, 梯度接近零, 或者函数值变化较小.
输出结果: 最终参数值即为函数的极小值点. (Eg: 损失函数值最小时, w和b的值)
# M-P 神经元模型
1943 年, 心理学家 Warren McCulloch(沃伦·麦卡洛克) 和逻辑学家 Walter Pitts(沃尔特·皮茨).
将生物神经网络的神经元抽象为一个简易数学模型, 也就是一直沿用至今的 M-P 神经元模型..
注: 此处阐述的就是单个人工神经元
x0、x1、x2 是每个特征的权重, 该权重代表了 该特征对当前神经元的重要性..
每个特征的值乘以各自权重的结果 [之和] 代入 一个 [激活函数] 中, 计算得到的就是该神经元的 [输出] ..
- 对输入信号加权求和(汇总信号) 有点像是多元线性回归的方程.. (b可看作是
w0*x0
x0值固定为1 - 上述过程的特征值、加权求和公式、激活函数、该样本真实/正确标签 都是已知的.
未知部分是 每个特征的权重, 这个权重如何计算的呢? 是根据学习规则对w进行迭代调整得到的, 详见单层感知机.
# 单层感知机
单层感知器是1958年提出的一种具有 [单层] 计算单元的神经网络结构.
# 输入层+输出层
单层感知机对应的网络结构 [只] 包含两层: 输入层(又称为感知层) 和输出层(又称为处理层)
图中 空心的蓝色圆点 是 输入的每个特征值. (此处有4个特征 x1、x2、x3、x4)
实心的蓝色圆点 就是 上一小节所说的 M-P神经元.. 此处有两个.
它会将各个特征值与其权重进行加权求和,并将求和结果代入激活函数中.
在上图整个单层感知感知机的架构中:
我们可以 先 [随机] 生成各个特征维度对应的w.. 然后根据学习规则对各个特征的权值w进行迭代调整.
(注: 特征x1输入给b1、b2神经元的特征权重w11、w21是不一样的. 这表明 ☆[每个特征到每个神经元的权重是独立的])
# 学习规则
此处我们不必知道这个学习规则是怎么推导出来的. 在这里我们接受下面的学习规则公式即可..
学习规则规定, 其权值的调整 取决于期望输出与实际输出之差.. (在GBDT中叫作 残差)
- 学习率 是人为设定的一个超参数, 主要是在训练阶段用来控制模型参数调整的快慢.
关于学习率主要有 2 个要点需要注意:- 学习率 𝜼 取值一般取 0-1 之间
- 学习率太大容易造成权值调整不稳定; 学习率太小模型参数调整太慢, 迭代次数太多.
学习率的值到底取多少比较合适? 这个问题其实是没有明确答案的, 需要根据建模的经验以及测试才能找到合适的学习率.
- 模型的收敛 是指在训练过程中.
随着参数(如神经网络中的权重和偏差)的不断调整, 模型的性能逐渐提高, 直到达到一种稳定状态.
通常模型的收敛条件可以有以下 2 个:- 两次迭代之间权值的变化已经很小了
- 设定最大迭代次数, 当迭代超过最大次数就停止
# 权重调整示例
我们来看看对神经元b1的特征权重x11、w12、w13、w14是如何通过 学习规则 进行迭代调整的.. (神经元b2的特征权重调整同理..)
step1: 我们首先计算神经元对4个输入信号的输出 = 加权求和 + 激活函数
step2: 只要输出与真实值不一致, 就根据学习规则调整各个特征权值, 再次计算神经元的输出结果, 直到和正确标签一致, 则迭代停止.
ps: 也许你查阅资料会看到偏差这一项(线性方程的截距), 其实你可以将其看成 w0*x0, w0=偏差值, x0=1
import numpy as np
# 定义输入特征(假设有4个特征输入 x1, x2, x3, x4)
x1 = 1
x2 = 0
x3 = -7
x4 = 3
# 随机初始化神经元 b1 的特征权重 w11, w12, w13, w14
w11 = -0.6
w12 = -0.4
w13 = 0.4
w14 = -0.8
# 定义正确的标签 t,真实值
t = 1
# 定义学习率 lr (learning rate)
lr = 0.1
for i in range(100):
# 计算感知器的输出 - 预测值 > 各个特征值与其权重的加权求和 + 激活函数
weighted_sum = w11 * x1 + w12 * x2 + w13 * x3 + w14 * x4
y = np.sign(weighted_sum) # 激活函数: 符号函数(sign)
# 打印当前权值和预测值
print(f"迭代次数:{i+1},权值:w11={w11:.4f},w12={w12:.4f},w13={w13:.4f},w14={w14:.4f},预测值: y={y}")
# 如果感知器输出不等于正确的标签
if y != t:
# 更新权值和偏置
# Δw = lr * (t - y) * xi
w11 = w11 + lr * (t - y) * x1
w12 = w12 + lr * (t - y) * x2
w13 = w13 + lr * (t - y) * x3
w14 = w14 + lr * (t - y) * x4
else:
print("训练完成!")
break
"""
迭代次数: 1, 权值: w11=-0.6000, w12=-0.4000, w13=0.4000, w14=-0.8000, 预测值: y=-1.0
迭代次数: 2, 权值: w11=-0.4000, w12=-0.4000, w13=-1.0000, w14=-0.2000, 预测值: y=1.0
训练完成!
"""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 多层神经网络
关于ANN神经网络, 我们已经阐述了 单层感知机..
单层感知器对人工神经网络的发展发挥了极大的作用, 但是它的结构只有输入层和输出层, 不能解决较难问题的求解.
解决较难问题的网络结构应该具有隐藏层, 但是对隐藏层神经元的学习规则还没有合理的理论依据..
也就是说 对于各个隐藏层的节点来说:
不存在已知的期望输出(只有到输出层才会有期望输出结果), 因而前面提及的学习规则不能用于隐藏层的权值调整..
因此, 误差反向传播算法就应运而生了
神经网络的结构可以有多层, 多层的神经网络可以由"输入层", "隐藏层"以及"输出层"组成.
其中隐藏层(输入和输出层中间的都是隐层)可能有0到多个, 所以最简单的神经网络就只有输入层和输出层.
神经网络的每一层都由若干个"神经元"节点组成!
思考: 神经网络为何会设计成多层结构呢?
-1- 特征学习与提取: 每一层神经元都可以从上一层的输出中学习并提取更有用的特征.
-2- 提高泛化能力:
当网络有足够的层数和节点时,会使得多层神经网络具有较好的泛化能力.
这就像是你学会了骑自行车后,即使换了一辆不同的自行车,你也能很快适应并骑好它. 因为你已经掌握了骑自行车的基本技能和原理.
-3- 层次化的信息处理:
多层结构提供了层次化的信息处理机制,每层负责不同的抽象级别.这种层次化有助于理解和解决问题.
比如在图像识别任务中,第一层可能会识别出图像中的线条和边缘,第二层可能会识别出形状和纹理,而更高层则可能识别出整个物体或场景!
综上所述,神经网络设计多层的作用和意义在于可以使其能够更好地处理复杂问题并适应新环境.
2
3
4
5
6
7
8
9
10
11
12
13
14
隐藏层是什么? 误差反向传播算法又是什么? 带着疑问, 进入下面的学习.
# 隐层的作用
前面我们提及了, 解决较难问题的网络结构应该具有隐藏层.. 什么叫作 较难的问题?
现在有一只猫的图片, 我们想要使得神经网络可以学习到猫的主要特征, 并且最终可以将猫正确的识别出来..
假设猫的特征矩阵为X, 其中包含了整张图片所有的特征(比如: 海水,礁石,天空,猫).
假设: x0是海水, x1是礁石, x2是猫, 如果w0为0, w1为0, w2为1, 则神经网络就可以学习到图片是猫.
如果w的值不合适的话,则模型无法识别出是猫.
因此,通过不断迭代w值的过程也就是网络模型学习的过程(提取重要特征的过程)
但是,如果只有一个网络层的话,提取重要特征一定是不准确的.因此可以添加更多的网络层(隐层).
2
3
4
5
若网络模型只有输入层和输出层的话 > 单层感知机.
则将X作为输入数据给输入层,经过 输出层的神经元 加权求和(x1w1+xnwn)以及经过激活函数后 进行输出.- ★ 加权求和的过程 就是在通过权重系数w来使得网络模型提取猫的主要特征让神经网络学习,使得其最终可以识别出猫
- ★ 如果w的值不合适的话,则模型无法识别出是猫.
因此, 通过不断迭代w值的过程也就是网络模型学习的过程 (提取重要特征的过程) - 但是, 如果只有一个网络层的话, 提取重要特征一定是不准确的. 因此可以添加更多的网络层(隐层)
网络模型包含一个输入层+n个隐藏层+一个输出层
- 假设我们现在有3个隐层.
则第一个隐层可以提取到图片的前景特征,第二个隐层可以提取到猫整个轮廓特征,第三个隐层可以提取到猫的脸部细节特征.
不断通过更多的隐层, 可以更加精准的提取到图像更多更重要的特征, 从而使得模型的学习性能更好. - ★ 每前一层的输出都作为每后一层的输入数据.
因此每后一个隐层都是在每前一个隐层提取特征基础上再次进行特征优化的提取.
- 假设我们现在有3个隐层.
# BP算法
对于各个隐藏层的节点来说, 不存在已知的期望输出(只有到输出层才会有期望输出结果).
因而该学习规则不能用于隐藏层的权值调整. 因此, 反向传播算法就应运而生了.
BP算法 的基本思想是, 神经网络的学习过程由 信号的正向传播 和 误差的反向传播 两个过程组成.
- 正向传播时, 把样本的特征从输入层进行输入, 信号经过各个隐藏层逐层处理后, 最后从 输出层传出.
- 反向传播时, 根据神经网络的实际输出与期望输出之间的误差, 把误差信号从最后一层逐层反传.
从而获得各个层的误差学习信号. 再根据 误差 "学习信号" 来修正各个层神经元的权值 - 这种信号正向传播与误差反向传播, 使得各个网络层调整权值的过程是周而复始地进行的, 也就是说BP是一种 "迭代算法"
- 在前面的"隐层的作用"小节,我们提及过:
通过权值不断调整的过程,使得损失变小,这也就是网络学习训练的过程. 周而复始的进行此过程直到满足停止条件为止.
- 在前面的"学习规则"小节,我们提及过:
停止条件一般为: 相邻两次迭代的误差小于预定义的阙值,或者是超过预先设置的最大训练次数,又或者误差减小到预先设置的阈值以下!
2
3
4
# 案例分析
假设我们有这样一个网络层 (默认激活函数为sigmoid), 我们通过这个全连接的神经网络来了解整个传播的流程.
前一层的每一个神经元依次链接后一层的每一个神经元的形式, 称为全连接
当前神经网络的 [学习目标] 就是给出输入数据x1, x2.. 迭代更新权重值 使输出尽可能与目标值接近!!
# 信号的正向传播
前向传播的过程
Step1: 输入层到隐藏层
Step2: 隐藏层到输出层
到这一步, 整个前向传播过程就结束了, 经过计算得到的输出结果为[0.7514, 0.7729], 与实际目标值[0.01, 0.99]有一定差距.
所以接下来就要进行反向传播, 更新参数(权重、偏置) 后, 重新进行新一轮的前向传播输出结果..
# 误差的反向传播
反向传播的过程
step1: 计算总损失
针对这一截图过程的一点小说明:
1. 在均方误差(MSE)损失函数中, 这里引入1/2是为了在后续计算梯度时简化表达式.
具体来说,在进行梯度下降时,我们需要对损失函数求导.如果没有这个 1/2,导数中会多出一个2,这样会稍微麻烦一点.
因此加入1/2只是一个数学上的简化策略,不影响最终的结果.
2. 关于截图中的求和符号,在公式表达时保持通用性,方便适应更复杂的场景.
比如 一个节点输出的是一个序列,例如未来的温度预测 [target_1, target_2, target_3]
这里当只有一个目标值,求和符号退化为对单个值的计算,依然是正确的
3. 再补充一点,这里只是对一个样本数据计算了损失.
要对样本数据集作总损失的话,需要按照截图的流程计算每个样本的损失,然后相加,并除以样本数量!!才是最终数据集的总损失.
2
3
4
5
6
7
8
step2: 利用梯度下降进行 隐藏层参数更新
求出总损失后就可以使用 损失进行梯度计算 和 参数更新了..
首先明确这是一个 "链式法则" 的求导过程, 需要求总误差 Etotal对 w5 的导数(偏导).
1> 回顾下, 求得out_o1和损失的过程为:
w5、w6和out_h1、out_h2加权求和 ---> net-o1 ---> 激活函数 ---> out-o1 ---> 损失
2> 因此链式法则求导过程如下:
- 求误差Etotal对outo1(激活函数的输出)的导数(偏导)
- 求outo1对neto1的导数(偏导)
- 求neto1对w5的导数(偏导)
求解过程省略, 最终得到总误差 Etotal对 w5 的导数的求导结果为 0.0822
3> 梯度/求导计算出来后, 接着就可以对w5进行参数更新了 (w6、w7、w8的权值更新同理)
一开始的时候,我还没反应过来,w5参数值的更新为啥是这样计算的! 你这样想:
- 参照前面 "梯度的性质" 这一小节的内容.在该小节中,优化的是函数f(x, y),变量是二维坐标 x, y
- 此处的神经网络中,图中优化的是损失函数 E_total,变量是神经网络的权重 w5.
2
3
至此, 输出层的权重参数更新方式的整个流程就结束了. 接下来我们可以看下输入层参数的更新方式.
step3: 利用梯度下降进行 输入层参数更新
其实过程跟 隐藏层参数更新 到差不差的.. 具体过程如下:
唯一让我疑惑的是 total的公式中没有out_h1这个变量, 那如何对其作的偏导呢? 我查阅了资料,在梯度消失那,我恍然大悟..
至此, 误差的反向传播就完成了一次迭代过程.
最后我们再把更新后的权重值重新加入到前向传播中进行计算, 不停地迭代, 从而完成整个神经网络的训练过程.