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
4 Réponses :
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.
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?
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 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]])
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?
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 dimensionPouvez-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]]