如何使用 tensorflow/keras 计算梯度?

How can I compute gradient with tensorflow/keras?

我正在尝试使用 tensorflow 2.6.0 绘制 显着图 。我用 tensorflow.keras.models.Sequential 定义了模型并完成了训练。但是,当我尝试像这样计算梯度时:

with GradientTape(persistent=True) as tape:
    tape.watch(image)
    result = model.predict(image)[:, 4]
    gradient = tape.gradient(result, image)

其中 image 是张量,[:, 4] 用于为该图像选择实际标签。

image.shape = (1, 48, 48, 1)
result.shape = (1, 10)

然后我收到错误信息:

---------------------------------------------------------------------------
LookupError                               Traceback (most recent call last)
/opt/conda/lib/python3.7/site-packages/tensorflow/python/ops/gradients_util.py in _GradientsHelper(ys, xs, grad_ys, name, colocate_gradients_with_ops, gate_gradients, aggregation_method, stop_gradients, unconnected_gradients, src_graph)
    605           try:
--> 606             grad_fn = ops.get_gradient_function(op)
    607           except LookupError:

/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/ops.py in get_gradient_function(op)
   2731     op_type = op.type
-> 2732   return gradient_registry.lookup(op_type)
   2733 

/opt/conda/lib/python3.7/site-packages/tensorflow/python/framework/registry.py in lookup(self, name)
     99       raise LookupError(
--> 100           "%s registry has no entry for: %s" % (self._name, name))

LookupError: gradient registry has no entry for: IteratorGetNext
During handling of the above exception, another exception occurred:

LookupError                               Traceback (most recent call last)
/tmp/ipykernel_36/2425374110.py in <module>
      1 with GradientTape(persistent=True) as tape:
      2     tape.watch(image)
----> 3     result = model.predict(image)[:, 4]
      4 #     result = tf.convert_to_tensor(result)
      5 #     probs = tf.nn.softmax(result, axis=-1)[:, 4]

/opt/conda/lib/python3.7/site-packages/keras/engine/training.py in predict(self, x, batch_size, verbose, steps, callbacks, max_queue_size, workers, use_multiprocessing)
   1749           for step in data_handler.steps():
   1750             callbacks.on_predict_batch_begin(step)
-> 1751             tmp_batch_outputs = self.predict_function(iterator)
   1752             if data_handler.should_sync:
   1753               context.async_wait()

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in __call__(self, *args, **kwds)
    883 
    884       with OptionalXlaContext(self._jit_compile):
--> 885         result = self._call(*args, **kwds)
    886 
    887       new_tracing_count = self.experimental_get_tracing_count()

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py in _call(self, *args, **kwds)
    922       # In this case we have not created variables on the first call. So we can
    923       # run the first trace but we should fail if variables are created.
--> 924       results = self._stateful_fn(*args, **kwds)
    925       if self._created_variables and not ALLOW_DYNAMIC_VARIABLE_CREATION:
    926         raise ValueError("Creating variables on a non-first call to a function"

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in __call__(self, *args, **kwargs)
   3038        filtered_flat_args) = self._maybe_define_function(args, kwargs)
   3039     return graph_function._call_flat(
-> 3040         filtered_flat_args, captured_inputs=graph_function.captured_inputs)  # pylint: disable=protected-access
   3041 
   3042   @property

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _call_flat(self, args, captured_inputs, cancellation_manager)
   1967         possible_gradient_type,
   1968         executing_eagerly)
-> 1969     forward_function, args_with_tangents = forward_backward.forward()
   1970     if executing_eagerly:
   1971       flat_outputs = forward_function.call(

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in forward(self)
   1493     """Builds or retrieves a forward function for this call."""
   1494     forward_function = self._functions.forward(
-> 1495         self._inference_args, self._input_tangents)
   1496     return forward_function, self._inference_args + self._input_tangents
   1497 

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in forward(self, inference_args, input_tangents)
   1224       (self._forward, self._forward_graph, self._backward,
   1225        self._forwardprop_output_indices, self._num_forwardprop_outputs) = (
-> 1226            self._forward_and_backward_functions(inference_args, input_tangents))
   1227     return self._forward
   1228 

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _forward_and_backward_functions(self, inference_args, input_tangents)
   1449       outputs = list(self._func_graph.outputs)
   1450       self._build_functions_for_outputs(
-> 1451           outputs, inference_args, input_tangents)
   1452 
   1453     (forward_function, forward_graph,

/opt/conda/lib/python3.7/site-packages/tensorflow/python/eager/function.py in _build_functions_for_outputs(self, outputs, inference_args, input_tangents)
    946             self._func_graph.inputs,
    947             grad_ys=gradients_wrt_outputs,
--> 948             src_graph=self._func_graph)
    949 
    950       if input_tangents:

/opt/conda/lib/python3.7/site-packages/tensorflow/python/ops/gradients_util.py in _GradientsHelper(ys, xs, grad_ys, name, colocate_gradients_with_ops, gate_gradients, aggregation_method, stop_gradients, unconnected_gradients, src_graph)
    634               raise LookupError(
    635                   "No gradient defined for operation '%s' (op type: %s)" %
--> 636                   (op.name, op.type))
    637         if loop_state:
    638           loop_state.EnterGradWhileContext(op, before=False)

LookupError: No gradient defined for operation 'IteratorGetNext' (op type: IteratorGetNext)

我应该怎么做才能解决这个问题?感谢您的回答。

使用 model(image)[:, 4] 而不是 model.predict(image)[:, 4]。最后一个将输出转换为 numpy 数组(没有任何 autograd 功能),然后 tensorflow 无法计算梯度。顺便说一句,在持久上下文中,在上下文中调用 tape.gradient 的效率要低得多,因为您还会记录梯度操作。唯一有趣的情况是当你想要更高程度的推导时。

with tf.GradientTape(persistent=True) as tape:
    tape.watch(image)
    result = model(image)[:, 4]
gradient = tape.gradient(preds, A)