Aer*_*rin 14 machine-learning neural-network gradient-descent pytorch
哪个optimizer与loss?之间有明确的联系?
优化器如何知道在没有通话的情况下从哪里获得损失的梯度optimizer.step(loss)?
- 更多背景 -
当我最小化损失时,我没有必要将渐变传递给优化器.
loss.backward() # Back Propagation
optimizer.step() # Gardient Descent
Run Code Online (Sandbox Code Playgroud)
Sha*_*hai 16
在不深入研究pytorch内部的情况下,我可以提供一个简单的答案:
回想一下,在初始化时,optimizer您明确地告诉它应更新模型的哪些参数(张量)。一旦调用损失,梯度将由张量本身(它们具有grad和requires_grad属性)“存储” backward()。在计算了模型中所有张量的梯度之后,调用optimizer.step()使优化器对应该更新的所有参数(张量)进行迭代,并使用其内部存储grad的值来更新其值。
Aka*_*all 14
假设我们定义了一个模型:model和损失函数:criterion我们有以下步骤序列:
pred = model(input)
loss = criterion(pred, true_labels)
loss.backward()
Run Code Online (Sandbox Code Playgroud)
pred将有一个grad_fn属性,该属性引用创建它的函数,并将其与模型联系起来。因此,loss.backward()将有关于它正在使用的模型的信息。
尝试删除grad_fn属性,例如:
pred = pred.clone().detach()
Run Code Online (Sandbox Code Playgroud)
然后模型梯度将是None,因此权重不会更新。
并且优化器是和模型绑定的,因为我们model.parameters()在创建优化器的时候就通过了。
pse*_*vin 10
也许这会稍微澄清loss.backward和之间的联系optim.step(尽管其他答案是重点)。
# Our "model"
x = torch.tensor([1., 2.], requires_grad=True)
y = 100*x
# Compute loss
loss = y.sum()
# Compute gradients of the parameters w.r.t. the loss
print(x.grad) # None
loss.backward()
print(x.grad) # tensor([100., 100.])
# MOdify the parameters by subtracting the gradient
optim = torch.optim.SGD([x], lr=0.001)
print(x) # tensor([1., 2.], requires_grad=True)
optim.step()
print(x) # tensor([0.9000, 1.9000], requires_grad=True)
Run Code Online (Sandbox Code Playgroud)
loss.backward()设置
计算图grad中所有张量的属性,requires_grad=True其损失是叶子(仅x在这种情况下)。
优化器只是迭代它在初始化时接收到的参数列表(张量)以及张量具有 的任何地方requires_grad=True,它减去存储在其.grad属性中的梯度值(在 SGD 的情况下简单地乘以学习率)。它不需要知道计算梯度的损失是什么,它只是想访问该.grad属性,以便它可以做到x = x - lr * x.grad
请注意,如果我们在训练循环中执行此操作,我们会调用,optim.zero_grad()因为在每个训练步骤中我们都想计算新的梯度——我们不关心上一批的梯度。不将 grads 归零会导致跨批次的梯度累积。
小智 8
有些答案解释得很好,但我想举一个具体的例子来解释机制。
假设我们有一个函数:z = 3 x^2 + y^3。
z wrt x 和 y 的更新梯度公式为:
初始值为 x=1 和 y=2。
x = torch.tensor([1.0], requires_grad=True)
y = torch.tensor([2.0], requires_grad=True)
z = 3*x**2+y**3
print("x.grad: ", x.grad)
print("y.grad: ", y.grad)
print("z.grad: ", z.grad)
# print result should be:
x.grad: None
y.grad: None
z.grad: None
Run Code Online (Sandbox Code Playgroud)
然后计算当前值(x=1,y=2)中x和y的梯度
# calculate the gradient
z.backward()
print("x.grad: ", x.grad)
print("y.grad: ", y.grad)
print("z.grad: ", z.grad)
# print result should be:
x.grad: tensor([6.])
y.grad: tensor([12.])
z.grad: None
Run Code Online (Sandbox Code Playgroud)
# create an optimizer, pass x,y as the paramaters to be update, setting the learning rate lr=0.1
optimizer = optim.SGD([x, y], lr=0.1)
# executing an update step
optimizer.step()
# print the updated values of x and y
print("x:", x)
print("y:", y)
# print result should be:
x: tensor([0.4000], requires_grad=True)
y: tensor([0.8000], requires_grad=True)
Run Code Online (Sandbox Code Playgroud)
小智 6
当您调用时loss.backward(),它所做的只是计算损耗中具有的所有参数的损耗梯度,requires_grad = True并将它们存储在parameter.grad每个参数的属性中。
optimizer.step() 根据更新所有参数 parameter.grad
| 归档时间: |
|
| 查看次数: |
2651 次 |
| 最近记录: |