tutorial instalar example español curso python memory pytorch torch tensor

python - instalar - pytorch tutorial



¿Cómo funciona el método de "vista" en PyTorch? (5)

¿Cuál es el significado del parámetro -1?

Puede leer -1 como número dinámico de parámetros o "cualquier cosa". Por eso solo puede haber un parámetro -1 en view() .

Si le pregunta a x.view(-1,1) esto generará la forma del tensor [anything, 1] dependiendo del número de elementos en x . Por ejemplo:

import torch x = torch.tensor([1, 2, 3, 4]) print(x,x.shape) print("...") print(x.view(-1,1), x.view(-1,1).shape) print(x.view(1,-1), x.view(1,-1).shape)

Saldrá:

tensor([1, 2, 3, 4]) torch.Size([4]) ... tensor([[1], [2], [3], [4]]) torch.Size([4, 1]) tensor([[1, 2, 3, 4]]) torch.Size([1, 4])

Estoy confundido sobre el método view() en el siguiente fragmento de código.

class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2,2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16*5*5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16*5*5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net()

Mi confusión es con respecto a la siguiente línea.

x = x.view(-1, 16*5*5)

¿Qué hace la función tensor.view() ? He visto su uso en muchos lugares, pero no puedo entender cómo interpreta sus parámetros.

¿Qué sucede si le doy valores negativos como parámetros a la función view() ? Por ejemplo, ¿qué sucede si llamo tensor_variable.view(1, 1, -1) ?

¿Alguien puede explicar el principio principal de la función view() con algunos ejemplos?


Hagamos algunos ejemplos, de más simple a más difícil.

  1. El método de view devuelve un tensor con los mismos datos que el self tensor (lo que significa que el tensor devuelto tiene el mismo número de elementos), pero con una forma diferente. Por ejemplo:

    a = torch.arange(1, 17) # a''s shape is (16,) a.view(4, 4) # output below 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [torch.FloatTensor of size 4x4] a.view(2, 2, 4) # output below (0 ,.,.) = 1 2 3 4 5 6 7 8 (1 ,.,.) = 9 10 11 12 13 14 15 16 [torch.FloatTensor of size 2x2x4]

  2. Suponiendo que -1 no es uno de los parámetros, cuando los multiplica, el resultado debe ser igual al número de elementos en el tensor. Si lo hace: a.view(3, 3) , generará un RuntimeError porque la forma (3 x 3) no es válida para la entrada con 16 elementos. En otras palabras: 3 x 3 no es igual a 16 sino a 9.

  3. Puede usar -1 como uno de los parámetros que pasa a la función, pero solo una vez. Todo lo que sucede es que el método hará los cálculos matemáticos sobre cómo llenar esa dimensión. Por ejemplo, a.view(2, -1, 4) es equivalente a a.view(2, 2, 4) . [16 / (2 x 4) = 2]

  4. Observe que el tensor devuelto comparte los mismos datos . Si realiza un cambio en la "vista", está cambiando los datos del tensor original:

    b = a.view(4, 4) b[0, 2] = 2 a[2] == 3.0 False

  5. Ahora, para un caso de uso más complejo. La documentación dice que cada nueva dimensión de vista debe ser un subespacio de una dimensión original, o solo abarcar d, d + 1, ..., d + k que satisfagan la siguiente condición similar a la contigüidad que para todo i = 0,. .., k - 1, zancada [i] = zancada [i + 1] x tamaño [i + 1] . De lo contrario, debe llamarse contiguous() antes de que se pueda ver el tensor. Por ejemplo:

    a = torch.rand(5, 4, 3, 2) # size (5, 4, 3, 2) a_t = a.permute(0, 2, 3, 1) # size (5, 3, 2, 4) # The commented line below will raise a RuntimeError, because one dimension # spans across two contiguous subspaces # a_t.view(-1, 4) # instead do: a_t.contiguous().view(-1, 4) # To see why the first one does not work and the second does, # compare a.stride() and a_t.stride() a.stride() # (24, 6, 2, 1) a_t.stride() # (24, 2, 1, 6)

    Observe que para a_t , stride [0]! = Stride [1] x size [1] desde 24! = 2 x 3


La función de vista está destinada a remodelar el tensor.

Digamos que tienes un tensor

import torch a = torch.range(1, 16)

a es un tensor que tiene 16 elementos del 1 al 16 (incluidos). Si desea remodelar este tensor para convertirlo en un tensor de 4 x 4 , puede usar

a = a.view(4, 4)

Ahora a será un tensor de 4 x 4 . Tenga en cuenta que después de la remodelación, el número total de elementos debe permanecer igual. Cambiar la forma del tensor a a un tensor de 3 x 5 no sería apropiado.

¿Cuál es el significado del parámetro -1?

Si hay alguna situación en la que no sabe cuántas filas desea pero está seguro del número de columnas, puede especificar esto con un -1. ( Tenga en cuenta que puede extender esto a tensores con más dimensiones. Solo uno de los valores del eje puede ser -1 ). Esta es una manera de decirle a la biblioteca: "dame un tensor que tenga tantas columnas y calcules el número apropiado de filas que es necesario para que esto suceda".

Esto se puede ver en el código de red neuronal que ha proporcionado anteriormente. Después de la línea x = self.pool(F.relu(self.conv2(x))) en la función de avance, tendrá un mapa de características de 16 profundidades. Tienes que aplanar esto para darle a la capa completamente conectada. Entonces le dice a pytorch que cambie la forma del tensor que obtuvo para tener un número específico de columnas y le dice que decida el número de filas por sí mismo.

Dibujando una similitud entre numpy y pytorch, la view es similar a la función de reshape de numpy.


Me di cuenta de que x.view(-1, 16 * 5 * 5) es equivalente a x.flatten(1) , donde el parámetro 1 indica que el proceso de aplanar comienza desde la primera dimensión (no aplanar la dimensión de ''muestra'') Como puede ver, el último uso es semánticamente más claro y más fácil de usar, por lo que prefiero flatten() .


weights.reshape(a, b) devolverá un nuevo tensor con los mismos datos que los pesos con tamaño (a, b) ya que en él copia los datos a otra parte de la memoria.

weights.resize_(a, b) devuelve el mismo tensor con una forma diferente. Sin embargo, si la nueva forma resulta en menos elementos que el tensor original, algunos elementos se eliminarán del tensor (pero no de la memoria). Si la nueva forma da como resultado más elementos que el tensor original, los nuevos elementos no se inicializarán en la memoria.

weights.view(a, b) devolverá un nuevo tensor con los mismos datos que los pesos con tamaño (a, b)