《PyTorch深度学习实践》第三讲 梯度下降算法

穷举法的缺点

随着权重个数的增加,权重空间的维度提高,搜索区域呈指数型增长。

举例来说,假设对w搜索了100个数值,现在只有一个权重,只需要搜索一百次。如果有两个权重,那么需要搜索一个平面:100^2次;如果有10个权重,需要搜索100^10次。计算量太大,程序会算不出来。

分治法思路及缺点

分治法思路

把权重空间划分成16个区域,先搜索16次找到最小的局部区域,再将这个小的局部区域划分为16个区域,这样一共搜索了16+16=32次。

比从一开始搜索16*16=256次 搜索次数减少。

分治法的缺点

  • 数据量过大时,划分空间搜索效率低。

  • 针对凸函数成立,但针对非凸函数,可能最开始取的点略过了最小值区域,会陷入局部最小值。

凸函数的几何意义在于,定义域中任意两点连线组成的线段都在这两点的函数曲线(面)上方。由凸函数的定义可以类似地引出凹函数的定义:如果函数 f是凸函数,那么函数 −f是凹函数。从凸函数与凹函数的定义,我们可以发现所有的仿射函数(Affine Function)即满足凸函数的性质,又满足凹函数的性质,因此是“既凸又凹”的。

优化问题

定义:寻找使目标函数最小的自变量的值,此处找的是权重组合

梯度下降算法 Gradient Descent Algorithm

梯度方向上升最快,负梯度方向下降最快。

更新权重:往导数下降的方向走。

α:学习率,决定每一步走多远,一般取小一点,否则会出现以下情况。

数学分析

代码解析

计算损失函数

计算梯度,累加后除以长度

epoch:

epoch:当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一个 epoch。

其实cost_val不需要计算,是为了最后输出,能够画图,查看日志。

思想分析

利用了贪心法的思想:只看眼前最好的一步。不一定能得到最优的结果,但一定能得到在局部区域内最优的结果。

针对非凸函数,会出现陷在局部最优的情况。

但深度学习中仍然使用该方法的原因是:大家原本认为深度学习神经网络的目标函数会陷入上述情况,但实际上,神经网络的损失函数中的局部最优点较少。在深度学习中需要解决的最大问题是鞍点。

实际中,会存在特殊的点——鞍点:此处梯度=0

一维空间中,走到这已经无法迭代了。

鞍点:高维空间中,从一个切面看是最小值,从另一个切面看是最大值。

指数加权均值方法

能够将cost function 波动的曲线变圆滑

如果cost function 曲线出现下降又上升,说明训练发散了,本次训练是有问题的,最有可能原因是学习率取得太大。

随机梯度下降法SGD

stochastic gradient descent

实际在深度学习中,使用随机梯度下降法。在深度神经网络中被证明此方法是有效的。

数学分析

cost function中包含N个数据,我从这N个数据中随机选择一个。

权重更新公式发生变化:用单个样本的损失函数对权重求导进行更新

用该方法的原因

原本用包含N个数据的cost function陷入了鞍点,无法继续更新w。现在使用一个样本作为w更新公式,这是因为实际拿到的数据基本都是有噪声的,引入了随机噪声,那么我们陷入鞍点时,可能会继续推动w的更新。

引入了随机性,将来有可能跨越这个鞍点,向最优值前进。

代码解析

计算损失函数

计算梯度

对每一个样本的梯度进行了更新。(嗯其实这里并没有体现出随机性,后文自己写的代码做了修改,用了random.randint函数

Mini-Batch

在实际的深度学习中,会遇到问题:

  • 使用梯度下降法时,计算xi和xi+1 的函数值时没有相互依赖关系。所以这些运算可以并行。效率高

个人理解,w计算时是前后相互依赖的,但每个点的梯度是固定的,这些计算可以并行

  • 使用随机梯度下降法时,权重的更新有依赖,无法并行化。性能好

所以在深度学习中会用一种折中的方式

批量的随机梯度下降 称为Batch

小批量的随机梯度下降 Mini-Batch,由于目前该方法是主流,直接把前缀省略了,可以直接叫Batch

梯度下降法代码

import matplotlib.pyplot as plt
 
# prepare the training set
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
 
# initial guess of weight 
w = 1.0
 
# define the model linear model y = w*x
def forward(x):
    return x*w
 
#define the cost function 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)
 
# define the gradient function  gd
def gradient(xs,ys):
    grad = 0
    for x, y in zip(xs,ys):
        grad += 2*x*(x*w - y)
    return grad / len(xs)
 
epoch_list = []
cost_list = []
print('predict (before training)', 4, forward(4))
for epoch in range(100):
    cost_val = cost(x_data, y_data)
    grad_val = gradient(x_data, y_data)
    w-= 0.01 * grad_val  # 0.01 learning rate
    print('epoch:', epoch, 'w=', w, 'loss=', cost_val)
    epoch_list.append(epoch)
    cost_list.append(cost_val)
 
print('predict (after training)', 4, forward(4))
plt.plot(epoch_list,cost_list)
plt.ylabel('cost')
plt.xlabel('epoch')
plt.show() 

学习率=0.01时,100个epoch后w=1.9999逼近2;

增大学习率=0.05时,在第58个epoch时能达到全局最优,w=2 能取到。

这里是为啥?还没想清楚...

随机梯度下降法代码

import matplotlib.pyplot as plt
import random
 
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
 
w = 5.0
 
def forward(x):
    return x*w
 
# calculate loss function
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y)**2
 
# define the gradient function  sgd
def gradient(x, y):
    return 2*x*(x*w - y)
 
epoch_list = []
loss_list = []
print('predict (before training)', 4, forward(4))

# for epoch in range(100):
#     for x,y in zip(x_data, y_data):
#         grad = gradient(x,y)
#         w = w - 0.01*grad    # update weight by every grad of sample of training set
#         print("\tgrad:", x, y, w,grad)
#         l = loss(x,y)
for epoch in range(100):
    rand = random.randint(0,2)
    grad = gradient(x_data[rand],y_data[rand])
    w = w - 0.01*grad    # update weight by 三个数据集中的随机一个数据
    print("\tgrad:", x_data[rand], y_data[rand], w, grad)
    l = loss(x_data[rand], y_data[rand])

    print("progress:",epoch,"w=",w,"loss=",l)
    epoch_list.append(epoch)
    loss_list.append(l)

弹幕提醒:视频中的代码是把所有数据都用来更新了w,没有提现随机性,所以我根据这个老哥梯度下降法解决线性模型_牛客博客 (nowcoder.net)的写法改了一下,跑的结果不错。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值