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(...)
.
Entonces, me pregunto cuáles son las diferencias entre ellos y cuándo debo usar cualquiera de ellos.
torch.view
existe desde hace 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 permitirá
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.reshape
puede devolver una copia o una vista del tensor original. No puede 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 remodelar() es que puede o no compartir el almacenamiento y no lo sabe de antemano.
Otra diferencia es que reshape()
puede operar tanto en tensores contiguos como no contiguos, mientras que view()
solo puede operar en tensores contiguos. También vea aquí sobre el significado de contiguous
.
Aunque tanto torch.view
como torch.reshape
se usan para remodelar tensores, estas son las diferencias entre ellos.
torch.view
simplemente 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.]])
torch.view
impone algunas restricciones de contigüidad en las formas de los dos tensores [ docs ]. La mayoría de las veces esto no es una preocupación, pero a veces torch.view
arroja un error incluso si las formas de los dos tensores son compatibles. He aquí un famoso contraejemplo. >>> z = torch.zeros(3, 2) >>> y = zt() >>> 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().
torch.reshape
no impone ninguna restricción de contigüidad, pero tampoco garantiza el intercambio de datos. El nuevo tensor puede ser una vista del tensor original o puede ser un tensor completamente nuevo. >>> z = torch.zeros(3, 2) >>> y = z.reshape(6) >>> x = zt().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;RD:
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, use torch.view
.
Tensor.reshape()
es más robusto. Funcionará en cualquier tensor, mientras que Tensor.view()
solo funciona en el tensor t
donde t.is_contiguous()==True
.
Explicar sobre no contiguos y contiguos es otra historia, pero siempre puede hacer que el tensor t
sea contiguo si llama a t.contiguous()
y luego puede llamar a view()
sin el error.