簡體   English   中英

"訪問在 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

有關這方面的更多詳細信息,請參閱SO Answer

有一種方法可以使用 TF 版本 2.7.0 訪問預訓練 Keras 模型的預激活層。 這是從 VGG19 訪問兩個中間預激活輸出的方法。

初始化 3 個 VGG19 模型。 第一個只是事后比較結果和進行完整性檢查。 我們可以省略頂層以避免將不必要的參數加載到內存中。

vgg19 = tf.keras.applications.VGG19(
    include_top=False,
    weights="imagenet"
)

vgg192 = tf.keras.applications.VGG19(
    include_top=False,
    weights="imagenet"
)

vgg193 = tf.keras.applications.VGG19(
    include_top=False,
    weights="imagenet"
)

這是重要的部分:將卷積層的激活更改為線性(即不激活)。

vgg192.get_layer("block2_conv2").activation = tf.keras.activations.linear

vgg193.get_layer("block5_conv4").activation = tf.keras.activations.linear

這也是為什么當我們喜歡有兩個中間輸出時需要兩個獨立的 VGG19 模型的原因。 當改變較低層的激活時,較高層的輸出也會改變。

最后,在我們應用 ReLU 激活時,獲取輸出並檢查它們是否等於激活后的輸出。

inter = Model(vgg19.input, [vgg19.get_layer("block2_conv2").output, vgg19.get_layer("block5_conv4").output])
inter2 = Model(vgg192.input, [vgg192.get_layer("block2_conv2").output])
inter3 = Model(vgg193.input, [vgg193.get_layer("block5_conv4").output])

b2c2, b5c4 = inter(tf.keras.applications.vgg19.preprocess_input(img))
b2c2_preact = inter2(tf.keras.applications.vgg19.preprocess_input(img))
b5c4_preact = inter3(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 等人的圖 6 的可視化。 查看特征空間中的效果。 VGG19-中級

輸入圖像

輸入圖像

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM