KAIST Junior · 2026년 1학기 · AI
🧠

End-to-end
가짜 이미지 탐지 모델 학습

AI를 활용한 가짜 이미지탐지 모델 만들기 · 2차시

CLIP + k-NN을 넘어, ResNet-18 딥러닝 모델을 직접 학습시켜 봅니다.
탐정(Convolutional Layer)과 판사(Linear Layer)가 협력해
이미지를 보고 "진짜"인지 "가짜"인지 스스로 판단하는 모델을 완성해 봅시다.

📑 목차

1
1. 발상 전환
CLIP + k-NN을 직접 학습시키는 딥러닝 모델로 확장
2
2. 심화 탐구
End-to-end 학습 / ResNet-18 구성요소 / End-to-end 이진 분류 11단계 코드
3
3. 실전 해결
1차시 결과와 비교 · 원인 분석 · 성능 향상 방안
4
참고자료
ResNet · PyTorch · Adam · CrossEntropyLoss
Part 1

1. 발상 전환

왜 이번에는 딥러닝 모델을 직접 학습시킬까?

발상 전환

지난 시간에는 CLIP 모델을 활용해 진짜와 가짜 이미지를 구분하는 과정을 배웠습니다. CLIP은 미리 학습된 딥러닝 모델로, 이미지의 특징을 추출하고 이를 기반으로 k-NN 알고리즘을 사용해 가짜 이미지를 분류했죠. 여러분은 이 과정에서 딥러닝 모델이 이미지를 분석하고 진짜와 가짜를 구분하는 데 얼마나 강력한지 직접 확인할 수 있었습니다.

그런데 한 가지 궁금하지 않나요?
"우리가 직접 딥러닝 모델을 학습시킨다면 어떨까요?"

CLIP과 같은 사전 학습된 모델은 이미 수많은 데이터를 기반으로 학습된 결과물이지만, 이번에는 여러분이 직접 딥러닝 모델을 설계하고, 학습시키고, 진짜와 가짜 이미지를 분류하는 과정을 체험해 볼 거예요. "내가 만든 모델이 정말 가짜 이미지를 잘 찾아낼까?"라는 질문과 함께 말이죠!

이번 차시에는 간단한 CNN(Convolutional Neural Network) 모델을 사용해 진짜와 가짜 이미지를 분류하는 방법을 배웁니다. 이번 학습을 통해 CNN이 이미지를 이해하는 과정을 탐구하면서, 특징 추출과 분류가 어떻게 이루어지는지 배울 수 있습니다.

💡 딥러닝 모델을 직접 학습시키며, AI 기술을 더 깊이 이해하고 재미를 느껴봅시다!

학습내용

이번 수업은 End-to-End 가짜 이미지 탐지 모델 학습을 중심으로 진행됩니다.

학습목표

핵심 키워드

🔁 End-to-end 학습

데이터 입력과 출력, 특징 학습, 학습 파이프라인

🧩 CNN의 구성요소

Convolutional Layer, Linear Layer

✅ End-to-end 이진 분류

데이터셋 분리, 손실 함수, 평가 지표

프로젝트를 위한 사전 준비물 혹은 설치해야 하는 소프트웨어

Part 2

2. 심화 탐구

End-to-end 학습 · ResNet-18 구조 · 11단계 학습 파이프라인

2-1. End-to-end 학습

지난 시간에는 이미지를 분석해서 중요한 특징을 먼저 뽑아내고, 그 특징으로 진짜인지 가짜인지 예측했어요. 이번에는 End-to-End 학습 방법을 써서 이미지를 모델에 넣기만 하면, 바로 진짜인지 가짜인지 결과를 알려주는 방법을 배워볼 거예요. 모델이 스스로 배우고 똑똑해지는 과정을 함께 알아봅시다.

End-to-end 학습이란?

End-to-End 학습은 처음부터 끝까지 한 번에 모든 과정을 배우는 방법이에요. 가짜 이미지 탐지에서는 이미지를 모델에 넣으면, 모델이 진짜인지 가짜인지 바로 판단할 수 있도록 학습합니다. 이 방식은 사람이 직접 단계별로 작업을 설계할 필요 없이, 모델이 스스로 필요한 특징을 찾아내고 결과를 보여줘요.

예를 들어, 기존 방식에서는 이미지를 분석하기 위해 여러 단계를 거쳤지만, End-to-End 학습은 이 모든 단계를 하나의 모델로 통합해 처리합니다. 이 덕분에 더 간단하고 효율적인 학습이 가능해요.

두 방법의 비교

📚 CLIP + k-NN 방식 (1차시)

  1. 이미지를 넣으면, CLIP 모델이 이미지에서 중요한 정보를 숫자로 변환 (특징 추출).
  2. 변환된 숫자를 k-NN 알고리즘이 비교해 가장 가까운 결과를 찾아냄. 가장 좋은 결과를 찾는 k의 값을 실험으로 찾아야 함.
  3. 결과로 진짜인지 가짜인지 알려줌.

🚀 End-to-End 학습 방식 (2차시)

  1. 이미지를 넣으면, 모델이 특징을 직접 학습하고 결과까지 바로 출력.
  2. 중간 과정 없이 모델이 모든 과정을 한 번에 학습.

End-to-end 학습의 장점

1. 모델이 스스로 가짜 이미지를 찾아내는 패턴을 배워요.
2. End-to-End 학습은 고차원 데이터(복잡한 이미지 데이터)의 세부적인 차이도 잘 이해해요.
3. 한 번에 모든 과정을 '최적화'합니다.
최적화는 모델이 더 똑똑해지도록 학습하는 과정입니다.

End-to-end 학습의 단점

1. 많은 데이터가 필요합니다.
2. 문제가 생기면 원인을 찾기 어렵습니다.
3. 학습 속도가 느릴 수 있습니다.

2-2. ResNet의 구성요소 이해하기

ResNet-18이라는 모델은 탐정과 판사 팀이 협력해 이미지를 분석하고 진짜인지 가짜인지 판단하는 과정을 거칩니다. 여기서 탐정은 Convolutional Layer, 판사는 Linear Layer 역할을 합니다. 이제 이 팀이 어떻게 일을 하는지 차근차근 알아볼게요!

1. Convolutional Layer (탐정)

탐정은 이미지를 보면서 중요한 단서를 찾아냅니다. 처음에는 간단한 단서를 보고, 나중에는 더 복잡한 단서를 찾아요.

· 탐정의 첫 번째 일: 기본 단서 찾기

탐정은 먼저 "이 이미지에서 가장 뚜렷한 선은 어디지?" 또는 "어떤 부분이 더 밝고 어두운가?" 같은 단서를 모읍니다. 예를 들어, 고양이 사진이라면 "여기 둥근 귀가 있네!", "여기 수염 같은 선이 있어!" 같은 기본적인 정보를 찾습니다.

· 탐정의 두 번째 일: 세부적인 단서 찾기

탐정은 점점 더 깊이 들어가며, "이건 고양이의 눈 모양 같아!", "고양이의 꼬리가 이런 방향으로 휘었네!" 같은 세부적인 단서를 추가로 모읍니다. 단서를 많이 모으면 모을수록 이미지를 더 잘 이해할 수 있게 됩니다.

탐정 (Convolutional Layer) 코드

코드를 통해 탐정이 하는 일을 좀 더 자세히 살펴봅시다. 탐정은 이미지에서 단서를 찾는 역할을 합니다. ResNet-18의 Conv1은 가장 첫 번째 탐정 역할을 수행하며, 단순한 선과 색상 같은 기본적인 패턴을 찾습니다.

Python# ResNet-18 모델 불러오기
model = models.resnet18(pretrained=True)

# 첫 번째 Convolutional Layer 확인 (탐정의 첫 번째 역할)
conv1 = model.conv1
print(conv1)
OutputConv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
구성 요소의미
필터 (7×7)7×7 크기의 작은 창으로 이미지를 훑으며 패턴을 찾습니다.
입력 채널 (3)RGB 이미지의 3개 채널 (빨강, 초록, 파랑).
출력 채널 (64)64개의 단서를 찾아냅니다.
Stride (2)탐정이 한 번에 두 칸씩 점프하며 이미지를 분석합니다.

탐정의 진행 과정 (Residual Block)

탐정은 처음에 찾은 단서를 가지고 더 복잡한 단서를 찾아갑니다. Residual Block은 탐정이 정보를 잃지 않고 더 깊은 분석을 가능하게 합니다.

Python# Residual Block 확인 (탐정의 두 번째 역할)
layer1 = model.layer1
print(layer1)
OutputSequential(
  (0): BasicBlock(
    (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
    (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    (relu): ReLU(inplace=True)
    (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
    (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  )
  (1): BasicBlock( ... 동일 구조 ... )
)
구성 요소의미
Residual Block기존 단서를 더 깊이 분석하면서도 중요한 정보를 잃지 않도록 돕는 역할입니다.
Conv2d (64, 64)64개의 입력 단서를 받아 더 세밀한 64개의 단서를 만듭니다.
Stride (1)탐정이 한 번에 한 칸씩 점프하므로 더 촘촘히 분석합니다.

2. Linear Layer (판사)

탐정이 단서를 모두 모아오면, 이제 판사가 "이 단서들을 보니, 이건 진짜야!" 또는 "이건 가짜야!"라고 판단합니다.

· 판사의 첫 번째 일: 단서 정리하기

탐정이 가져온 여러 단서를 하나로 정리합니다. 예를 들어, 탐정이 "둥근 귀, 날카로운 수염, 길다란 꼬리"라는 단서를 가져오면, 판사는 이것들을 조합해 "이건 진짜 고양이일 가능성이 높아!"라고 생각합니다.

· 판사의 두 번째 일: 최종 판결 내리기

판사는 정리된 단서를 바탕으로 최종 결정을 내립니다.

판사 (Linear Layer) 코드

탐정이 단서를 모두 정리하면, 판사는 이를 종합하여 "진짜"인지 "가짜"인지 최종 결론을 내립니다.

Python# ResNet-18의 Linear Layer 확인 (판사 역할)
model.fc = nn.Linear(model.fc.in_features, 2)  # 2개의 출력값 (진짜/가짜)
print(model.fc)
OutputLinear(in_features=512, out_features=2, bias=True)
구성 요소의미
입력 노드 (512)탐정이 마지막으로 정리한 512개의 단서를 받습니다.
출력 노드 (2)진짜(0)와 가짜(1)를 두 가지로 구분하는 결과를 출력합니다.
Bias분류를 더 잘하도록 조정 값을 추가합니다.

3. 탐정과 판사의 협력 과정

탐정이 단서를 찾는 과정
Python# 임의의 입력 이미지 텐서 생성 (3x224x224 크기)
# 배치 크기 1, RGB 채널 3, 크기 224x224
dummy_image = torch.randn(1, 3, 224, 224)

# 첫 번째 탐정(Conv1)이 단서를 찾음
features = model.conv1(dummy_image)
print(f"Conv1 출력 크기: {features.shape}")
OutputConv1 출력 크기: torch.Size([1, 64, 112, 112])

→ 64개의 특징 맵(단서)을 찾고, 이미지 크기는 절반(112×112)으로 줄어듭니다.

판사가 최종 결론을 내리는 과정
Python# 전체 모델을 통해 최종 출력 생성
model.fc = nn.Linear(model.fc.in_features, 2)  # 두 가지 분류를 하는 판사
model = model.to("cpu")  # CPU로 이동
output = model(dummy_image)  # 임의의 이미지로 예측
print(f"최종 출력: {output}")
Output최종 출력: tensor([[0.1456, 0.1755]], grad_fn=<AddmmBackward0>)

두 개의 값(진짜, 가짜)에 대한 점수를 출력합니다.
예시처럼 두 값 중 더 높은 값이 가짜(1)로 분류됩니다.

Part 2-3

2-3. End-to-end 이진 분류 학습 완성하기

11단계 학습 파이프라인 — 데이터 준비부터 모델 평가까지

이번에는 ResNet-18 모델을 사용해 이미지를 "진짜"와 "가짜"로 분류하는 과정을 체험해 볼 거예요. ResNet-18은 탐정(Convolutional Layer)판사(Linear Layer)로 구성된 팀처럼 작동합니다.

탐정과 판사 팀의 여정

🔍 탐정 (Conv Layer)

이미지를 분석하고 단서를 모아 패턴을 학습합니다.

⚖️ 판사 (Linear Layer)

탐정이 모은 단서를 바탕으로 "진짜"인지 "가짜"인지 최종 판단합니다.

🚀 전체 과정

데이터를 준비하고 모델을 학습시킨 뒤, 결과를 평가하는 단계로 진행됩니다.

11단계 학습 파이프라인 한눈에 보기


설치

import

경로 설정

Dataset 클래스

전처리

train/test 분리

ResNet-18 정의

손실/최적화

train_model

evaluate_model

실행 & 평가

Step 1필수 라이브러리 설치

Colab에서 실행할 코드를 준비하려면, 먼저 필요한 도구들을 설치해야 합니다.

Colab# Google Colab에서만 실행하세요. 이 명령어는 딥러닝과 데이터 처리를 위한 라이브러리를 설치합니다.
%pip install torch torchvision matplotlib tqdm scikit-learn gdown

Step 2라이브러리 불러오기

필수 라이브러리를 불러와 코드를 준비합니다.

Pythonimport os       # 폴더와 파일을 다루기 위한 라이브러리
import random   # 랜덤하게 데이터를 섞기 위한 라이브러리
import numpy as np      # 수학 계산용 라이브러리
from PIL import Image  # 이미지를 다루기 위한 라이브러리
import matplotlib.pyplot as plt   # 그래프와 이미지를 시각화하기 위한 라이브러리
from tqdm import tqdm        # 진행 상태를 보여주는 라이브러리

import torch                       # 딥러닝의 핵심 라이브러리
import torch.nn as nn             # 신경망 구성에 필요한 모듈
import torch.optim as optim       # 최적화를 위한 모듈
from torchvision import models, transforms   # 사전 학습된 모델과 데이터 변환 모듈
from torch.utils.data import DataLoader, Dataset   # 데이터 로딩에 필요한 모듈

Step 3데이터 경로 설정

1차시와 같이 진짜/가짜 이미지 데이터셋을 다운받고 압축을 풀어줍니다.

Python%gdown https://drive.google.com/uc?id=1q8mDau3_VCXqKamNqkfqVw3hAzy600jD
%unzip /content/real_vs_fake_dataset.zip

# Real과 Fake 이미지를 저장한 폴더 경로를 입력합니다.
real_image_dir = "/content/real_vs_fake_dataset/0_real"   # Real 이미지가 들어 있는 폴더
fake_image_dir = "/content/real_vs_fake_dataset/1_fake"   # Fake 이미지가 들어 있는 폴더

Step 4데이터 처리 클래스 정의

탐정이 이미지를 쉽게 분석할 수 있도록 데이터를 준비합니다. 이미지가 들어있는 폴더에서 하나씩 이미지를 불러오고 라벨(진짜/가짜)도 정해줍니다.

Python# 이미지를 불러오고, 변환하며, 학습에 사용할 준비를 합니다.
class ImageDataset(Dataset):
    def __init__(self, image_dirs, labels, transform=None):
        self.image_paths = []
        self.labels = []
        for image_dir, label in zip(image_dirs, labels):
            paths = [os.path.join(image_dir, img)
                     for img in os.listdir(image_dir)
                     if img.endswith(('.png', '.jpg', '.jpeg'))]
            self.image_paths.extend(paths)
            self.labels.extend([label] * len(paths))
        self.transform = transform

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        image = Image.open(self.image_paths[idx]).convert("RGB")
        label = self.labels[idx]
        if self.transform:
            image = self.transform(image)
        return image, label
구성 요소역할
ImageDataset 클래스이미지를 가져와서 각 이미지에 라벨(진짜/가짜)을 추가합니다.
__getitem__해당 번호(인덱스)의 이미지를 읽고, 변환한 후 라벨과 함께 반환합니다.
__len__데이터셋에 포함된 이미지 개수를 반환합니다.

Step 5데이터 전처리

이미지를 ResNet-18에 맞게 변환합니다.

Pythontransform = transforms.Compose([
    # ResNet-18은 224x224 크기의 이미지를 입력으로 받습니다.
    transforms.Resize((224, 224)),
    # 이미지를 텐서(숫자 배열)로 변환합니다.
    transforms.ToTensor(),
    # ResNet-18에 맞는 표준화 값
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

Step 6데이터셋 생성 및 분리

전체 데이터를 학습용 80%테스트용 20%로 나눠요. 학습용 데이터로 모델을 배우게 하고, 테스트용 데이터로 모델이 잘 배웠는지 확인합니다.

Python# Real과 Fake 이미지를 라벨링하여 데이터셋을 생성합니다.
real_label = 0   # Real 이미지는 0으로 라벨링
fake_label = 1   # Fake 이미지는 1로 라벨링

dataset = ImageDataset([real_image_dir, fake_image_dir],
                       [real_label, fake_label],
                       transform=transform)

# 데이터셋을 학습용과 테스트용으로 나눕니다.
train_size = int(0.8 * len(dataset))
test_size = len(dataset) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(dataset, [train_size, test_size])

# DataLoader를 사용해 데이터를 배치로 나눕니다.
batch_size = 16   # 한 번에 처리할 데이터 개수
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
구성 요소역할
이미지 변환이미지를 ResNet-18 모델이 이해할 수 있는 크기(224×224)로 줄입니다. 이미지를 숫자로 바꾸고, 숫자의 크기를 일정하게 맞춥니다(정규화).
데이터셋 나누기전체 데이터를 학습용(80%)테스트용(20%)으로 나눠요.
DataLoader데이터를 한 번에 여러 개씩 묶어서(배치) 모델에 전달합니다. 이렇게 하면 모델이 더 빠르게 학습할 수 있어요.

Step 7ResNet-18 모델 정의 — 모델 만들기와 학습 준비

탐정과 판사가 팀을 이뤄 이미지를 분석합니다.

Python# 사전 학습된 ResNet-18 모델을 불러오고 출력 크기를 조정합니다.
model = models.resnet18(pretrained=True)

# 모델의 마지막 레이어를 2개의 출력 노드(진짜/가짜)로 변경합니다.
model.fc = nn.Linear(model.fc.in_features, 2)

# 모델을 GPU로 이동합니다 (가능한 경우).
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)

Step 8학습 준비 (손실 함수와 최적화 정의)

Python# 분류 문제에 적합한 손실 함수
criterion = nn.CrossEntropyLoss()
# 모델 학습을 위한 최적화 알고리즘
optimizer = optim.Adam(model.parameters(), lr=0.001)
구성 요소역할
ResNet-18 불러오기ResNet-18은 이미 많은 데이터를 학습한 똑똑한 모델이에요. 이 모델을 가져와서 우리가 사용할 거예요.
출력 수정하기ResNet-18은 원래 여러 종류의 이미지를 구분하지만, 여기서는 진짜(0)와 가짜(1)만 구분하도록 수정합니다.
손실 함수 (Loss)모델이 얼마나 틀렸는지 계산하는 도구입니다. 모델이 잘못된 예측을 하면 손실 값을 통해 고칠 수 있어요.
최적화 도구 (Optimizer)손실 값을 줄이기 위해 모델이 더 잘 배울 수 있도록 돕는 도구입니다.

Step 9모델 학습 함수 정의 — 탐정과 판사의 학습

탐정은 이미지를 분석하며 단서를 찾고, 판사는 결과를 판단합니다.

Python# 모델을 학습시키기 위한 함수입니다.
def train_model(model, train_loader, criterion, optimizer, epochs=5):
    model.train()   # 모델을 학습 모드로 설정
    for epoch in range(epochs):
        total_loss = 0
        for images, labels in tqdm(train_loader, desc=f"Epoch {epoch + 1}/{epochs}"):
            images, labels = images.to(device), labels.to(device)

            # 모델이 예측한 결과와 손실 계산
            outputs = model(images)
            loss = criterion(outputs, labels)

            # 역전파를 통해 모델 가중치 업데이트
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            total_loss += loss.item()
        print(f"Epoch {epoch + 1}, Loss: {total_loss / len(train_loader):.4f}")
구성 요소역할
train_model 함수모델이 데이터를 보고 "이건 진짜다!" 또는 "이건 가짜다!"를 판단하도록 학습시킵니다.
모델이 틀렸을 때
  • 손실 값을 계산해서 왜 틀렸는지 알아냅니다.
  • 잘못된 부분을 고치기 위해 가중치를 업데이트합니다.
  • 매 에포크(학습 반복)마다 손실 값을 출력해 얼마나 잘 배우고 있는지 확인합니다.

Step 10모델 평가 함수 정의 — 학습한 탐정과 판사의 평가

탐정과 판사 팀이 협력해 이미지를 분석하고 학습한 모델이 얼마나 잘 판단하는지 최종 평가합니다.

Python# 모델을 평가하기 위한 함수입니다.
def evaluate_model(model, test_loader):
    model.eval()   # 모델을 평가 모드로 설정
    correct = 0
    total = 0
    with torch.no_grad():   # 평가 시에는 가중치 업데이트를 하지 않음
        for images, labels in test_loader:
            images, labels = images.to(device), labels.to(device)
            outputs = model(images)
            _, predicted = torch.max(outputs, 1)   # 가장 높은 값을 가진 클래스를 예측값으로 설정
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    print(f"Accuracy: {100 * correct / total:.2f}%")

Step 11모델 학습 및 평가 실행

Pythontrain_model(model, train_loader, criterion, optimizer, epochs=5)
evaluate_model(model, test_loader)
구성 요소역할
evaluate_model 함수테스트 데이터를 사용해서 모델이 학습한 내용을 점검합니다.
model.eval()평가 모드로 전환해 학습 과정에서 사용하던 불필요한 도구를 끕니다.
정확도 계산모델이 맞춘 예측의 비율을 계산해 "정확도"를 출력합니다. 몇 퍼센트 맞췄는지 알 수 있어요.

🎯 마무리하며

여기까지 따라왔다면 여러분은 이제 딥러닝 모델을 직접 학습시킨 사람입니다. 1차시의 CLIP+k-NN과 비교해서 정확도가 얼마나 달라졌는지, 학습 시간이 얼마나 걸렸는지 직접 확인해 봅시다. 다음 Part 3 실전 해결에서 결과를 정리해 봐요!

Part 3

3. 실전 해결

나의 첫 인공지능 모델을 평가하고 개선하기

1차시에서 만든 CLIP+k-NN 모델과 비교해서, 이번에 만든 ResNet-18 End-to-End 모델은 어떤 결과를 보여줬나요? 정확도, 학습 시간, 데이터 양과의 관계를 정리해 봅시다.

📝 Q1. 1차시 CLIP + k-NN과 비교해서 어떤 결과를 얻었나요?
예시 답안:
• 1차시 정확도: ___% / 2차시 정확도: ___%
• 학습 시간: 1차시는 즉시 분류 가능 / 2차시는 5 epoch 학습에 약 ___분
• 정확도가 더 높은가요? 낮은가요? 그 차이는 얼마나 되나요?
💡 힌트: 두 노트북을 모두 실행한 뒤 출력된 Accuracy 값을 비교해 보세요.
🤔 Q2. 왜 이런 결과가 나왔을까요?
생각해 볼 포인트:
• 데이터 양은 충분했나요? (real_vs_fake_dataset의 이미지 개수)
• Epoch 수(5)가 적절했을까요? 더 많이 학습하면 어떻게 될까요?
• ResNet-18이 사전학습(pretrained)된 가중치를 활용한 점이 어떤 영향을 줬을까요?
• k-NN의 k 값과 ResNet-18의 lr(0.001)을 비교하면?
💡 힌트: End-to-End 학습의 장점/단점 (Section 2-1) 을 다시 살펴보세요.
🚀 Q3. 어떻게 하면 더 좋은 성능을 달성할 수 있을까요?
개선 아이디어:
데이터 늘리기: 데이터 증강(Data Augmentation, e.g. 좌우 반전, 회전)을 추가하면?
학습 길게 하기: epochs를 5 → 10, 20으로 늘리면?
학습률 조정: lr=0.001 → 0.0005, 0.0001로 바꾸면?
모델 변경: ResNet-18 → ResNet-50, EfficientNet 등 더 큰 모델을 쓰면?
과적합 방지: Dropout, Weight Decay를 추가하면?
💡 힌트: 한 번에 다 바꾸지 말고, 한 가지씩 바꿔가며 실험해 보세요!

실험 기록 권장 양식

실험 번호변경한 항목설정 값학습 시간정확도비고
실험 1 (기준)epochs=5, lr=0.001약 ___분___%기준 모델
실험 2epochs ↑epochs=10
실험 3lr ↓lr=0.0001
실험 4증강 추가RandomHorizontalFlip
Part 4

참고자료

더 깊이 공부하고 싶다면

핵심 개념 정리

End-to-End 학습
입력에서 출력까지 모든 과정을 하나의 모델 안에서 학습하는 방식. 사람이 단계별로 손볼 필요 없이 모델이 스스로 최적화함. 단, 충분한 데이터와 학습 시간이 필요함.
CNN (Convolutional Neural Network)
이미지의 공간 정보를 보존하며 특징을 추출하는 신경망. 필터(kernel)를 이미지 위에서 슬라이드시키며 패턴을 찾음.
ResNet-18
2015년 Microsoft Research가 발표한 ResNet(Residual Network) 계열 중 가장 작은 18-layer 모델. Skip connection (Residual Block)으로 깊은 네트워크의 학습 안정성을 확보. ImageNet으로 사전학습된 버전을 활용 가능.
Convolutional Layer
입력에 필터를 컨볼루션 연산으로 적용해 특징 맵(feature map)을 만드는 층. Conv2d(in_channels, out_channels, kernel_size, stride, padding) 형태로 정의.
Linear Layer (Fully Connected Layer)
벡터를 받아 가중치 행렬과 곱한 뒤 편향을 더해 출력하는 층. 분류 문제의 마지막 단에서 클래스별 점수(logit)를 출력함.
CrossEntropyLoss
다중 분류(2개 이상)에 사용하는 손실 함수. 모델 출력값(logit)과 정답 라벨 사이의 차이를 측정. PyTorch에서는 내부에 softmax가 포함되어 있어 raw logit을 그대로 입력함.
Adam Optimizer
2014년 Kingma & Ba가 제안한 적응형 학습률 최적화 알고리즘. 모멘텀과 RMSProp의 장점을 결합. 일반적으로 lr=0.001이 무난한 시작값.
Epoch / Batch / Iteration
Epoch: 전체 학습 데이터를 한 번 다 본 횟수 / Batch: 한 번에 모델에 넣는 데이터 묶음 (여기서는 16) / Iteration: 한 batch를 처리하는 한 번의 학습 단계.

자주 만나는 에러와 해결

증상원인해결
CUDA out of memorybatch_size가 너무 큼batch_size를 16 → 8 → 4로 줄이기
Loss가 계속 같은 값에서 멈춤학습률(lr)이 너무 큼/작음lr을 0.0001 ~ 0.01 사이에서 조정
Accuracy가 50%에서 안 오름이진 분류에서 한쪽 클래스만 예측데이터 균형 확인, epochs 늘리기
FileNotFoundErrorgdown/unzip 단계 실패Step 3을 다시 실행해 폴더 존재 확인

더 알아보기

🎓 다음 단계로 가는 다리

2차시까지 마쳤다면 딥러닝 모델 학습의 전체 사이클을 한 번 돌려본 셈입니다. 다음 단계로는 (1) 전이학습(Transfer Learning) 깊이 다루기, (2) Vision Transformer(ViT)로 모델 확장, (3) 설명 가능한 AI(Grad-CAM)로 모델이 어디를 보고 판단했는지 시각화 — 이 세 가지를 추천합니다.

Junior KAIST 2026년 1학기 · AI 2차시 수업자료 · End-to-end 가짜 이미지 탐지 모델 학습