web-dev-qa-db-fra.com

Quelle est la difference entre reshape et view in pytorch?

En numpy, nous utilisons ndarray.reshape() pour remodeler un tableau.

J'ai remarqué que dans pytorch, les gens utilisent torch.view(...) dans le même but, mais en même temps, il existe aussi un torch.reshape(...).

Je me demande donc quelles sont les différences entre eux et quand devrais-je utiliser l'un ou l'autre?

26
Lifu Huang

torch.view existe depuis longtemps. Il retournera un tenseur avec la nouvelle forme. Le tenseur renvoyé partagera les données sous-jacentes avec le tenseur d'origine. Voir la documentation ici .

D'autre part, il semble que torch.reshapea été introduit récemment dans la version 0.4 . Selon le document , cette méthode sera

Retourne un tenseur avec les mêmes données et le même nombre d'éléments que l'entrée, mais avec la forme spécifiée. Si possible, le tenseur renvoyé sera une vue de l’entrée. Sinon, ce sera une copie. Les entrées contiguës et les entrées compatibles peuvent être modifiées sans être copiées, mais vous ne devez pas dépendre du comportement de copie ou d'affichage.

Cela signifie que torch.reshape peut renvoyer une copie ou une vue du tenseur d'origine. Vous ne pouvez pas compter sur cela pour renvoyer une vue ou une copie. Selon le développeur:

si vous avez besoin d'une copie, utilisez clone () si vous avez besoin du même affichage d'utilisation du stockage (). La sémantique de reshape () veut qu'il puisse ou non partager le stockage et que vous ne le sachiez pas auparavant.

22
jdhao

Bien que torch.view et torch.reshape soient tous deux utilisés pour remodeler les tenseurs, voici les différences entre eux.

  1. Comme son nom l'indique, torch.view crée simplement un vue du tenseur d'origine. Le nouveau tenseur va toujours partager ses données avec le tenseur d'origine. Cela signifie que si vous modifiez le tenseur d'origine, le tenseur modifié sera modifié et inversement.
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. Pour s'assurer que le nouveau tenseur partage toujours ses données avec l'original, torch.view impose des contraintes de contiguïté sur la forme des deux tenseurs [ docs ]. Le plus souvent, ce n’est pas une préoccupation, mais parfois torch.view génère une erreur même si les formes des deux tenseurs sont compatibles. Voici un célèbre contre-exemple.
>>> z = torch.zeros(3, 2)
>>> y = z.t()
>>> y.size()
torch.Size([2, 3])
>>> y.view(6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: invalid argument 2: view size is not compatible with input tensor's
size and stride (at least one dimension spans across two contiguous subspaces).
Call .contiguous() before .view().
  1. torch.reshape n'impose aucune contrainte de contiguïté, mais ne garantit pas non plus le partage des données. Le nouveau tenseur peut être une vue du tenseur d'origine ou il peut s'agir d'un nouveau tenseur.
>>> z = torch.zeros(3, 2)
>>> y = z.reshape(6)
>>> x = z.t().reshape(6)
>>> z.fill_(1)
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])
>>> y
tensor([1., 1., 1., 1., 1., 1.])
>>> x
tensor([0., 0., 0., 0., 0., 0.])

TL; DR:
Si vous voulez seulement remodeler les tenseurs, utilisez torch.reshape. Si vous êtes également préoccupé par l'utilisation de la mémoire et que vous souhaitez vous assurer que les deux tenseurs partagent les mêmes données, utilisez torch.view.

1
nikhilweee