有没有办法访问 tensorflow_hub.KerasLayer 对象中的图层?

Is there any way to access layers in tensorflow_hub.KerasLayer object?

我正在尝试将来自 tensorflow hub 的预训练模型用于我的对象检测模型。我按照官方说明将来自集线器的模型包装为 KerasLayer 对象。然后我意识到我无法访问这个预训练模型中的层。但我需要使用某些特定层的输出来构建我的模型。有什么方法可以访问 tensorflow_hub.KerasLayer 对象中的图层?

为了能够轻松做到这一点,预训练模型的创建者需要准备好输出以供访问。例如。通过一个额外的函数或一个额外的签名来输出你想要使用的激活。

有一种未记录的方法可以从 TF-Slim 导出的某些 TF2 SavedModel 中获取中间层,例如 https://tfhub.dev/google/imagenet/inception_v1/feature_vector/4:将 return_endpoints=True 传递给 SavedModel 的 __call__ 函数将输出更改为 dict.

注意:此界面可能会更改或删除,并且存在已知问题。

model = tfhub.KerasLayer('https://tfhub.dev/google/imagenet/inception_v1/feature_vector/4', trainable=False, arguments=dict(return_endpoints=True))
input = tf.keras.layers.Input((224, 224, 3))
outputs = model(input)
for k, v in sorted(outputs.items()):
  print(k, v.shape)

此示例的输出:

InceptionV1/Conv2d_1a_7x7 (None, 112, 112, 64)
InceptionV1/Conv2d_2b_1x1 (None, 56, 56, 64)
InceptionV1/Conv2d_2c_3x3 (None, 56, 56, 192)
InceptionV1/MaxPool_2a_3x3 (None, 56, 56, 64)
InceptionV1/MaxPool_3a_3x3 (None, 28, 28, 192)
InceptionV1/MaxPool_4a_3x3 (None, 14, 14, 480)
InceptionV1/MaxPool_5a_2x2 (None, 7, 7, 832)
InceptionV1/Mixed_3b (None, 28, 28, 256)
InceptionV1/Mixed_3c (None, 28, 28, 480)
InceptionV1/Mixed_4b (None, 14, 14, 512)
InceptionV1/Mixed_4c (None, 14, 14, 512)
InceptionV1/Mixed_4d (None, 14, 14, 512)
InceptionV1/Mixed_4e (None, 14, 14, 528)
InceptionV1/Mixed_4f (None, 14, 14, 832)
InceptionV1/Mixed_5b (None, 7, 7, 832)
InceptionV1/Mixed_5c (None, 7, 7, 1024)
InceptionV1/global_pool (None, 1, 1, 1024)
default (None, 1024)

需要注意的问题:

  • 未记录,可能会更改或删除,无法始终如一地提供。
  • __call__ 计算所有输出(并在训练期间应用所有更新操作),而不管稍后使用的输出。

来源:https://github.com/tensorflow/hub/issues/453

因为 return_endpoints=True 似乎不再有效了。

你可以这样做:

efficientnet_lite0_base_layer = hub.KerasLayer(
    "https://tfhub.dev/tensorflow/efficientnet/lite0/feature-vector/2",
    output_shape=[1280],
    trainable=False
)

print("Thickness of the model:", len(efficientnet_lite0_base_layer.weights))
print ("{:<80} {:<20} {:<10}".format('Layer','Shape','Type'))

for i in range(len(efficientnet_lite0_base_layer.weights)):
    model_weights_raw_string = str(efficientnet_lite0_base_layer.weights[i])
    model_weights_wo_weights = model_weights_raw_string.split(", numpy", 1)[0]
    dtype = model_weights_wo_weights.split(" dtype=")[1]
    shape = model_weights_wo_weights.split(" shape=")[1].split(" dtype=")[0]
    
    print ("{:<80} {:<20} {:<10}".format(efficientnet_lite0_base_layer.weights[i].name, shape, dtype))