I have pretty simple code
import torch
import random
image_width, image_height = 128, 128
def apply_ellipse_mask(img, pos, axes):
mask = torch.zeros_like(img)
for r in range(image_height):
for c in range(image_width):
val = ((c - pos[0])**2) / axes[0]**2 + ((r - pos[1])**2) / axes[1]**2
assert not torch.isnan(val)
mask[r][c] = torch.where(0.9 < val < 1, torch.tensor(1.0), torch.tensor(0.0))
return img * (1.0 - mask) + mask
random.seed(0xced)
sphere_radius = image_height / 3
sphere_position = torch.tensor([image_width / 2, image_height / 2 ,0], requires_grad=True)
ref_image = apply_ellipse_mask(torch.zeros(image_width, image_height, requires_grad=True), sphere_position, [sphere_radius, sphere_radius, sphere_radius])
ellipsoid_pos = torch.tensor([sphere_position[0], sphere_position[1], 0], requires_grad=True)
ellipsoid_axes = torch.tensor([image_width / 3 + (random.random() - 0.5) * image_width / 5, image_height / 3 + (random.random() - 0.5) * image_height / 5, image_height / 2], requires_grad=True)
optimizer = torch.optim.Adam([ellipsoid_axes], lr=0.1)
criterion = torch.nn.MSELoss()
for _ in range(100):
optimizer.zero_grad()
current_image = torch.zeros(image_width, image_height, requires_grad=True)
current_image = apply_ellipse_mask(current_image, ellipsoid_pos, ellipsoid_axes)
# mixed_img = (((ref_image + current_image) / 2.0) * 255).byte()
# mixed_img = Image.fromarray(mixed_img.numpy(), mode='L')
# mixed_img.show()
loss = criterion(current_image, ref_image)
loss.backward()
print(_, loss)
optimizer.step()
However, I’m encoutering two issues that as a Pytorch beginner I find hard to understand.
- The first one is that this code throws an error.
RuntimeError: Trying to backward through the graph a second time (or directly access saved tensors after they have already been freed). Saved intermediate values of the graph are freed when you call .backward() or autograd.grad(). Specify retain_graph=True if you need to backward through the graph a second time or if you need to access saved tensors after calling backward.
I don’t understand why it would be trying to backward through the same graph a second time? or am I directly accessing saved tensors after they were freed? I don’t understand why this happens.
- The other issue is the following:
ellipsoid_axes.grad
is None for my function. I believe the issue arises in
apply_ellipse_mask
in the line
mask[r][c] = torch.where(0.9 < val < 1, torch.tensor(1.0), torch.tensor(0.0))
. How can I fix this?