什么是梯度下降法?

而梯度下降这个算法,也涉及到了高数上的一些知识,比如高数求导求最小化

所以,我们在学习梯度下降法之前,就需要学习有关高数求导求最小化以及其他的一些基础知识知识了

必备基础知识

高数导数最小化策略

导数最小化是一种常见的问题,解决这个问题可以帮助我们更好的找到函数的极小值

其中的数值优化算法和迭代调整参数就是梯度下降法的核心了。

通过导数最小化,我们就可以得到函数的最优解了。

学习率--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")

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐