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)
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]
vous pourriez utiliser
a.view(1,5)
Out:
1 2 3 4 5
[torch.FloatTensor of size 1x5]
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])
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]
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)
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'
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