我通过两个简单的nn.模块PyTorch模型实例,model1
和model2
。你知道吗
如果不使用depreciated ^{
这样就可以了:
y1 = model1(X)
v = Variable(y1.data, requires_grad=training) # Its all about this line!
y2 = model2(v)
criterion = nn.NLLLoss()
loss = criterion(y2, y)
loss.backward()
y1.backward(v.grad)
self.step()
但这将引发一个错误:
y1 = model1(X)
y2 = model2(y1)
criterion = nn.NLLLoss()
loss = criterion(y2, y)
loss.backward()
y1.backward(y1.grad) # it breaks here
self.step()
>>> RuntimeError: grad can be implicitly created only for scalar outputs
我只是找不到第一个实现中的v
和第二个实现中的y1
之间的相关区别。在这两种情况下,requires_grad
都设置为True
。我唯一能找到的就是y1.grad_fn=<ThnnConv2DBackward>
和v.grad_fn=<ThnnConv2DBackward>
我错过了什么?什么(张量属性?)我不知道,如果Variable
被贬低,还有什么其他的实现可以工作?
经过一番调查,我得出了以下两种解决办法。 此线程中其他地方提供的解决方案手动保留计算图,没有释放它们的选项,因此最初运行良好,但稍后会导致OOM错误。你知道吗
第一种解决方案是使用内置的
torch.nn.Sequential
将模型绑定在一起:就这么简单。它看起来很干净,行为和普通模特一模一样。你知道吗
另一种方法是简单地手动将它们捆绑在一起:
我担心这只会反向传播
model2
结果是没有根据的,因为model1
也存储在反向传播的计算图中。 与以前的实现相比,这种实现增强了两个模型之间接口的透明性。你知道吗你知道吗 [更新] 在第二个示例中,您没有正确地将
y1.grad
传递到y1.backward
。在第一次backward
之后,所有中间梯度都将被销毁,您需要一个特殊的钩子来提取该梯度。在您的例子中,您传递的是None
值。下面是一个小例子来重现您的案例:代码:
输出:
因此,您需要正确提取它们:
代码:
输出:
相关问题 更多 >
编程相关推荐