在Keras 2上具有自定义(无)丢失的三重嵌入层

时间:2018-04-19 19:44:52

标签: python deep-learning keras

我一直在寻找深度学习中三元组嵌入的简单实现。我想使用Keras,因为这是我稍微熟悉的(尽管仍然非常缺乏经验)。

以下是其中一个灵感作品的参考:paper on embedded triplets

我已经找到了一个很好的例子,开始使用mnist数据集,据我所知,它工作得很好。实现3个嵌入层的合并时会出现问题。

def build_model(input_shape):

base_input = Input(input_shape)
x = Conv2D(32, (3, 3), activation='relu')(base_input)
x = MaxPooling2D((2, 2))(x)
x = Conv2D(64, (3, 3), activation='relu')(x)
x = MaxPooling2D((2, 2))(x)
x = Dropout(0.25)(x)
x = Flatten()(x)
x = Dense(2, activation='linear')(x)
embedding_model = Model(base_input, x, name='embedding')

anchor_input = Input(input_shape, name='anchor_input')
positive_input = Input(input_shape, name='positive_input')
negative_input = Input(input_shape, name='negative_input')

anchor_embedding = embedding_model(anchor_input)
positive_embedding = embedding_model(positive_input)
negative_embedding = embedding_model(negative_input)

inputs = [anchor_input, positive_input, negative_input]
outputs = [anchor_embedding, positive_embedding, negative_embedding]
triplet_model = Model(inputs, outputs)
triplet_model.add_loss(K.mean(triplet_loss(outputs)))
triplet_model.compile(loss=None, optimizer='adam') # <-- CRITICAL LINE

return embedding_model, triplet_model

通过当前实施,损失是通过model.add_loss添加的,我还没有找到这样的例子。 真正的问题是,我无法加载已保存的模型。

triplet_model.save('triplet.h5')
model = load_model('triplet.h5')

返回:

ValueError: The model cannot be compiled because it has no loss to optimize.

在“损失”中添加参数&#39;当我尝试编译模型时,参数引发了另一个错误。 我想问一下如何绕过这个问题,或者是否有更好的方法来创建嵌入模型的模型(可能没有空的损失函数)。

以下是triplet_loss函数供参考:

def triplet_loss(inputs, dist='sqeuclidean', margin='maxplus'):
    anchor, positive, negative = inputs
    positive_distance = K.square(anchor - positive)
    negative_distance = K.square(anchor - negative)
    if dist == 'euclidean':
        positive_distance = K.sqrt(K.sum(positive_distance, axis=-1, keepdims=True))
        negative_distance = K.sqrt(K.sum(negative_distance, axis=-1, keepdims=True))
    elif dist == 'sqeuclidean':
        positive_distance = K.mean(positive_distance, axis=-1, keepdims=True)
        negative_distance = K.mean(negative_distance, axis=-1, keepdims=True)
    loss = positive_distance - negative_distance
    if margin == 'maxplus':
        loss = K.maximum(0.0, 1 + loss)
    elif margin == 'softplus':
        loss = K.log(1 + K.exp(loss))
    return K.mean(loss)

以下是完整的脚本:link

1 个答案:

答案 0 :(得分:2)

这里的问题是您离开triplet_model.compile(loss=None),但keras不知道如何在load_model()中正确处理它。我知道你必须这样做,但你可以用不同的方式加载模型来解决当前的问题。

简而言之,不要通过load_model()加载整个模型,而只是加载load_weights()的权重。

例如,您可以

# save only weights
triplet_model.save_weights('tmp.h5') 
# load saved weights
new_embedding_model, new_triplet_model = build_model(input_shape)
new_triplet_model.load_weights('tmp.h5') # load only weights