pytorch自动求导

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 属性归零;后者根据特定优化器实施的优化策略更新这些参数的值。

设置损失函数:均方差损失函数

loss=\frac{\sum_{i=1}^{i=n}(t_p-t_c)^{2}}{n}

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)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种豆得瓜er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值