Tensorflow 如何在Keras或Tf 2中为基于ResNet50的暹罗网络应用三重态损耗

Tensorflow 如何在Keras或Tf 2中为基于ResNet50的暹罗网络应用三重态损耗,tensorflow,machine-learning,keras,deep-learning,conv-neural-network,Tensorflow,Machine Learning,Keras,Deep Learning,Conv Neural Network,我有一个基于ResNet的siamese网络,它使用的思想是,你尝试最小化两幅图像之间的l-2距离,然后应用一个sigmoid,这样它会给你{0:'same',1:'different'}输出,并基于预测的距离,您只需将渐变流回到网络,但存在一个问题,即渐变的更新太少,因为我们正在更改{0,1}之间的距离,所以我考虑使用相同的架构,但基于三重态丢失 I1 = Input(shape=image_shape) I2 = Input(shape=image_shape) r

我有一个基于
ResNet
siamese
网络,它使用的思想是,你尝试最小化两幅图像之间的
l-2
距离,然后应用一个sigmoid,这样它会给你
{0:'same',1:'different'}
输出,并基于预测的距离,您只需将渐变流回到网络,但存在一个问题,即渐变的更新太少,因为我们正在更改
{0,1}
之间的距离,所以我考虑使用相同的架构,但基于
三重态丢失

    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)

那么,如何将其更改为使用
三重丢失功能
?为了完成这项工作,这里应该做哪些调整?一个变化是我必须计算

res_m_3 = ResNet50(include_top=False, weights='imagenet', input_tensor=I2, pooling='avg')
x3 = res_m_3.output
tf文档中发现的一件事是
三重半硬损耗
,如下所示:

tfa.loss.TripletSemiHardLoss()

如本文所示,最好的结果来自于被称为“半硬”的三胞胎。这些被定义为三联体,其中负片比正片离锚更远,但仍然产生正损耗。为了有效地找到这些三胞胎,我们利用在线学习,只从每个批次的半硬示例中进行训练

我在Kaggle上发现的
三重态丢失的另一个实现是:

我应该使用哪一个,最重要的是,如何使用

附言:人们也会在模型输出后使用这样的东西:
x=Lambda(Lambda x:K.l2_normalize(x,axis=1))(x)
。为什么呢?这是做什么的?

接下来,考虑到
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)

我不熟悉三重态损耗,但你能说这些例子中是否有任何一个与“三重态损耗”对应吗?我没有资格说什么是或不是三重态损耗,但如果是,我肯定可以告诉你如何使用它。你能告诉我基于
暹罗
网络可以建立吗?使用我现有的或其他一些体系结构?正如我在最近的文章中提到的,是否有一项出色的工作向您展示了如何使用
TripletSemiHardLoss
,所以在使用它时是否仍然存在此问题?在使用之前,我问了这个问题。您能告诉我如何制作数据集,以便在
model.compile()
中直接使用这些损失,或者手动制作硬/半数据集并传入简单的
三重损失
?我会把赏金给你的。我从那里得到了答案。出于好奇,我留下了一些评论。看看这个关于堆栈溢出的答案是否有帮助-PS:我试图向您展示输出,但我无法在短时间内用我的笔记本电脑或在Colab完成训练,使用ResNet50时速度太慢了:(但你只使用了一个网络。对吗?是的,一个网络就足够了,
tfa.loss.tripletsimhardloss
注意所有细节