我是梯度下降的新手,我完全迷失在下面的练习中。第一部分是用一个简单的例子进行解释。这是这个例子:
训练模型时,我们要找到参数(记作 θ ),最大限度地减少所有训练示例的总损失:
θ=argminθ 𝐿(θ)。 为此,我们将通过逐步降低损失函数的方向更新参数来迭代地减少误差。该算法称为梯度下降。梯度下降最简单的应用是对损失函数求导。让我们看看如何做到这一点。
作为一个玩具示例,假设我们对函数 𝑦=2𝐱⊤𝐱 的微分感兴趣 相对于列向量 𝐱 。首先,让我们创建变量 x 并为其分配一个初始值。
这是代码:
x = torch.arange(4.0)
x.requires_grad_(True)
x.grad
y = 2 * torch.dot(x, x)
y.backward()
x.grad
#checking if gradient calculated correctly
x.grad == 4 * x
现在,基于上述我必须解决这个问题:
设 𝑓(𝑥)=sin(𝑥)。绘制 𝑓(𝑥) 和 𝑑𝑓(𝑥)𝑑𝑥,其中后者是在不利用 𝑓′(𝑥)=cos(𝑥) 的情况下计算的。
x = np.linspace(-np.pi, np.pi, 100) x = torch.tensor(x, requires_grad=True) y = torch.sin(x)
...现在怎么办?
我尝试过:
y.backward() x.grad
但是我收到一个错误,y 不是标量值。
我需要通过这些断言:
assert torch.allclose(x.grad[10].float(), torch.Tensor([-0.8053]), rtol=1e-2) assert torch.allclose(x.grad[50].float(), torch.Tensor([0.9995]), rtol=1e-2)
默认情况下,pytorch 希望您对标量值调用
backward
。这就是为什么如果您调用 y.backward()
,您会收到错误 grad can be implicitly created only for scalar outputs
。
一种解决方案是使用
y
操作聚合 sum
,这不会影响下游梯度。
x = np.linspace(-np.pi, np.pi, 100)
x = torch.tensor(x, requires_grad=True)
y = torch.sin(x)
loss = y.sum()
loss.backward()
如果您提供上游梯度向量,您还可以对向量值调用
backward
。
x = np.linspace(-np.pi, np.pi, 100)
x = torch.tensor(x, requires_grad=True)
y = torch.sin(x)
grad_vector = torch.ones_like(y)
y.backward(grad_vector)
两种方法都会通过您提供的断言。