머신러닝 모델에 입력하기 전 데이터는 적절한 형태로 가공되어야 합니다. torchvision.transforms는 이미지와 레이블을 전처리할 수 있는 다양한 변환 도구를 제공하며, Dataset 생성 시 transform과 target_transform 인자를 통해 적용할 수 있습니다.
핵심 변환 클래스
| 클래스 | 역할 |
|---|---|
ToTensor | PIL Image/NumPy 배열을 Tensor로 변환 및 정규화 |
Lambda | 사용자 정의 함수를 변환 파이프라인에 통합 |
Compose | 여러 변환을 순차적으로 적용 |
실전 예제: FashionMNIST 전처리
FashionMNIST 데이터셋의 이미지는 PIL 형식이며, 레이블은 정수입니다. 이를 모델 입력에 맞게 Tensor로 변환하고, 레이블은 one-hot 벡터로 바꿔보겠습니다.
import torch
from torchvision import datasets
from torchvision.transforms import ToTensor, Lambda, Compose
# one-hot 인코딩 함수 분리 정의
def make_one_hot(label_idx, num_classes=10):
base = torch.zeros(num_classes, dtype=torch.float32)
return base.scatter_(0, torch.tensor(label_idx), 1.0)
# 커스텀 변환 파이프라인 구성
img_transform = Compose([
ToTensor(), # [0, 255] -> [0.0, 1.0] 범위의 FloatTensor
])
label_transform = Lambda(make_one_hot)
# 데이터셋 로드
fashion_data = datasets.FashionMNIST(
root='./fashion_data',
train=True,
download=True,
transform=img_transform,
target_transform=label_transform
)
ToTensor 동작 상세
ToTensor는 다음 세 가지 핵심 연산을 수행합니다:
- 입력 데이터 타입을
torch.float32로 캐스팅 - 픽셀 값을 255로 나누어 [0.0, 1.0] 구간으로 스케일링
- 차원 순서를 (H, W, C) → (C, H, W)로 재배치
Lambda를 활용한 고급 변환
복잡한 로직은 별도 함수로 분리하여 가독성을 높이는 것이 좋습니다. 다음은 레이블에 부가 정보를 추가하는 예시입니다:
def enhanced_label_transform(raw_label):
# 기본 one-hot 벡터
one_hot = torch.zeros(10, dtype=torch.float)
one_hot[raw_label] = 1.0
# 추가 메타데이터 (예: 짝수/홀수 클래스 구분)
metadata = torch.tensor([
float(raw_label % 2 == 0), # 짝수 여부
float(raw_label > 4) # 상위 카테고리 여부
])
return {'class_vector': one_hot, 'extra': metadata}
# 활용
enhanced_ds = datasets.FashionMNIST(
root='./fashion_data',
train=False,
transform=ToTensor(),
target_transform=Lambda(enhanced_label_transform)
)
주의사항
target_transform의 오타(target_tansform등)는 무시되며 변환이 적용되지 않습니다- 변환은 즉시 실행(eager)되므로, 무거운 연산은
DataLoader의num_workers로 병렬화하세요 - GPU에서 실행 시
pin_memory=True설정으로 호스트-디바이스 전송 최적화