目录
一、为什么使用梯度下降
二、什么是梯度下降
三、为什么要用梯度下降
四、怎么进行梯度下降
1、微分
1.单变量的微分
2.多变量的微分
2、梯度
3、步骤
(1)学习率α
(2)梯度(导数)前的负号
4、实例实现
五、sklearn梯度下降
一、为什么使用梯度下降
前面利用正规方程求解的w是最优解的原因是均方误差(MSE)这个损失函数是凸函数。但是,机器学习的损失函数并非都是凸函数,设置导数为0会得到很多个极值,不能确定唯一解,MSE还有一个问题,当数据量和特征较多时,矩阵计算量太大。
二、什么是梯度下降
假设你在一个陌生星球的山地上,你想找到一个谷底,那么肯定是想沿着向下的坡行走,如果想尽快的走到谷底,那么肯定是要沿着最陡峭的坡下山。每走一步,都找到当前位置为基准的最陡峭的地方走下一步,同理上山也是如此,这时就变成了梯度上升算法了。
在这个比喻中,梯度就像是山上的坡度,告诉我们在当前位置上地势变化最快的方向。为了尽快走向谷底,我们需要沿着最陡峭的坡向下行走,而梯度下降算法正是这样的方法。
梯度下降法(Gradient Descent)是一个算法,但不是像多元线性回归那样是一个具体做回归任务的算法,而是一个非常通用的优化算法来帮助一些机器学习算法求解出最优解,所谓的通用就是很多机器学习算法都是用梯度下降,甚至深度学习也是用它来求解最优解。
三、为什么要用梯度下降
梯度在微积分中的意义:
- 在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率
- 在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向
用前面的例子来说,我们需要到达山底,就需要在每一步观测到此时最陡峭的地方,梯度就恰巧告诉了我们这个方向。梯度的方向是函数在给定点上升最快的方向,那么梯度的反方向就是函数在给定点下降最快的方向,这正是我们所需要的。所以我们只要沿着梯度的方向一直走,就能走到局部的最低点。
四、怎么进行梯度下降
在机器学习中,梯度表示损失函数对于模型参数的偏导数,而梯度的方向就是函数变化最快的方向。
具体来说,对于每个可训练参数,梯度告诉我们在当前参数值下,沿着每个参数方向变化时,损失函数的变化率。通过反复计算损失函数对参数的梯度,最后就能到达局部最小值。
梯度下降算法能够根据梯度的信息来调整参数,朝着减少损失的方向更新模型,从而逐步优化模型,使得模型性能更好。
1、微分
微分常用的两种的意义:
- 函数图像中,某点的切线的斜率
- 函数的变化率
1.单变量的微分
2.多变量的微分
分别对每个变量进行求微分
2、梯度
梯度实际上是多变量微分的一般化
3、步骤
此公式的意义是:J是关于的一个函数,我们当前所处的位置为点,要从这个点走到J的最小值点,也就是山底。首先我们先确定前进的方向,也就是梯度的反向,然后走一段距离的步长,也就是α,走完这个段步长,就到达了这个点。
(1)学习率α
α在梯度下降算法中被称作为学习率或者步长,意味着可以通过α来控制每一步走的距离。设置大的学习率α;每次调整的幅度就大,设置小的学习率α;每次调整的幅度就小。
一般情况下学习率在整体迭代过程中是不变,但是也可以设置成随着迭代次数增多学习率逐渐变小,因为越靠近山谷我们就可以步子迈小点,可以更精准的走入最低点,同时防止走过。还有一些深度学习的优化算法会自己控制调整学习率这个值。
(2)梯度(导数)前的负号
梯度前加一个负号,就意味着朝着梯度相反的方向前进。梯度的方向实际就是函数在此点上升最快的方向,而我们需要朝着下降最快的方向走,即负的梯度的方向,所以此处需要加上负号;那么如果时上坡,也就是梯度上升算法,就不需要添加负号了。
4、实例实现
单变量的梯度下降
import numpy as np
import matplotlib.pyplot as plt
w = np.linspace(-10,20,100)
# 损失函数
def loss(w):
return (w-3.5)**2 - w*4.5 + 10
# 导函数
def dloss(w):
return 2*(w-3.5) - 4.5
plt.plot(w,loss(w))
# 梯度下降
np.random.seed(1)
# 随机设置w值
w = np.random.randint(-10,20)
e = loss(w) # 误差
x = [w]
y = [e]
alpha = 0.1 # 学习率
# 循环
for i in range(5):
w = w - alpha*dloss(w)
e = loss(w)
x.append(w)
y.append(e)
plt.scatter(x,y)
plt.show()
import numpy as np
# 损失函数
def loss(w):
return (w-3.5)**2 - 4.5*w + 10
# 导函数
def dloss(w):
return 2*(w-3.5) - 4.5
# 梯度下降算法
def train():
# 随机初始化一个w值
w = -10 # np.random.randint(-10,20)
# 初始化学习率
lr = 0.1
t0,t1 = 1,10
# 梯度下降更新w
epoch = 100 # 循环次数
for i in range(epoch):
lr = t0/(t1+i) # 学习率递减
w = w - lr*dloss(w)
print(f'w更新后的值为:{w},更新后的损失函数的值:{loss(w)}')
train()
多变量的梯度下降
import numpy as np
# 损失函数
def loss(w1,w2):
return (w1-3.5)**2 + (w2-3.5)**2 + 3*w1*w2 - 4.5*w1 - 2*w2 + 20
# w1偏导数
def dloss_w1(w1,w2):
return 2*(w1-3.5) + 3*w2 - 4.5
# w2偏导数
def dloss_w2(w1,w2):
return 2*(w2-3.5) + 3*w1 - 2
# 梯度下降算法
def train():
# 随机初始化一个w值
w1 = -10 # np.random.randint(-10,20)
w2 = -10
# 初始化学习率
lr = 0.1
t0,t1 = 1,10
# 梯度下降更新w
epoch = 100 # 循环次数
for i in range(epoch):
# 设置临时变量
w1_ = w1
w2_ = w2
# 更新w1
w1 = w1 - lr*dloss_w1(w1_,w2_)
# 更新w2
w2 = w2 - lr*dloss_w2(w1_,w2_)
lr = t0/(t1+i) # 学习率递减
print(f'w1更新后:{w1},w2更新后:{w2} \n 更新后的损失函数的值:{loss(w1,w2)}')
train()
五、sklearn梯度下降
官方的梯度下降API常用有三种:
批量梯度下降BGD(Batch Gradient Descent):在这种情况下,每一次迭代都会使用全部的训练样本计算梯度来更新权重。这意味着每一步梯度更新都是基于整个数据集的平均梯度。这种方法的优点是每次更新的方向是最准确的,但缺点是计算量大且速度慢,尤其是在大数据集上
小批量梯度下降MBGD(Mini-BatchGradient Descent):这种方法介于批量梯度下降和随机梯度下降之间。它不是用全部样本也不是只用一个样本,而是每次迭代从数据集中随机抽取一小部分样本(例如,从500个样本中选取32个),然后基于这一小批样本的平均梯度来更新权重。这种方法在准确性和计算效率之间取得了一个平衡。
随机梯度下降SGD(Stochastic Gradient Descent):在随机梯度下降中,每次迭代仅使用随机单个样本(或有时称为“例子”)来计算梯度并更新权重。这种方法能够更快地收敛,但由于每次更新都基于单个样本,所以会导致权重更新路径不稳定。
文章有参考:梯度下降算法原理讲解——机器学习