深度学习的数学基础
深度学习究竟干了什么
对于其过程以及结果的理解, 这个思维模式可以很有用
想象有两张彩纸:一张红色,一张蓝色。将一张纸放在另一张上,然后把它们一起揉成一个小球。这个皱巴巴的纸团就是你的输入数据,每张纸对应分类问题中的一个数据类别。神经网络要做的就是,找到可以让纸团恢复平整的变换,从而再次让两个类别明确可分
机器"学习"的过程
对于普通的模型实例, 每个神经层都对输入的数据进行了如下转换
o
u
t
p
u
t
=
r
e
l
u
(
d
o
t
(
i
n
p
u
t
,
W
)
+
b
)
output = relu(dot(input, W)+b)
output=relu(dot(input,W)+b)
其中W, b是张量, 均为该层的属性, 被称为该层的权重(可训练参数),
其中
W
→
k
e
r
n
e
l
属性
,
b
→
b
i
a
s
属性
其中W\rightarrow kernel属性, b\rightarrow bias属性
其中W→kernel属性,b→bias属性
-
最开始, 这两个属性取随机的值, 不会得到任何有用的表示, 叫做随机初始化,
-
根据上一步的反馈信号调整权重, 调整权重的过程称为训练
训练循环
以上两步发生在一个训练循环之内, 训练循环的具体流程如下
- 抽取训练样本 x 和对应目标 y_true 组成的一个数据批量。
- 在 x 上运行模型[这一步叫作前向传播(forward pass)],得到预测值 y_pred。
- 计算模型在这批数据上的损失值,用于衡量 y_pred 和 y_true 之间的差距。
- 更新模型的所有权重,以略微减小模型在这批数据上的损失值。
若干个训练循环过后, y_pred与y_true之间的差距将会非常小, 可以说若干个训练循环组成了训练机器学习的过程
在一个训练循环中, 最重要的是第4步, 该怎样更新权重?
梯度下降法
梯度下降是驱动现代神经网络的优化方法, 基本逻辑是利用线性代数中的导数, 判断张量函数的结果会怎样随着权重的改变而改变
而
梯度就是张量函数的导数
就像高中时期对函数求导, 但是这里的数字不再是12345, 而是张量
对什么求导?
L
o
s
s
V
a
l
u
e
=
f
(
W
)
LossValue = f(W)
LossValue=f(W)
在高中时, 要想LossValue越来越小, 就应对f(W)求导, 找到导数为零的位置(极大值或者极小值), 在这些极大值与极小值中, 最小的就是函数的最小值
在神经网络中, W所包含的变量不会少于千位数, 甚至上千万个, 不能像高中那样去求导解方程, 因此只能一点点挪动权重W的值, 一点点减小LossValue, 具体流程如下
-
抽取训练样本 x 和对应目标 y_true 组成的一个数据批量
-
在 x 上运行模型,得到预测值 y_pred。这一步叫作前向传播
-
计算模型在这批数据上的损失值,用于衡量 y_pred 和 y_true 之间的差距。
-
计算损失相对于模型参数的梯度。这一步叫作反向传播(backward pass)。
-
将参数沿着梯度的反方向移动一小步,比如
W − = L e a r n i n g R a t e ∗ G r a d i e n t W-=LearningRate * Gradient W−=LearningRate∗Gradient
,从而使这批数据上的损失值减小一些。学习(learning_rate)是一个调节梯度下降“速度”的标量因子。
上面的第一步决定了这个方法叫做小批量随机梯度下降(小批量SGD), 与他对应的还有真SGD----只抽取一个样本, 批量梯度下降----对所有数据操作
但是就像高中时, 经常会把局部极小值当成函数最小值, 这个时候正在一点点下降的梯度就会认定此时到达了最小点, 就像卡在了峡谷里.
这时候就应该涉及到带动量的SGD
这一方法的灵感来源于物理学。一个有用的思维模型是将优化过程想象成小球从损失函数曲线上滚下来。如果小球的动量足够大,那么它不会卡在
峡谷里,最终会到达全局极小点。动量方法的实现过程是,每一步移动小球,不仅要考虑当前的斜率值(当前的加速度),还要考虑当前的速度(由之前的加速度产生)。这在实践中的含义是,更新参数 w 不仅要考虑当前梯度值,还要考虑上一次参数更新,
链式法则
就像高中时的嵌套求导, 一个复杂函数的导等于组成它的函数的导数之积(似乎是这样). 神经网络中的函数链也可以进行嵌套求导, 即为链式法则
链式法则规定:grad(y, x) == grad(y, x1) * grad(x1, x)。因此,只要知道 f 和
g 的导数,就可以求出 fg 的导数。如果添加更多的中间函数,看起来就像是一条链,因此得名链式法则
这与高中的时期的求导有着同工之妙
def fghj(x):
x1 = j(x)
x2 = h(x1)
x3 = g(x2)
y = f(x3)
return y
grad(y, x) == (grad(y, x3) * grad(x3, x2) * grad(x2, x1) * grad(x1, x))
那我要求的梯度, 本质上也是个导数, 可不可以用这样的思路求梯度呢 …
将链式法则应用于神经网络梯度值的计算,就得到了一种叫作反向传播的算法…