什么是梯度下降法?
而梯度下降这个算法,也涉及到了高数上的一些知识,比如高数求导求最小化
所以,我们在学习梯度下降法之前,就需要学习有关高数求导求最小化以及其他的一些基础知识知识了
必备基础知识
高数导数最小化策略
导数最小化是一种常见的问题,解决这个问题可以帮助我们更好的找到函数的极小值
其中的数值优化算法和迭代调整参数就是梯度下降法的核心了。
通过导数最小化,我们就可以得到函数的最优解了。
学习率--learning rate
它是一个控制模型参数更新速度的超参数。在进行梯度下降优化时,学习率决定了每次参数更新的步长。
可以通过以下的公式来更好地理解学习率的作用:
学习率控制了我们朝着梯度方向下降的速度或者说步长。如果学习率太大,那么可能会“跳过”最小值,导致模型无法收敛;反之,如果学习率太小,那么优化过程会非常慢,甚至可能停留在一个不理想的局部最小值点。
而学习率又引出了一个新的概念--梯度
梯度
梯度是一个向量,它既有大小也有方向。对于函数f(x,y),在某一特定点P0处的梯度方向,是函数在该点处变化率(即方向导数)最大的方向。换句话说,梯度的方向代表了函数在该点增长最快的方向,而梯度的模(大小)则为该方向导数的最大值。
也就是说,在单变量的实值函数的情况,梯度只是导数,或者,对于一个线性函数,也就是线的斜率。我们在计算梯度时,只要计算函数的偏导数就好。
同时,我们也需要具有机器学习方面的基础知识
机器学习
损失函数和代价函数
损失函数(Loss Function),又称为代价函数,是用来衡量算法拟合数据的好坏程度,具体评价的是模型的预测值与真实值之间的不一致程度。
在训练模型时,损失函数越小,代表模型拟合得越好,对历史数据的学习也就越好。
损失函数在机器学习和深度学习中扮演着至关重要的角色,它指导模型如何最小化误差,从而提高模型的预测性能。
权值,权重,模型参数
权值,权重,模型参数,三者本是上是一个东西。
模型参数是模型内部的配置变量,其值可以根据数据进行估计。它们用于表示模型对数据的学习结果,并且在模型进行预测时是必需的。模型参数的值定义了可使用的模型,并且通常是通过过去的训练数据中总结得出的。在机器学习中,模型参数通常表示为权重或权值,或者说是系数。
而关于梯度下降方面的基础知识,我们需要了解的基础知识大概就是这些了。
接下来,我们就需要逐步去实现梯度下降了。
要实现梯度下降法的步骤
准备性工作
比如导入库,设置数据集等。
import torch
import numpy as np
# 数据集
x = np.array([0.18, 0.1, 0.16, 0.08, 0.09, 0.11, 0.12, 0.17, 0.15, 0.14, 0.13])
y = np.array([0.18, 0.1, 0.16, 0.08, 0.09, 0.11, 0.12, 0.17, 0.15, 0.14, 0.13])
初始化参数
在梯度下降中,我们需要初始化的就是w和b了,
w=10
b在这里,我们就暂且不考虑。
计算损失函数
在计算损失函数时,也被用来更新损失函数的值
def loss_new(x,y,w):
return 0.5*np.sum((w*x-y)**2)
计算梯度
我们先设置梯度为0
grad=0
接下来,我们就进行梯度的计算,而这部分在后面也被我们用来更新梯度
def grad_new(x,y,w):
return np.mean((x*w-y)*w)
更新参数
根据梯度的方向来更新参数,通常是采用学习率来控制每次更新的步长。学习率越大,每次更新的步长越大,但可能会导致算法不收敛;学习率越小,每次更新的步长越小,但可能会导致算法收敛速度过慢。
在这里,我们用lr来表示学习率
w=w-lr*grad
核心部分--进行迭代
我们需要先定义迭代次数epoches=500
后面这部分是为可视化做准备
epoches=500
list_w=[]
list_loss=[]
list_grad=[]
list_i=[]
for i in range(epoches):
grad=grad_new(x,y,w)
w=w-lr*grad
loss=loss_new(x,y,w)
print(f"第{i+1}次迭代的梯度为{grad},权值为{w},损失值为{loss}")
list_w.append(w)
list_i.append(i)
list_loss.append(loss)
list_grad.append(grad)
可视化处理
我们可以用各种工具来实现它的可视化,这里我们使用pyecharts,在我之前的博客有做过详细的笔记。
# 导包
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,ToolboxOpts
line1=Line()
line1.add_xaxis(list_i)
line1.add_yaxis("梯度",list_grad)
line1.set_global_opts(
title_opts=TitleOpts(title="梯度与迭代次数的关系",pos_left="center",pos_bottom="1%"),
toolbox_opts=ToolboxOpts(is_show=True),
)
line1.render("梯度与迭代次数的关系.html")
line2=Line()
line2.add_xaxis(list_w)
line2.add_yaxis("损失值",list_loss)
line2.set_global_opts(
title_opts=TitleOpts(title="损失值与参数的关系",pos_left="center",pos_bottom="1%"),
toolbox_opts=ToolboxOpts(is_show=True),
)
line2.render("损失值与参数的关系.html")
图像
完整代码
下面是完整代码:
import torch
import numpy as np
# 数据集
x = np.array([0.18, 0.1, 0.16, 0.08, 0.09, 0.11, 0.12, 0.17, 0.15, 0.14, 0.13])
y = np.array([0.18, 0.1, 0.16, 0.08, 0.09, 0.11, 0.12, 0.17, 0.15, 0.14, 0.13])
# lr为学习率
lr = 0.01
# w为权值
w = 10
# epoches为循环进行的次数
epoches =500
# grad为维度
grad=0
list_w=[]
list_loss=[]
list_grad=[]
list_i=[]
# 进行梯度的更新
def grad_new(x,y,w):
return np.mean((x*w-y)*w)
# 进行损失值的更新
def loss_new(x,y,w):
return 0.5*np.sum((w*x-y)**2)
for i in range(epoches):
grad=grad_new(x,y,w)
w=w-lr*grad
loss=loss_new(x,y,w)
print(f"第{i+1}次迭代的梯度为{grad},权值为{w},损失值为{loss}")
list_w.append(w)
list_i.append(i)
list_loss.append(loss)
list_grad.append(grad)
# 导包
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,ToolboxOpts
line1=Line()
line1.add_xaxis(list_i)
line1.add_yaxis("梯度",list_grad)
line1.set_global_opts(
title_opts=TitleOpts(title="梯度与迭代次数的关系",pos_left="center",pos_bottom="1%"),
toolbox_opts=ToolboxOpts(is_show=True),
)
line1.render("梯度与迭代次数的关系.html")
line2=Line()
line2.add_xaxis(list_w)
line2.add_yaxis("损失值",list_loss)
line2.set_global_opts(
title_opts=TitleOpts(title="损失值与参数的关系",pos_left="center",pos_bottom="1%"),
toolbox_opts=ToolboxOpts(is_show=True),
)
line2.render("损失值与参数的关系.html")