[CV] CNN

fragrance_0·2023년 12월 9일
0

CV

목록 보기
2/4

📂 CNN 개념

📎 CNN 등장 배경

전통적인 완전 연결 계층(Fully Connected Layer, FC Layer)만을 가진 신경망이 이미지 처리에 어려움을 겪음

  1. 공간 구조 무시

    • 완전 연결 계층은 입력 데이터를 1차원 벡터로 취급
    • 이미지와 같은 2차원 데이터에서의 픽셀 간의 공간적인 관계를 무시함
      (ex) 이미지 내에서 인접한 픽셀 간의 관계는 중요한 정보를 가지고 있지만, 이러한 정보는 FC Layer에서는 고려되지 않음
  2. 파라미터의 수

    • 완전 연결 계층은 각 노드가 모든 입력과 연결되어 있기 때문에,
    • 대규모 이미지를 처리하는 데 필요한 파라미터의 수가 지나치게 많음.
    • 이는 과적합의 위험을 증가시키며, 계산적인 부담을 가중시킴.

📎 CNN의 제안

CNN(Convolutional Neural Networks)

  • FC Layer의 문제점을 극복하고 이미지를 분석하기 위해 많은 양의 공간적 구조 정보를 처리하고자 함

  • CNN은 이미지 데이터의 공간적 구조를 활용하고, 작은 인식 영역(Receptive Field)을 통해 지역적인 특징을 학습하며, 위치에 무관한 특징을 인식하는 등의 가정이 내포되어 있음

  • 이러한 Inductive Bias덕분에 CNN은 이미지 데이터에 특화된 강력한 성능을 냄

Inductive Bias : 주어지지 않은 입력의 출력을 예측하는 것


📎 CNN 계층 구성

1️⃣ 합성곱 계층

  • 합성곱 계층은 지역적인 특징들을 검출하기 위해 사용되는 핵심적인 구성 요소임
  • 이미지 내에서 작은 영역의 패턴을 탐지
  • 탐지 위해 입력 데이터에 가중치 필터(Filter)를 적용
  • 필터는 작은 가중치 행렬로 구성되어 입력 데이터 내에 대응하는 인식 영역인 (Receptive Field)과 합성곱을 수행함
  • 전체 입력 데이터를 스캔하면서 이미지의 여러 공간적인 특징을 탐지

🤔 필터(Filter)와 커널(Kernel)
필터와 커널은 약간의 의미적 차이가 있지만, 보통 CNN 구조 내에서는 동의어로 사용됩니다. 커널은 여러 층 중 하나의 층에서 인식 영역과 계산하는 작은 가중치 행렬 개념이라면 필터는 이 커널이 중첩되어 여러 층에 적용될 때 활용하는 개념입니다. 쉽게 말하면 커널의 집합을 필터라고 합니다.

1️⃣-2. 합성곱 계층의 특징

  • 지역적인 특징 검출
    → 필터와 입력 데이터의 합성곱을 통해 합성곱 계층은 에지(Edge), 코너(Corner), 질감(Texture) 등과 같은 지역적인 특징을 탐지 가능
    → 합성곱 계층은 이러한 특성들을 추출하는 Feature Extraction 역할
    → CNN은 계층별로 입력 데이터의 패턴을 포착하며, 낮은 계층에서는 간단한 특징을, 높은 계층에서는 보다 복잡한 특징을 탐지


  • 변환 불변성
    → 합성곱 계층은 변환 불변성(Translation Invariance)을 가지며, 한 번 학습한 특징은 공간적인 위치에 상관없이 인식
    → 필터의 공유된 가중치로 인해 해당 특징은 전체 입력 데이터에 적용되므로 학습된 특징은 위치에 상관없이 인식
    → CNN이 이미지 내에서 공간적인 변화에도, 불변한 패턴을 인식하는 것


2️⃣ 풀링(Pooling) 계층

풀링 계층은 이미지의 크기를 줄이는 과정에서 주로 Max Pooling을 사용함

Max Pooling은 주어진 영역에서 가장 큰 값을 선택하여,
DownSampling된 특성맵(Feature Map)을 생성하는 과정을 말함

  • 계산 복잡도 감소
    ⤬ Pooling은 입력 데이터의 공간 해상도(Resolution)를 감소시키는 연산이기 때문에, 특성맵의 크기를 줄이고 연산량을 감소시킴.
    ⤬ 모델의 학습과 추론 속도를 향상시키는 데 도움.
  • 과적합(Overfitting) 방지
    ⤬ Pooling은 입력 영역에서 가장 큰 값(또는 영역 내 평균값)을 선택하므로, 작은 변동성이나 노이즈에 덜 민감한 특징을 추출 가능.
    ⤬ 모델의 일반화 성능을 향상시켜 과적합 방지.
  • 영역 내에서 공간적인 불변성(Spatial Invariance)
    ⤬ Pooling은 입력 영역에서 가장 큰 값을 선택하기 때문에, 영역 내에서의 변동이나 이동에 덜 민감함.
    ⤬ 입력 이미지의 조금씩 이동하거나 변형되더라도 풀링 계층의 출력이 일정한 특성을 가지게 함.
    ⤬ 이러한 불변성은 이미지의 공간적인 변화에 더 강인한(Robust) 모델을 구축하는 데 도움.

3️⃣ 완전 연결 계층

⤬ 이미지 전체에 대한 정보를 종합하고, 이를 사용하여 최종 출력을 생성
⤬ 이 전 계층까지는 공간적인 정보를 담고 있어 출력된 값이 2차원 이상으로 표현되었지만, 이 계층을 통과하기 위해 평탄화(Flattened) 작업이 이루어짐
⤬ 이전 레이어에서 학습한 특징을 기반으로 고수준의 추상성을 포착하고 최종 예측을 수행하는 데 중요한 역할을 함
⤬ 네트워크가 복잡한 비선형 관계를 모델링하고 분류, 회귀 또는 다른 작업을 수행할 수 있도록 해줌


📂 CNN 특징

📎 변수 공유와 희소 연결

CNN은 이미지의 공간 구조를 활용하기 때문에 효과적으로 파라미터를 공유하고, 훨씬 적은 수의 파라미터로 복잡한 모델을 만들 수 있습니다. 이로 인해 모델의 메모리 사용량이 줄고, 계산 효율성이 향상되며, 과적합의 가능성이 줄어듭니다.

📎 공간적 불변성

CNN은 이미지 내의 객체가 어디에 위치해 있더라도 그 객체를 인식할 수 있습니다. 이는 합성곱 계층과 풀링 계층 덕분에 가능하며, 이를 통해 CNN은 위치에 무관한 특징을 학습할 수 있습니다.

📎 다계층 구조

CNN은 일반적으로 여러 계층으로 구성됩니다. 이를 통해 저수준의 특징(선분, 색상 등)에서부터 고수준의 특징(형상, 객체 등)까지 차례대로 학습할 수 있습니다.


📂 CNN의 연산 과정

📎 합성곱 계층 계산 과정

합성곱 레이어에서는 이름에서 알 수 있듯이 합성곱(Convolution) 연산이 이루어집니다. 합성곱은 필터가 이미지를 슬라이드하면서 해당 필터와 이미지 부분 간의 요소별 곱셈을 수행하고 결과를 모두 더하는 과정입니다.

합성곱 계층 연산과정
이 과정을 거치면서 각 위치에서의 합성곱 연산의 결과로 생성된 출력값 행렬이 생성되는데요, 이를 특성맵(Feature Map)이라고 합니다. 이러한 연산은 필터가 탐지한 특정 패턴이 이미지의 어디에 존재하는지를 파악하는 데 도움이 됩니다.

이미지는 상당히 고차원적인 데이터입니다. 예를 들어, 128 × 128 픽셀의 작은 이미지라고 하더라도 컬러 이미지는 각 픽셀마다 빨강, 초록, 파랑의 3개 채널이 있으므로 총 49,152개의 값을 가지게 됩니다. 이렇게 큰 데이터를 처리하려면 많은 계산량이 필요합니다. 그러나 합성곱은 지역적인 영역에 집중하여 계산을 수행하므로 계산량을 크게 줄일 수 있습니다.

👩🏻‍💻 합성곱 pytorch 코드

import torch
import torch.nn as nn

# 간단한 CNN 모델 정의
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv = nn.Conv2d(3, 16, kernel_size=5)
    
    def forward(self, x):
        conv = self.conv(x)
        return conv

# 모델의 인스턴스 생성
model = CNN()

# 입력 텐서
x = torch.randn(1, 3, 32, 32)  # (배치 크기, 채널, 높이, 너비)

# 합성곱 연산
conv = model(x)

print(conv.shape)

👩🏻‍💻 합성곱 numpy 코드

import numpy as np

# 입력 텐서
x = np.random.randn(1, 3, 32, 32)  # (배치 크기, 채널, 높이, 너비)

# 합성곱 레이어의 가중치
w_conv = np.random.randn(16, 3, 5, 5)  # (필터 개수, 입력 채널, 커널 높이, 커널 너비)
b_conv = np.random.randn(16)  # (필터 개수)

# 합성곱 연산
conv = np.zeros((1, 16, 28, 28))  # (배치 크기, 필터 개수, 출력 높이, 출력 너비)
for f in range(16):
    for i in range(28):
        for j in range(28):
            conv[0, f, i, j] = np.sum(x[0, :, i:i+5, j:j+5] * w_conv[f]) + b_conv[f]

print(conv.shape)

📎 풀링 계층의 계산 과정

풀링(Pooling)은 특성맵의 크기를 줄이기 위해 DownSampling하는 과정입니다. Pooling의 방법으로는 Average Pooling과 Max Pooling이 있습니다. 이미지 처리 분야에서는 보통 Max Pooling을 활용합니다. Max Pooling은 특성맵을 구성하는 값 중에서 가장 큰 값을 선택하는 방법입니다.

👩🏻‍💻 Max Pooling pytorch 코드


import torch
import torch.nn as nn

# Create a 2D input tensor
input_tensor = torch.tensor([[1, 2, 3, 4],
                             [5, 6, 7, 8],
                             [9, 10, 11, 12],
                             [13, 14, 15, 16]], dtype=torch.float32)

# Define max pooling layer
max_pool = nn.MaxPool2d(kernel_size=2, stride=2)

# Apply max pooling
output = max_pool(input_tensor.unsqueeze(0).unsqueeze(0))  # Add dimensions for batch and channels

print(output.squeeze(0).squeeze(0))

👩🏻‍💻 Max Pooling numpy 코드

import numpy as np

def max_pooling(x, k):
    # x: input feature map
    # k: pooling size
    
    height, width = x.shape
    h_out = height // k
    w_out = width // k
    
    pooled = np.zeros((h_out, w_out))
    
    for i in range(h_out):
        for j in range(w_out):
            r_start = i * k
            r_end = r_start + k
            c_start = j * k
            c_end = c_start + k
            
            pooled[i, j] = np.max(x[r_start:r_end, c_start:c_end])
    
    return pooled

📎 완전 연결 계층의 계산 과정

완전 연결 레이어는 각 입력 노드와 출력 노드가 모두 연결되어 있습니다.
이 레이어에서의 계산은 기본적으로 입력 특징과 가중치 벡터 간의 내적을 계산하고, 편향을 더하는 것입니다. 수식으로 나타내면 아래와 같습니다.

f(x)=Wx+bf(x) = Wx + b

여기서 WW는 가중치, xx는 입력 데이터(특성맵), bb는 편향을 나타냅니다.
계산된 출력은 비선형 활성화 함수(주로 Softmax 등)를 통과하여 최종 결괏값이 출력됩니다.

완전 연결 계층은 보통 네트워크의 마지막 부분에서 계산됩니다.
앞선 단계에서 종합한 공간적 특성들로 최종적인 예측을 수행하는 단계라고 볼 수 있습니다.

이미지 분류 문제로 예를 들면, 마지막 완전 연결 계층의 최종 출력 값은 클래스의 수만큼 지정되고 각 클래스에 대한 확률을 계산합니다. 이를 통해 모델은 이미지가 지닌 복잡한 패턴과 클래스 레이블 사이의 관계를 학습할 수 있습니다.

👩🏻‍💻 완전 연결 계층 pytorch 코드


import torch
import torch.nn as nn

# 랜덤한 입력 텐서 생성
x = torch.randn(32, 16)  # (배치 크기, 입력 크기)

# 완전 연결 레이어 정의
fc = nn.Linear(16, 10)  # (입력 크기, 출력 크기)

# 완전 연결 레이어 적용
output = fc(x)

print(output.shape)  # 출력 형태: (32, 10)

👩🏻‍💻 완전 연결 계층 numpy 코드

import numpy as np

# 입력 텐서
x = np.random.randn(32, 16)  # (배치 크기, 입력 크기)

# FC 레이어의 가중치
w_fc = np.random.randn(16, 10)  # (입력 크기, 출력 크기)
b_fc = np.random.randn(10)  # (출력 크기)

# FC 연산
fc = np.dot(x, w_fc) + b_fc

print(fc.shape)

[출처 | 딥다이브 Code.zip 매거진]

profile
@fragrance_0의 개발로그

0개의 댓글