...
char comma = ',';
for (unsigned int i = 0; i < str.length(); i++)
{
// previously str[i] != ",";
if(str[i] != comma)
cout<<str[i];
else
cout<<"\n";
}
...
和optimizer
之间有何明确联系?
优化器如何知道在没有调用的情况下如何在loss
上获得损耗的梯度?
-更多上下文-
当我将损失最小化时,我不必将梯度传递给优化器。
optimizer.step(loss)
答案 0 :(得分:7)
比方说,我们定义了一个模型:model
,并定义了损失函数:criterion
,我们具有以下步骤序列:
pred = model(input)
loss = criterion(pred, true_labels)
loss.backward()
pred
将具有一个grad_fn
属性,该属性引用创建该函数并将其与模型绑定的函数。因此,loss.backward()
将获得有关正在使用的模型的信息。
尝试删除grad_fn
属性,例如:
pred = pred.clone().detach()
然后模型梯度将为None
,因此权重将不会更新。
优化器与模型相关联,因为我们在创建优化器时通过了model.parameters()
。
答案 1 :(得分:6)
有些答案解释得很好,但我想举一个具体的例子来解释机制。
假设我们有一个函数:z = 3 x^2 + y^3.
z w.r.t 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
然后计算当前值(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
# 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)
答案 2 :(得分:5)
在不深入研究pytorch内部的情况下,我可以提供一个简单的答案:
回想一下,在初始化optimizer
时,您明确告诉它应更新模型的哪些参数(张量)。一旦对损失调用backward()
,则由张量本身(它们具有grad
和requires_grad
属性)“存储”梯度。计算完模型中所有张量的梯度后,调用optimizer.step()
使优化器对应该更新的所有参数(张量)进行迭代,并使用其内部存储的grad
来更新其值。
答案 3 :(得分:5)
也许这可以澄清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)
loss.backward()
用grad
设置所有张量的requires_grad=True
属性
在计算图中,损失是叶子(在这种情况下只有x
)。
Optimizer只是遍历初始化时以及在张量具有requires_grad=True
的所有地方接收到的参数(张量)列表,它减去存储在其.grad
属性中的梯度值(乘以SGD的学习率)。它不需要知道计算梯度的损失是多少,它只想访问该.grad
属性,以便可以执行x = x - lr * x.grad
请注意,如果我们在火车循环中执行此操作,我们会调用optim.zero_grad()
,因为在每个火车步骤中我们都想计算新的梯度-我们不在乎来自前一批。梯度不清零会导致批次间的梯度累积。
答案 4 :(得分:3)
调用loss.backward()
时,它所做的只是计算所有具有requires_grad = True
的损耗参数并将损耗存储在parameter.grad
属性的每个参数中。
optimizer.step()
根据parameter.grad
答案 5 :(得分:-1)
简短答案:
loss.backward()
#对我们设置的required_grad= True
的所有参数进行渐变。参数可以是代码中定义的任何变量,例如h2h
或i2h
。
optimizer.step()
#根据优化器功能(在我们的代码中先前定义),我们更新了这些参数以最终获得最小损失(错误)。