Может кто-нибудь помочь мне понять, почему веса не обновляются?
unet = Unet()
optimizer = torch.optim.Adam(unet.parameters(), lr=0.001)
loss_fn = torch.nn.MSELoss()
input = Variable(torch.randn(32, 1, 64, 64, 64 ), requires_grad=True)
target = Variable(torch.randn(32, 1, 64, 64, 64), requires_grad=False)
optimizer.zero_grad()
y_pred = unet(input)
y = target[: , : , 20:44, 20:44, 20:44]
loss = loss_fn(y_pred, y)
print(unet.conv1.weight.data[0][0]) # weights of the first layer in the unet
loss.backward()
optimizer.step()
print(unet.conv1.weight.data[0][0]) # weights havent changed
Модель определяется как:
class Unet(nn.Module):
def __init__(self):
super(Unet, self).__init__()
# Down hill1
self.conv1 = nn.Conv3d(1, 2, kernel_size=3, stride=1)
self.conv2 = nn.Conv3d(2, 2, kernel_size=3, stride=1)
# Down hill2
self.conv3 = nn.Conv3d(2, 4, kernel_size=3, stride=1)
self.conv4 = nn.Conv3d(4, 4, kernel_size=3, stride=1)
#bottom
self.convbottom1 = nn.Conv3d(4, 8, kernel_size=3, stride=1)
self.convbottom2 = nn.Conv3d(8, 8, kernel_size=3, stride=1)
#up hill1
self.upConv0 = nn.Conv3d(8, 4, kernel_size=3, stride=1)
self.upConv1 = nn.Conv3d(4, 4, kernel_size=3, stride=1)
self.upConv2 = nn.Conv3d(4, 2, kernel_size=3, stride=1)
#up hill2
self.upConv3 = nn.Conv3d(2, 2, kernel_size=3, stride=1)
self.upConv4 = nn.Conv3d(2, 1, kernel_size=1, stride=1)
self.mp = nn.MaxPool3d(kernel_size=3, stride=2, padding=1)
# some more irrelevant properties...
Функция пересылки выглядит следующим образом:
def forward(self, input):
# Use U-net Theory to Update the filters.
# Example Approach...
input = F.relu(self.conv1(input))
input = F.relu(self.conv2(input))
input = self.mp(input)
input = F.relu(self.conv3(input))
input = F.relu(self.conv4(input))
input = self.mp(input)
input = F.relu(self.convbottom1(input))
input = F.relu(self.convbottom2(input))
input = F.interpolate(input, scale_factor=2, mode='trilinear')
input = F.relu(self.upConv0(input))
input = F.relu(self.upConv1(input))
input = F.interpolate(input, scale_factor=2, mode='trilinear')
input = F.relu(self.upConv2(input))
input = F.relu(self.upConv3(input))
input = F.relu(self.upConv4(input))
return input
Я следовал подходу любого примера и документации, которую смог найти, и мне кажется, почему это не работает?
Я могу понять, что y_pred.grad
после обратного вызова - это не то, что не должно быть.Если у нас нет градиента, то, конечно, оптимизатор не может изменять веса в любом направлении, но почему нет градиента?