访问在 TF 2.0 中未显式公开为层的 Keras 模型的中间张量
Accessing intermediate tensors of a Keras Model that were not explicitly exposed as layers in TF 2.0
是否可以在 Keras 模型中访问预激活张量?例如,给定此模型:
import tensorflow as tf
image_ = tf.keras.Input(shape=[224, 224, 3], batch_size=1)
vgg19 = tf.keras.applications.VGG19(include_top=False, weights='imagenet', input_tensor=image_, input_shape=image_.shape[1:], pooling=None)
访问图层的常用方法是:
intermediate_layer_model = tf.keras.models.Model(inputs=image_, outputs=[vgg19.get_layer('block1_conv2').output])
intermediate_layer_model.summary()
这给出了一个层的 ReLU 输出,而我想要 ReLU 输入。我试过这样做:
graph = tf.function(vgg19, [tf.TensorSpec.from_tensor(image_)]).get_concrete_function().graph
outputs = [graph.get_tensor_by_name(tname) for tname in [
'vgg19/block4_conv3/BiasAdd:0',
'vgg19/block4_conv4/BiasAdd:0',
'vgg19/block5_conv1/BiasAdd:0'
]]
intermediate_layer_model = tf.keras.models.Model(inputs=image_, outputs=outputs)
intermediate_layer_model.summary()
但我收到错误
ValueError: Unknown graph. Aborting.
我发现的唯一解决方法是编辑模型文件以手动公开中间体,像这样转动每一层:
x = layers.Conv2D(256, (3, 3), activation="relu", padding="same", name="block3_conv1")(x)
分为 2 层,其中第一层可以在激活前访问:
x = layers.Conv2D(256, (3, 3), activation=None, padding="same", name="block3_conv1")(x)
x = layers.ReLU(name="block3_conv1_relu")(x)
有没有一种方法可以在不编辑 Tensorflow 2 源代码的情况下访问模型中的预激活张量,或者恢复到具有完全灵活性访问中间体的 Tensorflow 1?
获取每一层的输出。您必须定义一个 keras 函数并为每一层评估它。
请参考如下代码
from tensorflow.keras import backend as K
inp = model.input # input
outputs = [layer.output for layer in model.layers] # all layer outputs
functors = [K.function([inp], [out]) for out in outputs] # evaluation functions
更多详情请参考。
有一种方法可以使用 TF 2.7.0 版访问预训练 Keras 模型的 pre-activation 层。以下是如何在 单 正向传递中访问来自 VGG19 的两个中间 pre-activation 输出。
初始化 VGG19 模型。我们可以省略顶层以避免将不必要的参数加载到内存中。
vgg19 = tf.keras.applications.VGG19(
include_top=False,
weights="imagenet"
)
这是重要的部分:创建一个你喜欢的中间层形式的深度复制,将conv层的激活更改为线性(即无激活),重命名该层(否则模型中的两层将具有相同的名称,这将引发错误)并最终通过复制的 conv 层传递 previous 的输出。
# for more intermediate features wrap a loop around it to avoid copy paste
b5c4_layer = deepcopy(vgg19.get_layer("block5_conv4"))
b5c4_layer.activation = tf.keras.activations.linear
b5c4_layer._name = b5c4_layer.name + str("_preact")
b5c4_preact_output = b5c4_layer(vgg19.get_layer("block5_conv3").output)
b2c2_layer = deepcopy(vgg19.get_layer("block2_conv2"))
b2c2_layer.activation = tf.keras.activations.linear
b2c2_layer._name = b2c2_layer.name + str("_preact")
b2c2_preact_output = b2c2_layer(vgg19.get_layer("block2_conv1").output)
最后,当我们应用 ReLU-activation.
时,获取输出并检查它们是否等于 post-activation 输出
vgg19_features = Model(vgg19.input, [b2c2_preact_output, b5c4_preact_output])
vgg19_features_control = Model(vgg19.input, [vgg19.get_layer("block2_conv2").output, vgg19.get_layer("block5_conv4").output])
b2c2_preact, b5c4_preact = vgg19_features(tf.keras.applications.vgg19.preprocess_input(img))
b2c2, b5c4 = vgg19_features_control(tf.keras.applications.vgg19.preprocess_input(img))
print(np.allclose(tf.keras.activations.relu(b2c2_preact).numpy(),b2c2.numpy()))
print(np.allclose(tf.keras.activations.relu(b5c4_preact).numpy(),b5c4.numpy()))
True
True
这是类似于 Wang et al. 的图 6 的可视化效果,可以查看特征 space 中的效果。
输入图片
是否可以在 Keras 模型中访问预激活张量?例如,给定此模型:
import tensorflow as tf
image_ = tf.keras.Input(shape=[224, 224, 3], batch_size=1)
vgg19 = tf.keras.applications.VGG19(include_top=False, weights='imagenet', input_tensor=image_, input_shape=image_.shape[1:], pooling=None)
访问图层的常用方法是:
intermediate_layer_model = tf.keras.models.Model(inputs=image_, outputs=[vgg19.get_layer('block1_conv2').output])
intermediate_layer_model.summary()
这给出了一个层的 ReLU 输出,而我想要 ReLU 输入。我试过这样做:
graph = tf.function(vgg19, [tf.TensorSpec.from_tensor(image_)]).get_concrete_function().graph
outputs = [graph.get_tensor_by_name(tname) for tname in [
'vgg19/block4_conv3/BiasAdd:0',
'vgg19/block4_conv4/BiasAdd:0',
'vgg19/block5_conv1/BiasAdd:0'
]]
intermediate_layer_model = tf.keras.models.Model(inputs=image_, outputs=outputs)
intermediate_layer_model.summary()
但我收到错误
ValueError: Unknown graph. Aborting.
我发现的唯一解决方法是编辑模型文件以手动公开中间体,像这样转动每一层:
x = layers.Conv2D(256, (3, 3), activation="relu", padding="same", name="block3_conv1")(x)
分为 2 层,其中第一层可以在激活前访问:
x = layers.Conv2D(256, (3, 3), activation=None, padding="same", name="block3_conv1")(x)
x = layers.ReLU(name="block3_conv1_relu")(x)
有没有一种方法可以在不编辑 Tensorflow 2 源代码的情况下访问模型中的预激活张量,或者恢复到具有完全灵活性访问中间体的 Tensorflow 1?
获取每一层的输出。您必须定义一个 keras 函数并为每一层评估它。
请参考如下代码
from tensorflow.keras import backend as K
inp = model.input # input
outputs = [layer.output for layer in model.layers] # all layer outputs
functors = [K.function([inp], [out]) for out in outputs] # evaluation functions
更多详情请参考
有一种方法可以使用 TF 2.7.0 版访问预训练 Keras 模型的 pre-activation 层。以下是如何在 单 正向传递中访问来自 VGG19 的两个中间 pre-activation 输出。
初始化 VGG19 模型。我们可以省略顶层以避免将不必要的参数加载到内存中。
vgg19 = tf.keras.applications.VGG19(
include_top=False,
weights="imagenet"
)
这是重要的部分:创建一个你喜欢的中间层形式的深度复制,将conv层的激活更改为线性(即无激活),重命名该层(否则模型中的两层将具有相同的名称,这将引发错误)并最终通过复制的 conv 层传递 previous 的输出。
# for more intermediate features wrap a loop around it to avoid copy paste
b5c4_layer = deepcopy(vgg19.get_layer("block5_conv4"))
b5c4_layer.activation = tf.keras.activations.linear
b5c4_layer._name = b5c4_layer.name + str("_preact")
b5c4_preact_output = b5c4_layer(vgg19.get_layer("block5_conv3").output)
b2c2_layer = deepcopy(vgg19.get_layer("block2_conv2"))
b2c2_layer.activation = tf.keras.activations.linear
b2c2_layer._name = b2c2_layer.name + str("_preact")
b2c2_preact_output = b2c2_layer(vgg19.get_layer("block2_conv1").output)
最后,当我们应用 ReLU-activation.
时,获取输出并检查它们是否等于 post-activation 输出vgg19_features = Model(vgg19.input, [b2c2_preact_output, b5c4_preact_output])
vgg19_features_control = Model(vgg19.input, [vgg19.get_layer("block2_conv2").output, vgg19.get_layer("block5_conv4").output])
b2c2_preact, b5c4_preact = vgg19_features(tf.keras.applications.vgg19.preprocess_input(img))
b2c2, b5c4 = vgg19_features_control(tf.keras.applications.vgg19.preprocess_input(img))
print(np.allclose(tf.keras.activations.relu(b2c2_preact).numpy(),b2c2.numpy()))
print(np.allclose(tf.keras.activations.relu(b5c4_preact).numpy(),b5c4.numpy()))
True
True
这是类似于 Wang et al. 的图 6 的可视化效果,可以查看特征 space 中的效果。
输入图片