张量为什么能自动求导 作者:马育民 • 2026-01-10 10:13 • 阅读:10004 # 介绍 **因为张量不是“死的数据”,它会记录自己参与过的所有计算,形成一张“计算图”,反向传播时沿着这张图一步步算出梯度。** # 张量会“记住自己从哪来”(记录计算历史) 当你写: ``` x = torch.tensor(2.0, requires_grad=True) y = x ** 2 z = 2 * y + 3 ``` 张量 z 并不是只知道自己的值是 11,它还知道: - 我是由 2 * y + 3 得到的 - y 是由 x ** 2 得到的 - x 是一个叶子节点(用户输入) 也就是说,**每个张量都保存着自己的“诞生过程”**。 这就是自动求导的基础。 --- # 每个张量都有一个 grad_fn:它的“求导函数” 当你打印 z.grad_fn,会看到类似: ``` ``` 这说明 z 是通过一个加法操作产生的。 同理,y.grad_fn 会显示: ``` ``` 说明 y 是通过幂运算产生的。 这些 grad_fn 就是**反向传播时用来计算梯度的函数**。 它们构成了一条链: ``` z → AddBackward → y → PowBackward → x ``` 这就是“计算图”。 --- # 调用 backward() 时,会沿着计算图反向“链式求导” 当你执行: ``` z.backward() ``` 它会从 z 开始,沿着 grad_fn 链,反向一步步计算梯度。 过程像这样: 1. z 对 y 的导数是 2 2. y 对 x 的导数是 2x 3. 所以 z 对 x 的导数是 2 * 2x = 4x 4. 代入 x=2,得到梯度 8 所以 x.grad 最终是: ``` tensor(8.) ``` 这就是自动求导的全部秘密。 # 总结 张量能自动求导,是因为它具备三件事: 1. **记录计算历史**(知道自己怎么来的) 2. **保存 grad_fn**(知道怎么求导) 3. **调用 backward() 时沿计算图反向链式求导** 这三件事组合在一起,就实现了“自动求导”。 # 更形象的比喻(非常好理解) 你可以把张量想象成一个“有记忆的计算器”: - 你每按一次按钮(做一次运算),它都会记录“我刚才做了什么操作” - 当你说“算梯度”时,它会根据记录的操作,从结果倒推每一步的导数 - 最终把梯度存到叶子节点(如 x.grad)里 原文出处:http://malaoshi.top/show_1GW2Z8GaRIct.html