簡體   English   中英

凱拉斯。 Siamese 網絡和三元組損失

[英]Keras. Siamese network and triplet loss

我想建立一個應該能夠驗證圖像(例如人臉)的網絡。 據我了解,最好的解決方案是具有三重損失的連體網絡。 我沒有找到任何現成的實現,所以我決定創建自己的。

但我對 Keras 有疑問。 例如,這里是網絡的結構:

網絡結構

代碼是這樣的:

embedding = Sequential([
  Flatten(),
  Dense(1024, activation='relu'),
  Dense(64),
  Lambda(lambda x: K.l2_normalize(x, axis=-1))
])

input_a = Input(shape=shape, name='anchor')
input_p = Input(shape=shape, name='positive')
input_n = Input(shape=shape, name='negative')

emb_a = embedding(input_a)
emb_p = embedding(input_p)
emb_n = embedding(input_n)

out = Concatenate()([emb_a, emb_p, emp_n])

model = Model([input_a, input_p, input_n], out)

model.compile(optimizer='adam', loss=<triplet_loss>)

我只定義了一個嵌入模型。 這是否意味着一旦模型開始訓練,每個輸入的權重都會相同?

如果是,我如何從model提取嵌入權重?

是的,在三元組損失函數中,權重應該在所有三個網絡之間共享,即Anchor、Positive 和 Negetive 在 Tensorflow 1.x 中,您可以在tf.layers使用reuse=True來實現權重共享。

但是在 Tensorflow 2.x 中,因為tf.layers已移至tf.keras.layers並且reuse功能已被刪除。 為了實現權重共享,您可以編寫一個自定義層,該層采用父層並重用其權重。

下面是執行相同操作的示例示例。

class SharedConv(tf.keras.layers.Layer):
    def __init__(
        self,
        filters,
        kernel_size,
        strides=None,
        padding=None,
        dilation_rates=None,
        activation=None,
        use_bias=True,
        **kwargs
    ):
        self.filters = filters
        self.kernel_size = kernel_size
        self.strides = strides
        self.padding = padding
        self.dilation_rates = dilation_rates
        self.activation = activation
        self.use_bias = use_bias
        super().__init__(*args, **kwargs)

   def build(self, input_shape):
       self.conv = Conv2D(
           self.filters,
           self.kernel_size,
           padding=self.padding,
           dilation_rate=self.dilation_rates[0]
       )
       self.net1 = Activation(self.activation)
       self.net2 = Activation(self.activation)

   def call(self, inputs, **kwargs):
       x1 = self.conv(inputs)
       x1 = self.act1(x1)
       x2 = tf.nn.conv2d(
                inputs,
                self.conv.weights[0], 
                padding=self.padding,
                strides=self.strides,
                dilations=self.dilation_rates[1]
              )
        if self.use_bias:
            x2 = x2 + self.conv.weights[1]
        x2 = self.act2(x2)
        return x1, x2

我將回答如何提取嵌入(參考我的 Github 帖子):

我訓練的siamese_model.summary()模型如下所示: siamese_model.summary()

圖片

請注意,我新定義的模型與以黃色突出顯示的模型基本相同

然后我重新定義了我想用於提取嵌入的模型(它應該與您定義的模型相同,但現在它不會有像 siamese 這樣的多個輸入),如下所示:

siamese_embeddings_model = build_siamese_model(input_shape)

siamese_embeddings_model .summary()

圖片

然后我只是從我訓練的 siamese 模型中提取權重並將它們設置到我的新模型中

embeddings_weights = siamese_model.layers[-3].get_weights()

siamese_embeddings_model.set_weights(embeddings_weights )

然后您可以提供新圖像以從新模型中提取嵌入

vector = siamese.predict(image)

len(vector[0])它將打印 150 因為我的細密層(這是輸出向量)

暫無
暫無

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

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