Machine Learning/ML DL

ResNet 이란 무엇인가?

코방코 2024. 7. 9. 18:51
728x90

 

 

요약

ResNet(Residual Network)은 2015년 He et al.에 의해 제안된 Deep Learning 모델로,

Deep Neural Network 에서의 학습 문제를 해결하기 위해 도입되었습니다.

ResNet은 전통적인 CNN(Convolutional Neural Network)에서 residual connection이라는 개념을 사용하여

매우 깊은 네트워크에서도 효과적으로 학습할 수 있습니다.

ResNet은 Object Detection, Classification 등 다양한 Computer Vision Task에서 널리 사용됩니다.

말이 어려워 보이지만, Output에 Input을 Short cut으로 연결하여 학습을 수행하는 간단한 구조를 가집니다.


기존 CNN의 문제점

CNN은 깊이가 깊어질수록 다음과 같은 문제가 발생했습니다.

  • Vanishing Gradient (기울기 소실): Back Propagation에서 기울기가 점점 작아져, 초기 층으로 전달되지 않는 문제.
  • Exploding Gradient (기울기 폭발): 기울기가 너무 커져서 수렴이 어려워지는 문제.
  • 어려운 학습: 네트워크가 깊어질수록 학습이 어려워지고, 정확도가 떨어지는 문제.

 

주요 장점

ResNet은 residual connection 을 이용하는 방식으로 다음과 같은 장점이 있습니다.

  1. DNN의 효과적 학습 가능: 매우 깊은 네트워크에서도 효과적으로 학습할 수 있습니다.
  2. Vanishing gradient problem 해결: Skip 연결이 기울기 소실 문제를 완화하여 안정적인 학습을 가능하게 합니다.
  3. 성능 향상: Object Detection , Semantic Segmentation 등 다양한 Computer Vision Task에서 뛰어난 성능을 보입니다.

 


주요 개념 및 구조

1. Residual Learning(잔차 학습)

Residual Learning은 DNN의 학습을 용이하게 하기 위해 사용됩니다.

핵심 아이디어는 각 층에서 직접 원하는 Mapping을 학습하는 대신,

그 차이(residual)를 학습하는 것입니다.

이는 다음과 같이 표현될 수 있습니다:

여기서 x 는 Input, F는 학습할 Residual Function, y는 Output입니다.

Residual connection 을 추가하면 네트워크가 쉽게 residual을 학습할 수 있으며,

이를 통해 Vanishing gradient problem (기울기 소실 문제)을 완화할 수 있습니다.

 

2. Basic Block과 Bottleneck Block

ResNet은 Basic Block과 Bottleneck Block 두 가지 주요 블록으로 구성됩니다.

  • Basic Block:
    • 두 개의 3x3 Convolution Layer로 구성됩니다.
    • 각 Convolution Layer 뒤에 Batch Normalization과 ReLU Activation Function이 추가됩니다.
    • 입력 x 가 Skip 연결을 통해 출력에 더해집니다.

  • Bottleneck Block
    • 1x1, 3x3, 1x1 Convolution Layer 로 구성됩니다.
    • 1x1 Convolution Layer는 차원을 줄이거나 늘리는 역할을 합니다.
    • 차원을 줄이며 속도는 올라가지만 정보를 잃을 수 있는 Trade off 존재
    • 각 Convolution Layer 뒤에 Batch Normalization과 ReLU Activation Funciton 가 추가됩니다.
    • 입력 x 가 Skip 연결을 통해 출력에 더해집니다.

ResNet 아키텍처

ResNet은 다양한 깊이로 설계될 수 있으며,

주로 ResNet-18, ResNet-34, ResNet-50, ResNet-101, ResNet-152 등이 사용됩니다.

여기서 숫자는 네트워크의 총 Layer 수를 의미합니다.

  • ResNet-18 및 ResNet-34는 Basic Block을 사용합니다.
  • ResNet-50, ResNet-101, ResNet-152는 Bottlenet Block을 사용합니다.

 


PyTorch 예제 코드

다음은 PyTorch를 사용하여 ResNet-18을 구현한 예제 코드입니다.

import torch
import torch.nn as nn
import torch.nn.functional as F

class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, in_planes, planes, stride=1):
        super(BasicBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_planes != self.expansion * planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(self.expansion * planes)
            )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)
        out = F.relu(out)
        return out

class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=1000):
        super(ResNet, self).__init__()
        self.in_planes = 64

        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.linear = nn.Linear(512 * block.expansion, num_classes)

    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1] * (num_blocks - 1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.max_pool2d(out, kernel_size=3, stride=2, padding=1)
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = F.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

def ResNet18():
    return ResNet(BasicBlock, [2, 2, 2, 2])

# 모델 생성
model = ResNet18()
print(model)

 


Reference

 

Understanding Residual Connections in Neural Networks

The problem of vanishing gradient

cdanielaam.medium.com

 

https://www.researchgate.net/figure/Replacement-process-in-Basic-block-and-Bottleneck-block-of-ResNet-We-use-the-Xwise_fig5_342337449

 

 

Residual Network (ResNet)

잔차(residual)를 학습하는 CNN 기반 모델 ResNet을 소개합니다.

ljm565.github.io

 

728x90
반응형

'Machine Learning > ML DL' 카테고리의 다른 글

Activation Function 이란 무엇인가?  (0) 2024.07.10