梯度赋值时遇到的bug:
问题描述:
梯度赋值出现以下错误:
RuntimeError: expected Variable or None (got tuple)
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import torch.nn as nn
from graphviz import Digraph
H = 99
x = Variable(torch.rand(1, 1, H, H), requires_grad=True)
label = torch.ones(1, 1, 99, 99).requires_grad_(False)
learning_rate = 0.001
train_time = 1
def printf(contains, string="bianliang"):
print("**" * 20)
print("var_name:" + string)
print(contains)
print("**" * 20)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 1, kernel_size=5, stride=3, padding=1)
self.conv2 = nn.ConvTranspose2d(1, 1, kernel_size=5, stride=3, padding=1)
def forward(self, img):
with torch.no_grad():
self.x = self.conv1(img)
self.recon = self.conv2(self.x)
return self.recon
def calculate_grad(self, input, output):
weight = torch.ones_like(output)
grad = torch.autograd.grad(inputs=input,
outputs=output,
grad_outputs=weight,
retain_graph=True,
create_graph=True,
only_inputs=True)
return grad
def backpropation(self, img):
criterion = nn.MSELoss()
self.recon.requires_grad = True
printf(img, "img")
loss = criterion(img, self.recon)
printf(loss, "loss")
recon_grad = self.calculate_grad(self.recon, loss)
net = Net()
for i in range(train_time):
y = net(x)
net.backpropation(x)
}
原因分析:
grad函数返回的是一个tuple,梯度在grad[0]处存储。
解决方案:
self.recon.grad = self.calculate_grad(self.recon, loss)[0]