Deje que tenga una dimensión de tensor de (B, N ^ 2, C) y la remodelo en (B, C, N, N).

Creo que tengo dos opciones a continuación.

A = torch.rand(5, 100, 20) # Original Tensor

# First Method
B = torch.transpose(2, 1)
B = B.view(5, 20, 10, 10)

# Second Method
C = A.view(5, 20, 10, 10)

Ambos métodos funcionan, pero los resultados son ligeramente diferentes y no puedo captar la diferencia entre ellos.

Gracias

0
Suho Cho 5 oct. 2021 a las 10:29

2 respuestas

La mejor respuesta

La diferencia entre B y C es que ha usado torch.transpose lo que significa que ha intercambiado dos ejes, esto significa que ha cambiado el diseño de la memoria. La vista al final es solo una interfaz agradable para que acceda a sus datos, pero no tiene ningún efecto sobre los datos subyacentes de su tensor. Todo se reduce a un búfer de datos de memoria contiguo.

Si toma un ejemplo más pequeño, algo que podemos comprender más fácilmente:

>>> A = torch.rand(1, 4, 3)
tensor([[[0.2656, 0.5920, 0.3774],
         [0.8447, 0.5984, 0.0614],
         [0.5160, 0.8048, 0.6260],
         [0.1644, 0.3144, 0.1040]]])

Aquí, el intercambio de axis=1 y axis=2 se reduce a una transposición por lotes (en términos matemáticos):

>>> B = A.transpose(2, 1)
tensor([[[0.4543, 0.7447, 0.7814, 0.3444],
         [0.9766, 0.2732, 0.4766, 0.0387],
         [0.0123, 0.7260, 0.8939, 0.8581]]])

En términos de distribución de memoria, A tiene la siguiente distribución de memoria:

>>> A.flatten()
tensor([0.4543, 0.9766, 0.0123, 0.7447, 0.2732, 0.7260, 0.7814, 0.4766, 0.8939,
        0.3444, 0.0387, 0.8581])

Mientras que B tiene un diseño diferente. Por diseño me refiero a la disposición de la memoria, no me refiero a su forma , que es irrelevante:

>>> B.flatten()
tensor([0.4543, 0.7447, 0.7814, 0.3444, 0.9766, 0.2732, 0.4766, 0.0387, 0.0123,
        0.7260, 0.8939, 0.8581])

Como dije, remodelar es decir, construir una vista sobre un tensor no cambia su diseño de memoria, es un nivel de abstracción para manipular mejor los tensores.

Entonces, al final, sí, terminas con dos resultados diferentes: C comparte los mismos datos que A, mientras que B es una copia y tiene un diseño de memoria diferente.

1
Ivan 5 oct. 2021 a las 08:00

¡Transponer / permutar y ver / remodelar NO son lo mismo!
reshape y view solo afecta al shape de un tensor, pero no cambia el orden subyacente de los elementos.
Por el contrario, transpose y < a href = "https://pytorch.org/docs/stable/generated/torch.Tensor.permute.html#torch.Tensor.permute" rel = "nofollow noreferrer"> permute cambiar el orden subyacente de elementos en el tensor. Consulte esta respuesta y esta one para obtener más detalles.

A continuación, se muestra un ejemplo, con B=1, N=3 y C=2, el primer canal tiene números pares 0..16 y el segundo canal tiene números impares 1..17:

A = torch.arange(2*9).view(1,9,2)
tensor([[[ 0,  1],
         [ 2,  3],
         [ 4,  5],
         [ 6,  7],
         [ 8,  9],
         [10, 11],
         [12, 13],
         [14, 15],
         [16, 17]]])

Si transpone correctamente y luego cambia la forma, obtiene la división correcta en canales pares e impares:

A.transpose(1,2).view(1,2,3,3)
tensor([[[[ 0,  2,  4],
          [ 6,  8, 10],
          [12, 14, 16]],

         [[ 1,  3,  5],
          [ 7,  9, 11],
          [13, 15, 17]]]])

Sin embargo, si solo cambia la forma (es decir, usando view o reshape), "mezcla" incorrectamente los valores de los dos canales:

A.view(1,2,3,3)
tensor([[[[ 0,  1,  2],
          [ 3,  4,  5],
          [ 6,  7,  8]],

         [[ 9, 10, 11],
          [12, 13, 14],
          [15, 16, 17]]]])

1
Shai 5 oct. 2021 a las 07:53