40 votes

Implémentation de la perte de contraste et de la perte de triplet dans Tensorflow

J'ai commencé à jouer avec TensorFlow il y a deux jours et je me demande s'il y a le triplet et les pertes contrastées implémentées.

J'ai regardé la documentation , mais je n'ai trouvé aucun exemple ou description de ces choses.

86voto

Olivier Moindrot Points 17630

Mise à jour (2018/03/19): j'ai écrit un billet de blog expliquant en détail comment mettre en œuvre triplet perte de TensorFlow.


Vous avez besoin de mettre en œuvre vous-même les contrastive de la perte ou du triplet de la perte, mais une fois que vous connaissez les paires ou triplets c'est assez facile.


Contrastive De La Perte

Supposons que vous avez comme entrée les paires de données et de leur label (positif ou négatif, c'est à dire d'une même classe ou d'une autre classe). Par exemple, vous avez des images en entrée de taille 28x28x1:

left = tf.placeholder(tf.float32, [None, 28, 28, 1])
right = tf.placeholder(tf.float32, [None, 28, 28, 1])
label = tf.placeholder(tf.int32, [None, 1]). # 0 if same, 1 if different
margin = 0.2

left_output = model(left)  # shape [None, 128]
right_output = model(right)  # shape [None, 128]

d = tf.reduce_sum(tf.square(left_output - right_output), 1)
d_sqrt = tf.sqrt(d)

loss = label * tf.square(tf.maximum(0., margin - d_sqrt)) + (1 - label) * d

loss = 0.5 * tf.reduce_mean(loss)

Triplet Perte

Même avec contrastive de la perte, mais avec des triplets (ancre, positif, négatif). Vous n'avez pas besoin d'étiquettes ici.

anchor_output = ...  # shape [None, 128]
positive_output = ...  # shape [None, 128]
negative_output = ...  # shape [None, 128]

d_pos = tf.reduce_sum(tf.square(anchor_output - positive_output), 1)
d_neg = tf.reduce_sum(tf.square(anchor_output - negative_output), 1)

loss = tf.maximum(0., margin + d_pos - d_neg)
loss = tf.reduce_mean(loss)

Les vrais problèmes lors de la mise en œuvre de triplet de perte ou contrastive perte de TensorFlow est comment faire pour l'échantillon des triplets ou des paires. Je vais me concentrer sur la génération de triplets parce qu'il est plus difficile de générer des paires.

Le plus simple est de les générer à l'extérieur de la Tensorflow graphique, c'est à dire en python et les nourrir pour le réseau à travers les espaces réservés. Fondamentalement, vous sélectionnez des images 3 à la fois, avec les deux premiers dans la même catégorie et la troisième d'une autre classe. Nous effectuons ensuite une anticipation sur ces triplets, et de calculer le triplet perte.

Le problème ici est que la génération de triplets est compliqué. Nous voulons qu'ils soient valides, des triplés, les triplés avec un positif de la perte (dans le cas contraire, la perte est de 0 et le réseau n'a pas à apprendre).
Pour savoir si un triplet qui est bon ou non vous avez besoin de calculer sa perte, afin de vous faire déjà une anticipation à travers le réseau...

Clairement, la mise en œuvre de triplet perte de Tensorflow est dur, et il y a des façons de le rendre plus efficaces que l'échantillonnage en python, mais en expliquant pourrait faire l'objet d'un blog ensemble !

14voto

Corey Lynch Points 91

Triplet perte de semihard négatifs de l'exploitation minière est maintenant mis en œuvre en tf.contrib, comme suit:

triplet_semihard_loss(
    labels,
    embeddings,
    margin=1.0
)

où:

Args:

  • étiquettes: 1-D tf.int32 Tenseur de la forme [batch_size] de la multiclasse étiquettes entières.

  • les incorporations: 2-D float Tenseur de l'intégration des vecteurs.Plongements devrait soit l2 normalisé.

  • marge: Float, marge terme dans theloss définition.

Retourne:

  • triplet_loss: tf.float32 scalaire.

Pour de plus amples informations, consultez le lien ci-dessous:

https://www.tensorflow.org/versions/master/api_docs/python/tf/contrib/losses/metric_learning/triplet_semihard_loss

5voto

Wassim Gr Points 203

Tiago, je ne pense pas que tu utilises la même formule qu'Olivier. Voici le bon code (pas sûr que cela fonctionnera cependant, juste en fixant la formule):

 def compute_euclidean_distance(x, y):
    """
    Computes the euclidean distance between two tensorflow variables
    """

    d = tf.reduce_sum(tf.square(tf.sub(x, y)),1)
    return d


def compute_contrastive_loss(left_feature, right_feature, label, margin):

    """
    Compute the contrastive loss as in


    L = 0.5 * Y * D^2 + 0.5 * (Y-1) * {max(0, margin - D)}^2

    **Parameters**
     left_feature: First element of the pair
     right_feature: Second element of the pair
     label: Label of the pair (0 or 1)
     margin: Contrastive margin

    **Returns**
     Return the loss operation

    """

    label = tf.to_float(label)
    one = tf.constant(1.0)

    d = compute_euclidean_distance(left_feature, right_feature)
    d_sqrt = tf.sqrt(compute_euclidean_distance(left_feature, right_feature))
    first_part = tf.mul(one-label, d)# (Y-1)*(d)

    max_part = tf.square(tf.maximum(margin-d_sqrt, 0))
    second_part = tf.mul(label, max_part)  # (Y) * max(margin - d, 0)

    loss = 0.5 * tf.reduce_mean(first_part + second_part)

    return loss
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X