ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从梯度到大模型(006):从手算梯度到 PyTorch 自动求导,完整训练一个线性模型

从梯度到大模型(006):从手算梯度到 PyTorch 自动求导,完整训练一个线性模型 从梯度到大模型(006):从手算梯度到 PyTorch 自动求导,完整训练一个线性模型课程:《从梯度到大模型:LLM 系统实践课》预计用时:90~120 分钟前置知识:Tensor、shape、MSE、梯度下降本课可以分两次学习:第一次理解求导和一次参数更新;第二次运行完整训练,理解梯度累积与计算图。CPU 即可完成实验。学习目标:看懂requires_grad → 前向计算 → loss.backward() → 参数.grad → 更新参数的每一步,并能用手算检查一个结果。一、第 5 课作业答案1. 创建与描述若X.shape == (3, 3),它表示3条样本、每条3个特征;ndim=2、numel=9。显式指定dtype=torch.float32后,默认创建在 CPU。2. 索引与批次轴X[0].shape# [3]X[0:1].shape# [1, 3]X[:,0].shape# [3]X[:,0:1].shape# [3, 1]整数索引删除对应维度,切片保留维度。3. 类型转换values=torch.tensor([1,2,3])# torch.int64values=values.to(torch.float32)# 必须接收返回值4. 手算预测与 Loss预测为[[4.0], [7.5], [7.0]],shape 为[3,1];误差为[[0.0], [0.5], [-1.0]],MSE 为1.25/3 ≈ 0.4167。5. 静默广播[3,1] - [3]会广播成[3,3],不会报错。应将标签改成[3,1],并在 Loss 前断言:target=bad_target.unsqueeze(1)assertprediction.shape==target.shape6. 共享内存torch.from_numpy(array)与 NumPy 数组共享内存;clone()创建独立副本。7. 设备报告CUDA 检查 NVIDIA GPU 后端,MPS 检查 Apple GPU 后端。两者都是False时仍可在 CPU 正常学习。MPS 对部分类型和运算支持不同,迁移前要核对兼容性。设备报告可运行以下代码,填写本机实际输出,不照抄他人的版本号:importtorchprint(torch.__version__)print(torch.cuda.is_available())print(torch.backends.mps.is_available())print(torch.tensor([1.0],device="cpu").device)本课程示例默认 CPU、未修改全局默认设备。MPS 不支持本课数值检查所用的 float64,因此后面的高精度差分实验保留在 CPU。二、本课要解决的问题假设要预测软件任务需要多少小时。我们先用三条人为构造的数据理解训练:任务工作量单位 x实际工时 targetA13B25C37暂时使用一个模型:预测工时 = x × w + b。其中 w 表示每个工作量单位对应的工时,b 表示固定准备时间。这里数据恰好满足target = 2x + 1,方便检查训练结果;真实工时还受人员经验、需求变更等影响。开始时参数可能不准确,例如w=1,b=0,预测就是 1、2、3 小时。我们希望通过数据把参数逐步调整到接近 2 和 1。训练数据的低误差只能证明模型拟合了这些样本。这个小实验没有独立测试集,不能据此宣称它能可靠预测真实项目。第 3 课中,我们手工推导了:prediction → error → loss → dw、db → 更新 w、b模型变复杂后,手工求导容易出错。Autograd 的任务是记录前向计算关系,然后利用链式法则自动计算梯度。它不是自动训练器;数据、Loss、学习率、更新规则仍由我们决定。三、最小自动求导例子先分清函数值与导数函数值回答“当前预测多少”;导数回答“输入在当前位置稍微变化时,结果变化得有多快”。例如y=x²,当 x=3,y=9,导数为6。把 x 增加0.01:原来的 y = 3² = 9 新的 y = 3.01² = 9.0601 y 的变化 = 0.0601,约等于 6 × 0.01这个近似只描述当前位置附近的小变化,不能把导数当作任意大步长下的精确变化量。求导前保留系数,看清常数对本课使用的多项式,逐项求导再相加:原来的一项对 x 求导理由x²2x幂次乘到前面,指数减13x²6x原系数3保留:3×2x2x2x每增加一点,这项增加其2倍10常数不随x变化例如y=3x²+2x+1:x=4 时,y = 3×16 + 8 + 1 = 57 dy/dx = 6x + 2 x=4 时,dy/dx = 26计算函数值时,不能遗漏+1;计算导数时,常数项才变成0。导数中的系数3和2也必须来自原式,不能丢掉。让 PyTorch 计算设y=x²,在x=3处导数是2x=6:importtorch x=torch.tensor(3.0,requires_grad=True)y=x**2print(x.is_leaf)# Trueprint(y.is_leaf)# Falseprint(y.grad_fn)# 有反向计算入口y.backward()print(x.grad)# tensor(6.)五个动作分别是:requires_grad=True:告诉 PyTorch 追踪与 x 有关的运算。y=x**2:进行前向计算,并建立动态计算图。y.backward():从 y 开始按链式法则反向传播。x.grad:读取 y 对 x 的导数。此时只得到梯度,参数并没有自动改变。requires_grad=True需要在相关前向运算发生前设置;本课参数使用浮点 Tensor。x.grad在首次反向传播前一般是None,表示尚未得到保存在这里的梯度,不等于导数为0。backward()的结果通过.grad读取;不要把result = y.backward()的返回值当作梯度。四、什么是计算图对于:a=x*2b=a+1loss=b**2前向关系是:x ──×2── a ──+1── b ──平方── loss反向传播沿相反方向使用链式法则:dLoss/dx = dLoss/db × db/da × da/dxAutograd 保存的是求导所需的运算关系和中间信息,不是提前把所有导数都算好。把上面的 x 设为2,逐步算出:a=4,b=5,loss=25 dLoss/db=2b=10 db/da=1 da/dx=2 dLoss/dx=10×1×2=20自动求导使用这些局部求导规则沿图传播。第4课的中心差分则是用“向左右各扰动一点”的方式近似导数;两者机制不同,可以用来相互检查。五、叶子 Tensor 与非叶子 Tensor由用户直接创建、没有上游运算的参数通常是叶子 Tensor:w=torch.tensor([[1.0]],requires_grad=True)# 叶子prediction=X @ w# 非叶子调用backward()后,默认把梯度累积在需要梯度的叶子 Tensor 的.grad中。中间结果虽然参与反向传播,但其.grad默认不会保留。现阶段主要查看w.grad和b.grad。六、在线性回归中使用 AutogradX=torch.tensor([[1.0],[2.0]
返回列表