• 【深度学习1】 BGD梯度下降算法


    🍊本文从行人下山故事引入梯度下降法,随后详细阐述其原理,并做了两个简单实验进行实战

    🍊实验一使用Pytorch来求解函数的最小值

    🍊实验二使用批量梯度下降算法和随机梯度下降算法来拟合函数求解最佳参数

    一、Introduction

    1.1 案例

    梯度下降/上升算法是一种优化算法,主要用于ML中递归性逼近最小偏差模型,主要用于寻找目标函数的最值(也有可能是拟合函数参数,其本质上是求解Loss最小值),其主要思想如下图中所示,假设有一个人需要经过最短的时间爬到山脚(不考虑走陡坡比较累),怎么做呢?首先他以当前的位置为基准,随后寻找该位置最陡峭的地方,沿该方向行走,走了一段路程后重复上述操作走到山脚就会花费最小时间

    1.2 抽象化

    以数学的角度看待下山过程

    目标函数
    山顶函数最值
    陡峭方向

    梯度正方向(找函数最大值)

    梯度反方向(找函数最小值)

    下山步子学习率α
    是否已到达山脚阈值β,判断是否完成收敛
    是否已到达山脚阈值γ,判断是否达到最大迭代次数

    因此梯度下降算法求解的过程就是对函数不断的求梯度,并使用学习率α进行约束的

    学习率的设置比较灵活,设置的太小似跺小碎步,设置的太大容易扯到蛋。因为我们的最终目标是最短的时间内到达山顶,因此最理想的状态是先大步子下山,随后小碎步逼近山脚,但是这样又出现一个问题是在山脚跺小碎步要很久😕,因此还需要设置一个阈值来进行限制,阈值的设置主要有两种策略,第一种是判断是否收敛完成,第二种为判断是否到达最大迭代次数。

    二、Principle

    2.1 性质

    • BGD可以找到局部最优解,不一定是全局最优解
    • 若损失函数为凸函数,则BGD所求解一定为全局最优解
    • 所求函数必须为连续可微分

    2.2 单变量函数推导过程

    符号含义
    θ待求参数
    α学习率
    ∇J(θ)目标函数的梯度

    其推导公式如下

    \theta _{i+1}=\theta _{i}−α∗∇J(\theta _{i})

    2.3 梯度下降三种形式

    形式特点
    Batch Gradient Descent 批量梯度下降算法直接整个数据集来训练,若数据量大将面临内存不足,收敛速度慢问题
    Stochastic Gradient Descent 随机梯度下降算法(在线学习)一个一个数据来训练,每训练一个就更新一次参数,收敛速度较快,但是可能高频的参数更新导致方差过大最终导致目标函数数值震荡
    Mini-batch Gradient Descent 小批量梯度下降算法综合BGD和SGD算法,每次取一小个batch数量的数据来计算,训练过程较稳定

    三、Experiment

    3.1 实验一:函数最小值求解

    题目:求解函数y=2.1\huge x^{2}-2.5x+1.3的最小值

     伪代码

    1. 1 初始化函数、学习率、随机初始值
    2. 2 计算函数梯度
    3. 3 更新参数
    4. 4 循环次数若小于阈值,则输出,若大于阈值则跳2

    代码

    1. # 求解f(x) = a*x**2 + b*x + c 的最小值
    2. import numpy as np
    3. import torch
    4. # 1 Initialize parameters
    5. x = torch.tensor(0.0, requires_grad=True) # x需要被求导
    6. a = torch.tensor(2.1)
    7. b = torch.tensor(-2.5)
    8. c = torch.tensor(1.3)
    9. # 2 Design optimizer
    10. optimizer = torch.optim.SGD(params=[x], lr=0.01) # SGD Stochastic Gradient Descent
    11. def f(x):
    12. result = a * torch.pow(x, 2) + b * x + c
    13. return (result)
    14. for i in range(500):
    15. optimizer.zero_grad() # Initialize grad to zero
    16. y = f(x)
    17. y.backward() # BP
    18. optimizer.step() # Update parameters
    19. print("x=", x.data, "y=", f(x))

    3.2 实验二:函数拟合求参

    题目:已知有如下数据集,其对应的函数为y=ω*x,问如何拟合出最优的ω?

    解题思路

    1  要拟合出最佳的ω,也就是让所有Loss之和最小,因此实际上还是一个求解最小值问题

    2 求解Loss之和的导数

    3 求解更新公式 

     3.2.1 BGD梯度下降法

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. # Initialize parameters
    4. x_data = [1.0, 2.0, 3.0]
    5. y_data = [2.0, 4.0, 6.0]
    6. w = 1.0
    7. # Define function
    8. def forward(x):
    9. return x * w
    10. # Define the loss function
    11. def cost(xs, ys):
    12. cost = 0
    13. for x, y in zip(xs, ys):
    14. y_pred = forward(x)
    15. cost += (y_pred - y) ** 2
    16. return cost / len(xs)
    17. # Gradient function
    18. def gradient(xs, ys):
    19. grad = 0
    20. for x, y in zip(xs, ys):
    21. grad += 2 * x * (x * w - y)
    22. return grad / len(xs)
    23. cost_list = []
    24. epoch_list = []
    25. # Trainging
    26. for epoch in range(100):
    27. epoch_list.append(epoch)
    28. cost_val = cost(x_data, y_data)
    29. cost_list.append(cost_val)
    30. grad_val = gradient(x_data, y_data)
    31. w -= 0.1 * grad_val
    32. print('Epoch:', epoch, 'w=', w, 'loss=', cost_val)
    33. # Visualize the results
    34. plt.plot(epoch_list, cost_list)
    35. plt.ylabel('Loss')
    36. plt.xlabel('Epoch')
    37. plt.show()

     可以很明显的看到,随着训练的进行,Loss是平滑的收敛于0

    3.2.2 SGD随机梯度下降法

    SGD与BGD最大的不同在于每个epoch,SGD是一个一个数据来训练,BGD是所有数据一起训练 

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. # Initialize parameters
    4. x_data = [1.0, 2.0, 3.0]
    5. y_data = [2.0, 4.0, 6.0]
    6. w = 1.0
    7. # Define function
    8. def forward(x):
    9. return x * w
    10. # Define the loss function
    11. def loss(x, y):
    12. y_pred = forward(x)
    13. return (y_pred - y) ** 2
    14. # Gradient function
    15. def gradient(x, y):
    16. return 2 * x * (x * w - y)
    17. loss_list = []
    18. epoch_list = []
    19. # Trainging
    20. for epoch in range(100):
    21. for x, y in zip(x_data, y_data):
    22. grad = gradient(x, y)
    23. w -= 0.01 * grad
    24. Loss = loss(x, y)
    25. loss_list.append(Loss)
    26. epoch_list.append(epoch)
    27. print('Epoch:', epoch, 'w=', w, 'loss=', Loss)
    28. # Visualize the results
    29. plt.plot(epoch_list, loss_list)
    30. plt.ylabel('Loss')
    31. plt.xlabel('Epoch')
    32. plt.show()

    可以看到明显的看到,随着训练的进行,Loss上下浮动的收敛于0

    参考资料

    《机器学习》周志华

    《深度学习与机器学习》吴恩达

    《神经网络与与深度学习》邱锡鹏

    《Pytorch深度学习实战》刘二大人

  • 相关阅读:
    rook-ceph部署
    快速掌握kafka原理以及常见面试题
    前端工程化02-复习jQuery当中的插件开发
    低成本、高效率!华为云桌面助力企业数字化转型
    网络安全新资讯-《关键信息基础设施安全保护要求》于明年五月正式实施
    sqli 靶场 Level23-Level30 wp
    “文化共传承 艺术润心灵”——江南大学国家艺术基金走向社区
    A tour of gRPC:07 - gRPC bidirectional straming 双向流
    Vue创建脚手架
    真是性价比之王,腾讯云这款88元云服务器已经圈粉无数!
  • 原文地址:https://blog.csdn.net/ccaoshangfei/article/details/126584958