2017-03-14 1 views
1

Étant donné un tableau, x, de forme (2, n, m) et un ensemble d'indices [i, j]i , j < n, je cherche à obtenir une matrice de forme (2, m) où la première matrice est à l'index [0, i] et le second réseau est à l'index [1, j] . Ceci est un cas de test pour généraliser à un tableau de forme (b, n, m) et un ensemble d'index de longueur b.Vectorized Création d'un tableau 2D de matrice 3D Compte tenu tableau 1D des indices

Le choix évident pour cette opération est np.choose, mais cela agit différemment que prévu. Nous voulons appairer la ligne i du premier tableau avec la ligne j du second tableau. Cependant, lors de l'utilisation np.choose ([i, j], x), np.choose paires de la première colonne de la matrice avec index i avec la deuxième colonne de la matrice avec index j (qui peut être vu dans le code ci-dessous) pour obtenir un tableau de forme (n, m). Évidemment, cette tâche est facilement réalisée avec une boucle for, mais en raison du cas d'utilisation (dans Keras comme fonction personnalisée d'un tenseur, où l'itération est interdite), je ne peux pas le faire. Existe-t-il une manière vectorisée d'effectuer cette opération, en utilisant soit les fonctions Keras Backend, soit Numpy? Je suis actuellement en train d'utiliser "map" pour faire ceci, et je mettrai à jour avec ma propre réponse si je le découvre.

Voici un extrait de code montrant comment gère np.choose le (2, n, m) Tableau:

>>> import numpy as np 
>>> x = np.random.rand(2,4,2) 
>>> choices = [3,1] 
>>> np.choose(choices,x) 
    ValueError: invalid entry in choice array 
>>> np.choose([0,0],x) 
    #Returns an array with x[0,:,0] and x[0,:,1] in shape(4,2) 
+0

Avez-vous un code de boucle de travail? – Divakar

+0

@Divakar Oui, mais c'est pour la tâche globale que j'effectue (trouver la sortie de probabilité maximale pour le lot "b" contenant "n" sorties softmax séparées). C'est la dernière étape de la vectorisation de cette fonction. Dois-je fournir le code pour la fonction globale, également? Cela semblait hors de propos, mais je suppose que cela donne un peu plus de contexte à ce qui se passe ici. – AGentleRose

Répondre

1

IIUC, vous pouvez utiliser advanced indexing. Sur un exemple:

import numpy as np 
x = np.random.randint(0,10,(2,4,3)) 

x est:

[[[0 4 1] 
    [8 8 1] 
    [3 3 6] 
    [4 7 8]] 

[[7 1 2] 
    [5 9 9] 
    [0 4 0] 
    [7 8 3]]] 

Maintenant x[[0,1],[3,1],:] est:

[[4 7 8] 
[5 9 9]] 

Cela peut être étendu à un problème (b,m,n):

import numpy as np 
x = np.random.randint(0,10,(100,200,300)) 
choices= np.random.randint(0,200,(100)) 

def loop(): 
    res=np.empty((100,300),int) 
    for i in range(100): 
     res[i]=x[i,choices[i]] 
    return res  

Et certains tests de performance:

In [30]: %timeit loop() 
10000 loops, best of 3: 140 µs per loop 

In [31]: %timeit x[arange(100),choices,:] 
10000 loops, best of 3: 23.7 µs per loop 

Voici la méthode d'indexation est seulement 6 fois plus rapide qu'une boucle, parce que la tâche (extraction) ne peut pas tirer parti de l'alignement de la mémoire.

Enfin, vous pouvez améliorer la boucle avec la compilation juste à temps par loop2=numba.njit(loop).

In [32]: %timeit loop2() 
10000 loops, best of 3: 32 µs per loop 

qui montre que la méthode d'indexation est optimale.

+0

Ceci n'est pas vectorisé - si vous obtenez un tableau de forme aléatoire (b, 4,3), vous devrez parcourir la liste des indices (qui a la longueur b) pour utiliser cette méthode. De même, si vous essayez d'indexer x [0,1], le résultat ne devrait-il pas être [8,8,1], et ne devrait-il pas [3,1] vous donner une erreur hors limites? – AGentleRose

+0

Non, renvoie les tableaux indexés par [0,3 ,:] et [1,1 ,:]. x [a, b ,:] renvoie [x [a0, b0,:], x [a1, b1 ,:], etc.] –

+0

D'accord, cela a du sens. Cependant, si on vous donne le tableau des «choix» des indices, vous ne pouvez pas simplement appeler x [choix ,:]. Pour que votre code fonctionne, vous devez parcourir les "choix" en appelant x [choix [0], choix [1] ,:] (dans le cas où b = 2). Nous devons éviter l'itération et avoir une solution générale où b est arbitraire. – AGentleRose