Мы представляем реализацию 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