怒鼓踊 发表于 昨天 20:42

梯度下降算法

所学习的B站视频链接 2 梯度下降算法

目录

[*]0 复习
[*]1 模型原理

[*]1.1 分治思路
[*]1.2 梯度下降算法
[*]1.3 梯度下降算法的数学模型推导

[*]2 代码编撰

[*]2.1 分块解答
[*]2.2 代码综合


0 复习

上一次课堂中我们采用了最简单的线性模型进行了尝试,当时我们的输入维度和输出的维度均是一维的。

我们随机猜测我们的权重,看看什么样子的权重是可以让我们的损失函数\(MSE\)达到最小,采用的是一个暴力枚举法,来得到咱们的曲线。

但是这仅仅只是单一权重的方法,一旦咱们的权重组合多了,这个时候咱们的程序便非常的难以运行,这个时候需要采用其他的方法和思路进行处理。
1 模型原理

1.1 分治思路

假设有\(W_1和W_2\)这两个权重需要寻找,在进行搜索的时候先进行一些稀疏的计算,找到可能的最小区块,然后在那个区块里面进行搜索,不断重复几轮即可。

但是这个东西也不一定,因为实际上咱们的真实函数长得是非常的抽象的,而非普通的凸函数。上面的那个方法仅仅对比较好的凸函数才是可以使用的。对于下面这种函数而言,采用分治法很有可能会错过一些优秀点。

因此需要其他的方法进行使用。这种问题就是优化问题罢了。
1.2 梯度下降算法


仔细看上面这个图片,咱们的红点是所需要进行下降的点,我们需要寻找使得这个点下降的方向,向左还是向右。
对函数的自变量求偏导,得到的方向是函数上升的方向,因此我们需要取导数的一个负方向进行下降,即,

\
可以看出他一直向着下降速度最快的方向进行跑动-贪心,但是这个不一定能找到最优解,只能找到一定区间内的局部最优点。例如下面这个函数

存在很多的局部最优点,这个时候采用咱们的梯度下降算法的时候是只能找到局部最优点,不能找到全局最优点。

但是实际使用的过程中,咱们在进行深度学习的过程中,局部最优点是比较少的,因此大量的使用梯度下降算法。
但是会存在鞍点也就是所谓的\(f'=0\)的点

对于这个位置一旦到达时刻,便会停止迭代,此时会陷入到鞍点无法进行运动。毕竟导数为零了,学习率不论是多少都已经没有用了。

\
可见最大的问题就是鞍点的问题了,我们要尽可能的避免鞍点。
1.3 梯度下降算法的数学模型推导

首先先给出上一次课程的损失函数,咱们用这个函数进行推导

\[\frac{1}{N}\sum_{n=1}^{N}(x_{n}\cdot\omega-y_{n})^{2}\]
对这个损失函数进行求导可以得到

\[\begin{aligned}\frac{\partial cost(\omega)}{\partial\omega}&=\frac{\partial}{\partial\omega}\frac{1}{N}\sum_{n=1}^{N}(x_{n}\cdot\omega-y_{n})^{2}\\&=\frac{1}{N}\sum_{n=1}^N\frac{\partial}{\partial\omega}(x_n\cdot\omega-y_n)^2\\&=\frac{1}{N}\sum_{n=1}^{N}2\cdot(x_{n}\cdot\omega-y_{n})\frac{\partial(x_{n}\cdot\omega-y_{n})}{\partial\omega}\\&=\frac{1}{N}\sum_{n=1}^{N}2\cdot x_{n}\cdot(x_{n}\cdot\omega-y_{n})\end{aligned}\]
最后可以求出来咱们的训练过程进行更新

\[\begin{aligned}\omega&=\omega-\alpha\frac{\partial cost}{\partial\omega}\\&=\omega-\alpha\frac{1}{N}\sum_{n=1}^{N}2\cdot x_{n}\cdot(x_{n}\cdot\omega-y_{n})\end{aligned}\]
这就是咱们的更新函数\(Update\)
2 代码编撰

2.1 分块解答

import numpy as np
import matplotlib.pyplot as plt引入两个库函数
x_data =
y_data = 引入需要使用的训练集数据
global w
w = 1.0定义一个猜测,初始化权重
def forward(x):
    return x*w定义 \(\hat{y}\) 的公式,令\(\hat{y}=\chi*\omega\)
def cost(xs , ys):
    sum = 0
    for x , y in zip(x_data , y_data):
      sum += forward(x)**2
    return sum/len(xs)定义这个平均损失函数\(MSE\),\(cost(\omega)=\frac{1}{N}\sum_{n=1}^N(\hat{y}_n-y_n)^2\)
def grad(xs , ys):
    sum = 0
    for x , y in zip(xs , ys):
      sum += 2*x*(forward(x) - y)
    return sum/len(xs)定义这个梯度函数\(Gradient\),\(\frac{\partial cost}{\partial\omega}=\frac{1}{N}\sum_{n=1}^N2\cdot x_n\cdot(x_n\cdot\omega-y_n)\)
for epoch in range(100):
    cost_val = cost(x_data , y_data)
    grad_val = grad(x_data , y_data)
    w -= 0.01*grad_val开始进行学习拟合处理,\(\omega=\omega-\alpha\frac{\partial cost}{\partial\omega}\)
训练更新的过程,这个\(0.001\)是学习率,这个是自己取得,凭感觉把。

不难看出这个玩意儿是收敛到\(w=2\)的。
只要是总体收敛便就可以了。
当然实际上可以采用指数均值的方式将这个图像变得更加的平滑。

如果你的训练图像,学着学着,成下面这个样子,那么你就训练失败了,可以适当降低学习率。

实际上我们梯度下降用的不多用的是随机梯度下降多一些。

[*]更新函数

[*]\(Gradient Descent : \omega=\omega-\alpha\frac{\partial cost}{\partial\omega}\)
[*]$ Stochastic Gradient Descent : \omega=\omega-\alpha\frac{\partial loss}{\partial\omega}$

[*]梯度求导

[*]\(Deribative of Cost Function : \frac{\partial cost}{\partial\omega}=\frac{1}{N}\sum_{n=1}^N2\cdot x_n\cdot(x_n\cdot\omega-y_n)\)
[*]\(Derivative of Loss Function : \frac{\partial loss_n}{\partial\omega}=2\cdot x_n\cdot(x_n\cdot\omega-y_n)\)


从里面随机选择一个就可以了,就直接拿上单个损失直接用,注意随机二字
这个有可能可以跨过去鞍点哈,也是有点运气成分的额。
看看相对于梯度下降而言,这个随机梯度下降的代码做了些修改
def loss(x , y):
        y_pred = forward()
    return (y_pred - y)**2重新计算损失函数,\(loss=(\hat{y}-y)^{2}=(x*\omega-y)^{2}\)
def grad(x , y)
        return 2 * x * (x*w - y)重新计算梯度函数,\(\frac{\partial loss_n}{\partial\omega}=2\cdot x_n\cdot(x_n\cdot\omega-y_n)\)
for epoch in range(100):
    for x,y in zip(x_data ,y_data):
      gradient = grad(x , y)
                w = w - 0.001 * gradient
      print("\tgradient:" , x , y , gradient)
      l = loss(x , y)重新进行学习更新
不过在真正的深度学习的过程中,梯度下降中每一个\(f(X_i)\)是相互独立的,是可以并行求解的。因此他的时间复杂度低,代码的效率高。但是由于计算量过大因此性能很低。

但是随机梯度下降中的\(w\)是从上一个哪来的,前后两个是由依赖的,算法的效率过低时间复杂度高,但是他的性能比较高

因此我们会使用\(Batch或是Mini-Batch\)进行两种算法的一个这种,一部分进行随机梯度下降,一部分进行梯度下降。分组进行使用。
2.2 代码综合

首先是最原始的梯度下降算法的代码
'''@name:梯度下降算法'''import numpy as np
import matplotlib.pyplot as pltx_data = y_data = w = 1.0def forward(x):# 前馈相乘求假设    global w    return x*wdef cost(xs , ys):# 计算平均误差和    res = 0    for x,y in zip(xs , ys):      res += (x*w - y)**2    res = res /len(xs)    return resdef gradient(xs , ys):# 求解相应的梯度    sum = 0    for x , y in zip(xs , ys):      sum = 2*x*(x*w-y)    sum = sum/len(xs)    return sum epc_list = []cos_list = []for epoch in range(0 , 100 , 1):# 进行程序深度学习    epc_list.append(epoch)    cost_val = cost(x_data , y_data)    cos_list.append(cost_val)    grad_val = gradient(x_data , y_data)    w -= alpha * grad_valplt.plot(epc_list , cos_list , 'r')plt.xlabel('epoch')plt.ylabel('MSE')plt.show()
其次是更新后的随机梯度下降算法的代码
'''@name:随机梯度下降算法'''import numpy as np
import matplotlib.pyplot as pltdef forward(x):# 前馈相乘求假设    global w    return x*wdef loss(x , y):# 计算平均误差和    return (forward(x) - y)**2def gradient(x , y):# 求解相应的梯度    return (2*x*(forward(x) - y))x_data = y_data = w = 1.0alpha = 0.01 # learning rateepc_list = []loss_list = []for epoch in range(0 , 100 , 1):# 进行程序深度学习    epc_list.append(epoch)    n = 0.0    sum = 0.0    for x,y in zip(x_data ,y_data):      n+=1      grad = gradient(x , y)      w = w - 0.01 * grad      l = loss(x , y)      sum += l    sum =sum / n    loss_list.append(sum)plt.plot(epc_list ,loss_list , 'r')plt.xlabel('epoch')plt.ylabel('loss')plt.show()

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 梯度下降算法