The reason for the bug is that the tf.keras optimizers apply gradients to variable objects (of type tf.Variable), while you are trying to apply gradients to tensors (of type tf.Tensor). Tensor objects are not mutable in TensorFlow, thus the optimizer cannot apply gradients to it.
img = tf.Variable(img)
opt = tf.optimizers.Adam(learning_rate=lr, decay = 1e-6)
for _ in range(epoch):
with tf.GradientTape() as tape:
tape.watch(img)
y = model(img.value())[:, :, :, filter]
loss = -tf.math.reduce_mean(y)
grads = tape.gradient(loss, img)
opt.apply_gradients(zip([grads], [img]))
Also, it is recommended to calculate the gradients outside the tape’s context. This is because keeping it in will lead to the tape tracking the gradient calculation itself, leading to higher memory usage. This is only desirable if you want to calculate higher-order gradients. Since you don’t need those, I have kept them outside.