前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Pytorch基础】梯度下降算法的改进

【Pytorch基础】梯度下降算法的改进

作者头像
yhlin
发布2023-02-27 16:57:44
7650
发布2023-02-27 16:57:44
举报
文章被收录于专栏:yhlin's blog

回顾

  上偏文章我们了解到,权重迭代过程中可能遇到 鞍点 而阻断迭代过程,这是因为每一次迭代都以 所有样本(故又称为批梯度下降算法)为依据(前后有直接联系),因此当梯度为零时相应增量也为零,导致新权重与不会改变。为了尽量避免这种情况出现,引入随机梯度下降算法,降低甚至消除权重前后权重间的联系,使得权重有可能从鞍点中‘跳脱’出来。

随机梯度下降(SGD)

批梯度下降:

\text{更新方法:} w = w - \alpha \frac{\partial cost}{\partial w}
\text{梯度函数:} \frac{\partial cost}{\partial w}= \frac{1}{n}\sum_{i=1}^{n}2\cdot x_i \cdot (x_i \cdot w - y_i)

随机梯度下降:

\text{更新方法:} w = w - \alpha \frac{\partial loss}{\partial w}
\text{梯度函数:} \frac{\partial loss}{\partial w}= 2\cdot x_i \cdot (x_i \cdot w - y_i)

观察公式,随机梯度下降算法与梯度下降算法的区别在于每次迭代依据为随机的单个样本的梯度,而不是所有样本的梯度和平均值,而单个样本之间是独立的,由此降低了前后权重的联系,为跳出鞍点束缚提供了可能。

实现

同样以上篇文章的例子为例,只需修改部分代码即可:

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt

# 准备数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# 初始化权重 w, 学习率 a
w = 0.1
a = 0.01

# 定义模型函数
def forward(x):
    return x * w;

# 定义平均损失函数
'''
def cost(xs, ys):
    loss = 0 #损失和
    for x, y in zip(xs,ys):
        y_predict = forward(x)
        loss += (y - y_predict) ** 2
    return loss / len(xs)
'''
# 定义损失函数(单样本)def loss(x, y):
    y_predict = forward(x)
    return (y_predict - y) ** 2

# 定义平均梯度函数
'''
def gradient(xs, ys):
    grad = 0 # 初始化梯度
    for x, y in zip(xs, ys):
        grad += 2 * x * (x * w - y)
    return grad / len(xs)
'''

# 定义梯度函数
def gradient(x, y):
    return 2 * x * (x * w - y)

print(' 训练前预测:',4,forward(4))

# 用于绘制损失函数
w_list = []
cost_list = []

# 开始训练模型 16 个世代
for epoch in range(100):
    # 每次更新只以一个样本为根据,这里没用随机函数选取样本是因为实际过程中样本排列本就有可能是随机的,故无需多此一举
    for x, y in zip(x_data, y_data): 
        cost_val = loss(x, y)
        grad_val = gradient(x, y)
        w -= a * grad_val
    w_list.append(w)
    cost_list.append(cost_val)
    print(' 第 ',epoch,' 世代 ',' w = ',w,' loss = ',cost_val)

print(' 训练后预测:',4,forward(4))

# 绘图(权重与平均损失的关系)
plt.plot(w_list, cost_list)
plt.ylabel('cost')
plt.xlabel('W')
plt.xlim(0.5,2)
plt.show()

损失函数图像

【Pytorch 基础】梯度下降算法的改进
【Pytorch 基础】梯度下降算法的改进

优缺点

批梯度下降(BGD)

  批梯度下降算法每一次迭代都要用到所有的样本,如果样本数量很多的话将会非常耗时,但其每次迭代都会朝着当前最优方向前进,故迭代次数相对较少。

【Pytorch 基础】梯度下降算法的改进
【Pytorch 基础】梯度下降算法的改进
随机梯度下降(SGD)

  随机梯度下降是通过每个样本来迭代更新一次,对比上面的批量梯度下降,迭代一次需要用到所有训练样本(往往如今真实问题训练数据都是非常巨大),一次迭代不可能最优,如果迭代 10 次的话就需要遍历训练样本 10 次。但是,SGD 伴随的一个问题是噪音较 BGD 要多,使得 SGD 并不是每次迭代都向着整体最优化方向。

【Pytorch 基础】梯度下降算法的改进
【Pytorch 基础】梯度下降算法的改进

小批量梯度下降算法(MBGD)

 BGD 与 SGD 各有各的优缺点,那么能不能在两种方法的性能之间取得一个折衷呢?即,算法的训练过程比较快,而且也要保证最终参数训练的准确率,而这正是小批量梯度下降法(Mini-batch Gradient Descent,简称 MBGD)的初衷。具体方法为:将所有样本划分为多个组(Mini-Batch),每组内使用 BGD 算法。

【Pytorch 基础】梯度下降算法的改进
【Pytorch 基础】梯度下降算法的改进

实现

代码语言:javascript
复制
# 准备数据集
x_data = [1.0, 2.0, 3.0, 4.0,5.0,6.0,7.0,8.0,9.0]
y_data = [2.0, 4.0, 6.0, 8.0,10.0,12.0,14.0,16.0,18.0]

# 初始化权重 w, 学习率 a
w = 1.0
a = 0.01

# 定义模型函数
def forward(x):
    return x * w;

# 定义平均损失函数
def cost(xs, ys):
    loss = 0 #损失和
    for x, y in zip(xs,ys):
        y_predict = forward(x)
        loss += (y - y_predict) ** 2
    return loss / len(xs)

# 定义损失函数(单样本)def loss(x, y):
    y_predict = forward(x)
    return (y_predict - y) ** 2

# 定义平均梯度函数

def Gradient(xs, ys):
    grad = 0 # 初始化梯度
    for x, y in zip(xs, ys):
        grad += 2 * x * (x * w - y)
    return grad / len(xs)

# 定义梯度函数
def gradient(x, y):
    return 2 * x * (x * w - y)

print(' 训练前预测:',4,forward(4))

# 用于绘制损失函数
w_list = []
cost_list = []

# 数据集分组,假设每次更新以 batch 个样本为一组
batch = 3
x_data = [x_data[i:i+batch] for i in range(0,len(x_data),batch)]
y_data = [y_data[i:i+batch] for i in range(0,len(y_data),batch)]

# 开始训练模型 100 个世代
for epoch in range(100):
    for x_batch, y_batch in zip(x_data, y_data):
        cost_val = cost(x_batch, y_batch)
        grad_val = Gradient(x_batch, y_batch)
        w -= a * grad_val
    w_list.append(w)
    cost_list.append(cost_val)
    print(' 第 ',epoch,' 世代 ',' w = ',w,' loss = ',cost_val)

print(' 训练后预测:',4,forward(4))

# 绘图(权重与平均损失的关系)
plt.plot(w_list, cost_list)
plt.ylabel('cost')
plt.xlabel('W')
plt.show()

损失函数

代码语言:javascript
复制
训练前预测:4 4.0
第 0 世代  w =  2.1294317037037036  loss =  12.59038399736626
第 1 世代  w =  1.9832474340763566  loss =  0.21092123791986206
第 2 世代  w =  2.0021683131489056  loss =  0.0035334719429489605
第 3 世代  w =  1.999719351534974  loss =  5.919472166357302e-05
第 4 世代  w =  2.00003632480897  loss =  9.916634770013522e-07
第 5 世代  w =  1.9999952984180882  loss =  1.6612907772933173e-08
第 6 世代  w =  2.000000608533757  loss =  2.783088326603426e-10
第 7 世代  w =  1.999999921236439  loss =  4.6623870701412184e-12
第 8 世代  w =  2.0000000101945017  loss =  7.810694676889426e-14
第 9 世代  w =  1.9999999986805082  loss =  1.3084916871004463e-15
第 10 世代  w =  2.000000000170784  loss =  2.1920595657819074e-17
第 11 世代  w =  1.9999999999778952  loss =  3.672259062606486e-19
第 12 世代  w =  2.0000000000028613  loss =  6.152111786372818e-21
第 13 世代  w =  1.9999999999996299  loss =  1.0306734572061392e-22
第 14 世代  w =  2.000000000000048  loss =  1.727096304196513e-24
第 15 世代  w =  1.9999999999999938  loss =  2.938349099767225e-26
第 16 世代  w =  2.000000000000001  loss =  4.627983977296602e-28
第 17 世代  w =  1.9999999999999998  loss =  1.262177448353619e-29
第 18 世代  w =  2.0  loss =  0.0
第 19 世代  w =  2.0  loss =  0.0
训练后预测:4 8.0

点集:(w,cost)
    2.1294317037037036 12.59038399736626 ,
    1.9832474340763566 0.21092123791986206 ,
    2.0021683131489056 0.0035334719429489605 ,
    1.999719351534974 5.919472166357302e-05 ,
    2.00003632480897 9.916634770013522e-07 ,
    1.9999952984180882 1.6612907772933173e-08 ,
    2.000000608533757 2.783088326603426e-10 ,
    1.999999921236439 4.6623870701412184e-12 ,
    2.0000000101945017 7.810694676889426e-14 ,
    1.9999999986805082 1.3084916871004463e-15 ,
    2.000000000170784 2.1920595657819074e-17 ,
    1.9999999999778952 3.672259062606486e-19 ,
    2.0000000000028613 6.152111786372818e-21 ,
    1.9999999999996299 1.0306734572061392e-22 ,
    2.000000000000048 1.727096304196513e-24 ,
    1.9999999999999938 2.938349099767225e-26 ,
    2.000000000000001 4.627983977296602e-28 ,
    1.9999999999999998 1.262177448353619e-29 ,
    2.0 0.0 ,
    2.0 0.0 ,
【Pytorch 基础】梯度下降算法的改进
【Pytorch 基础】梯度下降算法的改进

由图像可以看出其收敛速度较快,事实上在本例中它只迭代了 20 次左右就取得最优权重。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 回顾
  • 随机梯度下降(SGD)
  • 实现
    • 损失函数图像
      • 批梯度下降(BGD)
      • 随机梯度下降(SGD)
  • 优缺点
  • 小批量梯度下降算法(MBGD)
    • 实现
      • 损失函数
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档