【问题标题】:How to get intermediate outputs in TF 2.3 Eager with learning_phase?如何使用 learning_phase 在 TF 2.3 Eager 中获得中间输出?
【发布时间】:2020-11-24 00:54:03
【问题描述】:

以下示例适用于 2.2; K.function 在 2.3 中发生了显着变化,now building 在 Eager 执行中变为 Model,因此我们传递了 Model(inputs=[learning_phase,...])

我确实有一个解决方法,但它很老套,而且比K.function 复杂得多;如果没有人可以展示一个简单的方法,我会发布我的。


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

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

outs_fn = K.function([model.input, K.symbolic_learning_phase()],
                     [model.layers[1].output])  # error
x = np.random.randn(32, 16)
print(outs_fn([x, True]))
>>> ValueError: Input tensors to a Functional must come from `tf.keras.Input`. 
Received: Tensor("keras_learning_phase:0", shape=(), dtype=bool) 
(missing previous layer metadata).

【问题讨论】:

  • 这是否适用于您的用例:K.function([symbolic_inputs], [symbolic_outputs])([input_arrays], training=True)?
  • 我误解了最近的变化。实际上,K.function 不会返回 Model 实例(尽管它会构建并运行 Model 实例)。但是对于您在问题中的用例,为什么不这样做:partial_model = Model(model.inputs, model.layers[1].output) 然后使用partial_model([x], training=True) 在训练模式下运行它。如果您有其他特殊用例,请将其包含在问题中。

标签: python tensorflow keras tf.keras tensorflow2.x


【解决方案1】:

对于在 Eager 模式下获取中间层的输出,无需构建 K.function 并使用学习阶段。相反,我们可以建立一个模型来实现这一点:

partial_model = Model(model.inputs, model.layers[1].output)

x = np.random.rand(...)
output_train = partial_model([x], training=True)   # runs the model in training mode
output_test = partial_model([x], training=False)   # runs the model in test mode

或者,如果你坚持使用K.function,并且想在渴望模式下切换学习阶段,你可以使用tensorflow.python.keras.backend中的eager_learning_phase_scope(注意这个模块是tensorflow.keras.backend的超集并且包含内部函数,比如上面提到的,可能会在未来的版本中改变):

from tensorflow.python.keras.backend import eager_learning_phase_scope

fn = K.function([model.input], [model.layers[1].output])

# run in test mode, i.e. 0 means test
with eager_learning_phase_scope(value=0):
    output_test = fn([x])

# run in training mode, i.e. 1 means training
with eager_learning_phase_scope(value=1):
    output_train = fn([x])

【讨论】:

  • 有趣的方法,但我想知道它的效率和内存影响;每个Model 都会在图中添加一些张量——重复使用,我们不是用非垃圾收集的张量污染了吗?或者不会对大型模型进行密集收集?顺便说一句,用例有多个输出,您的方法仍然适用。
  • 然后我想到的方法是this,它可以使内存使用翻倍;最坏的情况我认为K.function 仍然可用,但无论如何它确实在引擎盖下使用Modeleager_learning_phase_scope 估计是在 2.3 中引入的?
  • @OverLordGoldDragon 不,它从 1.14 开始存在。我不确定内存使用的影响,因为我对非常低级 TF 的了解是有限的,尤其是关于 2.x,与我现在的 1.x 相比,它似乎有大量的低级优化和图形执行的变化比较熟悉;因此,我不想只是推测,因为它可能是错误的或不完整的。但是,您可以使用一些工具来实现此目的。其中之一是 TF Profiler,尤其是它的 Memory Profiler,它提供了每个操作的报告。
  • 很公平。顺便说一句,不妨将您的模型放在 TF 2.3.0 Eager 中;我在 Colab 中发现它确实将大型模型大数据设置(相对于 2.2-)的速度 加倍 ...并将其减半以用于 Graph 执行。不确定后者是怎么回事,但 TF 要么更好地利用 CUDA 与前者或一些新天才。不过我的 GPU 上没有这样的差异,所以它似乎取决于设备。
  • @OverLordGoldDragon 自从 TF 2.0 和 Eager 模式推出以来,出现了很多奇怪的问题,不一致或令人惊讶的行为。有时,我不知道我应该对改进和新功能感到高兴,还是对那些令人沮丧的问题感到生气。不过,感谢您提供的信息。
【解决方案2】:

另一种解决方法:

import tensorflow as tf

tf.compat.v1.disable_eager_execution()

【讨论】:

    猜你喜欢
    • 2020-03-18
    • 2023-03-12
    • 2021-06-06
    • 1970-01-01
    • 2019-08-15
    • 2017-10-18
    • 2016-05-22
    • 2019-06-14
    • 1970-01-01
    相关资源
    最近更新 更多