1
votes

Découpage explicite dans une dimension particulière

J'ai un tenseur 3D x (par exemple 4x4x100). Je veux en obtenir un sous-ensemble en choisissant explicitement des éléments dans la dernière dimension. Cela aurait été facile si j'avais choisi les mêmes éléments dans la dernière dimension (par exemple x [:,:, 30:50] mais je veux cibler différents éléments à travers cette dimension en utilisant le tenseur 2D index qui spécifie l'idx dans la troisième dimension. Existe-t-il un moyen simple de le faire dans numpy?

Un exemple 2D plus simple:

[[2,3],[40,50]]

Disons Je veux saisir deux éléments dans la troisième dimension de x à partir de points spécifiés par indices . Donc, la sortie souhaitée est:

x = [[1,2,3,4,5,6],[10,20,30,40,50,60]]
indices = [1,3]

Mise à jour: je pense que je pourrais utiliser une combinaison de take () et ravel_multi_index () mais certaines des plates-formes qui sont inspirées par numpy (comme PyTorch) don ' t semble avoir ravel_multi_index donc je cherche des solutions alternatives


8 commentaires

Que contiennent les indices ? Exemple de données?


Non, il contient des indices que je souhaite prendre de x le long de la troisième dimension


Pouvez-vous ajouter des exemples de données de cas (entrée et sortie attendue)?


Pourquoi indices est-il un tenseur 2D? Ne devrait-il pas s'agir d'un tenseur 1D, par exemple [0, 1, 10, 33, 50, ...] ?


J'ai ajouté un exemple où je ne suis même pas en train de trancher et je veux simplement extraire ces éléments. Cela rend-il les choses plus claires?


Utilisez un échantillon de données représentatif minimal. Donc, quelque chose qui doit être tranché.


assez juste - fait


si indices est censé donner la sortie dans la nième dimension le long de ces indéces, la sortie ne serait pas [[2,4], [20,40]]


4 Réponses :


0
votes

le long de l'axe 3D:

x = [x[:,i,index] for i,index in enumerate(indices)]
x = torch.stack(x,dim=1)

en énumérant, vous obtenez l'index de l'axe et l'index à partir duquel vous souhaitez commencer le découpage en un.

étroit vous donne une longue tranche de longueur sans copie à partir d'un index de départ start le long d'un certain axe

vous avez dit que vous vouliez:

dim = 2
start = index
length = 2

alors vous devez simplement les empiler tenseurs de retour à une seule 3D.

C'est la chose la moins intensive en travail à laquelle je puisse penser pour pytorch.

MODIFIER

si vous voulez juste différents indices le long de différents axes et que indices est un tenseur 2D, vous pouvez faire:

x = [x[:,i].narrow(2,index,2) for i,index in enumerate(indices)]
x = torch.stack(x,dim=1)

Vous devriez vraiment avoir donné un exemple de travail correct , ce qui rend les choses inutilement déroutantes.


3 commentaires

Cela fonctionne si vous voulez les mêmes indices pour chaque a, b dans x [a, b ,:] mais je veux avoir des indices différents pour chaque élément dans les deux premiers dimensions


que diriez-vous de cette solution, vous n'avez pas lu que vous vouliez 2 valeurs à partir de index


il y a une modification si vous avez déjà vu la réponse, peut-être que cette solution est plus appropriée?



0
votes

Voici comment le faire dans numpy, maintenant un indice sur la torche, cependant.

Ce qui suit choisit une tranche de longueur n le long de la troisième dimension à partir des points idx en fonction des deux autres dimensions:

< pré> XXX


0 commentaires

2
votes

Itérer sur idx et collecter les tranches n'est pas une mauvaise option si le nombre de «lignes» n'est pas trop grand (et la taille des tailles est relativement grande).

In [65]: np.ravel_multi_index((np.arange(2)[:,None],idxs),x.shape)              
Out[65]: 
array([[ 1,  2],
       [ 9, 10]])
In [66]: x.flat[_]                                                              
Out[66]: 
array([[ 2,  3],
       [40, 50]])
In [67]: np.arange(2)[:,None]*x.shape[1]+idxs                                   
Out[67]: 
array([[ 1,  2],
       [ 9, 10]])

Rejoindre les tranches comme celle-ci ne fonctionne que si elles sont toutes de la même taille.

Une alternative est de rassembler les indices dans un tableau et de faire une indexation.

Par exemple avec une itération similaire:

In [58]: idxs = np.array(idx)[:,None]+np.arange(2)                              
In [59]: idxs                                                                   
Out[59]: 
array([[1, 2],
       [3, 4]])
In [60]: x[np.arange(2)[:,None], idxs]                                          
Out[60]: 
array([[ 2,  3],
       [40, 50]])

Mais l'ajout diffusé peut être meilleur:

idxs = np.array([np.arange(i,i+2) for i in idx])

ravel_multi_index n'est pas difficile à reproduire (si vous n'avez pas besoin de découpage, etc.):

In [55]: x = np.array([[1,2,3,4,5,6],[10,20,30,40,50,60]])                      
In [56]: idx = [1,3]                                                            
In [57]: np.array([x[j,i:i+2] for j,i in enumerate(idx)])                       
Out[57]: 
array([[ 2,  3],
       [40, 50]])


0 commentaires

0
votes

Je suis venu avec ci-dessous en utilisant la diffusion:

x = np.array([[1,2,3,4,5,6,7,8,9,10],[10,20,30,40,50,60,70,80,90,100]]) 
i = np.array([1,5])
N = 2 # number of elements I want to extract along each dimension. Starting points specified in i

r = np.arange(x.shape[-1])
r = np.broadcast_to(r, x.shape)

ii = i[:, np.newaxis]
ii = np.broadcast_to(ii, x.shape)

mask = np.logical_and(r-ii>=0, r-ii<=N) 

output = x[mask].reshape(2,3)

Est-ce que cela vous convient?


0 commentaires