李宏毅机器学习[2]-DL优化

SGD-Stochastic Gradient Descent随机梯度下降

首先回顾一下梯度下降公式:
θ1θ^1θ1=θ0θ^0θ0∂(L)∂(θ0)\frac{∂(L)}{∂(θ^0)}(θ0)(L)
θ2θ^2θ2=θ1θ^1θ1∂(L)∂(θ1)\frac{∂(L)}{∂(θ^1)}(θ1)(L)

θt+1θ^{t+1}θt+1=θtθ^tθt∂(L)∂(θt)\frac{∂(L)}{∂(θ^t)}(θt)(L)

每次计算出梯度方向,然后把该点朝梯度的相反方向移动。反复操作直到计算出梯度值为0,即η∂(L)∂(θt)\frac{∂(L)}{∂(θ^t)}(θt)(L)=0时,达到local minimal。
当loss function作用在整个训练集上的时候,此时函数上会存在很多个local minimal。最原始使用的是BGD批量梯度下降,使用的是整个数据集。每进行一次梯度下降,就会遍历整个数据集,当数据集特别大的时候,效率就特别低。因此SGD每次选择一部分数据集进行梯度下降,这部分数据集可能也就只有几百条数据而已。由于BGD使用的是整个数据集,因此函数图像上就会存在很多个local minimal,并且BGD每次下降方式是梯度的相反方向,因此BGD很容易陷入一个local minimal,并且整个local minimal并不是一个最优的minimal或者说不是一个global minimal,此时就很难再跳出这个local minimal;但是SGD使用的是部分数据集,当陷入一个local minimal时,进行下一次梯度下降会使用另一组数据集,此时就可以跳出local minimal。
来自课程视频截图
但是SGD会产生震荡。这是因为在选择部分数据集时,如果选择的数据集包含的数据特别少,则下降到global minimal时所经历的曲线就会很曲折,此时我们就要适当增大所选择的部分数据集,即适当增大batch size。但是特别注意,当batch size达到一定的数量级时,SGD就会变成BGD。减少震荡的方法比如SGDM,即在梯度下降时增加一个动量momentum。

SGD-Stochastic Gradient Descent Momentum带动量的梯度下降

所谓带动量的梯度下降,就是每次下降时,都要带上前一次下降的动量。这就是为了解决在SGD中当batch size特别小时会产生动荡的问题。
来自课程视频截图

在SGD中,我们是这样进行下降的:

θt+1θ^{t+1}θt+1=θtθ^tθt∂(L)∂(θt)\frac{∂(L)}{∂(θ^t)}(θt)(L)

在SGDM中,我们设置初始动量v0v^{0}v0。即
第一次下降时的动量:v1v^{1}v1=λv0λv^0λv0∂(L)∂(θ0)\frac{∂(L)}{∂(θ^0)}(θ0)(L)
然后移动θ0θ^{0}θ0θ1θ^{1}θ1=θ0θ^{0}θ0+v1v^{1}v1
第二次下降时的动量:v2v^{2}v2=λv1λv^1λv1∂(L)∂(θ1)\frac{∂(L)}{∂(θ^1)}(θ1)(L)
然后移动θ1θ^{1}θ1θ2θ^{2}θ2=θ1θ^{1}θ1+v2v^{2}v2

第t次下降时的动量:vtv^{t}vt=λvt−1λv^{t-1}λvt1∂(L)∂(θt−1)\frac{∂(L)}{∂(θ^{t-1})}(θt1)(L)
然后移动θt−1θ^{t-1}θt1θtθ^{t}θt=θt−1θ^{t-1}θt1+vtv^{t}vt
来自课程视频截图
简单的梯度下降应用-对函数y=0.5*(x−0.25)2(x-0.25)^{2}(x0.25)2求最小值

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

mpl.rcParams['font.family'] = 'sans-serif'
mpl.rcParams['font.sans-serif'] = 'SimHei'
mpl.rcParams['axes.unicode_minus'] = False


# 构建函数
def func(x):
    return 0.5 * (x-0.25) ** 2


# 构建该函数的一阶导数
def derivative(x):
    return x-0.25


GD_X = []
GD_Y = []
x = 2  # 初始值
step = 0.05  # 步长
y = func(x)  # 求y
temp = y  # 记录当前y的值以便计算变化率
GD_X.append(x)
GD_Y.append(y)
rateY = temp  # 初始变化率
iter_num = 0


# 构造x变化函数
def changeX(x):
    return x - step * derivative(x)


# 梯度下降
while rateY > 1e-10 and iter_num < 1000:
    iter_num += 1
    temp = y  # 上次y的值存在temp中
    x = changeX(x)  # 移动x
    y = func(x)  # 移动x之后y的值
    rateY = np.abs(y - temp)  # y的变化率,
    GD_X.append(x)  # 变化率太大,迭代次数增加,变化率太小,产生震荡
    GD_Y.append(y)

print("最终计算结果:(%.5f,%.5f)" % (x, temp))
print("迭代次数:%d" % iter_num)

print(GD_X)
print(GD_Y)

X = np.arange(-4.5, 4.5, 0.05)
Y = np.array(list(map(lambda t: func(t), X)))

plt.figure(facecolor="w")
plt.plot(X, Y, "r-", linewidth=2)
plt.plot(GD_X, GD_Y, "bo--", linewidth=2)
plt.title(u"一元函数0.5 * (x - 0.25)^2进行梯度下降求函数最小值\n 学习率:%.3f,最终值:%.3f,迭代次数:%d" % (step, y, iter_num))

plt.show()

图像如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值