如何获得关于输入的梯度并改变输入(而不是可训练的变量)以最小化 TF 2 中的损失?

How to get gradients with respect to input and change input (rather than trainable vars) to minimize loss in TF 2?

我想使用经过训练的模型来更改输入,从而最大限度地减少损失(而不是更改可训练变量),就像 Tensorflow 2.0 中的 Deep Dreaming,但我没有成功。

假设我有一个基本的 NN,就像文档中的那样

class MyModel(Model):
  def __init__(self):
    super(MyModel, self).__init__()
    self.conv1 = Conv2D(32, 3, activation='relu')
    self.flatten = Flatten()
    self.d1 = Dense(128, activation='relu')
    self.d2 = Dense(10, activation='softmax')

  def call(self, x):
    x = self.conv1(x)
    x = self.flatten(x)
    x = self.d1(x)
    return self.d2(x)

model = MyModel()

我使用一个简单的 tf.GradientTape 函数进行训练

@tf.function
def train_step(image, label):
  with tf.GradientTape() as tape:
    predictions = model(image)
    loss = loss_object(label, predictions)
  gradients = tape.gradient(loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

创建将计算梯度并将其应用于输入图像的函数的惯用方法是什么。

我以为它会像

一样简单
def train_step(image, label):
  with tf.GradientTape() as tape:
    predictions = model(image)
    loss = loss_object(label, predictions)
  gradients = tape.gradient(loss, image)
  optimizer.apply_gradients(zip(gradients, image))

然而,这不起作用。

tf.GradientTape.gradients 只能将 wrt 区分为观察张量。第一次访问时会自动监视变量。为了区分任意张量,您必须明确地 watch 它:

>>> x = tf.constant([4.0])
>>> y = tf.constant([2.0])
>>> with tf.GradientTape() as tape:
...     tape.watch([x, y])
...     z = x * y
...     
>>> tape.gradient(z, [x, y])
[<tf.Tensor: id=9, shape=(1,), dtype=float32, numpy=array([ 2.], dtype=float32)>, 
 <tf.Tensor: id=10, shape=(1,), dtype=float32, numpy=array([ 4.], dtype=float32)>]