Programing

PyTorch에서 "보기"방법은 어떻게 작동합니까?

lottogame 2020. 6. 24. 07:56
반응형

PyTorch에서 "보기"방법은 어떻게 작동합니까?


view()다음 코드 스 니펫에서 방법 대해 혼란 스럽습니다 .

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()

내 혼란은 다음 줄에 관한 것입니다.

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

tensor.view()기능은 무엇을 합니까? 여러 곳에서 사용법을 보았지만 매개 변수를 해석하는 방법을 이해할 수 없습니다.

view()함수에 매개 변수로 음수 값을 지정하면 어떻게됩니까 ? 예를 들어, 전화하면 어떻게됩니까 tensor_variable.view(1, 1, -1)?

누구든지 view()몇 가지 예를 들어 주요 기능 원리를 설명 할 수 있습니까 ?


뷰 기능은 텐서를 재 형성하기위한 것입니다.

텐서가 있다고 해

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

a1에서 16 (포함)까지 16 개의 요소를 가진 텐서입니다. 당신이 그것을 만들기 위해이 텐서 모양을 변경하려면 4 x 4텐서 당신은 사용할 수 있습니다

a = a.view(4, 4)

이제 텐서 a가 될 것 4 x 4입니다. 모양을 변경 한 후에는 총 요소 수를 동일하게 유지해야합니다. 텐서 a텐서 바꾸는 3 x 5것은 적절하지 않습니다.

매개 변수 -1의 의미는 무엇입니까?

원하는 행 수를 모르지만 열 수를 확신하는 상황이있는 경우 -1로이를 지정할 수 있습니다. ( 이를 더 많은 치수의 텐서로 확장 할 수 있습니다. 축 값 중 하나만 -1이 될 수 있습니다 ). 이것은 라이브러리에 다음과 같은 방법으로 "열이 많은 텐서 (tensor)를 제공하고이를 수행하는 데 필요한 적절한 수의 행을 계산합니다"라고 말합니다.

이것은 위에서 지정한 신경망 코드에서 볼 수 있습니다. x = self.pool(F.relu(self.conv2(x)))정방향 기능 의 선 뒤에 16 개의 깊이 피처 맵이 있습니다. 완전히 연결된 레이어에 제공하려면 이것을 평평하게 만들어야합니다. 따라서 pytorch에게 얻은 텐서를 재구성하여 특정 수의 열을 가지도록하고 행 수를 결정하도록 지시하십시오.

numpy와 pytorch 사이의 유사성을 그리는 것은 viewnumpy의 변형 기능 과 유사 합니다.


더 간단한 것부터 더 어려운 것까지 몇 가지 예를 들어 봅시다.

  1. view메서드는 텐서와 동일한 데이터를 가진 self텐서를 반환합니다 (반환 된 텐서는 동일한 개수의 요소를 가짐을 의미합니다). 예를 들면 다음과 같습니다.

    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. Assuming that -1 is not one of the parameters, when you multiply them together, the result must be equal to the number of elements in the tensor. If you do: a.view(3, 3), it will raise a RuntimeError because shape (3 x 3) is invalid for input with 16 elements. In other words: 3 x 3 does not equal 16 but 9.

  3. You can use -1 as one of the parameters that you pass to the function, but only once. All that happens is that the method will do the math for you on how to fill that dimension. For example a.view(2, -1, 4) is equivalent to a.view(2, 2, 4). [16 / (2 x 4) = 2]

  4. Notice that the returned tensor shares the same data. If you make a change in the "view" you are changing the original tensor's data:

    b = a.view(4, 4)
    b[0, 2] = 2
    a[2] == 3.0
    False
    
  5. Now, for a more complex use case. The documentation says that each new view dimension must either be a subspace of an original dimension, or only span d, d + 1, ..., d + k that satisfy the following contiguity-like condition that for all i = 0, ..., k - 1, stride[i] = stride[i + 1] x size[i + 1]. Otherwise, contiguous() needs to be called before the tensor can be viewed. For example:

    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)
    

    Notice that for a_t, stride[0] != stride[1] x size[1] since 24 != 2 x 3


I figured it out that x.view(-1, 16 * 5 * 5) is equivalent to x.flatten(1), where the parameter 1 indicates the flatten process starts from the 1st dimension(not flattening the 'sample' dimension) As you can see, the latter usage is semantically more clear and easier to use, so I prefer flatten().


What is the meaning of parameter -1?

You can read -1 as dynamic number of parameters or "anything". Because of that there can be only one parameter -1 in view().

If you ask x.view(-1,1) this will output tensor shape [anything, 1] depending on the number of elements in x. For example:

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)

Will output:

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])

weights.reshape(a, b) will return a new tensor with the same data as weights with size (a, b) as in it copies the data to another part of memory.

weights.resize_(a, b) returns the same tensor with a different shape. However, if the new shape results in fewer elements than the original tensor, some elements will be removed from the tensor (but not from memory). If the new shape results in more elements than the original tensor, new elements will be uninitialized in memory.

weights.view(a, b) will return a new tensor with the same data as weights with size (a, b)

참고URL : https://stackoverflow.com/questions/42479902/how-does-the-view-method-work-in-pytorch

반응형