1.求导
params = torch.tensor([1.0, 0.0], requires_grad=True)
注意到了张量构造函数的 require_grad = True 吗?这个参数告诉PyTorch需要追踪在 params 上进行运算而产生的所有张量。换句话说,任何以 params 为祖先的张量都可以访问从 params 到该张量所调用的函数链。如果这些函数是可微的(大多数PyTorch张量运算都是可微的),则导数的值将自动存储在参数张量的 grad 属性中。
你可以将包含任意数量的张量的 require_grad 设置为 True 以及组合任何函数。在这种情况下,
PyTorch会在沿着整个函数链(即计算图)计算损失的导数,并在这些张量(即计算图的叶节点)的grad 属性中将这些导数值累积(accumulate)起来
警告:PyTorch的新手(以及很多经验丰富的人)经常忽视的事情:是积累(accumulate)而不是存储(store)。
为防止这种情况发生,你需要在每次迭代时将梯度显式清零。可以使用就地方法 zero_ 轻松地做到这一点:
if params.grad is not None:
params.grad.zero_()# 这可以在调用backward之前在循环中的任何时候完成
如果不使用 params.grad.zero_()会出现梯度累积的效果
第一次求导
第二次求导
求和的梯度为1,但是梯度不归0就累计了
请注意,更新参数时,你还执行了奇怪的 .detach().requires_grad_() 。要了解原因,请考虑一下你构建的计算图。为了避免重复使用变量名,我们重构 params 参数更新行: p1 = (p0 * lr *
p0.grad) 。这里 p0 是用于初始化模型的随机权重, p0.grad 是通过损失函数根据 p0 和训练数据计算出来的。
解答参考:detach()、data、with no_grad()、requires_grad之间关系_一扣解千愁的博客-CSDN博客detach()、.data、with no_grad()、requires_grad之间关系[@TOC](detach ()、.data、with no_grad()、requires_grad之间关系)https://blog.csdn.net/qq_37344125/article/details/107426741
2.优化
每个优化器都有两个方法: zero_grad 和 step 。前者将构造时传递给优化器的所有参数的 grad 属性归零;后者根据特定优化器实施的优化策略更新这些参数的值。
设置损失函数:均方差损失函数
def loss_fn(t_p, t_c):
squared_diffs = (t_p - t_c)**2
return squared_diffs.mean()
现在创建参数并实例化一个梯度下降优化器:
t_p = model(t_u, *params)
loss = loss_fn(t_p, t_c)
loss.backward()
optimizer.step()
params
调用 step 后 params 的值就会更新,无需亲自更新它!调用 step 发生的事情是:优化器通过将
params 减去 learning_rate 与 grad 的乘积来更新的 params ,这与之前手动编写的更新过程完全相同。
params = (params - learning_rate *params.grad).detach().requires_grad_()
以下就是准备循环的代码,需要在正确的位置(在调用 backward 之前)插入额外的 zero_grad :
params = torch.tensor([1.0, 0.0], requires_grad=True)
learning_rate = 1e-2
optimizer = optim.SGD([params], lr=learning_rate)
t_p = model(t_un, *params)
loss = loss_fn(t_p, t_c)
optimizer.zero_grad() # 此调用可以在循环中更早的位置
loss.backward()
optimizer.step()
params
for循环开始
def training_loop(n_epochs, learning_rate, params, t_u, t_c):
for epoch in range(1, n_epochs + 1):
if params.grad is not None:
params.grad.zero_() # 这可以在调用backward之前在循环中的任何时候完成
t_p = model(t_u, *params)
loss = loss_fn(t_p, t_c)
loss.backward()
params = (params - learning_rate *params.grad).detach().requires_grad_()
if epoch % 500 == 0:
print('Epoch %d, Loss %f' % (epoch, float(loss)))
return params
开始训练
t_un = 0.1 * t_u
training_loop(
n_epochs = 5000,
learning_rate = 1e-2,
params = torch.tensor([1.0, 0.0], requires_grad=True),
t_u = t_un,
t_c = t_c)
优化器设置
params = torch.tensor([1.0, 0.0], requires_grad=True)
learning_rate = 1e-5
optimizer = optim.SGD([params], lr=learning_rate)