Calculer les paires de distance en un lot, sans les reproduire tenseur dans Tensorflow?
Je veux calculer les combinaisons carré de la distance d'un lot de fonctionnalité dans Tensorflow. J'ai une simple mise en œuvre à l'aide de + et * les opérations par
carrelage du tenseur d'origine :
def pairwise_l2_norm2(x, y, scope=None):
with tf.op_scope([x, y], scope, 'pairwise_l2_norm2'):
size_x = tf.shape(x)[0]
size_y = tf.shape(y)[0]
xx = tf.expand_dims(x, -1)
xx = tf.tile(xx, tf.pack([1, 1, size_y]))
yy = tf.expand_dims(y, -1)
yy = tf.tile(yy, tf.pack([1, 1, size_x]))
yy = tf.transpose(yy, perm=[2, 1, 0])
diff = tf.sub(xx, yy)
square_diff = tf.square(diff)
square_dist = tf.reduce_sum(square_diff, 1)
return square_dist
Cette fonction prend en entrée deux matrices de taille (m,d) et (n,d), et de calculer la distance au carré entre chaque vecteur ligne. La sortie est une matrice de taille (m,n) avec élément " d_ij = dist(x_i, y_j)'.
Le problème est que j'ai un gros lot et de la haute dim fonctions "m, n, d' reproduisant le tenseur de consommer beaucoup de mémoire.
Je suis à la recherche d'une autre façon de mettre en œuvre ce sans augmentation de l'utilisation de la mémoire et juste que le magasin de la distance finale tenseur. Sorte de double boucle du tenseur d'origine.
- Il n'est pas évident que votre code est en train de faire 'par paires distance d'un lot de la fonctionnalité". Pouvez-vous préciser la fonction que vous voulez le faire de façon plus formelle? Aussi, avez-vous considéré tf.squared_difference
- - Je mettre à jour la question de l'expliquer. Si vous mettez un lot de fonctionnalités que l'entrée de cette fonction, il faut calculer la distance entre ses lignes.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser de l'algèbre linéaire pour le transformer en matrice de la fpo. Notez que ce que vous avez besoin de la matrice
D
oùa[i]
est lei
ème ligne de la matrice d'origine etVous pouvez réécrire en
Où
r[i]
est le carré de la norme dei
ième ligne de la matrice d'origine.Dans un système qui prend en charge la norme les règles de la radiodiffusion vous pouvez traiter
r
comme un vecteur colonne et écrireD
commeDans TensorFlow vous pouvez écrire ce que
résultat
tf.expand_dims
à exploiter la radiodiffusion et ensuite utilisertf.squared_difference
?transpose
dans ma solution qui est coûteux. Si vous postez une solution comme une autre réponse que j'ai pu comparer la performance sur la grande matricetf.matmul
a des arguments pour la transposition de tableaux à la volée (transpose_a
ettranspose_b
).À l'aide de
squared_difference
:Une chose que j'ai remarqué, c'est que cette solution à l'aide de
tf.squared_difference
me donne de mémoire (OOM) pour de très grands vecteurs, alors que l'approche par @YaroslavBulatov ne l'est pas. Donc, je pense que la décomposition de l'opération génère une plus petite empreinte mémoire (qui je pensaissquared_difference
serait mieux gérer sous le capot).Ici est un plus générale de la solution de deux tenseurs de coordonnées
A
etB
:Noter que c'est le carré de la distance. Si vous voulez changer la distance Euclidienne, effectuer une
tf.sqrt
sur le résultat. Si vous voulez le faire, n'oubliez pas d'ajouter une petite constante pour compenser la virgule flottante instabilités:dist = tf.sqrt(squared_dist(A, B) + 1e-6)
.Si vous voulez calculer les autres méthode , puis changer l'ordre de la tf modules.