
📓Google Colab에서 실습하기
이 레슨은 PyTorch/GPU가 필요합니다. 노트북을 다운로드 후 Google Colab에서 열어주세요.
학습 내용
데이터 로딩
학습 목표
이 레슨을 완료하면:
- •Dataset과 DataLoader의 역할과 관계를 이해합니다
- •커스텀 Dataset 클래스를 직접 구현합니다
- •transforms를 활용한 데이터 증강의 원리를 설명합니다
- •효율적인 데이터 파이프라인을 설계합니다
데이터 로딩이 왜 중요한가?
비유: 아무리 좋은 요리사(모델)라도 재료(데이터)가 제때 공급되지 않으면 요리를 할 수 없습니다. GPU가 아무리 빨라도 데이터가 느리게 도착하면 GPU는 대부분의 시간을 기다리며 낭비합니다. 효율적인 데이터 로딩은 학습 속도에 직접적인 영향을 미칩니다.
데이터 로딩 파이프라인 전체 흐름
| 단계 | 구성 요소 | 역할 | 비유 |
|---|---|---|---|
| 1 | 원본 데이터 | 디스크에 저장된 파일 | 창고의 원재료 |
| 2 | Dataset | 데이터 접근 방법 정의 | 재료 꺼내기 규칙 |
| 3 | transforms | 전처리 및 변환 | 재료 손질 |
| 4 | DataLoader | 배치 묶기, 셔플, 병렬 처리 | 컨베이어 벨트 |
| 5 | 모델 학습 | 배치 단위 학습 | 요리 시작 |
Dataset 클래스 이해하기
Dataset은 "데이터 하나를 어떻게 가져올 것인가"를 정의하는 클래스입니다.
반드시 구현해야 하는 메서드
| 메서드 | 역할 | 반환값 |
|---|---|---|
| init | 데이터 경로, 변환 등 초기 설정 | 없음 |
| len | 데이터셋의 총 크기 | 정수 |
| getitem | 인덱스로 데이터 1개 가져오기 | (입력, 라벨) 튜플 |
python⚠️ 로컬 실행 필요from torch.utils.data import Dataset import torch class MyDataset(Dataset): def __init__(self, data, labels, transform=None): """데이터셋 초기화 - 데이터를 메모리에 올리거나 경로를 저장""" self.data = data self.labels = labels self.transform = transform def __len__(self): """데이터셋 크기 반환 - DataLoader가 전체 크기를 알아야 배치를 나눌 수 있음""" return len(self.data) def __getitem__(self, idx): """인덱스로 데이터 1개를 가져옴 - DataLoader가 이 메서드를 반복 호출""" x = self.data[idx] y = self.labels[idx] # 변환(전처리)이 정의되어 있으면 적용 if self.transform: x = self.transform(x) return x, y
왜 __getitem__이 핵심인가?
DataLoader는 내부적으로 인덱스를 생성하고, 각 인덱스에 대해 __getitem__을 호출합니다. 이 메서드가 효율적이지 않으면 전체 학습 속도가 느려집니다.
DataLoader 상세 설명
비유: DataLoader는 레스토랑의 웨이터입니다. 주방(Dataset)에서 음식(데이터)을 가져와 테이블(모델)에 배달하는데, 한 번에 여러 접시(배치)를 나르고, 매번 다른 메뉴 순서(셔플)로 서빙합니다.
python⚠️ 로컬 실행 필요from torch.utils.data import DataLoader train_loader = DataLoader( dataset=train_dataset, # 위에서 만든 Dataset 객체 batch_size=64, # 한 번에 처리할 데이터 수 shuffle=True, # 매 에폭마다 순서를 섞을지 여부 num_workers=4, # 데이터 로딩에 사용할 프로세스 수 pin_memory=True, # GPU 전송 최적화 (CUDA 사용 시) drop_last=True # 마지막 불완전 배치를 버릴지 여부 )
DataLoader 파라미터 상세
| 파라미터 | 기본값 | 설명 | 팁 |
|---|---|---|---|
| batch_size | 1 | 배치 크기 | 메모리 허용 범위에서 크게 설정 |
| shuffle | False | 데이터 섞기 | 훈련: True, 테스트: False |
| num_workers | 0 | 병렬 로딩 프로세스 | CPU 코어 수의 2~4배 시도 |
| pin_memory | False | GPU 전송 최적화 | GPU 사용 시 True 권장 |
| drop_last | False | 마지막 불완전 배치 처리 | BatchNorm 사용 시 True 권장 |
왜 shuffle이 중요한가?
셔플을 하지 않으면, 모델이 데이터의 순서에서 패턴을 학습할 수 있습니다. 예를 들어 고양이 이미지가 앞에, 개 이미지가 뒤에 몰려 있으면 모델은 "앞쪽 = 고양이"라는 잘못된 규칙을 학습할 수 있습니다.
DataLoader 사용 패턴
python# 기본 사용법: for 문으로 배치를 하나씩 가져옴 for batch_idx, (data, target) in enumerate(train_loader): # data 크기: [batch_size, channels, height, width] # target 크기: [batch_size] data, target = data.to(device), target.to(device) # ... 학습 코드 ... if batch_idx % 100 == 0: print("Batch {}/{}".format(batch_idx, len(train_loader)))
transforms: 데이터 변환과 증강
기본 변환
모든 이미지 데이터에 필수적으로 적용하는 변환입니다.
pythonfrom torchvision import transforms # 기본 변환 파이프라인 basic_transform = transforms.Compose([ transforms.Resize((224, 224)), # 크기 통일 (모델 입력 크기에 맞춤) transforms.ToTensor(), # PIL 이미지 -> PyTorch 텐서 (0~1) transforms.Normalize( # 정규화 mean=[0.485, 0.456, 0.406], # ImageNet 평균 std=[0.229, 0.224, 0.225] # ImageNet 표준편차 ) ])
데이터 증강 (Data Augmentation)
비유: 데이터 증강은 "같은 시험 문제를 조금씩 변형해서 연습량을 늘리는 것"입니다. 고양이 사진을 뒤집거나, 밝기를 바꾸거나, 약간 회전시키면 모델 입장에서는 새로운 데이터입니다.
python# 훈련용 변환: 증강 포함 train_transform = transforms.Compose([ transforms.RandomHorizontalFlip(p=0.5), # 50% 확률로 좌우 반전 transforms.RandomRotation(15), # -15도 ~ +15도 무작위 회전 transforms.RandomCrop(32, padding=4), # 패딩 후 무작위 자르기 transforms.ColorJitter( # 색상 변화 brightness=0.2, # 밝기 +/- 20% contrast=0.2, # 대비 +/- 20% saturation=0.2 # 채도 +/- 20% ), transforms.ToTensor(), transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2470, 0.2435, 0.2616)) ]) # 테스트용 변환: 증강 없음 (공정한 평가) test_transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2470, 0.2435, 0.2616)) ])
왜 테스트 데이터에는 증강을 적용하지 않는가?
테스트는 모델의 "진짜 실력"을 측정하는 것입니다. 테스트 데이터에 무작위 변환을 적용하면 매번 다른 결과가 나와서 공정한 평가가 불가능합니다.
| 변환 | 훈련 시 | 테스트 시 | 이유 |
|---|---|---|---|
| RandomHorizontalFlip | 적용 | 미적용 | 데이터 다양성 증가 |
| RandomRotation | 적용 | 미적용 | 회전에 강건해지도록 |
| ToTensor | 적용 | 적용 | 형식 변환 (필수) |
| Normalize | 적용 | 적용 | 분포 통일 (필수) |
실전 예제 1: 이미지 폴더 Dataset
폴더 이름이 클래스 라벨이 되는 구조는 실무에서 가장 흔합니다.
python# 폴더 구조 예시: # data/ # train/ # cat/ # cat001.jpg, cat002.jpg, ... # dog/ # dog001.jpg, dog002.jpg, ... # test/ # cat/ # cat101.jpg, ... # dog/ # dog101.jpg, ... from torchvision.datasets import ImageFolder # ImageFolder는 폴더 이름을 자동으로 클래스 라벨로 사용합니다 train_dataset = ImageFolder( root="data/train", transform=train_transform ) print(train_dataset.classes) # ["cat", "dog"] print(train_dataset.class_to_idx) # {"cat": 0, "dog": 1} print("Total images:", len(train_dataset)) # 폴더 내 전체 이미지 수
실전 예제 2: CSV 데이터 로딩
pythonimport pandas as pd class CSVDataset(Dataset): def __init__(self, csv_file, feature_cols, label_col): """CSV 파일에서 데이터를 로드하는 커스텀 Dataset""" self.df = pd.read_csv(csv_file) self.features = self.df[feature_cols].values self.labels = self.df[label_col].values def __len__(self): return len(self.df) def __getitem__(self, idx): x = torch.tensor(self.features[idx], dtype=torch.float32) y = torch.tensor(self.labels[idx], dtype=torch.long) return x, y # 사용 예시 dataset = CSVDataset( csv_file="data.csv", feature_cols=["age", "income", "score"], label_col="target" ) loader = DataLoader(dataset, batch_size=32, shuffle=True)
데이터셋 분할: 훈련/검증 나누기
python⚠️ 로컬 실행 필요from torch.utils.data import random_split # 전체 데이터를 80% 훈련, 20% 검증으로 분할 full_dataset = MyDataset(data, labels, transform=train_transform) train_size = int(0.8 * len(full_dataset)) val_size = len(full_dataset) - train_size train_dataset, val_dataset = random_split(full_dataset, [train_size, val_size]) # 각각 DataLoader 생성 train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True) val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)
핵심 요약
| 개념 | 설명 | 비유 |
|---|---|---|
| Dataset | 데이터 1개를 가져오는 방법 정의 | 재료 꺼내기 규칙 |
| DataLoader | 배치 묶기, 셔플, 병렬 로딩 | 컨베이어 벨트 |
| transforms | 전처리 및 데이터 증강 | 재료 손질 과정 |
| ImageFolder | 폴더 구조 기반 이미지 로딩 | 자동 분류 시스템 |
| random_split | 데이터셋 분할 | 재료를 훈련/검증용으로 나누기 |
학습 체크리스트
- • Dataset의 필수 메서드 3가지(init, len, getitem)를 안다
- • DataLoader의 주요 파라미터(batch_size, shuffle, num_workers)를 설명할 수 있다
- • 훈련 데이터에만 증강을 적용하는 이유를 안다
- • ImageFolder의 사용법을 이해한다
- • random_split으로 데이터를 분할하는 방법을 안다
- • num_workers와 pin_memory의 역할을 설명할 수 있다
레슨 정보
- 레벨
- Level 4: 실전 프로젝트
- 예상 소요 시간
- 약 5분
- 참고 영상
- YouTube 링크
💡실습 환경 안내
이 레벨은 PyTorch/GPU가 필요하여 Google Colab 사용을 권장합니다.
Colab은 무료 GPU를 제공하여 PyTorch, CNN, Transformer 등을 실행할 수 있습니다.