web-dev-qa-db-fra.com

Dimension de tenseur de remodelage de Pytorch

Par exemple, j'ai un vecteur 1D de dimension (5). Je voudrais le remodeler en matrice 2D (1,5).

Voici comment je le fais avec numpy

>>> import numpy as np
>>> a = np.array([1,2,3,4,5])
>>> a.shape
(5,)
>>> a = np.reshape(a, (1,5))
>>> a.shape
(1, 5)
>>> a
array([[1, 2, 3, 4, 5]])
>>> 

Mais comment puis-je faire cela avec Pytorch Tensor (et Variable). Je ne veux pas revenir à numpy et passer à nouveau à la variable Torch, car cela entraînera une perte d'informations sur la propagation.

Voici ce que j'ai à Pytorch

>>> import torch
>>> from torch.autograd import Variable
>>> a = torch.Tensor([1,2,3,4,5])
>>> a

 1
 2
 3
 4
 5
[torch.FloatTensor of size 5]

>>> a.size()
(5L,)
>>> a_var = variable(a)
>>> a_var = Variable(a)
>>> a_var.size()
(5L,)
.....do some calculation in forward function
>>> a_var.size()
(5L,)

Maintenant, je veux que sa taille soit (1, 5) . Comment puis-je redimensionner ou remodeler la dimension du tenseur de pytorque dans Variable sans information de degré de perte (parce que je vais intégrer un autre modèle avant de revenir en arrière) 

23
Haha TTpro

Utilisez torch.unsqueeze (input, dim, out = None)

>>> import torch
>>> a = torch.Tensor([1,2,3,4,5])
>>> a

 1
 2
 3
 4
 5
[torch.FloatTensor of size 5]

>>> a = a.unsqueeze(0)
>>> a

 1  2  3  4  5
[torch.FloatTensor of size 1x5]
16
Haha TTpro

vous pourriez utiliser

a.view(1,5)
Out: 

 1  2  3  4  5
[torch.FloatTensor of size 1x5]
13
Lelik

Pour la modification sur place du tenseur, vous devez absolument utiliser tensor.resize_ () :

In [23]: a = torch.Tensor([1, 2, 3, 4, 5])

In [24]: a.shape
Out[24]: torch.Size([5])


# tensor.resize_((`new_shape`))    
In [25]: a.resize_((1,5))
Out[25]: 

 1  2  3  4  5
[torch.FloatTensor of size 1x5]

In [26]: a.shape
Out[26]: torch.Size([1, 5])

Dans PyTorch, s'il y a un trait de soulignement à la fin d'une opération (comme tensor.resize_()), cette opération modifie le code tenseur d'origine avec in-place.


En outre, vous pouvez simplement utiliser np.newaxis dans un tenseur de torche pour augmenter la dimension. Voici un exemple:

In [34]: list_ = range(5)
In [35]: a = torch.Tensor(list_)
In [36]: a.shape
Out[36]: torch.Size([5])

In [37]: new_a = a[np.newaxis, :]
In [38]: new_a.shape
Out[38]: torch.Size([1, 5])
5
kmario23

ou vous pouvez utiliser ceci, le '-1' signifie que vous n'avez pas à spécifier le nombre d'éléments.

In [3]: a.view(1,-1)
Out[3]:

 1  2  3  4  5
[torch.FloatTensor of size 1x5]
4
Mou Cai

Cette question a déjà fait l'objet d'une réponse complète, mais je souhaite ajouter aux développeurs python moins expérimentés que vous pourriez trouver l'opérateur * utile en conjonction avec view().

Par exemple, si vous avez une taille de tenseur particulière à laquelle vous souhaitez qu'un autre tenseur de données se conforme, vous pouvez essayer:

img = Variable(tensor.randn(20,30,3)) # tensor with goal shape
flat_size = 20*30*3
X = Variable(tensor.randn(50, flat_size)) # data tensor

X = X.view(-1, *img.size()) # sweet maneuver
print(X.size()) # size is (50, 20, 30, 3)

Cela fonctionne aussi avec numpy shape:

img = np.random.randn(20,30,3)
flat_size = 20*30*3
X = Variable(tensor.randn(50, flat_size))
X = X.view(-1, *img.shape)
print(X.size()) # size is (50, 20, 30, 3)
2
saetch_g
import torch
>>>a = torch.Tensor([1,2,3,4,5])
>>>a.size()
torch.Size([5])
#use view to reshape

>>>b = a.view(1,a.shape[0])
>>>b
tensor([[1., 2., 3., 4., 5.]])
>>>b.size()
torch.Size([1, 5])
>>>b.type()
'torch.FloatTensor'
1
hindamosh

Supposons le code suivant:

import torch
import numpy as np
a = torch.tensor([1, 2, 3, 4, 5])

Les trois appels suivants ont exactement le même effet:

res_1 = a.unsqueeze(0)
res_2 = a.view(1, 5)
res_3 = a[np.newaxis,:]
res_1.shape == res_2.shape == res_3.shape == (1,5)  # Returns true

Notez que pour tous les tenseurs résultants, si vous modifiez les données qu'ils contiennent, vous modifiez également les données d'un, car ils ne possèdent pas de copie des données mais référencent les données d'origine dans un.

res_1[0,0] = 2
a[0] == res_1[0,0] == 2  # Returns true

L'autre façon de le faire serait d'utiliser l'opération resize_ in place:

a.shape == res_1.shape  # Returns false
a.reshape_((1, 5))
a.shape == res_1.shape # Returns true

Veillez à utiliser resize_ ou une autre opération sur place avec autograd. Voir l'analyse suivante: https://pytorch.org/docs/stable/notes/autograd.html#in-place-operations-with-autograd

0
Jadiel de Armas