PyTorch深度学习实践笔记—03梯度下降算法

学习视频来源: link.

课程概括

问题:如何去寻找权重的最优值
如下图假设w初始值为红色圆点所在位置,那么如何更新w才能去接近损失函数的最小值
在这里插入图片描述
更新算法为:
在这里插入图片描述
算法解释:当损失函数对w的偏导为正时,说明当前处于上升阶段,即损失函数的值要增大,要想找到损失函数的最小值则要减小w;当损失函数对w的偏导为负时,说明当前处于下降阶段,损失函数的值会减小,为找到损失函数的最小值就要继续增大w。其中α为学习率,控制学习的步长,一般取值较小。
若遇到损失函数为非凸函数,便会容易困在局部最优位置而找不到全局最优点。如下图所示:
在这里插入图片描述
但在实际的深度学习网络中发现,出现局部最优的情况并不多,所以暂不做考虑
还有一种特殊的情况叫鞍点,其数学含义为:目标函数在此点上的梯度(一阶导数)值为 0, 但从改点出发的一个方向是函数的极大值点,而在另一个方向是函数的极小值点。如下图:
在这里插入图片描述
鞍点可以使用随机梯度下降进行解决,后面会对随机梯度下降进行具体介绍。
将之前所用的损失函数代入到更新w的式子中进行化简可得到:
在这里插入图片描述
因此最终的梯度更新式子为:
在这里插入图片描述
在实际的应用中,会使用随机梯度下降(Stochastic Gradient Descent,SGD)代替梯度下降,具体实现过程如下
在这里插入图片描述
跟梯度下降不同的是将全部样本的损失函数cost()换为单个随机样本的损失函数loss(),这样做的目的是减小鞍点带来的影响,在神经网络中被证实是非常有效的。
但也应该注意随机梯度下降无法像梯度下降那样对数据进行并行处理,即梯度下降可以保证时间复杂度低,但同时性能低,而随机梯度下降则可以保证预测的性能,但同时时间复杂度高,因此在深度学习中取两者折中,使用Batch。(后续会讲)

代码实现

使用梯度下降的方法进行权重更新

# 导入画图所需要的库
import matplotlib.pyplot as plt

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

# 初始化权重
w = 1.0

# 对权重与对应损失值进行存储
cost_val_list = []
epoch_list = []

# 前向函数
def forward(x):
    return x * w

# 损失函数
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):
        grad += 2 * x * (x * w - y)
    return grad / len(xs)

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
    print('Epoch', epoch, 'w=', w, 'loss=', cost_val)

    cost_val_list.append(cost_val)
    epoch_list.append(epoch)
print('Predict (after training)', 4, forward(4))

plt.plot(epoch_list, cost_val_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

迭代次数与损失函数之间的对应图为:
在这里插入图片描述
使用随机梯度下降对权重进行更新:

# 导入画图所需要的库
import matplotlib.pyplot as plt

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

# 初始化权重
w = 1.0

# 对权重与对应损失值进行存储
loss_val_list = []
epoch_list = []

# 前向函数
def forward(x):
    return x * w

# 损失函数
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 (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
        print("\tgrad", x, y, grad)
        l = loss(x, y)
    print('Epoch', epoch, 'w=', w, 'loss=', l)
    loss_val_list.append(l)
    epoch_list.append(epoch)
print('Predict (after training)', 4, forward(4))

plt.plot(epoch_list, loss_val_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

对应的损失函数与迭代次数的关系图为:
在这里插入图片描述
从图中可以看出随机梯度下降前期一段时间内比梯度下降算法下降更快。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值