keras中的三重损失,如何从合并向量中获取锚点、正向和负向

Triple loss in keras, how to get the anchor, positive, and negative from merged vector

我想做的是使用三重损失作为我的损失函数,但我不知道我是否从所使用的合并向量中获得了正确的值。

所以这是我的损失函数:

def triplet_loss(y_true, y_pred, alpha=0.2):
    """
    Implementation of the triplet loss function
    Arguments:
    y_true -- true labels, required when you define a loss in Keras, not used in this function.
    y_pred -- python list containing three objects:
            anchor:   the encodings for the anchor data
            positive: the encodings for the positive data (similar to anchor)
            negative: the encodings for the negative data (different from anchor)
    Returns:
    loss -- real number, value of the loss
    """
    print("Ypred")
    print(y_pred.shape)

    anchor = y_pred[:,0:512]
    positive = y_pred[:,512:1024]
    negative = y_pred[:,1024:1536]

    print(anchor.shape)
    print(positive.shape)
    print(negative.shape)

    #anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2] # Dont think this is working
    # distance between the anchor and the positive
    pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)))
    print("PosDist", pos_dist)
    # distance between the anchor and the negative
    neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)))
    print("Neg Dist", neg_dist)
    # compute loss
    basic_loss = (pos_dist - neg_dist) + alpha
    loss = tf.maximum(basic_loss, 0.0)
    return loss

现在,当我在代码中使用这一行而不是切片时,这确实有效

anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2] 

但我认为这是不正确的,因为合并向量的形状是 (?, 3, 3, 1536) 我认为它抓住了错误的信息。但我似乎无法弄清楚如何正确切片。因为未注释的代码给了我这个问题。

Dimensions must be equal, but are 3 and 0 for 'loss_9/concatenate_10_loss/Sub' (op: 'Sub') with input shapes: [?,3,3,1536], [?,0,3,1536].

我的网络设置是这样的:

input_dim = (7,7,2048)
anchor_in = Input(shape=input_dim)
pos_in = Input(shape=input_dim)
neg_in = Input(shape=input_dim)
base_network = create_base_network()
# Run input through base network
anchor_out = base_network(anchor_in)
pos_out = base_network(pos_in)
neg_out = base_network(neg_in)
print(anchor_out.shape)

merged_vector = Concatenate(axis=-1)([anchor_out, pos_out, neg_out])
print("Meged Vector", merged_vector.shape)
print(merged_vector)

model = Model(inputs=[anchor_in, pos_in, neg_in], outputs=merged_vector)

adam = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
model.compile(optimizer=adam, loss=triplet_loss)

更新

用这个好像是对的,谁能证实一下?

anchor = y_pred[:,:,:,0:512]
positive = y_pred[:,:,:,512:1024]
negative = y_pred[:,:,:,1024:1536]

您不需要进行串联操作:

# change this line to this
model = Model(inputs=[anchor_in, pos_in, neg_in], outputs=[anchor_out, pos_out, neg_out])

完整代码:

input_dim = (7,7,2048)
anchor_in = Input(shape=input_dim)
pos_in = Input(shape=input_dim)
neg_in = Input(shape=input_dim)
base_network = create_base_network()
# Run input through base network
anchor_out = base_network(anchor_in)
pos_out = base_network(pos_in)
neg_out = base_network(neg_in)
print(anchor_out.shape)

# code changed here
model = Model(inputs=[anchor_in, pos_in, neg_in], outputs=[anchor_out, pos_out, neg_out])
adam = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
model.compile(optimizer=adam, loss=triplet_loss) 

那么可以使用如下损失:

def triplet_loss(y_true, y_pred, alpha=0.3):
    '''
        Inputs:
                    y_true: True values of classification. (y_train)
                    y_pred: predicted values of classification.
                    alpha: Distance between positive and negative sample, arbitrarily
                           set to 0.3
        Returns:
                    Computed loss
        Function:
                    --Implements triplet loss using tensorflow commands
                    --The following function follows an implementation of Triplet-Loss 
                      where the loss is applied to the network in the compile statement 
                      as usual.
    '''
    anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]

    positive_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), -1)
    negative_dist = tf.reduce_sum(tf.square(tf.subtract(anchor,negative)), -1)

    loss_1 = tf.add(tf.subtract(positive_dist, negative_dist), alpha)
    loss = tf.reduce_sum(tf.maximum(loss_1, 0.0))

    return loss