Причина ошибки заключается в том, что оптимизаторы tf.keras применяют градиенты к переменным объектам (типа tf.Variable), в то время как вы пытаетесь применить градиенты к тензорам (типа tf.Tensor). Тензорные объекты не являются изменяемыми в TensorFlow, поэтому оптимизатор не может применять к нему градиенты.
Вы должны инициализировать переменную img
как переменную tf.Variable. Вот как должен выглядеть ваш код:
# NOTE: The original image is lost here. If this is not desired, then you can
# rename the variable to something like img_var.
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]))
Кроме того, рекомендуется рассчитывать градиенты вне контекста ленты. Это связано с тем, что его сохранение приведет к тому, что лента будет отслеживать сам расчет градиента, что приведет к более высокому использованию памяти. Это желательно только если вы хотите рассчитать градиенты более высокого порядка. Так как они вам не нужны, я оставил их снаружи.
Примечание. Я изменил строку y = model(img)[:, :, :, filter]
на y = model(img.value())[:, :, :, filter]
. Это потому, что модели tf.keras нужны тензоры в качестве входных данных, а не переменные (ошибка или особенность?).