李沐老师的<手动学习深度学习v2>课程里为什么要向量先求和再算梯度

学习场景:

最近在B站上跟着李沐大佬学【动手学深度学习v2】,大佬讲的很好,但是有些东西对我这种小白来说还是有一些不太好理解,所以在我想明白之后做个笔记。或许能帮助别人理解,也欢迎大佬指出我存在的问题。


问题描述

在【动手学深度学习v2】第八节课的 “P3线性回归的从零开始实现 ” 这个视频里,讲到一段代码:

lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

for epoch in range(num_epochs):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward() #这里的求和不太理解
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

里面的 l.sum().backward() 卡了我好久都没理解。

原因分析:

主要是输出了 l 看了一下 ,就是一个N*1的列向量(这么说好理解),形式如下:请添加图片描述
我看到一些解释,和李沐大佬的意思是对 I 求和(sum())就变成了一个数字累加和,也就是变成了一个标量,符合了.backward() 的只对标量求梯度的标准,能够用.backward() 进行梯度计算。但是我就是觉得这一堆数加起来再对w和b求梯度就感觉很怪,不知道应该怎么理解这里。


理解思路:

其实看上面这张图反而更难以理解,上面的列向量里面的值都为确定的是因为计算的式子里没有未知数,但是后面我们其实需要把w和b当成未知数去求梯度,所以 l = loss(net(X, w, b), y) 中我们获得的返回值,即 (y_hat - y.reshape(y_hat.shape)) ** 2 / 2 ,我们不要把他算出来,我们把它看成 一个 f(w,b)的函数,这样我们认为输出的 l 可以看成显示的结果为:

tensor([[ f1(w,b)],
[ f2(w,b)],
[ f3(w,b)],
[ f4(w,b)],
[ f5(w,b)],
[ f6(w,b)],
[ f7(w,b)],
[ f8(w,b)],
[ f9(w,b)],
[ f10(w,b)]])

那么我们再进行 l.sum() 的相加操作时得到的就是 [f1(w,b)+f2(w,b)+f3(w,b)+f4(w,b)+f5(w,b)+f6(w,b)+f7(w,b)+f8(w,b)+f9(w,b)+f10(w,b)] 这样的一个标量,对他就可以使用 .backward() 求梯度(也就是对于各个f(w,b)式子求导再加起来),最后得到的是各个梯度的和。

而后续的程序中函数sgd(params, lr, batch_size) 是对于w和b进行优化的函数,里面会对 l.sum().backward() 得到的梯度和进行处理,除一个梯度个数,得到平均梯度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值