Используйте различные вложения для расчета потери тройки - PullRequest
0 голосов
/ 01 февраля 2020

Я пытался использовать другое вложение для расчета потери тройки, но потеря заключена в поле.

Также я пытался найти количество действительных тройок, но результат застрял в половине общего экземпляра.

Это мой код:

# Sample Data
import numpy as np
import tensorflow as tf

batch = 64
emb_dim = 1024

np.random.seed(1234)
emb1 = np.random.rand(batch,emb_dim)
np.random.seed(2345)
emb2 = np.random.rand(batch,emb_dim)
margin = 0.3
labels = np.expand_dims(np.arange(batch), axis=1)

def _distance_metric(x, y):
    """
    Args:
        x: tensor, with shape [m, d], (batch_size, d)
        y: tensor, with shape [n, d], (batch_size, d)
    Returns:
        dist: tensor, with shape [m, n], (batch_size, batch_size)
    """
    # |x-y|^2 = x^2 - 2xy + y^2
    # xy
    xy = tf.matmul(x, tf.transpose(y))
    # x^2
    xx = tf.matmul(x, tf.transpose(x))
    xx = tf.linalg.diag_part(xx)
    # y^2
    yy = tf.matmul(y, tf.transpose(y))
    yy = tf.linalg.diag_part(yy)
    '''
    (batch_size,1)-(batch_size,batch_size):
        Equivalent to each column operation
    (batch_size,batch_size)+(1,batch_size):
        Equivalent to each row operation
    '''
    distances = tf.expand_dims(xx, 1) -2.0*xy + tf.expand_dims(yy, 0)
    return distances

def _label_mask(labels):
    '''
    if label is same, label_mask will return True
    ------------------------------------
    Args:
        labels:     Label Data, shape = (batch_size,1)
    Returns:
        label_mask: tensor, with shape [m, n], (batch_size, batch_size)
        ex.
            labels = [1,0,1]
            label_mask = [[1, 0, 1],
                          [0, 1, 0],
                          [1, 0, 1]]
    '''
    labels = tf.dtypes.cast(labels, tf.float32)
    label_mask = _distance_metric(labels, labels)
    label_mask = (label_mask == 0)
    return label_mask

def batch_all(labels, emb1, emb2, margin):
    '''
    batch all triplet loss of a batch
    ------------------------------------
    Args:
        labels:     Label Data, shape = (batch_size,1)
        emb1, emb2: Embedding Feature, shape = (batch_size, vector_size)
        margin:     margin, scalar
    Returns:
        triplet_loss: scalar, for one batch
    '''
    dist_mat = _distance_metric(emb1, emb2)
    # an and ap mask
    ap_mask = _label_mask(labels)
    an_mask = tf.dtypes.cast(tf.math.logical_not(ap_mask), dtype=tf.float64)
    ap_mask = tf.dtypes.cast(ap_mask, dtype=tf.float64)
    # distance between anchor and positive
    dist_ap = tf.reduce_sum(dist_mat*ap_mask, axis=1)/tf.reduce_sum(ap_mask, axis=1)
    # ap - dist_mat + margin
    mat = tf.expand_dims(dist_ap, 1) - dist_mat + margin
    # only need ap-an
    mat = mat*an_mask
    # caluculate the number of valid triplet loss
    mask = tf.dtypes.cast(tf.math.greater(mat, margin), dtype=tf.float64)
    num_valid_triplets = tf.reduce_sum(mask)
    triplet_loss = mat*mask
    # <1 : 1
    num_valid_triplets = tf.maximum(num_valid_triplets, 1.0)
    # divided triplet_loss by num_valid_triplets
    triplet_loss = tf.reduce_sum(triplet_loss)/(num_valid_triplets + 1e-16)
    return triplet_loss, num_valid_triplets

Есть ли какие-то глупые ошибки, которые я сделал?

А вот кривая обучения и число действительного триплета.

emb1 до emb2 триплетная потеря

число emb1 * От 1022 * до emb2 действительный триплет

emb2 до emb1 потеря триплета

число emb2 до emb1 действительный триплет

...