深度学习基础4:Backward Propagation
·
import torch
x_data = torch.tensor([1.0, 2.0, 3.0])
y_data = torch.tensor([2.0, 4.0, 6.0]) # 张量
w = torch.tensor([1.0]) # 将权重w封装为PyTorch张量,是一个形状为 [1] 的一维张量(本质是标量)
w.requires_grad_(True) # ☆在运算时,Python标量 1.0 会被广播。相当于告诉PyTorch:“请跟踪w的所有运算,以便后续计算梯度”
def forward(x):
return x * w # w是张量,返回值也是张量
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2 # 返回的l是一个包含计算历史的张量
print("predict (before training)", 4, forward(4).item())
learning_rate = 0.01
for epoch in range(100):
for x, y in zip(x_data, y_data):
l = loss(x, y) # 1. 前向传播,计算损失(构建计算图)
l.backward() # 2.☆自动反向传播,计算梯度并存入w.grad
print('\tgrad:', x, y, w.grad.item()) # 3. 查看计算出的梯度
#1.如果不使用torch.no_grad():
# 后果:这个减法操作 -= 会被PyTorch的Autograd引擎记录到计算图中。因为w是requires_grad = True的张量,任何对它的操作都会被跟踪。
# 这会导致:计算图无限膨胀:每次更新都会在图中添加新节点,训练几百次后,图会变得巨大,可能内存泄漏。
# 逻辑错误:你本意是“用梯度修正参数”,但这个“修正动作”本身又被记录下来等待求导,这毫无意义且浪费资源。
with torch.no_grad(): # 4.☆在更新参数时禁用梯度跟踪
w.data -= learning_rate * w.grad.data # 5. 执行梯度下降更新
#2. 如果不使用 zero_grad():
# 后果:PyTorch 的 backward() 函数计算出的梯度是累积到 .grad 属性中的,而不是覆盖。如果不清零,下一次的梯度会与上一次的梯度相加,导致更新方向错误。
# 梯度值爆炸:梯度会随着迭代次数不断累加,数值异常增大。
# 更新方向完全错误:参数会朝着一个混乱的合成方向更新,模型无法收敛。
w.grad.data.zero_() # 6.☆将w的梯度清零,防止累积
print("progress:", epoch, l.item()) # 7. 打印当前损失(.item()从张量提取数值)
print("predict (after training)", 4, forward(4).item())
更多推荐
所有评论(0)