ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ pytorch ] ConvTranspose2d 알아보기
    AI-ML 2023. 9. 11. 09:19
    728x90
    반응형

    - 목차

     

    키워드.

    • - Convolution
    • - CNN
    • - AutoEncoder

     

    들어가며.

    CNN 이나 AutoEncoder, VAE (Variational Auto Encoder) 등을 구현할 때에 Convolution Layer 을 위해서 Con2d 레이어가 사용됩니다.

    Convolution Layer 로 구성된 Neural Network 는 필연적으로 뉴런의 사이즈가 작아지는 방향으로 이어집니다.

    예를 들어, 아래의 이미지처럼 36x36 사이즈의 이미지는 9x9 커널과 콘볼루션 연산을 통해 28x28 사이즈로 크기가 줄어듭니다.

    그리고 14x14 사이즈의 텐서 또한 5x5 커널과 연산되어 10x10 크기의 텐서로 변환됩니다.

     

    출처 : https://docs.ecognition.com/eCognition_documentation/User%20Guide%20Developer/8%20Classification%20-%20Deep%20Learning.htm

     

     

    즉, CNN 을 통한 Classification 이나 Auto Encoder 의 Encoding 과정은 Convolutional Layer 를 사용하며,

    이 과정에서 텐서의 크기를 줄어들게 됩니다.

    반면 오늘 알아볼 주제인 Transpose Convolution 은 Convolution 과 반대의 연산을 적용합니다.

    오히려 텐서의 크기가 커지는 방향으로 Forward Propagation 이 수행되죠.

    이번 글에서는 Transpose Convolution 을 구현한 pytorch 의 ConvTranspose2d 에 대해서 알아봅니다.

     

    nn.ConvTranspose2d 사용해보기.

    nn.ConvTranspose2d 의 간단한 사용법은 아래와 같습니다.

    아래와 같이 2x2 Input Tensor 와 3x3 Kernel Tensor 가 존재한다고 가정하겠습니다.

    그리고 2x2 Input Tensor 를 3x3 Kernel Tensor 와 Transpose Convolution 연산을 수행하면, 4x4 Output Tensor 가 생성되는데요.

     

    import torch
    import torch.nn as nn
    
    data = torch.tensor([[[
        [1, 2],
        [3, 4]
    ]]], dtype=torch.float32)
    # tensor([[[[1., 2.],
    #           [3., 4.]]]])
    
    t_conv = nn.ConvTranspose2d(1, 1, 4, 1)
    t_conv.weight = nn.Parameter(torch.tensor([[[
        [1, 2, 3],
        [2, 2, 1], 
        [3, 2, 1]
    ]]], dtype=torch.float32))
    t_conv.bias = nn.Parameter(torch.tensor([0], dtype=torch.float32))
    
    output = t_conv(data)
    
    # tensor([[[[ 1.,  4.,  7.,  6.],
    #           [ 5., 16., 22., 14.],
    #           [ 9., 22., 16.,  6.],
    #           [ 9., 18., 11.,  4.]]]], grad_fn=<ConvolutionBackward0>)

     

    이미지 텐서의 각 Item 별로 커널과 element-wise 연산이 수행됩니다.

    예를 들어 이미지 텐서의 첫번째 item 과 커널의 연산 아래와 같구요.

     

     

    이러한 방식으로 이미지 텐서의 모든 Item 은 커널과 Transpose Convolution 연산이 적용되고,  최종적인 Feature Map 이 만들어집니다.

     

     

    in_channels.

    ConvTranspose2d 의 여러 인자들 중에서 in_channels 인자를 Input Tensor, 즉 이미지 텐서의 Channel 수를 의미합니다.

    일반적으로 RGB 와 같은 이미지는 Channel 이 3개로 구성되구요.

    RGB 외의 Alpha 값을 가지는 이미지는 Channel 이 4개로 구성되기도 합니다.

    또한 Convolution Layer 를 통과한 텐서의 경우에는 커널 필터의 갯수만큼 Channel 의 갯수가 증가합니다.

     

    예를 들어, 아래와 같이 어떠한 png 이미지 파일을 Tensor 로 변형하였습니다.

    그 결과로 (4, 816, 1022) 의 사이즈를 가지는 Tensor 가 만들어지는데요.

    이는 816x1022 사이즈의 이미지가 4개의 Channel 로 구성됨을 의미합니다.

    from PIL import Image
    from torchvision import transforms
    
    ToTensor = transforms.ToTensor()
    image = Image.open("/tmp/test.png")
    image_tensor = ToTensor(image)
    
    image_tensor.shape
    # torch.Size([4, 816, 1022])

     

    여기에 4 개의 channel 을 8개의 channel 로 변형하는 Convolution Layer 를 통과시키게 되면,

    8개의 Channel 을 가지는 Tensor 로 변형됩니다.

    import torch.nn as nn
    
    conv = nn.Conv2d(4, 8, 1, 1)
    output = conv(image_tensor)
    output.shape
    
    # torch.Size([8, 816, 1022])

     

    Stride.

    Transpose Convolution 은 Input, Kernel, Output 세가지 Tensor 가 상호작용하게 됩니다.

    Transpose Convolution 을 말로써 표현하자면 Kernel Tensor 가 Output Tensor 에 투영되는 형태로 Output Tensor 의 값이 결정되는 구조인데요.

    쉬운 설명을 위해서 그림으로 설명을 이어가도록 하겠습니다.

    아래 이미지는 2x2 Input Tensor 와 2x2 Kernel Tensor 의 Transpose Convolution 을 보여줍니다.

    Stride 는 1로 설정된 상황에서 3x3 Output Tensor 로 투영되는 과정을 설명합니다.

     

    그럼 Stride 가 2인 상황은 어떻게 될까요 ?

    2x2 Input Tensor 와 2x2 Kernel Tensor 가 Stride 2 인 상황에서 Transpose Convolution 연산이 적용되는 과정은 아래와 같습니다.

    아래와 같이 4x4 Output Tensor 가 생성되구요.

    Output Tensor 에 Kernel 이 투영되는 Stride 가 2로 설정됩니다.

    아래 결과를 보시면, Input Tensor 는 각 Item 이 개별적인 색상으로 색칠되어 있습니다.

    각각 보라색, 하늘색, 노랑색, 분홍색으로 색칠되어 있는데요.

    Output Tensor 에 동일한 색상으로 색칠된 영역이 Kernel Tensor 가 투영될 공간입니다.

    그리고 Stride (보폭) 은 2로 되어있음을 알 수 있습니다.

     

     

    Padding.

    Padding 은 Output Tensor 에서 Padding 에 적용된 값만큼 Item 들을 제거합니다.

    예를 들어, 아래와 같이 Padding 이 1로 적용된다면 4x4 크기인 Output Tensor 는 외곽의 Item 들이 제거된 2x2 Tensor 만 남게 됩니다.

    이렇게 Transpose Convolution 연산에서 Padding 이 적용된다면 Output Tensor 의 크기는 Padding 의 값만큼 축소됩니다.

     

    pytorch 코드로써 Padding 이 어떻게 동작하는지를 살펴보면,

    3x3 Input Tensor 와 3x3 Kernel 이 Transpose Convolution 연산이 수행됩니다.

    일반적으로 5x5 의 Output Tensor 가 생성되어야 하지만, Padding 이 2인 관계로 1x1 인 Output Tensor 가 생성되게 됩니다.

    import torch
    import torch.nn as nn
    
    data = torch.tensor([[[
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]
    ]]], dtype=torch.float32)
    data
    
    t_conv = nn.ConvTranspose2d(
        in_channels=1, 
        out_channels=1, 
        kernel_size=3, 
        stride=1, 
        padding=2
    )
    
    t_conv.weight = nn.Parameter(torch.tensor([[[
        [1, 2, 3],
        [2, 2, 1], 
        [3, 2, 1]
    ]]], dtype=torch.float32))
    t_conv.bias = nn.Parameter(torch.tensor([0], dtype=torch.float32))
    
    output = t_conv(data)
    output
    tensor([[[[17.]]]], grad_fn=<ConvolutionBackward0>)

     

     

    output_padding.

    output_padding 은 Output Tensor 의 외곽에 추가적인 Item 들을 추가하여 Output Tensor 의 크기를 변경합니다.

    예시는 아래와 같습니다.

     

    3x3 Input Tensor 와 3x3 Kernel 이 Transpose Convolution 연산을 수행합니다.

    Stride 가 3으로 되어 있어서 최종적으로 9x9 Output Tensor 가 생성됩니다.

    하지만, output_padding 으로 1 을 설정하여 우측, 하단의 Item 이 0 으로 추가되게 됩니다.

    따라서 10x10 크기의 Output Tensor 가 생성되게 됩니다.

    import torch
    import torch.nn as nn
    
    data = torch.tensor([[[
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]
    ]]], dtype=torch.float32)
    
    t_conv = nn.ConvTranspose2d(
        in_channels=1, 
        out_channels=1, 
        kernel_size=3, 
        stride=3, 
        padding=0,
        output_padding=1
    )
    
    t_conv.weight = nn.Parameter(torch.tensor([[[
        [1, 2, 3],
        [2, 2, 1], 
        [3, 2, 1]
    ]]], dtype=torch.float32))
    t_conv.bias = nn.Parameter(torch.tensor([0], dtype=torch.float32))
    
    output = t_conv(data)
    output
    tensor([[[[1., 2., 3., 1., 2., 3., 1., 2., 3., 0.],
              [2., 2., 1., 2., 2., 1., 2., 2., 1., 0.],
              [3., 2., 1., 3., 2., 1., 3., 2., 1., 0.],
              [1., 2., 3., 1., 2., 3., 1., 2., 3., 0.],
              [2., 2., 1., 2., 2., 1., 2., 2., 1., 0.],
              [3., 2., 1., 3., 2., 1., 3., 2., 1., 0.],
              [1., 2., 3., 1., 2., 3., 1., 2., 3., 0.],
              [2., 2., 1., 2., 2., 1., 2., 2., 1., 0.],
              [3., 2., 1., 3., 2., 1., 3., 2., 1., 0.],
              [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]]],
           grad_fn=<ConvolutionBackward0>)

     

    반응형

    'AI-ML' 카테고리의 다른 글

    Collaborative Filtering 이해하기  (0) 2023.09.25
    [ CNN ] Feature Map 이해하기  (0) 2023.09.19
    [ pytorch ] AutoEncoder 구현하기  (0) 2023.09.05
    [pytorch] Dropout 알아보기  (0) 2023.08.17
    Association Rules (연관규칙) 이해하기  (0) 2023.05.16
Designed by Tistory.