• 1000 *
def loss_desc_triplet(y_true, y_pred):
"""Triplet loss.
"""
d1 = y_pred[:,0:128]
d2 = y_pred[:,128:256]
d3 = y_pred[:,256:384]
...
Код без жесткого отрицательного анализа выглядит так:
if mine_negative == False:
d_pos = tf.sqrt(tf.reduce_sum(tf.square(d1 - d2), axis=1))
d_neg = tf.sqrt(tf.reduce_sum(tf.square(d1 - d3), axis=1))
if loss_type == "triplet":
if squared_loss:
return tf.nn.relu(tf.square(d_pos) - tf.square(d_neg) + margin)
else:
return tf.nn.relu(d_pos - d_neg + margin)
Теперь моя идея состоит в том, чтобы вычислить евклидово расстояние от каждого отдельного якоря до каждого отдельного положительного дескриптора в пакете, а затем проверьте, меньше ли расстояние между исходной привязкой и любым из других положительных дескрипторов, чем расстояние между исходной привязкой и исходным негативом. В этом случае я хочу использовать положительное значение другого триплета для формирования нового триплета.
Вот мой код, который я придумал:
def hard_negative_mining_ec(anchor, positive, batch_size):
all_distances = []
for i in range(batch_size):
distances = []
for ii in range(batch_size):
if i == ii:
continue
current_dist = tf.sqrt(tf.reduce_sum(tf.square(anchor[i,:] - positive[ii,:])))
distances.append(current_dist)
current_desc_pairs = tf.stack(distances)
all_distances.append(tf.keras.backend.min(current_desc_pairs))
return tf.stack(all_distances)
и новую функцию потерь:
elif mine_negative == True:
d_pos = tf.sqrt(tf.reduce_sum(tf.square(d1 - d2), axis=1))
d_neg = tf.sqrt(tf.reduce_sum(tf.square(d1 - d3), axis=1))
d_hnm_neg = hard_negative_mining_ec(d1, d2, batch_size=batch_size)
d_opti_neg = tf.math.minimum(d_neg, d_hnm_neg)
if loss_type == "triplet":
if squared_loss:
return tf.reduce_mean(tf.nn.relu(tf.square(d_pos) - tf.square(d_opti_neg) + margin))
else:
return tf.reduce_mean(tf.nn.relu(d_pos - d_opti_neg + margin))
Однако теперь мой скрипт Tensorflow больше не работает. Моя системная память просто заполнена, но фактическое обучение не начинается.
Что мне здесь не хватает?
РЕДАКТИРОВАТЬ:
Я обновил свой код:
import numpy as np
np.set_printoptions(suppress=True)
import tensorflow as tf
gpus = tf.config.experimental.list_physical_devices('GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
anchor = (np.random.random((10,10))*10).astype(int).astype(np.float32)
positive = (np.random.random((10,10))*10).astype(int).astype(np.float32)
anchor_tf = tf.convert_to_tensor(anchor)
positive_tf = tf.convert_to_tensor(positive)
def hard_negative_mining_ec(anchor, positive):
x_r = tf.repeat(anchor, repeats=tf.shape(positive)[0])
y_r = tf.repeat(positive, repeats=tf.shape(anchor)[0])
x_r = tf.transpose(tf.reshape(x_r, [tf.shape(positive)[0],
tf.shape(positive)[0],tf.shape(positive)[0]]), [0,2,1])
y_r = tf.transpose(tf.reshape(y_r, [tf.shape(anchor)[0],
tf.shape(anchor)[0],tf.shape(anchor)[0]]), [2,0,1])
desc_dist = tf.sqrt(tf.reduce_sum(tf.square(x_r - y_r), axis=2))
eye_tf = tf.eye(tf.shape(desc_dist)[1])*1000
d_pos = desc_dist+eye_tf
print(d_pos)
best = tf.keras.backend.min(d_pos, axis=1)
print(best)
return best
hard_negative_mining_ec(anchor_tf, positive_tf)
Теоретически это работает так, как задумано, и у меня нет проблемы, упомянутой выше. Однако моя сеть больше не обучается должным образом, а точность снижается.