개요
ImageTransform은 이미지 전처리를 담당하는 클래스로, 학습 데이터의 다양성을 높여 모델의 일반화 성능을 향상시킵니다.
from torchvision import transforms
class ImageTransform:
def __init__(self, resize, mean, std):
"""학습/검증용 변환 정의"""
self.data_transform = {
'train': transforms.Compose([...]), # 증강 O
'val': transforms.Compose([...]) # 증강 X
}
def __call__(self, img, phase):
"""입력 이미지에 변환 적용"""
return self.data_transform[phase](img)
주요 구성 요소
| 요소 | 역할 |
|---|
__init__ | train/val 변환 파이프라인 정의 |
data_transform | phase별 변환 체인 저장 (딕셔너리) |
__call__ | 이미지를 받아 변환 적용 후 반환 |
Train vs Val 변환 차이
핵심 차이점
| 구분 | Train | Validation |
|---|
| 목적 | 다양한 데이터로 학습 | 일관된 조건에서 평가 |
| 증강 | 적용 | 미적용 |
| 무작위성 | 있음 (랜덤 변환) | 없음 (고정 변환) |
| 크롭 방식 | RandomResizedCrop | CenterCrop |
왜 이렇게 구분하나?
Train 모드:
- 모델이 다양한 변형 이미지를 학습하여 일반화 능력 향상
- 과적합(overfitting) 방지
- 실제 환경의 다양한 상황 시뮬레이션
Val 모드:
- 공정한 비교를 위해 매번 동일한 조건에서 평가
- 무작위성이 있으면 평가 결과가 매번 달라짐
- 모델의 실제 성능을 정확히 측정
Train 변환 파이프라인 (증강 적용)
'train': transforms.Compose([
transforms.Resize(256),
transforms.RandomResizedCrop(resize, scale=(0.5, 1.0)),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(45),
transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5),
transforms.RandomGrayscale(p=0.1),
transforms.ToTensor(),
transforms.Normalize(mean, std)
])
1️. Resize(256)
transforms.Resize(256)
- 역할: 이미지의 짧은 변을 256픽셀로 조정
- 예시:
- 입력: 1000×800 → 출력: 320×256
- 입력: 600×900 → 출력: 256×384
- 목적: 이후 크롭을 위한 여유 공간 확보
2️. RandomResizedCrop(resize, scale=(0.5, 1.0))
transforms.RandomResizedCrop(resize, scale=(0.5, 1.0))
- 역할: 랜덤한 영역을 잘라내고 지정된 크기로 리사이즈
- 동작:
- 이미지의 50%~100% 크기 영역을 랜덤 선택
- 선택된 영역을
resize 크기로 확대/축소
- 효과:
- 객체의 다양한 크기 학습 (줌인/줌아웃)
- 위치 변화 학습
3️. RandomHorizontalFlip()
transforms.RandomHorizontalFlip()
- 역할: 50% 확률로 좌우 반전
- 효과: 좌우 대칭성 학습
- 예시:
- 왼쪽 바라보는 강아지 → 오른쪽 바라보는 강아지
4️. RandomRotation(45)
transforms.RandomRotation(45)
- 역할: -45° ~ +45° 범위에서 랜덤 회전
- 효과: 다양한 각도의 객체 학습
- 주의: 너무 큰 각도는 이미지 왜곡 가능
5️. ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5)
transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5)
- 역할: 색상 관련 속성을 랜덤하게 변경
- 파라미터:
brightness=0.5: 밝기 ±50% 변경
contrast=0.5: 대비 ±50% 변경
saturation=0.5: 채도 ±50% 변경
- 효과: 다양한 조명 환경 학습
- 밝은 환경, 어두운 환경
- 흐린 날씨, 맑은 날씨
6️. RandomGrayscale(p=0.1)
transforms.RandomGrayscale(p=0.1)
- 역할: 10% 확률로 흑백 변환 (RGB 채널 수 유지)
- 주의: 완전히 흑백으로 변환되지만 채널은 3개 유지 (R=G=B)
- 효과: 색상에 과도하게 의존하지 않도록 학습
7️. ToTensor()
transforms.ToTensor()
- 역할: PIL Image 또는 numpy.ndarray를 PyTorch Tensor로 변환
- 변환 내용:
- 데이터 타입:
uint8 (0255) → float32 (0.01.0)
- 차원 순서:
(H, W, C) → (C, H, W)
- 범위:
[0, 255] → [0.0, 1.0] (자동 스케일링)
변환 예시:
PIL Image (H×W×C) Tensor (C×H×W)
[0, 255, 128] → [0.0, 1.0, 0.502]
(224, 224, 3) → (3, 224, 224)
8️. Normalize(mean, std)
transforms.Normalize(mean, std)
- 역할: 평균과 표준편차로 정규화
- 공식:
output = (input - mean) / std
- 일반적인 값 (ImageNet 기준):
mean = [0.485, 0.456, 0.406] # RGB 각 채널std = [0.229, 0.224, 0.225]
- 효과:
- 학습 안정성 향상
- 그래디언트 소실/폭발 방지
- 사전학습 모델과 동일한 분포로 맞춤
정규화 예시:
# R 채널 예시
input = 0.8
normalized = (0.8 - 0.485) / 0.229 = 1.376
Val 변환 파이프라인 (증강 미적용)
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(resize),
transforms.ToTensor(),
transforms.Normalize(mean, std)
])
주요 차이점
| 변환 | Train | Val |
|---|
| 크롭 | RandomResizedCrop | CenterCrop |
| 반전 | RandomHorizontalFlip | ❌ |
| 회전 | RandomRotation | ❌ |
| 색상 | ColorJitter | ❌ |
| 흑백 | RandomGrayscale | ❌ |
CenterCrop(resize)
transforms.CenterCrop(resize)
- 역할: 이미지 중앙 영역을 정확히 잘라냄
- 특징: 항상 동일한 위치 크롭 (무작위성 없음)
- 목적: 평가 시 일관성 유지
call 메서드: 변환 실행
def __call__(self, img, phase):
"""입력 이미지에 변환 적용"""
return self.data_transform[phase](img)
동작 원리
- phase 파라미터로 변환 선택
phase='train' → 증강 적용
phase='val' → 증강 미적용
- Compose 체인 실행
# 내부 동작 (의사 코드)
img = transforms.Resize(256)(img)
img = transforms.RandomResizedCrop(resize)(img)
img = transforms.RandomHorizontalFlip()(img)
# ... (이어서)
return img
- 호출 예시
transform = ImageTransform(224, mean, std)
# 학습용 변환
train_img = transform(original_img, 'train') # 증강 O
# 검증용 변환
val_img = transform(original_img, 'val') # 증강 X
전체 변환 흐름도
입력 이미지 (PIL Image)
↓
[phase 선택]
↓
┌───────┴───────┐
│ │
▼ ▼
[Train] [Val]
│ │
Resize Resize
RandomCrop CenterCrop
Flip (증강 없음)
Rotation
ColorJitter
Grayscale
│ │
└───────┬───────┘
↓
ToTensor
↓
Normalize
↓
출력 텐서 (C×H×W, float32)
핵심 포인트 정리
- 전처리: 이미지를 모델 입력 형태로 변환
- 증강: 학습 데이터의 다양성 확보
- 정규화: 학습 안정성 향상
Train vs Val 구분 이유
- Train: 다양한 변형으로 일반화 능력 향상
- Val: 일관된 조건으로 공정한 평가
변환 순서의 중요성
1. Resize → 크기 조정
2. Crop → 필요 영역 추출
3. Augmentation → 증강 적용
4. ToTensor → 텐서 변환
5. Normalize → 정규화 (마지막!)
실제 사용 위치
- Transform 생성:
create_dataloaders() 함수에서
- Transform 저장:
Dataset.__init__() 메서드에서
- Transform 실행:
Dataset.__getitem__() 메서드에서 ✨