如何在 TensorFlow 2 Eager 中获得 learning_phase?

How to get learning_phase in TensorFlow 2 Eager?

K.learning_phase() 获取值,而不是张量本身。我需要将学习阶段张量馈送到 K.function 以获得层梯度、输出等。在 import keras.backend as K 上工作正常,但在 import tensorflow.keras.backend as K 上失败。 Relevant Git 有部分解决方法

如何获取 张量 本身?


可重现的例子

import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
import numpy as np

ipt = Input((16,))
out = Dense(16)(ipt)
model = Model(ipt, out)
model.compile('adam', 'mse')

x = np.random.randn(32, 16)
model.train_on_batch(x, x)

grads = model.optimizer.get_gradients(model.total_loss, model.layers[-1].output)
grads_fn = K.function(inputs=[model.inputs[0], model._feed_targets[0], K.learning_phase()], 
                      outputs=grads)

完整错误跟踪:

File "<ipython-input-2-7f74922d7492>", line 3, in <module>
  outputs=grads)
File "D:\Anaconda\envs\tf2_env\lib\site-packages\tensorflow_core\python\keras\backend.py", line 3773, in function
  return EagerExecutionFunction(inputs, outputs, updates=updates, name=name)
File "D:\Anaconda\envs\tf2_env\lib\site-packages\tensorflow_core\python\keras\backend.py", line 3670, in __init__
  base_graph=source_graph)
File "D:\Anaconda\envs\tf2_env\lib\site-packages\tensorflow_core\python\eager\lift_to_graph.py", line 249, in lift_to_graph
  visited_ops = set([x.op for x in sources])
File "D:\Anaconda\envs\tf2_env\lib\site-packages\tensorflow_core\python\eager\lift_to_graph.py", line 249, in <listcomp>
  visited_ops = set([x.op for x in sources])

AttributeError: 'int' object has no attribute 'op'

作为(不太好的)解决方法,您可以使用 symbolic_learning_phase() from tensorflow.python.keras.backend:

from tensorflow.python.keras import backend

# ...
grads_fn = K.function(inputs=[model.inputs[0],
                              model._feed_targets[0],
                              backend.symbolic_learning_phase()], 
                      outputs=grads)

g_learning = grads_fn([x, x, True])
g_not_learning = grads_fn([x, x, False])

我不确定为什么这个函数不像 learning_phase(),没有导出到 tensorflow.keras.backend。也许有一个很好的理由不这样做。

此外,请注意,只有当您的模型包含一些 layers/ops 在训练和推理模式(例如辍学)中表现不同时,才有意义使用学习阶段。否则,函数的输出将是相同的。


更新backend.symbolic_learning_phase()用于tensorflow.keras代码(example),建议不要过多反对其public使用.它作为 Eager execution 中 K.learning_phase() 的替代品,用于 K.function().