【问题标题】:PyTorch Gradient DescentPyTorch 梯度下降
【发布时间】:2018-09-06 23:24:42
【问题描述】:

我正在尝试在 PyTorch 中手动实现梯度下降作为学习练习。我有以下内容来创建我的合成数据集:

import torch
torch.manual_seed(0)
N = 100
x = torch.rand(N,1)*5
# Let the following command be the true function
y = 2.3 + 5.1*x
# Get some noisy observations
y_obs = y + 2*torch.randn(N,1)

然后我创建我的预测函数 (y_pred),如下所示。

w = torch.randn(1, requires_grad=True)
b = torch.randn(1, requires_grad=True)
y_pred = w*x+b
mse = torch.mean((y_pred-y_obs)**2)

它使用 MSE 来推断权重 w,b。我使用下面的块根据渐变更新值。

gamma = 1e-2
for i in range(100):
  w = w - gamma *w.grad
  b = b - gamma *b.grad
  mse.backward()

但是,循环仅在第一次迭代中有效。 w.grad 开始的第二次迭代设置为None我很确定发生这种情况的原因是因为我将 w 设置为它自身的函数(我可能错了)。

问题是如何使用梯度信息正确更新权重?

【问题讨论】:

    标签: python pytorch


    【解决方案1】:
    1. 您应该在应用梯度下降之前调用 backward 方法。
    2. 您需要使用新的权重来计算每次迭代的损失。
    3. 每次迭代都创建没有梯度带的新张量。

    以下代码在我的计算机上运行良好,经过 500 次迭代训练后给出 w=5.1 & b=2.2。

    代码:

    import torch
    torch.manual_seed(0)
    N = 100
    x = torch.rand(N,1)*5
    # Let the following command be the true function
    y = 2.3 + 5.1*x
    # Get some noisy observations
    y_obs = y + 0.2*torch.randn(N,1)
    
    w = torch.randn(1, requires_grad=True)
    b = torch.randn(1, requires_grad=True)
    
    
    gamma = 0.01
    for i in range(500):
        print(i)
        # use new weight to calculate loss
        y_pred = w * x + b
        mse = torch.mean((y_pred - y_obs) ** 2)
    
        # backward
        mse.backward()
        print('w:', w)
        print('b:', b)
        print('w.grad:', w.grad)
        print('b.grad:', b.grad)
    
        # gradient descent, don't track
        with torch.no_grad():
            w = w - gamma * w.grad
            b = b - gamma * b.grad
        w.requires_grad = True
        b.requires_grad = True
    

    输出:

    499
    w: tensor([5.1095], requires_grad=True)
    b: tensor([2.2474], requires_grad=True)
    w.grad: tensor([0.0179])
    b.grad: tensor([-0.0576])
    

    【讨论】:

    • 有趣。所以在 no_grad 部分之后,我们需要再次重置requires_grad=True
    • 你是对的!因为 requires_grad 的默认值为 false
    • 其实我们新建了一个张量“w”,赋值给“original w - lr*grad”
    • @sachinruk 您可以将w = w - gamma * w.grad 替换为w -= gamma * w.grad。这会在原地更新 w,您可以在每次迭代时删除 w.requires_grad = True
    • @sachinruk 但是,您必须在每次迭代后将梯度设置为零:w.grad.zero_()
    猜你喜欢
    • 2021-10-07
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2016-09-25
    • 2012-08-17
    • 2021-12-18
    • 1970-01-01
    • 2020-07-06
    相关资源
    最近更新 更多