2017-10-01 9 views
3

いくつかのターゲットに対していくつかの入力を最小限に抑えるために、いくつかの逆方向パスの繰り返しを実行し、各ステップで入力を更新します。最初のパスが正常に実行されますが、私は2回目のパスで次のエラーを取得する: は RuntimeError: element 0 of variables tuple is volatile 揮発性変数によるピルトバックバックエラー

このコードスニペットは問題

import torch 
from torch.autograd import Variable 
import torch.nn as nn 

inp = Variable(torch.Tensor([1]), requires_grad=True) 
target = Variable(torch.Tensor([3])) 

loss_fn = nn.MSELoss() 

for i in range(2): 
    loss = loss_fn(inp, target) 
    loss.backward() 
    gradient = inp.grad 
    inp = inp - inp.grad * 0.01 

それが最後に再割り当てされる前に、私は、inpの値を調べる実証しますinp.volatile => Falseinp.requires_grad => Trueですが、再割り当て後には、それぞれTrueFalseに切り替わります。揮発性の変数が原因で2番目のバックプロップが実行されないのはなぜですか?

答えて

4

あなたは、このような各アップデートの前に勾配をゼロにする必要があります。

inp.grad.data.zero_() 

しかし、あなたのコード内で使用すると、このように歴史全体を更新する必要がありますので、あなたは、あなたが別のVariableオブジェクトを作成している勾配を更新するたびに:

import torch 
from torch.autograd import Variable 
import torch.nn as nn 

inp_hist = [] 
inp = Variable(torch.Tensor([1]), requires_grad=True) 
target = Variable(torch.Tensor([3])) 

loss_fn = nn.MSELoss() 

for i in range(2): 
    loss = loss_fn(inp, target) 
    loss.backward() 
    gradient = inp.grad 
    inp_hist.append(inp) 
    inp = inp - inp.grad * 0.01 
    for inp in inp_hist: 
     inp.grad.data.zero_() 

しかし、この方法は、あなたが歴史の中で作成したすべての以前の入力のための勾配を計算します(と、それは悪いですが、それはすべてのワストです)、正しい実装は次のようになります。

import torch 
from torch.autograd import Variable 
import torch.nn as nn 
inp = Variable(torch.Tensor([1]), requires_grad=True) 
target = Variable(torch.Tensor([3])) 
loss_fn = nn.MSELoss() 
for i in range(2): 
    loss = loss_fn(inp, target) 
    loss.backward() 
    gradient = inp.grad 
    inp.data = inp.data - inp.grad.data * 0.01 
    inp.grad.data.zero_() 
+1

最後の2行目は 'inp.data = ...'の代わりに 'inp.grad.data'ですか?これは本質的に同じ 'Variable'の場所修正ですが、前の例は毎回新しい' Variable'を作成していますか?最初の例では、私が新しい「変数」を繰り返し作成すると、なぜ前の変数の勾配が更新されるのでしょうか? – jvans

+0

ありがとうございました:)それは間違いでした:D – AmirHossein

関連する問題