私はこのエラーに出くわし続けます:
RuntimeError:グラフをもう一度逆方向に戻そうとしましたが、バッファーは既に解放されています。最初に逆方向に呼び出すときは、retain_graph = Trueを指定します。
Pytorchフォーラムで検索しましたが、カスタム損失機能で何が間違っていたかはまだわかりません。私のモデルはnn.GRUで、カスタム損失関数は次のとおりです。
def _loss(outputs, session, items): # `items` is a dict() contains embedding of all items
def f(output, target):
pos = torch.from_numpy(np.array([items[target["click"]]])).float()
neg = torch.from_numpy(np.array([items[idx] for idx in target["suggest_list"] if idx != target["click"]])).float()
if USE_CUDA:
pos, neg = pos.cuda(), neg.cuda()
pos, neg = Variable(pos), Variable(neg)
pos = F.cosine_similarity(output, pos)
if neg.size()[0] == 0:
return torch.mean(F.logsigmoid(pos))
neg = F.cosine_similarity(output.expand_as(neg), neg)
return torch.mean(F.logsigmoid(pos - neg))
loss = map(f, outputs, session)
return -torch.mean(torch.cat(loss))
トレーニングコード:
# zero the parameter gradients
model.zero_grad()
# forward + backward + optimize
outputs, hidden = model(inputs, hidden)
loss = _loss(outputs, session, items)
acc_loss += loss.data[0]
loss.backward()
# Add parameters' gradients to their values, multiplied by learning rate
for p in model.parameters():
p.data.add_(-learning_rate, p.grad.data)
問題はトレーニングループにあります。バッチ間で非表示の状態を切り離したり再パッケージしたりしませんか?その場合、loss.backward()
は最初のバッチで機能しますが、最初のバッチのグラフは破棄されているため、2番目のバッチでは機能しません。
2つの解決策があります。
1)バッチ間で非表示の状態をデタッチ/再パッケージ化します。これを行うには、少なくとも3つの方法があります(そして、このソリューションを選択しました)。
_ hidden.detach_()
hidden = hidden.detach()
_
2)loss.backward()をloss.backward(retain_graph=True)
に置き換えますが、最初のバッチの開始までずっと逆伝播する必要があるため、連続する各バッチは前のバッチよりも時間がかかることを知っています。