Level 5: CNN & 이미지 처리
🖼️

Level 5

합성곱 연산

커널, 스트라이드, 패딩, 특성 맵

50분
합성곱 연산 강의 영상
강의 영상 보기 (새 탭에서 재생)YouTube

📓Google Colab에서 실습하기

이 레슨은 PyTorch/GPU가 필요합니다. 노트북을 다운로드 후 Google Colab에서 열어주세요.

학습 내용

합성곱 연산

학습 목표

이 레슨을 완료하면:

  • 합성곱 연산의 원리를 이해합니다
  • 커널/필터의 역할을 배웁니다
  • 스트라이드와 패딩의 효과를 이해합니다
  • 특성 맵(Feature Map)의 의미를 파악합니다

핵심 메시지

"합성곱은 작은 창문으로 이미지를 훑으면서 특징을 찾아내는 연산입니다." 3×3 크기의 작은 필터가 이미지 위를 슬라이딩하면서 "여기에 세로선이 있나?", "모서리가 있나?" 같은 질문에 답합니다.


1. 합성곱(Convolution)이란?

비유: 돋보기로 신문을 읽는다고 상상해보세요. 돋보기(커널)를 신문(이미지) 위에서 한 칸씩 이동하면서 글자(특징)를 확인합니다. 합성곱은 이와 비슷하게 작은 필터로 이미지 전체를 훑으면서 패턴을 감지합니다.

MLP vs CNN 비교

특성MLPCNN
이미지 처리1차원으로 펼침 (flatten)2D 구조 유지
공간 정보손실됨보존됨
파라미터 수매우 많음적음 (가중치 공유)
위치 불변성없음있음

2. 합성곱 계산 방법

합성곱 연산은 커널과 이미지 영역의 요소별 곱셈 후 합산입니다.

계산 예시

입력 이미지의 3×3 영역과 3×3 커널:

이미지 영역커널
1, 2, 31, 0, 1
0, 1, 20, 1, 0
1, 2, 11, 0, 1

계산: (1×1) + (2×0) + (3×1) + (0×0) + (1×1) + (2×0) + (1×1) + (2×0) + (1×1) = 8

이 과정을 이미지 전체에서 반복하면 **특성 맵(Feature Map)**이 생성됩니다.

🔬 실습: 합성곱 연산 직접 구현

python
import numpy as np import matplotlib.pyplot as plt # ═══════════════════════════════════════════════════════════════ # 📊 합성곱 연산 직접 구현하기 # ═══════════════════════════════════════════════════════════════ def conv2d_manual(image, kernel): """합성곱 연산을 직접 구현 (padding=0, stride=1)""" h, w = image.shape kh, kw = kernel.shape out_h = h - kh + 1 out_w = w - kw + 1 output = np.zeros((out_h, out_w)) for i in range(out_h): for j in range(out_w): # 이미지 영역과 커널의 요소별 곱 후 합산 region = image[i:i+kh, j:j+kw] output[i, j] = np.sum(region * kernel) return output # 5×5 입력 이미지 image = np.array([ [1, 2, 3, 0, 1], [0, 1, 2, 3, 1], [1, 2, 1, 0, 0], [0, 1, 1, 2, 1], [2, 0, 1, 1, 0] ], dtype=float) # 3×3 커널 (엣지 검출용) kernel = np.array([ [1, 0, -1], [1, 0, -1], [1, 0, -1] ], dtype=float) # 합성곱 수행 output = conv2d_manual(image, kernel) print("=" * 50) print("📊 합성곱 연산 결과") print("=" * 50) print(f"입력 이미지 크기: {image.shape}") print(f"커널 크기: {kernel.shape}") print(f"출력 크기: {output.shape}") print(f"\n출력 특성 맵:\n{output}") # 시각화 fig, axes = plt.subplots(1, 3, figsize=(12, 4)) axes[0].imshow(image, cmap='gray') axes[0].set_title('Input Image (5x5)', fontsize=12) axes[0].axis('off') axes[1].imshow(kernel, cmap='RdBu', vmin=-1, vmax=1) axes[1].set_title('Kernel (Vertical Edge)', fontsize=12) axes[1].axis('off') axes[2].imshow(output, cmap='gray') axes[2].set_title('Output Feature Map (3x3)', fontsize=12) axes[2].axis('off') plt.suptitle('Convolution Operation', fontsize=14, fontweight='bold') plt.tight_layout() plt.show() print("\n💡 커널이 이미지를 훑으면서 수직 엣지를 감지했습니다!")

3. 커널(필터)의 역할

커널은 학습 가능한 작은 가중치 행렬입니다. 각 커널은 특정 패턴이나 특징을 감지합니다.

일반적인 커널 크기

크기용도
3×3가장 많이 사용, 효율적
5×5더 넓은 영역 감지
7×7초기 레이어에서 가끔 사용
1×1채널 수 조정용

커널의 특징 검출 예시

커널 종류역할
수평 엣지가로선 감지
수직 엣지세로선 감지
가우시안블러 (노이즈 제거)
샤프닝선명도 강화

4. 스트라이드(Stride)

스트라이드 = 커널이 이동하는 칸 수

스트라이드효과
1 (기본값)한 칸씩 이동, 출력 크기 큼
2두 칸씩 이동, 출력 크기 절반

출력 크기 계산

출력 크기 = (입력 - 커널) / 스트라이드 + 1

입력커널스트라이드출력
7×73×315×5
7×73×323×3
32×323×3130×30

5. 패딩(Padding)

패딩 = 이미지 가장자리에 값을 추가하여 출력 크기를 조절

패딩의 필요성

합성곱 후에는 크기가 줄어듭니다:

  • 입력 5×5 → (3×3 커널) → 출력 3×3

패딩을 사용하면 크기를 유지할 수 있습니다:

  • 입력 5×5 + 패딩 1 → (3×3 커널) → 출력 5×5

패딩 종류

종류설명
Valid (패딩 없음)크기 감소
Same출력 = 입력 크기
Zero Padding0으로 채움 (가장 일반적)

완전한 출력 크기 공식

출력 = (입력 + 2×패딩 - 커널) / 스트라이드 + 1

🔬 실습: 스트라이드와 패딩 효과

python
⚠️ 로컬 실행 필요
import torch import torch.nn as nn # ═══════════════════════════════════════════════════════════════ # 📊 스트라이드와 패딩에 따른 출력 크기 변화 # ═══════════════════════════════════════════════════════════════ def test_conv_output(in_size, kernel, stride, padding): """합성곱 출력 크기 테스트""" conv = nn.Conv2d(1, 1, kernel_size=kernel, stride=stride, padding=padding) x = torch.randn(1, 1, in_size, in_size) out = conv(x) return out.shape[-1] print("=" * 60) print("📊 합성곱 출력 크기 실험") print("=" * 60) print(f"{'설정':<30} {'출력 크기':<10}") print("-" * 40) # 다양한 설정 테스트 configs = [ (32, 3, 1, 0, "기본 (패딩 없음)"), (32, 3, 1, 1, "Same 패딩"), (32, 3, 2, 0, "Stride=2"), (32, 3, 2, 1, "Stride=2 + 패딩"), (32, 5, 1, 2, "5×5 커널, Same"), ] for in_size, kernel, stride, padding, desc in configs: out_size = test_conv_output(in_size, kernel, stride, padding) print(f"입력={in_size}, k={kernel}, s={stride}, p={padding} ({desc}): {out_size}×{out_size}") # 공식으로 직접 계산 print("\n" + "=" * 60) print("📐 출력 크기 공식: (입력 + 2×패딩 - 커널) / 스트라이드 + 1") print("=" * 60) for in_size, kernel, stride, padding, desc in configs: calc = (in_size + 2*padding - kernel) // stride + 1 print(f"({in_size} + 2×{padding} - {kernel}) / {stride} + 1 = {calc}") print("\n💡 패딩=1, 커널=3, 스트라이드=1이면 크기가 유지됩니다!")

6. PyTorch로 합성곱 구현

python
⚠️ 로컬 실행 필요
import torch import torch.nn as nn # ═══════════════════════════════════════════════════════════════ # 📊 PyTorch Conv2d 사용법 # ═══════════════════════════════════════════════════════════════ # 합성곱 레이어 정의 conv = nn.Conv2d( in_channels=3, # 입력 채널 수 (RGB) out_channels=64, # 출력 채널 수 (필터 개수) kernel_size=3, # 커널 크기 3×3 stride=1, # 스트라이드 padding=1 # 패딩 (same) ) # 입력: (배치, 채널, 높이, 너비) x = torch.randn(1, 3, 32, 32) output = conv(x) print("=" * 50) print("📊 Conv2d 레이어 분석") print("=" * 50) print(f"입력 shape: {x.shape}") print(f"출력 shape: {output.shape}") # 파라미터 수 계산 # 가중치: out_channels × in_channels × kernel × kernel # 편향: out_channels weight_params = 64 * 3 * 3 * 3 bias_params = 64 total_params = sum(p.numel() for p in conv.parameters()) print(f"\n파라미터 수:") print(f" 가중치: {weight_params} (64 × 3 × 3 × 3)") print(f" 편향: {bias_params}") print(f" 총합: {total_params}")

핵심 요약

개념핵심 내용기억할 포인트
합성곱커널 × 이미지 영역의 합특징 추출기
커널학습되는 가중치 행렬보통 3×3 사용
스트라이드커널 이동 칸 수크면 출력 작아짐
패딩가장자리에 값 추가크기 유지 가능
출력 크기(입력 + 2P - K) / S + 1공식 암기!

학습 체크리스트

  • 합성곱 연산 과정을 설명할 수 있다
  • 커널의 특징 추출 역할을 이해한다
  • 스트라이드와 패딩의 효과를 안다
  • 출력 크기 계산 공식을 사용할 수 있다

다음 강의 예고

"풀링과 정규화" - 특성 맵의 크기를 줄이고 학습을 안정화하는 기법을 배웁니다!

레슨 정보

레벨
Level 5: CNN & 이미지 처리
예상 소요 시간
50분
참고 영상
YouTube 링크

💡실습 환경 안내

이 레벨은 PyTorch/GPU가 필요하여 Google Colab 사용을 권장합니다.

Colab은 무료 GPU를 제공하여 PyTorch, CNN, Transformer 등을 실행할 수 있습니다.