Je veux comparer les valeurs prédites yp
de mon réseau de neurones de manière paire, et j'utilisais donc (de nouveau dans mon ancienne implémentation numpy):
idx = np.repeat(np.arange(len(yp)), len(yp))
jdx = np.tile(np.arange(len(yp)), len(yp))
s = yp[[idx]] - yp[[jdx]]
Cela crée essentiellement un maillage d'indexation que j'utilise ensuite. idx=[0,0,0,1,1,1,...]
tant que jdx=[0,1,2,0,1,2...]
. Je ne sais pas s'il y a une manière plus simple de le faire ...
Quoi qu'il en soit, TensorFlow a une tf.tile()
, mais il semble manquer de tf.repeat()
.
idx = np.repeat(np.arange(n), n)
v2 = v[idx]
Et je reçois l'erreur:
TypeError: Bad slice index [ 0 0 0 ..., 215 215 215] of type <type 'numpy.ndarray'>
De même, l’utilisation d’une constante TensorFlow pour l’indexation ne fonctionne pas:
idx = tf.constant(np.repeat(np.arange(n), n))
v2 = v[idx]
-
TypeError: Bad slice index Tensor("Const:0", shape=TensorShape([Dimension(46656)]), dtype=int64) of type <class 'tensorflow.python.framework.ops.Tensor'>
L'idée est de convertir mon RankNet implémentation en TensorFlow.
Vous pouvez obtenir l’effet de np.repeat()
en utilisant une combinaison de tf.tile()
et tf.reshape()
:
idx = tf.range(len(yp))
idx = tf.reshape(idx, [-1, 1]) # Convert to a len(yp) x 1 matrix.
idx = tf.tile(idx, [1, len(yp)]) # Create multiple columns.
idx = tf.reshape(idx, [-1]) # Convert back to a vector.
Vous pouvez simplement calculer jdx
en utilisant tf.tile()
:
jdx = tf.range(len(yp))
jdx = tf.tile(jdx, [len(yp)])
Pour l'indexation, vous pouvez essayer d'utiliser tf.gather()
pour extraire des tranches non contiguës du tenseur yp
:
s = tf.gather(yp, idx) - tf.gather(yp, jdx)
Il semble que votre question soit si populaire que les gens référez-la sur TF tracker . Malheureusement, la même fonction n’est pas encore mise en œuvre dans TF.
Vous pouvez le mettre en œuvre en combinant tf.tile , tf.reshape , tf.squeeze . Voici un moyen de convertir des exemples de np.repeat :
import numpy as np
import tensorflow as tf
x = [[1,2],[3,4]]
print np.repeat(3, 4)
print np.repeat(x, 2)
print np.repeat(x, 3, axis=1)
x = tf.constant([[1,2],[3,4]])
with tf.Session() as sess:
print sess.run(tf.tile([3], [4]))
print sess.run(tf.squeeze(tf.reshape(tf.tile(tf.reshape(x, (-1, 1)), (1, 2)), (1, -1))))
print sess.run(tf.reshape(tf.tile(tf.reshape(x, (-1, 1)), (1, 3)), (2, -1)))
Dans le dernier cas où les répétitions sont différentes pour chaque élément, vous aurez probablement besoin de boucles .
Juste pour les tenseurs 1-D, j'ai fait cette fonction
def tf_repeat(y,repeat_num)
return tf.reshape(tf.tile(tf.expand_dims(y,axis=-1),[1,repeat_num]),[-1])
import numpy as np
import tensorflow as tf
import itertools
x = np.arange(6).reshape(3,2)
x = tf.convert_to_tensor(x)
N = 3 # number of repetition
K = x.shape[0] # for here 3
order = list(range(0, N*K, K))
order = [[x+i for x in order] for i in range(K)]
order = list(itertools.chain.from_iterable(order))
x_rep = tf.gather(tf.tile(x, [N, 1]), order)
Résultats de:
[0, 1],
[2, 3],
[4, 5]]
À:
[[0, 1],
[0, 1],
[0, 1],
[2, 3],
[2, 3],
[2, 3],
[4, 5],
[4, 5],
[4, 5]]
Si tu veux:
[[0, 1],
[2, 3],
[4, 5],
[0, 1],
[2, 3],
[4, 5],
[0, 1],
[2, 3],
[4, 5]]
Utilisez simplement tf.tile(x, [N, 1])
Juste au cas où quelqu'un serait intéressé par une méthode 2D pour copier les matrices. Je pense que cela pourrait fonctionner:
TF_obj = tf.zeros([128, 128])
tf.tile(tf.expand_dims(TF_obj, 2), [1, 1, 2])
Bien que de nombreuses solutions simples et efficaces aient été proposées, elles semblent toutes reposer sur la production de l'ensemble d'indices à partir de zéro à chaque itération.
Bien que le coût de production de ces nœuds ne soit généralement pas significatif au cours de la formation, il peut s'avérer important si vous utilisez votre modèle pour l'inférence.
La répétition de tf.range (comme dans votre exemple) a été soulevée à quelques reprises. J'ai donc créé le créateur de fonctions suivant. Etant donné le nombre maximum de fois où quelque chose sera répété et le nombre maximum de choses qui devront être répétées, il retourne une fonction qui produit les mêmes valeurs que np.repeat(np.arange(len(multiples)), multiples)
.
import tensorflow as tf
import numpy as np
def numpy_style_repeat_1d_creator(max_multiple=100, max_to_repeat=10000):
board_num_lookup_ary = np.repeat(
np.arange(max_to_repeat),
np.full([max_to_repeat], max_multiple))
board_num_lookup_ary = board_num_lookup_ary.reshape(max_to_repeat, max_multiple)
def fn_to_return(multiples):
board_num_lookup_tensor = tf.constant(board_num_lookup_ary, dtype=tf.int32)
casted_multiples = tf.cast(multiples, dtype=tf.int32)
padded_multiples = tf.pad(
casted_multiples,
[[0, max_to_repeat - tf.shape(multiples)[0]]])
return tf.boolean_mask(
board_num_lookup_tensor,
tf.sequence_mask(padded_multiples, maxlen=max_multiple))
return fn_to_return
#Here's an example of how it can be used
with tf.Session() as sess:
repeater = numpy_style_repeat_1d_creator(5,4)
multiples = tf.constant([4,1,3])
repeated_values = repeater(multiples)
print(sess.run(repeated_values))
L'idée générale est de stocker un tenseur répété puis de le masquer, mais il peut être utile de le voir visuellement (c'est pour l'exemple donné ci-dessus):
In the example above the following Tensor is produced:
[[0,0,0,0,0],
[1,1,1,1,1],
[2,2,2,2,2],
[3,3,3,3,3]]
For multiples [4,1,3] it will collect the non-X values:
[[0,0,0,0,X],
[1,X,X,X,X],
[2,2,2,X,X],
[X,X,X,X,X]]
resulting in:
[0,0,0,0,1,2,2,2]
tl; dr: pour éviter de produire les indices à chaque fois (peut être coûteux), répétez tout avant de masquer ce tenseur à chaque fois
Vous pouvez simuler tf.repeat
manquant en tf.stack
avec la valeur elle-même:
value = np.arange(len(yp)) # what to repeat
repeat_count = len(yp) # how many times
repeated = tf.stack ([value for i in range(repeat_count)], axis=1)
Je conseille de ne l'utiliser que sur de petites répétitions.