簡體   English   中英

如何在 Keras 或 Tf 2 中為基於 ResNet50 的連體網絡應用 Triplet Loss

[英]How to apply Triplet Loss for a ResNet50 based Siamese Network in Keras or Tf 2

我有一個基於ResNetsiamese網絡,它使用的想法是,您嘗試最小化 2 個圖像之間的l-2距離,然后應用 sigmoid,以便它為您提供{0:'same',1:'different'} output 和基於關於預測有多遠,您只需將梯度流回網絡,但有一個問題是梯度更新太少,因為我們正在改變{0,1}之間的距離,所以我想使用相同的架構,但基於關於Triplet Loss

    I1 = Input(shape=image_shape)
    I2 = Input(shape=image_shape)

    res_m_1 = ResNet50(include_top=False, weights='imagenet', input_tensor=I1, pooling='avg')
    res_m_2 = ResNet50(include_top=False, weights='imagenet', input_tensor=I2, pooling='avg')

    x1 = res_m_1.output
    x2 = res_m_2.output
    # x = Flatten()(x) or use this one if not using any pooling layer

    distance = Lambda( lambda tensors : K.abs( tensors[0] - tensors[1] )) ([x1,x2] )
    final_output = Dense(1,activation='sigmoid')(distance)

    siamese_model = Model(inputs=[I1,I2], outputs=final_output)
 
    siamese_model.compile(loss='binary_crossentropy',optimizer=Adam(),metrics['acc'])

    siamese_model.fit_generator(train_gen,steps_per_epoch=1000,epochs=10,validation_data=validation_data)

那么如何將其更改為使用Triplet Loss function呢? 為了完成這項工作,應該在此處進行哪些調整? 一個變化是我必須計算

res_m_3 = ResNet50(include_top=False, weights='imagenet', input_tensor=I2, pooling='avg')
x3 = res_m_3.output

在 tf 文檔中發現的一件事是triplet-semi-hard-loss ,給出如下:

tfa.losses.TripletSemiHardLoss()

如論文所示,最好的結果來自被稱為“半硬”的三元組。 這些被定義為三元組,其中負數比正數離錨點更遠,但仍會產生正損失。 為了有效地找到這些三元組,我們利用在線學習,並且只從每批中的半困難示例中進行訓練。

我在 Kaggle 上找到的 Triplet Triplet Loss的另一個實現是: Triplet Loss Keras

我應該使用哪一個,最重要的是,如何

PS:人們還使用類似的東西: x = Lambda(lambda x: K.l2_normalize(x,axis=1))(x)model.output之后。 這是為什么? 這是在做什么?

按照我的這個答案,並考慮到TripletSemiHardLoss的作用,我們可以執行以下操作:

import tensorflow as tf
import tensorflow_addons as tfa
import tensorflow_datasets as tfds
from tensorflow.keras import models, layers

BATCH_SIZE = 32
LATENT_DEM = 128

def _normalize_img(img, label):
    img = tf.cast(img, tf.float32) / 255.
    return (img, label)

train_dataset, test_dataset = tfds.load(name="mnist", split=['train', 'test'], as_supervised=True)

# Build your input pipelines
train_dataset = train_dataset.shuffle(1024).batch(BATCH_SIZE)
train_dataset = train_dataset.map(_normalize_img)

test_dataset = test_dataset.batch(BATCH_SIZE)
test_dataset = test_dataset.map(_normalize_img)

inputs = layers.Input(shape=(28, 28, 1))
resNet50 = tf.keras.applications.ResNet50(include_top=False, weights=None, input_tensor=inputs, pooling='avg')
outputs = layers.Dense(LATENT_DEM, activation=None)(resNet50.output) # No activation on final dense layer
outputs = layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))(outputs) # L2 normalize embedding

siamese_model = models.Model(inputs=inputs, outputs=outputs)

# Compile the model
siamese_model.compile(
    optimizer=tf.keras.optimizers.Adam(0.001),
    loss=tfa.losses.TripletSemiHardLoss())

# Train the network
history = siamese_model.fit(
    train_dataset,
    epochs=3)

暫無
暫無

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

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