Мы представляем реализацию SoftTriple Loss, определенную в [1] Qi Qian et al. В документе также представлена ​​регуляризация, которая позволяет адаптировать количество центров. Мы, однако, не реализуем часть регуляризации.

Тройная потеря

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

Здесь xᵢ, xₖ принадлежат к одному классу, а xᵢ, xⱼ принадлежат к разным классам.

SoftTriple Loss

Однако недавно Qi Qian et al. в [1] оптимизация сглаженных триплетных потерь эквивалентна минимизации потерь SoftMax. Используя математическую формулировку, основанную на SoftMax, эта потеря устраняет выборку, необходимую для тройной потери (для выбора привязки, положительного и отрицательного изображения). Более того, это расширяет идею множественных «центров», где «центрами» могут быть, например, обучающие образцы (как в обучении N-Shot).

Авторы определяют слабое сходство между примером xᵢ и классом c следующим образом:

Где wᵏ_c — это веса, связанные с классом c (и их k). Для получения более подробной информации об общем выводе мы предлагаем прочитать упомянутую статью [1]. Однако важно отметить, что wᵏ_c и xᵢ нормализованы, поэтому умножение между ними соответствует косинусному расстоянию.

Помимо этой формулировки, они, наконец, определяют SoftTriple Loss как:

Эта формулировка делает реализацию в Tensorflow немного сложной, поэтому мы переформулируем уравнение для SoftTripleLoss следующим образом:

Где yᵢ — класс xᵢ, Class — набор всех классов и:

Мы также делаем некоторые дополнительные определения, которые облегчают кодирование потери:

  • Внутренние логиты: это в основном умножение между входами (xᵢ) и центрами (wᵏ_c). Мы можем представить набор входных данных в виде матрицы X (размеры N×D). Более того, поскольку для каждого из классов C существует K различных центров, и каждый центр имеет D размерностей, мы представляем множество центров в виде тензора W (с размерностями K× Д×С).
  • Внутренний softmax: соответствует Softmax, который участвует в расчете упрощенного сходства.
  • Внешний softmax: это Softmax, участвующий в расчете общего SofttripleLoss.

Код в Tensorflow

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#creating artificial data
sd = 0.5
center1, center2 = -2, 2 
c1 = np.vstack( [np.random.normal(center1, sd, 100), np.random.normal(center1, sd, 100)]).T
c2 = np.vstack( [np.random.normal(center1, sd, 100), np.random.normal(center2, sd, 100)]).T
c3 = np.vstack( [np.random.normal(center2, sd, 100), np.random.normal(center2, sd, 100)]).T
c4 = np.vstack( [np.random.normal(center2, sd, 100), np.random.normal(center1, sd, 100)]).T
X = np.vstack((c1,c2,c3,c4))
y1 = np.repeat([[1,0]], 100,0)
y2 = np.repeat([[0,1]], 100,0)
y3 = np.repeat([[1,0]], 100,0)
y4 = np.repeat([[0,1]], 100,0)
Y = np.vstack((y1, y2, y3, y4))
plt.scatter(X[:,0], X[:,1])
plt.grid()
#creating the graph
gamma = 0.1
delta = 0.01
lamb = 2
alpha = 1
epochs = 100
learning_rate= 0.05
X_p =  tf.placeholder(tf.float32, shape=(None, None), name='input_y')
Y_p = tf.placeholder(tf.float32, shape=(None,None), name = 'labels')
W = tf.Variable(tf.truncated_normal(shape= [2, 2, 2], mean=0, stddev=0.01))
X_n = tf.math.l2_normalize(X_p, axis=1) 
W_n = tf.math.l2_normalize(W, axis=1)
inner_logits = tf.einsum('ie,kec->ikc', X_n, W_n)
inner_SoftMax = tf.nn.softmax((1/gamma)*inner_logits, axis=1)
s =  lamb*( tf.reduce_sum( tf.multiply(inner_SoftMax, inner_logits), axis=1) - delta*Y_p)
outer_SoftMax = tf.nn.softmax(s)
soft_triple_loss = -tf.reduce_sum(tf.log(tf.reduce_sum(tf.multiply(outer_SoftMax, Y_p), axis=1)))
train_step = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(soft_triple_loss)
correct_pred = tf.equal(tf.argmax(outer_SoftMax, 1), tf.argmax(Y_p, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name='accuracy')
#running the graph
with tf.Session() as sess:
    # Initializing the variables
   
    sess.run(tf.global_variables_initializer())
    
    feed_dict = {
                 X_p : X,
                 Y_p : Y}
for e in range(epochs):
        _, stl, acc = sess.run([train_step, soft_triple_loss, accuracy], feed_dict = feed_dict)
        
        if e%10 == 0:
            print("Loss:", stl)
            print("Acc:", acc)
            
    [W_, correct_pred_ ]= sess.run([W,correct_pred], feed_dict = feed_dict)

использованная литература

[1] Ци Цянь и др. *SoftTriple Loss: глубокое метрическое обучение без TripletSampling*. 2019. Архив: 1909.05235