수달이네 기술 블로그

10. CNN 구현 본문

AI공부/딥러닝

10. CNN 구현

슬픈 수달이 2026. 2. 6. 21:20

구현

이미지 입력

import torch
import torch.nn as nn
import torch.optim as optim
inputs = torch.Tensor(1,1,28,28) # (배치크기, 채널, 높이, 너비)
print(inputs.shape)

입력값은 Tensor로 넣어줄 때, (배치크기, 채널(그레이스케일이므로 1), 높이, 너비 로 입력된다.

  • RGB의 경우 3, 그레이스케일 1
  • 지금은 28281의 이미지가 1개 있다는 이야기, 만약 이걸 30장 넣으면 배치크기가 30 (한번에 넣는 크기)

Conv1

conv1 = nn.Sequential(
    nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride = 1, padding='same'),
    nn.ReLU()
)
out = conv1(inputs) # (1, 32, 28, 28)

CNN은 Conv2d 즉 2차원 데이터를 통째로 넣는 연산을 진행한다.

  • in_channel: 데이터 n개를 통째로 넣음 (1개 채널)
  • out_channel: n개의 특징을 추출하겠다. (채널이 1 > 32이됨)

  • 위와 같이 Conv연산을 수행할때 첫번째 3에서 6개로 세분화 된것이 6개의 특징을 추출한 것이다.
  • Kernel_size: CNN에서 이미지를 스캔하는 가중치 행렬의 크기
  • padding: 가장자리에 패딩을 넣음 same의 경우 이전 이미지와 같은 결과의 크기를 만드는 연산, 즉 넣음
    • 여기서 stride를 넣는다면, 이걸 계산해서 같은 크기로 same연산을 진행한다.
  • stride: 커널이 한번에 몇칸을 갈 것인지

이후 ReLU 활성화 함수를 통해 비선형성을 만들어준다.

MaxPooling1

pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
out = pool1(out)

사이즈를 줄여주는 다운 스케일링(down scaling)

  • 여기선 커널 사이즈가 2이므로 절반크기 즉 14로 줄어듬
  • torch.Size([1, 32, 28, 28]) > torch.Size([1, 32, 14, 14])

Conv2

Conv2 = nn.Sequential(
    nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding='same'),
    nn.ReLU()
)

out = Conv2(out)
out.shape

위와 같은 연산이지만 입력 사이즈는 32로 이전 Conv1의 출력 크기와 같게한다

  • torch.Size([1, 32, 14, 14]) > torch.Size([1, 64, 14, 14])

MaxPooling2

pool2 = nn.MaxPool2d(kernel_size=2)
out = pool2(out)

out.shape
  • torch.Size([1, 64, 14, 14]) > torch.Size([1, 64, 7, 7])

Fully connected Layer

Flatten 평탄화

flatten = nn.Flatten()
out = flatten(out) # 1열로 만들어준다.
print(out.shape)
  • 1열로 평평하게 만들어준다 즉 1647*7 = 3136 > torch.Size([1, 3136])

fully connected

fc = nn.Sequential(
    nn.Dropout(0.5),
    nn.Linear(3136, 10)
)
out = fc(out)
print(out.shape)
  • Dropout으로 절반을 껐다 켜주어 과적합 방지(선형 모델과 비슷하게 진행)
  • Linear선형 연산 (3136 > 10)