【PyTorch】深度学习实践 03 梯度下降算法

梯度下降(Gradient Descent)

问题背景

穷举法

在上一节的线性回归中,所使用的思想基于穷举,即为提前设定好参数的准确值在某个区间内,并以某个步长进行穷举;

这样的思想在多维(多个参数)的情况下,会引起维度的诅咒,使得原问题不可解,因此需要对这个方法进行改进。

分治法

大化小,小化无,先对整体进行分割采样,在相对最低点进行进一步的采样,直到其步长与误差符合条件。

但是分治法仍然存在缺点:

  • 容易只找到局部最优解,不易找到全最优解;
  • 如果需要分得更加细致,则计算量仍然巨大。

由于上面这两个问题,所以我们需要优化参数,也就是求解使得loss最小的参数值:

梯度下降算法

 梯度

梯度就是导数变化最大的值,其方向为导数变化最大的方向。

 若设 Δx > 0 ,则对于增函数,梯度为上升方向,对于减函数,梯度为下降方向。如此方向都不是离极值点渐进的方向,因此需要梯度下降的方向(即梯度的反方向)作为变化方向。

梯度下降算法

以凸函数为例,对于当前所选择的w值,显然并不是最低点。而对于将来要到达的全局的最低点,当前点只能向下取值,即向梯度下降方向变化。

 则取值点需要向下更新,所取的梯度即为cost对于w的偏导数,公式如下:

 其中α为学习率,也就是下降的步长,不宜取太大。

 局限性

  1. 梯度下降算法容易进入局部最优解(非凸函数),但是实际问题中的局部最优点很少,或已经基本可以当成全局最优点;
  2. 梯度下降算法容易陷入鞍点。

梯度公式

由线性回归中的公式:

可知:

代码和图示

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]
_cost = []
w = 1.0
#前馈计算
def forward(x):
    return x * w
#求MSE
def cost(xs, ys):
    cost = 0
    for x, y in zip(xs,ys):
        y_pred = forward(x)
        cost += (y_pred-y) ** 2
    return cost/len(xs)
#求梯度
def gradient(xs, ys):
    grad = 0
    for x, y in zip(xs,ys):
        temp = forward(x)
        grad += 2*x*(temp-y)
    return grad / len(xs)

for epoch in range(100):
     cost_val = cost(x_data, y_data)
     _cost.append(cost_val)
     grad_val = gradient(x_data, y_data)
     w -= 0.01*grad_val
     print("Epoch: ",epoch, "w = ",w ,"loss = ", cost_val)
print("Predict(after training)",4,forward(4))

#绘图
plt.plot(_cost,range(100))
plt.ylabel("Cost")
plt.xlabel('Epoch')
plt.show()

随机梯度下降

随机选单个样本的损失为标准,即原公式变为:

其中:

代码

#随机梯度下降
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]
_cost = []
w = 1.0
#前馈计算
def forward(x):
    return x * w
#求单个loss
def loss(x, y):
    y_pred = forward(x)
    return (y_pred-y) ** 2
#求梯度
def gradient(x, y):
    return 2*x*(x*w-y)
print("Predict(after training)",4,forward(4))

for epoch in range(100):
    for x, y in zip(x_data,y_data):
        grad=gradient(x,y) 
        w -= 0.01*grad
        print("\tgrad:  ",x,y,grad)
        l = loss(x,y)
    print("progress: ",epoch,"w=",w,"loss=",l)
print("Predict(after training)",4,forward(4))

批量梯度下降

在前面的阐述中,普通的梯度下降算法利用数据整体,不容易避免鞍点,算法性能上欠佳,但算法效率高。随机梯度下降需要利用每个的单个数据,虽然算法性能上良好,但计算过程环环相扣无法将样本抽离开并行运算,因此算法效率低,时间复杂度高。

综上可采取一种折中的方法,即批量梯度下降方法。

将若干个样本分为一组,记录一组的梯度用以代替随机梯度下降中的单个样本。

该方法最为常用,也是默认接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值