UNet에서 직접 따라간 구현 흐름과 코드 증거를 다시 볼 수 있게 정리한 DL 학습 기록입니다. 본문은 실험의 큰 흐름을 먼저 훑고, @title UNet 모델 정의, from pdb import run, @title 학습 루프 같은 코드로 실제 구현을 이어서 확인할 수 있습니다. md 원본과 11개 코드 블록, 8개 실행 셀을 함께 남겨 구현 흐름을 다시 따라갈 수 있게 정리했습니다. 주요 스택은 os, numpy, PIL, torch입니다.

남겨둔 자료: md 원본과 11개 코드 블록, 8개 실행 셀을 함께 남겨 구현 흐름을 다시 따라갈 수 있게 정리했습니다. 주요 스택은 os, numpy, PIL, torch입니다.

주요 스택: os, numpy, PIL, torch, torchvision

Snapshot

Item Value
Track DL
Type Archive Note
Source Files md
Code Blocks 11
Execution Cells 8
Libraries os, numpy, PIL, torch, torchvision, matplotlib, pdb
Source Note (실습)UNet

What This Note Covers

  • 이 기록은 DL 트랙의 Archive Note 아카이브로 정리되어 있습니다.

Why This Matters

데이터 파이프라인

  • 왜 필요한가: 모델 성능 이전에 입력이 일정한 형식으로 잘 들어가야 학습과 평가가 안정적으로 반복됩니다.
  • 왜 이 방식을 쓰는가: Dataset/DataLoader 구조는 데이터 읽기, 변환, 배치 처리를 분리해 코드 재사용성과 실험 반복성을 높여줍니다.
  • 원리: 각 샘플을 Dataset이 제공하고, DataLoader가 이를 배치로 묶어 셔플·병렬 로딩·collate를 담당합니다.

학습 루프와 최적화

  • 왜 필요한가: 모델을 한 번 정의했다고 바로 학습되는 것이 아니라, 손실을 계산하고 가중치를 반복적으로 갱신하는 루프가 필요합니다.
  • 왜 이 방식을 쓰는가: optimizer와 scheduler를 명시적으로 두면 학습률 변화와 갱신 방식을 실험별로 비교하기 쉬워집니다.
  • 원리: 예측값과 정답의 차이로 손실을 계산하고, 역전파로 기울기를 구한 뒤 optimizer가 가중치를 업데이트합니다.

합성곱 기반 특징 추출

  • 왜 필요한가: 이미지는 인접 픽셀 관계와 지역 패턴이 중요해서, 완전연결층만으로는 공간 구조를 효율적으로 잡기 어렵습니다.
  • 왜 이 방식을 쓰는가: CNN은 필터를 공유하며 지역 특징을 반복적으로 추출할 수 있어 이미지 실습의 기본 뼈대로 적합합니다.
  • 원리: 작은 커널이 이미지 위를 이동하며 특징을 뽑고, 층이 깊어질수록 더 추상적인 패턴을 학습합니다.

Implementation Flow

  1. 원본 노트의 문제 정의를 먼저 확인합니다.
  2. 핵심 코드 블록과 구현 단계를 따라갑니다.
  3. 필요하면 이 흐름을 별도 케이스 스터디로 확장합니다.

Code Highlights

@title UNet 모델 정의

@title UNet 모델 정의는 이 노트에서 핵심 구현을 보여주는 코드 블록입니다. 코드 안에서는 UNet 모델 정의 흐름이 주석과 함께 드러납니다.

#@title UNet 모델 정의
class DoubleConv(nn.Module):
    def __init__(self, in_ch, out_ch):
        super().__init__()
        self.double_conv = nn.Sequential(
            nn.Conv2d(in_ch, out_ch, kernel_size=3, padding=1), # 원래 UNet 에서는 패딩을 추가하지 X
            nn.BatchNorm2d(out_ch),
            nn.ReLU(True),

            nn.Conv2d(out_ch, out_ch, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(True)
        )
    def forward(self, x):
        return self.double_conv(x)

class UNet(nn.Module):
    def __init__(self, n_ch=3, n_classes=2):
        super().__init__()
        self.inc = DoubleConv(n_ch, 64)

        self.down1 = nn.Sequential(
            nn.MaxPool2d(2),
            DoubleConv(64,128)
        )
        self.down2 = nn.Sequential(
            nn.MaxPool2d(2),
            DoubleConv(128,256)
# ... trimmed ...

from pdb import run

from pdb import run는 이 노트에서 핵심 구현을 보여주는 코드 블록입니다. 코드 안에서는 학습/평가 함수 흐름이 주석과 함께 드러납니다.

from pdb import run
#@title 학습/평가 함수
def train(model, dataloader, optimizer, criterion, device):
    model.train()
    running_loss = 0.0
    for imgs, masks in dataloader:
        imgs = imgs.to(device)
        masks = masks.to(device)

        optimizer.zero_grad()
        outputs = model(imgs)
        loss = criterion(outputs, masks)
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * imgs.size(0)
    epoch_loss = running_loss / len(dataloader.dataset)
    return epoch_loss

def evaluate(model, dataloader, criterion, device):
    model.eval()
    running_loss = 0.0
    with torch.no_grad():
        for imgs, masks in dataloader:
            imgs.to(device)
            masks.to(device)
            outputs = model(imgs)
            loss = criterion(outputs, masks)
# ... trimmed ...

@title 학습 루프

@title 학습 루프는 이 노트에서 핵심 구현을 보여주는 코드 블록입니다. 코드 안에서는 학습 루프 흐름이 주석과 함께 드러납니다.

#@title 학습 루프
num_epochs = 2
batch_size = 4
lr = 1e-4

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

dataset = PennFudanDataset(root="/content/data/PennFudanPed", transform=joint_transform)

train_size = int(0.8* len(dataset))
val_size = len(dataset)-train_size
train_dataset, val_dataset = torch.utils.data.random_split(dataset, [train_size, val_size])

train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)

model = UNet(n_ch=3, n_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

best_val_loss = float('inf')
for epoch in range(num_epochs):
    train_loss = train(model, train_dataloader, optimizer, criterion, device)
    val_loss = evaluate(model, val_dataloader, criterion, device)
    print(f"Epoch {epoch+1}/{num_epochs} , Train Loss : {train_loss:.4f}, Val Loss : {val_loss:.4f}")
    if val_loss < best_val_loss:
        best_val_loss = val_loss
        torch.save(model.state_dict(), 'best_unet.pt')

import matplotlib.pyplot as plt

import matplotlib.pyplot as plt는 이 노트에서 핵심 구현을 보여주는 코드 블록입니다. 코드 안에서는 예측: 각 픽셀에서 채널의 argmax (배경:0, 보행자:1) 흐름이 주석과 함께 드러납니다.

import matplotlib.pyplot as plt

def visualize_predictions(model, dataloader, device, num_images=4):
    model.eval()
    with torch.no_grad():
        for imgs, masks in dataloader:
            imgs = imgs.to(device)
            outputs = model(imgs)  # 출력: [B, n_classes, H, W]
            # 예측: 각 픽셀에서 채널의 argmax (배경:0, 보행자:1)
            preds = torch.argmax(outputs, dim=1).cpu().numpy()
            imgs = imgs.cpu().numpy().transpose(0, 2, 3, 1)  # [B, C, H, W] -> [B, H, W, C]로 변경
            masks = masks.cpu().numpy()

            for i in range(min(num_images, imgs.shape[0])):
                fig, axs = plt.subplots(1, 3, figsize=(15, 5))
                axs[0].imshow(imgs[i])
                axs[0].set_title("Input Image")
                axs[0].axis("off")
                axs[1].imshow(masks[i], cmap="gray")
                axs[1].set_title("Ground Truth")
                axs[1].axis("off")
                axs[2].imshow(preds[i], cmap="gray")
                axs[2].set_title("Predicted Mask")
                axs[2].axis("off")
                plt.show()
            break

val_dataloader_shuffle = DataLoader(val_dataset, batch_size=4, shuffle=True)

Source Bundle

  • Source path: 12_Deep_Learning/Code_Snippets/(실습)UNet.md
  • Source formats: md
  • Companion files: (실습)UNet.md
  • Note type: code-note
  • Last updated in the source vault: 2026-03-08T03:33:14
  • Related notes: 2025.10.1,2,13,14.md, 12_Deep_Learning_Code_Summary.md
  • External references: localhost, www.cis.upenn.edu

Note Preview

원본 노트에 별도 설명 문단이 많지 않아 코드 중심으로 보존했습니다.