I’m trying to visualize an already trained CNN model according to these instructions, which involve finding an input image that maximizes a feature map of interest. Unfortunately, the input variable is stuck with a None
grad after back-propagation, so learning is impossible. How can I get the gradients to be computed?
device = torch.device('cpu')
class M7(nn.Module):
# Zhang. M7-1
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 64, 3, padding=1)
self.conv2 = nn.Conv2d(64, 128, 3, padding=1)
self.conv3 = nn.Conv2d(128, 256, 3, padding=1)
self.conv4 = nn.Conv2d(256, 512, 3, padding=1)
self.conv5 = nn.Conv2d(512, 512, 3, padding=1)
self.fc1 = nn.Linear(512 * 4 * 4, 1024) # 4 = 64/(2^4)
self.fc2 = nn.Linear(1024, 200)
def forward(self, X):
X = F.max_pool2d(F.relu(self.conv1(X)), (2, 2), (2, 2))
X = F.max_pool2d(F.relu(self.conv2(X)), (2, 2), (2, 2))
X = F.max_pool2d(F.relu(self.conv3(X)), (2, 2), (2, 2))
X = F.relu(self.conv4(X))
X = F.max_pool2d(F.relu(self.conv5(X)), (2, 2), (2, 2))
X = F.dropout(torch.flatten(X, start_dim=1))
X = F.dropout(F.relu(self.fc1(X)))
X = self.fc2(X)
return F.log_softmax(X, dim=1) # log-probabilities
m7 = M7()
from torchvision import transforms
data_dir = '../input/casia-hwdb11-200-most-common/train/'
mean_image = 255 - np.load(os.path.join(data_dir, 'mean_image.npy'))
transform = transforms.Compose([
transforms.Lambda(cv2.bitwise_not),
transforms.Lambda(lambda img: img - mean_image),
transforms.Lambda(torch.from_numpy),
transforms.Lambda(lambda x: x.float()),
transforms.Lambda(lambda x: x[None][None])
])
class SavedFeatures():
def __init__(self, module):
self.hook = module.register_forward_hook(self.hook_fn)
def hook_fn(self, module, input, output):
self.features = torch.tensor(output, requires_grad=True, device=device)
def close(self):
self.hook.remove()
img = np.uint8(np.random.uniform(40 - 15, 40 + 15, (64, 64)))
img = transform(img)
img.requires_grad_()
m7.to(device).eval()
activations = SavedFeatures(list(m7.children())[1])
_ = m7(img)
loss = -activations.features[0, 0].mean()
loss.backward()
print('requires grad:', img.requires_grad)
print('is leaf:', img.is_leaf)
print()
print(loss)
print(img.grad)
Here’s the output, which always includes a warning for copying construct a tensor. I haven’t been able to identify what triggers this warning, but it may be related to my grad problem.
requires grad: True
is leaf: True
tensor(14.2372, grad_fn=<NegBackward>)
None
/opt/conda/lib/python3.6/site-packages/ipykernel_launcher.py:16: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).
app.launch_new_instance()