이번에는 딥러닝 모델 중 하나인 CNN(Convolutional Neural Network)에 대해 정리하며 학습해보려 한다. CNN은 딥러닝 기반의 신경망 구조로 인간의 시신경 구조를 모티브로 만들어졌다고 할 수 있다. 이는 사람이 여러 데이터를 보고 기억한 후에 무엇인지 맞추는 것과 유사하다고 할 수 있다.
이제 CNN(Convolutional Neural Network)에 대해 자세히 정리하며 학습해 볼 것이다.
✅ CNN(Convolutional Neural Network)
1️⃣ 정의
- CNN은 에지(edge) 검출, 특징(feature) 조합, 계층적 분석을 통해 이미지를 분류하는 딥러닝 기반 신경망 구조야.
- 인간의 시각 시스템을 모방해서, 입력 이미지의 국소적(local) 특징을 계층적으로 학습함.
2️⃣ 인간과 CNN의 이미지 인식 비교
단계 | 사람의 인식 | CNN의 처리 |
1단계 | 전체적인 윤곽 파악 | 에지 검출 (선, 경계선) |
2단계 | 세부 특징 확인 (귀, 눈 등) | 부분 특징 추출 (귀, 눈 등) |
3단계 | 전체 조합 후 판단 (고양이라고 판단) | 최종 판단 및 분류 (고양이 클래스 예측) |
3️⃣ CNN vs 전통적인 신경망 (Fully Connected Network)
🔸 기존 신경망의 한계
- 입력 이미지의 모든 픽셀을 연결 → 연산량 폭증
- 위치 변화, 크기 변화에 매우 민감
- 공간 정보 손실 발생
🔸 CNN의 장점
- 필터(kernel)를 사용해 핵심 특징만 추출
- 입력 위치나 크기 변화에도 강함
- 계산량 감소 + 위치 정보 유지
4️⃣ CNN의 주요 아이디어 3가지
1. 지역적 연결성(Local Connectivity)
- 하나의 뉴런은 입력 이미지의 일부분(receptive field)만 본다.
예시:
receptive_field = image[0:3, 0:3, :] # 이미지의 3x3 영역
print(f"수용장 크기: {receptive_field.shape}")
2. 매개변수 공유(Parameter Sharing)
- 하나의 필터를 전체 이미지에 슬라이딩(slide)하며 적용
예시 (수평 에지 검출 필터):
import numpy as np
edge_filter = np.array([
[-1, -1, -1],
[ 0, 0, 0],
[ 1, 1, 1]
])
→ 해당 필터를 이미지 전역에 동일하게 적용함으로써 모든 위치에서 수평 경계선 감지가 가능하도록 한다.
3. 계층적 특징 학습(Hierarchical Feature Learning)
계층 | 역할 | 예시 출력 크기 |
1층 | 에지 검출 | 30x30x32 |
2층 | 형태 검출 (코너, 원 등) | 14x14x64 |
3층 | 부분 인식 (눈, 귀 등) | 6x6x128 |
4층 | 객체 인식 (고양이, 자동차 등) | 클래스 수만큼 |
5️⃣ CNN의 실제 활용 분야
- 📱 스마트폰: 얼굴 인식 잠금 해제
- 🚗 자율주행: 도로 물체 인식
- 🏥 의료 영상 분석: X-ray에서 이상 탐지
- 🛒 쇼핑 플랫폼: 이미지 기반 유사 상품 추천
- 📷 카메라: 피사체 자동 인식
- 🎮 게임: 동작 인식 인터페이스
⚙️ 요약 정리
- CNN은 인간 시각 시스템을 모방하여 이미지의 에지 → 특징 → 분류 과정을 수행한다.
- 핵심 아이디어는:
- 지역적 연결성
- 매개변수 공유
- 계층적 특징 학습
- 기존의 완전 연결 방식보다 계산 효율성, 일반화 능력 우수하다.
- 다양한 이미지 처리 분야에 폭넓게 활용 중
✅ 컨볼루션(Convolution)
1️⃣ 정의
CNN에서 입력 이미지에서 의미 있는 특징(경계, 패턴 등)을 추출하는 연산으로, 필터(kernel) 또는 커널을 입력 데이터 위에서 슬라이딩시키며 연산을 수행한다.
2️⃣ 컨볼루션 연산 방식
🔸 구조 이해 예시
5x5 이미지에 3x3 필터를 적용한다고 가정하면:
import numpy as np
from scipy.signal import convolve2d
# 5x5 입력 이미지
image = np.array([
[1, 2, 3, 0, 1],
[4, 5, 6, 1, 0],
[7, 8, 9, 0, 1],
[1, 2, 3, 1, 0],
[4, 5, 6, 0, 1]
])
# 3x3 필터 (수직 엣지 검출 예)
kernel = np.array([
[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]
])
# 컨볼루션 연산
output = convolve2d(image, kernel, mode='valid')
print(output)
연산 원리
- 커널을 한 칸씩 이동(stride)하면서 해당 영역의 가중합(dot product) 을 계산.
- 계산된 값이 출력 행렬의 한 요소가 됨.
- 이를 통해 특정 패턴이 어디에 있는지를 추출.
3️⃣ 다양한 필터 예시
필터 종류 | 기능 |
수직 에지 검출 | 수직 경계선 감지 |
수평 에지 검출 | 수평 경계선 감지 |
블러 필터 | 흐릿하게 만듦 |
샤프닝 필터 | 윤곽 강조 |
4️⃣ 스트라이드(Stride)
- 필터가 한 번에 몇 칸씩 이동할지를 결정.
- 기본값은 stride=1 → 한 칸씩 이동
- 큰 stride는 더 빠른 처리 가능하지만 세밀한 정보 손실
Stride | 특징 |
1 | 정밀한 특징 추출 |
2 | 특징 추출 + 다운샘플링 |
≥3 | 속도 중시, 정보 손실 있음 |
5️⃣ 패딩(Padding)
🔸 개념
- 필터를 적용할 때 이미지의 경계 부분 정보가 손실되는 것을 보완하기 위해, 이미지 바깥에 추가 공간을 0으로 채움.
🔸 유형
패딩 종류 | 설명 | 사용 예시 |
Zero Padding | 0으로 채움 | 일반 CNN 대부분 |
Reflect Padding | 이미지 경계를 반사 | 고화질 이미지 복원 |
Edge Padding | 가장자리 반복 | 의료 영상 등 |
Wrap Padding | 주기적 반복 | 위성영상, 텍스처 분석 |
6️⃣ 출력 크기 계산 공식
출력 크기 = (입력 크기 - 필터 크기 + 2×패딩) ÷ 스트라이드 + 1
예시: 입력 32, 필터 3, 패딩 1, 스트라이드 1 → 출력 = (32-3+2×1)/1 + 1 = 32
7️⃣ 특징맵(Feature Map)
🔸 정의
- 컨볼루션을 통해 특정 패턴이 어디에 있는지 표시한 지도
- 층이 깊어질수록:
- 공간 크기↓
- 채널 수↑ (더 많은 특징 추출)
예:
입력: (224, 224, 3)
Conv1: (224, 224, 64) ← 에지
Conv2: (112, 112, 128) ← 패턴
Conv3: (56, 56, 256) ← 구조
Conv4: (28, 28, 512) ← 부분
Conv5: (14, 14, 512) ← 전체
8️⃣ 풀링(Pooling)
🔸 정의
특징맵 크기를 줄이면서 중요한 정보만 유지한다. 그리고 연산량이 감소되고, 과적합을 방지할 수 있으며, 위치 변화에 강한 특징을 갖는다.
🔸 종류
종류 | 설명 |
Max Pooling | 가장 큰 값 선택 |
Average Pooling | 평균값 선택 |
예: 2x2 Max Pooling
[1 3] → 3
[2 4]
⚙️ 요약 정리
개념 | 설명 |
컨볼루션 | 필터로 특징 추출 (slide하며 곱셈-합) |
스트라이드 | 필터 이동 간격 |
패딩 | 가장자리 보완 처리 |
출력 계산 | (입력 - 필터 + 2패딩)/스트라이드 + 1 |
특징맵 | 컨볼루션 결과로 나온 특징 지도 |
풀링 | 크기 축소 및 특징 요약 (max or average) |
CNN이 무엇인지와 컨볼루션에 대해 정리하며 학습해 보았으니 컨볼루션 연산 실습 코드를 통해 실제로 CNN이 이미지에서 어떻게 특징을 추출하는지, 예를 들어 체스보드 이미지에서 수직 에지를 검출하는 과정을 실습해 볼 것이다.
실습 목표: 체스보드의 수직 에지 검출
CNN에서 가장 기본적인 연산 중 하나는 에지(Edge) 를 검출하는 것이라고 할 수 있다. 특히 수직 경계선(Vertical edge)을 찾는 필터를 사용해서 이미지 내 수직선만을 뽑아내는 것을 이번 실습에서 중점적으로 이해해 볼 것이다.
[전체 코드]
import numpy as np
import matplotlib.pyplot as plt
# -----------------------------
# 1. 체스보드 이미지 생성
# -----------------------------
# 8x8 크기의 2차원 배열을 0으로 초기화 (흑백 이미지로 가정)
sample_image = np.zeros((8, 8))
# 홀수 행(1, 3, 5, 7) + 짝수 열(0, 2, 4, 6)에 1을 설정 (하얀 칸 역할)
sample_image[1::2, ::2] = 1
# 짝수 행(0, 2, 4, 6) + 홀수 열(1, 3, 5, 7)에 1을 설정 (하얀 칸 역할)
sample_image[::2, 1::2] = 1
# 이렇게 하면 0과 1이 교차하는 체스보드 패턴 완성됨
# -----------------------------
# 2. 수직 에지 커널 정의
# -----------------------------
# 수직 방향의 에지를 감지하기 위한 필터 (Sobel 필터 간략화 버전)
vertical_edge = np.array([
[-1, 0, 1], # 왼쪽 값 음수, 가운데 0, 오른쪽 값 양수 → 좌우 대비 강조
[-1, 0, 1],
[-1, 0, 1]
])
# -----------------------------
# 3. 컨볼루션 함수 정의
# -----------------------------
def convolution_2d(image, kernel, stride=1, padding=0):
"""
이미지에 대해 2D 컨볼루션 연산을 직접 구현한 함수
Args:
image: 입력 이미지 (2D 배열)
kernel: 필터 (정사각형)
stride: 커널의 이동 간격
padding: 이미지 주변을 0으로 확장하는 정도
"""
H, W = image.shape # 입력 이미지의 높이, 너비
K = kernel.shape[0] # 커널 한 변의 길이 (3이라면 3x3 필터)
# 이미지 패딩 적용: 주변에 padding만큼 0을 추가함
image = np.pad(image, padding, mode='constant') # constant 모드는 0으로 채움
H_padded, W_padded = image.shape # 패딩 적용 후의 새 이미지 크기
# 출력 크기 계산 공식: ((입력 - 커널) // 스트라이드) + 1
out_H = (H_padded - K) // stride + 1
out_W = (W_padded - K) // stride + 1
# 출력 배열 초기화 (컨볼루션 결과를 저장할 공간)
output = np.zeros((out_H, out_W))
# 컨볼루션 연산 수행
for i in range(out_H): # 세로 방향으로 슬라이딩
for j in range(out_W): # 가로 방향으로 슬라이딩
# 현재 커널이 덮을 이미지의 좌표 범위 계산
h_start = i * stride
h_end = h_start + K
w_start = j * stride
w_end = w_start + K
# 현재 위치의 이미지 조각(region) 추출
region = image[h_start:h_end, w_start:w_end]
# 커널과 이미지 조각을 원소별 곱하고 합산 → 해당 위치의 출력값
output[i, j] = np.sum(region * kernel)
return output # 완성된 컨볼루션 결과 반환
# -----------------------------
# 4. 커널 적용 및 결과 계산
# -----------------------------
# 커널이 3x3이므로 same padding 적용: (3-1)//2 = 1
padding = (vertical_edge.shape[0] - 1) // 2
# 샘플 이미지에 수직 에지 필터 적용
vertical_edges = convolution_2d(sample_image, vertical_edge, padding=padding)
# -----------------------------
# 5. 결과 출력
# -----------------------------
# 원본 이미지와 결과 이미지의 크기 출력
print(f"원본 크기: {sample_image.shape}")
print(f"결과 크기: {vertical_edges.shape}")
# -----------------------------
# 6. 시각화 (matplotlib 사용)
# -----------------------------
plt.figure(figsize=(10, 5)) # 가로 10, 세로 5인 크기로 시각화 영역 생성
# subplot 1: 원본 체스보드 이미지 출력
plt.subplot(1, 2, 1) # 1행 2열 중 첫 번째
plt.title("Original Image")
plt.imshow(sample_image, cmap='gray') # cmap='gray'는 흑백 컬러맵
plt.axis('off') # 축 제거
# subplot 2: 컨볼루션 결과 이미지 출력 (수직 에지 강조)
plt.subplot(1, 2, 2) # 1행 2열 중 두 번째
plt.title("Vertical Edges")
plt.imshow(vertical_edges, cmap='gray') # 수직 경계선이 보임
plt.axis('off') # 축 제거
plt.tight_layout() # 레이아웃 자동 조정
plt.show() # 실제 시각화 실행
[결과 예시]

[코드 설명]
# numpy와 matplotlib을 사용해 8x8 크기의 체스보드 형태 이미지 생성
→ 이 이미지는 흑(0)과 백(1)의 값이 번갈아가며 배열된 2차원 배열로 구성된다. np.zeros로 0으로 초기화한 후, 슬라이싱을 활용해 1이 들어갈 위치에 값을 설정함으로써 체스보드 패턴을 만든다.
# 수직 에지 검출용 필터(vertical_edge) 정의
→ 이 필터는 3x3 크기의 배열로, 좌측은 음수, 우측은 양수 값으로 구성돼 있다. 이렇게 구성된 필터는 이미지 내에서 수직 방향의 경계(에지) 를 강조하는 데 사용된다. 예를 들어 이미지의 한 영역에서 좌우 밝기 차이가 클 경우, 이 필터는 큰 값을 반환하며 그 위치를 에지로 인식하게 된다.
# convolution_2d라는 이름의 2D 컨볼루션 연산 함수 정의
→ 이 함수는 입력 이미지와 필터를 받아, stride(이동 간격)와 padding(경계 확장) 조건에 따라 직접 연산을 수행한다. 먼저 이미지의 크기와 커널의 크기를 확인한 후, np.pad 함수를 사용하여 padding을 적용한다. 이후 컨볼루션의 출력 크기를 계산하고, 이 크기에 맞는 결과 배열을 생성한다. 핵심 연산은 이중 for문으로 수행되며, 필터가 이미지 위를 이동하면서, 해당 위치의 입력 이미지 영역(region)과 필터를 원소별 곱셈한 후 합산하여 결과에 저장한다.
# 컨볼루션 연산을 수행할 때는 same padding을 적용하기 위해 커널 크기의 절반만큼 padding을 설정
→ 이렇게 설정된 padding은 컨볼루션 연산 후에도 출력 이미지가 원본 이미지와 동일한 크기를 유지하도록 도와준다. 이후, convolution_2d 함수를 통해 체스보드 이미지와 수직 에지 필터를 적용한 결과가 vertical_edges 변수에 저장된다.
# matplotlib.pyplot을 이용해 결과를 시각화한다.
→ 두 개의 subplot을 사용하여 좌측에는 원본 체스보드 이미지를, 우측에는 수직 에지가 검출된 결과 이미지를 출력한다. 출력된 결과에서는 수직 방향으로 값이 급격히 변하는 지점이 밝은 회색 또는 흰색으로 강조한다.
CNN을 학습하는 도중 컨볼루션(Convolution)이라는 핵심 개념이 잘 이해되지 않았다. 컨볼루션은 CNN에서 입력 이미지에서 의미 있는 특징(경계, 패턴 등)을 추출하는 연산으로, 필터(kernel) 또는 커널을 입력 데이터 위에서 슬라이딩시키며 연산을 수행한다고 정의한다.
하지만, 여기서 입력 이미지에서 의미 있는 특징을 추출하는데 이 특징(Feature)라는 것이 정확히 어떤 것을 의미하는지가 헷갈렸다. 색을 의미하는 것인지, 명암을 의미하는 것인지, 어떤 것을 의미하는지가 잘 이해되지 않아 추가적인 학습을 진행해 보았다.
이 개념에서 말하는 '특징(Feature)'는 Edge, Shape, Texture, Part를 포함하는 입력되어 있는 이미지에서 추출할 수 있는 거의 모든 속성을 의미하는 것 같다.
단계별로 CNN이 학습하는 특징이 다르지만 최종적으로 인식하는 대상을 결론짓기 위해서는 위와 같이 거의 모든 특징이 필요한 것으로 보인다.
이번에는 CNN이 무엇인지와 CNN의 가장 중요한 개념이라고 할 수 있는 컨볼루션(Convolution)에 대해 정리하며 학습해 보았다. 다음에는 CNN 중 다중 채널 컨볼루션과 풀링, CNN 아키텍처 설계 등을 학습하며, 그에 해당하는 실습 코드를 통해 학습 내용에 대해 이해해보려 한다.
본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 (B-log) 리뷰로 작성 되었습니다.