目录
前言
本文属于 线性回归算法【AIoT阶段三】(尚未更新),这里截取自其中一段内容,方便读者理解和根据需求快速阅读。本文通过公式推导+代码两个方面同时进行,因为涉及到代码的编译运行,如果你没有
N
u
m
P
y
NumPy
NumPy,
P
a
n
d
a
s
Pandas
Pandas,
M
a
t
p
l
o
t
l
i
b
Matplotlib
Matplotlib 的基础,建议先修文章:数据分析三剑客【AIoT阶段一(下)】(十万字博文 保姆级讲解),本文是梯度下降的第一部分,后续还会有:**梯度下降优化**,**梯度下降优化进阶****(暂未更新)**
1.无约束最优化
🚩无约束最优化问题(unconstrained optimizationproblem)指的是从一个问题的所有可能的备选方案中,选择出依某种指标来说是最优的解决方案。从数学上说,最优化是研究在一个给定的集合S上泛函
J
(
θ
)
J(\theta)
J(θ)的极小化或极大化问题:**广义上**,最优化包括数学规划、图和网络、组合最优化、库存论、决策论、排队论、最优控制等。**狭义上**,最优化仅指数学规划。
大白话说就是,比如对于一个二次函数我们要求其极值,无约束的意思就是
x
x
x 的取值是任意的,在
R
R
R 上都可取,对于有约束可以形象化理解为我们对
x
x
x 的范围进行了限制,比如我们要求
x
>
0
x>0
x>0 。
2.梯度下降
🚩梯度下降法
(
G
r
a
d
i
e
n
t
(Gradient
(Gradient
D
e
s
c
e
n
t
)
Descent)
Descent) 是一个算法,但不是像多元线性回归那样是一个具体做回归任务的算法,而是一个非常**通用**的优化算法来帮助一些机器学习算法(都是无约束最优化问题)求解出**最优解**, 所谓的通用就是很多机器学习算法都是用梯度下降,甚至**深度学习**也是用它来求解最优解。所有优化算法的目的都是期望以**最快**的速度把模型参数θ求解出来,梯度下降法就是一种**经典**常用的优化算法。
之前利用正规方程求解的
θ
\theta
θ 是最优解的原因是
M
S
E
MSE
MSE 这个损失函数是凸函数。但是,机器学习的损失函数并非都是凸函数,设置导数为
0
0
0 会得到很多个极值,不能确定唯一解。
使用正规方程
θ
=
(
X
T
X
)
−
1
X
T
y
\theta = (X^TX)^{-1}X^Ty
θ=(XTX)−1XTy 求解的另一个限制是特征维度(
X
1
、
X
2
…
…
、
X
n
X_1、X_2……、X_n
X1、X2……、Xn)不能太多,矩阵逆运算的时间复杂度通常为
O
(
n
3
)
O(n^3)
O(n3) 。换句话说,就是如果特征数量翻倍,你的计算时间大致为原来的
2
3
2^3
23 倍,也就是之前时间的
8
8
8 倍。举个例子,
2
2
2 个特征
1
1
1 秒,
4
4
4 个特征就是
8
8
8 秒,
8
8
8 个特征就是
64
64
64 秒,
16
16
16 个特征就是
512
512
512 秒,当特征更多的时候呢?运行时间会非常漫长~
所以正规方程求出最优解并不是机器学习甚至深度学习常用的手段。
之前我们令导数为
0
0
0,反过来求解最低点
θ
\theta
θ 是多少,而梯度下降法是**一点点**去逼近最优解!
其实这就跟生活中的情形很像,比如你问一个朋友的工资是多少,他说你猜?那就很难了,他说你猜完我告诉你是猜高了还是猜低了,这样你就可以奔着对的方向一直猜下去,最后总会猜对!梯度下降法就是这样的,多次尝试。并且,在试的过程中还得想办法知道是不是在猜对的路上,说白了就是得到正确的反馈再调整然后继续猜才有意义~
这个就好比道士下山,我们把
L
o
s
s
Loss
Loss (或者称为
C
o
s
t
Cost
Cost,即损失)曲线看成是**山谷**,如果走过了,就再往回返,所以是一个迭代的过程。
3.梯度下降公式
🚩这里梯度下降法的公式就是一个式子指导计算机迭代过程中如何去调整
θ
\theta
θ,可以通过泰勒公式一阶展开来进行推导和证明:
θ n + 1 = θ n − α ∗ g r a d i e n t \theta^{n + 1} = \theta^{n} - \alpha * gradient θn+1=θn−α∗gradient
其中
α
\alpha
α 表示步幅,也称为学习率,
g
r
a
d
i
e
n
t
gradient
gradient 表示梯度,即导数,
θ
\theta
θ 是方程系数
θ n + 1 = θ n − α ∗ ∂ J ( θ ) ∂ θ \theta^{n + 1} = \theta^{n} - \alpha * \frac{\partial J(\theta)}{\partial \theta} θn+1=θn−α∗∂θ∂J(θ)有些公式,使用其他字母表示:
θ n + 1 = θ n − η ∗ ∂ J ( θ ) ∂ θ \theta^{n + 1} = \theta^{n} - \eta * \frac{\partial J(\theta)}{\partial \theta} θn+1=θn−η∗∂θ∂J(θ)
w j n + 1 = w j n − η ∗ ∂ J ( θ ) ∂ θ j w_j^{n + 1} = w_j^{n} - \eta * \frac{\partial J(\theta)}{\partial \theta_j} wjn+1=wjn−η∗∂θj∂J(θ)
这里的
w
j
w_j
wj 就是
θ
\theta
θ 中的某一个
j
=
0
,
.
.
.
,
m
j = 0,...,m
j=0,...,m,这里的
η
\eta
η 就是梯度下降图里的
l
e
a
r
n
i
n
g
learning
learning
s
t
e
p
step
step,很多时候也叫学习率
l
e
a
r
n
i
n
g
learning
learning
r
a
t
e
rate
rate,很多时候也用
α
\alpha
α 表示,这个学习率我们可以看作是下山迈的**步子**的大小,步子迈的大下山就快。
学习率一般都是正数,如果在山左侧(曲线左半边)梯度是负的,那么这个负号就会把
w
j
w_j
wj 往大了调, 如果在山右侧(曲线右半边)梯度就是正的,那么负号就会把
w
j
w_j
wj 往小了调。每次
w
j
w_j
wj 调整的幅度就是
η
∗
g
r
a
d
i
e
n
t
\eta * gradient
η∗gradient,就是横轴上移动的距离。
因此,无论在左边,还是在右边,梯度下降都可以快速找到最优解,实现快速下山~
如果特征或维度越多,那么这个公式用的次数就越多,也就是每次迭代要应用的这个式子多次(多少特征,就应用多少次),所以其实上面的图不是特别准,因为
θ
\theta
θ 对应的是很多维度,应该每一个维度都可以画一个这样的图,或者是一个多维空间的图。
如果特征或维度越多,那么这个公式用的次数就越多,也就是每次迭代要应用的这个式子多次(多少特征,就应用多少次),所以其实上面的图不是特别准,因为
θ
\theta
θ 对应的是很多维度,应该每一个维度都可以画一个这样的图,或者是一个多维空间的图。
w 0 n + 1 = w 0 n − η ∗ ∂ J ( θ ) ∂ θ 0 w_0^{n + 1} = w_0^{n} - \eta * \frac{\partial J(\theta)}{\partial \theta_0} w0n+1=w0n−η∗∂θ0∂J(θ)
w 1 n + 1 = w 1 n − η ∗ ∂ J ( θ ) ∂ θ 1 w_1^{n + 1} = w_1^{n} - \eta * \frac{\partial J(\theta)}{\partial \theta_1} w1n+1=w1n−η∗∂θ1∂J(θ)
- ……
w m n + 1 = w m n − η ∗ ∂ J ( θ ) ∂ θ m w_m^{n + 1} = w_m^{n} - \eta * \frac{\partial J(\theta)}{\partial \theta_m} wmn+1=wmn−η∗∂θm∂J(θ)
所以观察上图我们可以发现不是某一个
θ
0
\theta_0
θ0 或
θ
1
\theta_1
θ1 找到最小值就是最优解,而是它们一起找到
J
(
θ
)
J(\theta)
J(θ) 最小值才是最优解。
4.学习率
🚩根据我们上面讲的梯度下降公式,我们知道
η
\eta
η 是学习率,设置大的学习率
w
j
w_j
wj 每次调整的幅度就大,设置小的学习率
w
j
w_j
wj 每次调整的幅度就小,然而如果步子迈的太大也会有问题,俗话说步子大了容易扯着蛋!学习率大,可能一下子迈过了,到另一边去了(从曲线左半边跳到右半边),继续梯度下降又迈回来, 使得来来回回震荡。步子太小呢,就像蜗牛一步步往前挪,也会使得整体迭代次数增加。
学习率的设置是门一门学问,一般我们会把它设置成一个比较小的正整数,
0.1
0.1
0.1、
0.01
0.01
0.01、
0.001
0.001
0.001、
0.0001
0.0001
0.0001,都是常见的设定数值(然后根据情况调整)。一般情况下学习率在整体迭代过程中是不变,但是也可以设置成随着迭代次数增多学习率逐渐变小,因为越靠近山谷我们就可以步子迈小点,可以更精准的走入最低点,同时防止走过。还有一些深度学习的优化算法会自己控制调整学习率这个值,后面学习过程中这些策略在讲解代码中我们会一一讲到。
5.全局最优化
🚩上图显示了梯度下降的两个主要挑战:
- 若随机初始化,算法从左侧起步,那么会收敛到一个局部最小值,而不是全局最小值;
- 若随机初始化,算法从右侧起步,那么需要经过很长时间才能越过 P l a t e a u Plateau Plateau(函数停滞带,梯度很小),如果停下得太早,则永远达不到全局最小值;
而线性回归的模型
M
S
E
MSE
MSE 损失函数恰好是个凸函数,凸函数保证了只有一个全局最小值,其次是个连续函数,斜率不会发生陡峭的变化,因此即便是乱走,梯度下降都可以趋近全局最小值。
上图损失函数是非凸函数,梯度下降法是有可能落到局部最小值的,所以其实步长不能设置的太小太稳健,那样就很容易落入局部最优解,虽说局部最小值也没大问题, 因为模型只要是堪用的就好嘛,但是我们肯定还是尽量要奔着全局最优解去
6.梯度下降步骤
🚩梯度下降流程就是“猜”正确答案的过程:
- 1、“瞎蒙”, R a n d o m Random Random 随机数生成 θ \theta θ,随机生成一组数值 w 0 、 w 1 … … w n w_0、w_1……w_n w0、w1……wn ,期望 μ \mu μ 为 0 方差 σ \sigma σ 为 1 的正太分布数据。
- 2、求梯度 g g g ,梯度代表曲线某点上的切线的斜率,沿着切线往下就相当于沿着坡度最陡峭的方向下降
- 3、 i f if if g < 0 g < 0 g<0, θ \theta θ 变大, i f if if g > 0 g > 0 g>0, θ \theta θ 变小
- 4、判断是否收敛 c o n v e r g e n c e convergence convergence,如果收敛跳出迭代,如果没有达到收敛,回第 2 2 2 步再次执行 2 2 2 ~ 4 4 4 步收敛的判断标准是:随着迭代进行损失函数 L o s s Loss Loss,变化非常微小甚至不再改变,即认为达到收敛
7.代码模拟梯度下降
- 梯度下降优化算法,比正规方程,应用更加广泛
- 什么是梯度?- 梯度就是导数对应的值!
- 下降?- 涉及到优化问题,最小二乘法
- 梯度下降呢?- 梯度方向下降,速度最快的~
接下来,我们使用代码来描述上面梯度下降的过程:
方程如下:
f
(
x
)
=
(
x
−
3.5
)
2
−
4.5
x
+
10
f(x) = (x - 3.5)^2 - 4.5x + 10
f(x)=(x−3.5)2−4.5x+10
7.1 构建函数和导函数
import numpy as np
import matplotlib.pyplot as plt
# 构建方程
f =lambda x :(x -3.5)**2-4.5* x +10# 方程的导函数
g =lambda x :2*(x -3.5)-4.5
7.2 函数可视化
# 绘制函数图像
x = np.linspace(0,11.5,100)
y = f(x)
_ = plt.plot(x, y)
7.3 求函数的最小值
7.3.1 导函数可解
'''
2 * (x - 3.5) - 4.5 = 0
2 * x = 11.5
x = 5.75
'''
_ = plt.plot(x, y)
_ = plt.scatter(5.75, f(5.75), color ='red')# 红点就是最小值
7.3.2 导函数不可解(梯度下降)
eta =0.1# 学习率
precision =0.0001# 设置精度# 瞎蒙(随机)一个初始值
x = np.random.randint(0,12)print('随机的值:x =', x)# 下面会进行多次 while 循环执行梯度下降# 每次都要更新 last_x,记录上一次的值# last_x 赋初值的时候要与 x 略微不同,赋值大于精度即可
last_x = x +0.1# x_ 就是每次梯度下降求解出的 x 值,一开始为 x 的初值
x_ =[x]
cnt =0whileTrue:if np.abs(x - last_x)< precision:break# 根据梯度下降进行更新
cnt +=1
last_x = x
x = x - eta * g(x)
x_.append(x)print('梯度下降的次数为:', cnt)print('算出的结果:x =', x)# 绘图
x1= np.linspace(0,11.5,100)
y = f(x1)
_ = plt.plot(x1, y)
x_ = np.array(x_)
_ = plt.scatter(x_, f(x_), color ='red')
版权归原作者 辰chen 所有, 如有侵权,请联系我们删除。