我有一个基于ResNet
的siamese
网络,它使用了最小化两张图像之间的l-2
距离的想法,然后应用一个sigmoid函数,使其输出{0:'same',1:'different'}
,并且根据预测的距离,你可以将梯度反馈到网络中,但问题是梯度的更新非常小,因为我们是在改变{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函数
?这里需要做哪些调整来实现这一点?一个变化将是我必须计算
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 Loss
实现是:Triplet Loss Keras
我应该使用哪个,最重要的是,如何使用?
附注:人们还在model.output
之后使用类似于x = Lambda(lambda x: K.l2_normalize(x,axis=1))(x)
的东西。这是为什么?这是在做什么?
回答:
根据我这个回答,并考虑到TripletSemiHardLoss
的作用,我们可以这样做:
import tensorflow as tfimport tensorflow_addons as tfaimport tensorflow_datasets as tfdsfrom tensorflow.keras import models, layersBATCH_SIZE = 32LATENT_DEM = 128def _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 pipelinestrain_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 layeroutputs = layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))(outputs) # L2 normalize embeddingsiamese_model = models.Model(inputs=inputs, outputs=outputs)# Compile the modelsiamese_model.compile( optimizer=tf.keras.optimizers.Adam(0.001), loss=tfa.losses.TripletSemiHardLoss())# Train the networkhistory = siamese_model.fit( train_dataset, epochs=3)