如何为这个共享权重模型提取中间层的输出?

问题描述 投票:0回答:0

这是我使用keras siamese网络实现搭建的siamese网络模型

base_cnn = resnet.ResNet50(
    weights="imagenet", input_shape=target_shape + (3,), include_top=False
)
flatten = layers.Flatten()(base_cnn.output)
#dense0 = layers.Dense(1024, activation="relu")(flatten)
#dense0 = layers.BatchNormalization()(dense0)
dense1 = layers.Dense(512, activation="relu")(flatten)
dense1 = layers.BatchNormalization()(dense1)
dense2 = layers.Dense(512, activation="relu")(dense1)
dense2 = layers.BatchNormalization()(dense2)
dense3 = layers.Dense(512, activation="relu")(dense2)
dense3 = layers.BatchNormalization()(dense3)
output = layers.Dense(256)(dense3)


embedding = Model(base_cnn.input, output, name="Embedding")

trainable = False
for layer in base_cnn.layers:
    layer.trainable = trainable

class DistanceLayer(layers.Layer):
    """
    This layer is responsible for computing the distance between the anchor
    embedding and the positive embedding, and the anchor embedding and the
    negative embedding.
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def call(self, anchor, positive, negative):
        #ap_distance = tf.reduce_sum(tf.square(anchor - positive), axis = -1)
        #an_distance = tf.reduce_sum(tf.square(anchor - negative), axis = -1)
        ap_distance = tf.keras.losses.cosine_similarity(anchor, positive)
        an_distance = tf.keras.losses.cosine_similarity(anchor, negative)
        
        return (ap_distance, an_distance)
    
anchor_input = layers.Input(name="anchor", shape=target_shape + (3,))
positive_input = layers.Input(name="positive", shape=target_shape + (3,))
negative_input = layers.Input(name="negative", shape=target_shape + (3,))

distances = DistanceLayer()(
    embedding(resnet.preprocess_input(anchor_input)),
    embedding(resnet.preprocess_input(positive_input)),
    embedding(resnet.preprocess_input(negative_input)),
)


siamese_network = Model(
    inputs=[anchor_input, positive_input, negative_input], outputs=distances
)
class SiameseModel(Model):
    """The Siamese Network model with a custom training and testing loops.

    Computes the triplet loss using the three embeddings produced by the
    Siamese Network.

    The triplet loss is defined as:
       L(A, P, N) = max(‖f(A) - f(P)‖² - ‖f(A) - f(N)‖² + margin, 0)
    """

    def __init__(self, siamese_network, margin= 0.2):
        super().__init__()
        self.siamese_network = siamese_network
        self.margin = margin
        self.loss_tracker = metrics.Mean(name="loss")

    def call(self, inputs):
        return self.siamese_network(inputs)

    def train_step(self, data):
        # GradientTape is a context manager that records every operation that
        # you do inside. We are using it here to compute the loss so we can get
        # the gradients and apply them using the optimizer specified in
        # `compile()`.
        with tf.GradientTape() as tape:
            loss = self._compute_loss(data)

        # Storing the gradients of the loss function with respect to the
        # weights/parameters.
        gradients = tape.gradient(loss, self.siamese_network.trainable_weights)

        # Applying the gradients on the model using the specified optimizer
        self.optimizer.apply_gradients(
            zip(gradients, self.siamese_network.trainable_weights)
        )

        # Let's update and return the training loss metric.
        self.loss_tracker.update_state(loss)
        return {"loss": self.loss_tracker.result()}

    def test_step(self, data):
        loss = self._compute_loss(data)

        # Let's update and return the loss metric.
        self.loss_tracker.update_state(loss)
        return {"loss": self.loss_tracker.result()}

    def _compute_loss(self, data):
        # The output of the network is a tuple containing the distances
        # between the anchor and the positive example, and the anchor and
        # the negative example.
        ap_distance, an_distance = self.__call__(data)

        # Computing the Triplet Loss by subtracting both distances and
        # making sure we don't get a negative value.
        loss = ap_distance - an_distance
        #loss = tf.maximum(loss + self.margin, 0.0)
        loss = tf.keras.backend.clip(loss + self.margin, 0., None)
        return loss
    
    def get_config(self):
        config = {
            "siamese_network": self.siamese_network,
            "margin": self.margin,
        }
        base_config = super().get_config()
        return dict(list(base_config.items()) + list(config.items()))

    @classmethod
    def from_config(cls, config):
        siamese_network = config.pop("siamese_network")
        margin = config.pop("margin")
        model = cls(siamese_network=siamese_network, margin=margin)
        return model

    @property
    def metrics(self):
        # We need to list our metrics here so the `reset_states()` can be
        # called automatically.
        return [self.loss_tracker]

这是模型架构: Model Architecture

现在我想在上面应用 GRAD CAM 算法来可视化模型关注的内容。我在这里使用了keras实现: Grad cam 的要求之一是获取模型中最后一个卷积层的输出并获取其激活以及 model.output。 我使用了以下代码:https://keras.io/examples/vision/grad_cam/

grad_model = tf.keras.models.Model(
    [siamese_network.input], [siamese_network.get_layer("Embedding").get_layer("conv5_block3_out").output, siamese_network.output]
)

为什么会出现以下错误? ValueError:图形断开连接:无法获取张量 KerasTensor(type_spec=TensorSpec(shape=(None, 200, 200, 3), dtype=tf.float32, name='input_1'), name='input_1', description="由“input_1”层“conv1_pad”层创建。可以毫无问题地访问以下先前的层:[]

有没有办法从我构建的 siamese_network 中制作一个模型来输出所有 3 个嵌入输出的结果以及给出距离 ap 和 an 的原始模型输出?

machine-learning deep-learning computer-vision tensorflow2.0 functional-api
© www.soinside.com 2019 - 2024. All rights reserved.