¿Cuál es la diferencia entre remodelar y ver en pytorch?

83

En numpy, usamos ndarray.reshape()para remodelar una matriz.

Noté que en pytorch, la gente usa torch.view(...)para el mismo propósito, pero al mismo tiempo, también existe un torch.reshape(...)archivo.

Entonces, me pregunto cuáles son las diferencias entre ellos y cuándo debería usar alguno de ellos.

Lifu Huang
fuente

Respuestas:

89

torch.viewha existido durante mucho tiempo. Devolverá un tensor con la nueva forma. El tensor devuelto compartirá los datos subyacentes con el tensor original. Consulte la documentación aquí .

Por otro lado, parece que torch.reshape se ha introducido recientemente en la versión 0.4 . Según el documento , este método

Devuelve un tensor con los mismos datos y número de elementos que la entrada, pero con la forma especificada. Cuando sea posible, el tensor devuelto será una vista de entrada. De lo contrario, será una copia. Las entradas contiguas y las entradas con pasos compatibles se pueden remodelar sin copiar, pero no debe depender del comportamiento de copia frente a visualización.

Significa que torch.reshapepuede devolver una copia o una vista del tensor original. No puedes contar con eso para devolver una vista o una copia. Según el desarrollador:

si necesita una copia, use clone () si necesita el mismo almacenamiento, use view (). La semántica de reshape () es que puede o no compartir el almacenamiento y usted no lo sabe de antemano.

Otra diferencia es que reshape()puede operar tanto en tensor contiguo como no contiguo mientras view()que solo puede operar en tensor contiguo. Vea también aquí el significado de contiguous.

jdhao
fuente
28
Quizás sea útil enfatizar que torch.view solo puede operar con tensores contiguos, mientras que torch.reshape puede operar en ambos.
p13rr0m
6
@pierrom contiguo aquí se refiere a tensores que se almacenan en la memoria contigua o algo más?
gokul_uf
3
@gokul_uf Sí, puede echar un vistazo a la respuesta escrita aquí: stackoverflow.com/questions/48915810/pytorch-contiguous
MBT
¿Qué significa la frase "una vista de un tensor" en pytorch?
Charlie Parker
42

Aunque ambos torch.viewy torch.reshapese utilizan para remodelar tensores, aquí están las diferencias entre ellos.

  1. Como sugiere el nombre, torch.viewsimplemente crea una vista del tensor original. El nuevo tensor siempre compartirá sus datos con el tensor original. Esto significa que si cambia el tensor original, el tensor remodelado cambiará y viceversa.
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. Para asegurar que el nuevo tensor siempre comparta sus datos con el original, torch.viewimpone algunas restricciones de contigüidad en las formas de los dos tensores [ docs ]. La mayoría de las veces, esto no es un problema, pero a veces torch.viewarroja un error incluso si las formas de los dos tensores son compatibles. He aquí un famoso contraejemplo.
>>> 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.reshapeno impone restricciones de contigüidad, pero tampoco garantiza el intercambio de datos. El nuevo tensor puede ser una vista del tensor original o puede ser un nuevo tensor por completo.
>>> 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 solo desea remodelar tensores, use torch.reshape. Si también le preocupa el uso de la memoria y desea asegurarse de que los dos tensores compartan los mismos datos, utilice torch.view.

nikhilweee
fuente
Tal vez sea solo yo, pero estaba confundido al pensar que la contigüidad es el factor decisivo entre cuándo la remodelación comparte datos y cuándo no. Según mis propios experimentos, parece que este no es el caso. (Tu xy ysuperior son ambos contiguos). ¿Quizás esto pueda aclararse? ¿Quizás un comentario sobre cuándo la remodelación hace y no copia sería útil?
RMurphy
6

Tensor.reshape()es más robusto. Funcionará en cualquier tensor, mientras que Tensor.view()solo funcionará en el tensor tdonde t.is_contiguous()==True.

Explicar sobre no contiguo y contiguo es otra historia de tiempo, pero siempre puede hacer que el tensor sea tcontiguo si llama t.contiguous()y luego puede llamar view()sin el error.

prosti
fuente