데이터 로딩의 3대 요소
__init__ (초기화)
def __init__ (self, file_list, transform = None , phase = 'train' ):
self .file_list = file_list
self .transform = transform
self .phase = phase
self .labels = []
for path in self .file_list:
folder = os.path.basename(os.path.dirname(path))
label = 1 if folder == "dog" else 0
self .labels.append(label)
역할
데이터셋 객체가 생성될 때 단 한 번만 실행 되는 초기화 함수
데이터셋에 필요한 메타 정보 를 미리 준비하고 저장
상세 동작
파일 경로 저장 : self.file_list에 모든 이미지 파일 경로를 저장
변환기 저장 : 이미지 전처리에 사용할 transform 함수를 저장
라벨 생성 :
각 이미지 파일의 경로에서 부모 폴더명 추출 (os.path.dirname → os.path.basename)
폴더명이 “dog”이면 라벨 1, “cat”이면 라벨 0으로 매핑
모든 이미지의 라벨을 미리 생성 하여 리스트에 저장
왜 미리 라벨을 만들까?
__getitem__에서 매번 폴더명을 파싱하는 것보다 효율적
한 번만 처리하고 메모리에 저장해두면 반복 접근 시 빠름
__len__ (길이 반환)
def __len__ (self):
return len ( self .file_list)
역할
데이터셋의 전체 샘플 개수 를 반환
Python의 len() 함수 호출 시 자동으로 실행됨
사용 예시
dataset = DogvsCatDataset(file_list, transform)
print ( len (dataset)) # __len__() 호출 → 전체 이미지 개수 출력
DataLoader와의 관계
DataLoader는 __len__()을 통해 전체 배치 수 를 계산
예: 1000개 이미지, batch_size=32 → 32개 배치 생성 (마지막 배치는 8개)
__getitem__ (개별 샘플 반환)
def __getitem__ (self, index):
img_path = self .file_list[index]
img = Image.open(img_path)
img_transformed = self .transform(img, self .phase)
label = torch.tensor( self .labels[index], dtype = torch.long)
return img_transformed, label
역할
특정 인덱스의 샘플(이미지 + 라벨) 1개를 반환
DataLoader가 배치를 구성할 때 반복적으로 호출 됨
상세 동작
이미지 로딩 :
index번째 파일 경로를 가져옴
Image.open()으로 디스크에서 이미지를 읽어 메모리에 로드
이미지 변환 :
self.transform으로 전처리 (리사이즈, 정규화, 텐서 변환 등)
phase 인자로 train/val 모드에 따라 다른 augmentation 적용 가능
라벨 텐서화 :
미리 생성한 self.labels[index]를 PyTorch 텐서로 변환
dtype=torch.long → 분류 문제의 정수 레이블용
반환 : (이미지 텐서, 라벨 텐서) 튜플 반환
호출 시점
dataloader = DataLoader(dataset, batch_size = 32 , shuffle = True )
for images, labels in dataloader:
# 내부적으로 __getitem__(0), __getitem__(15), ...
# 32번 호출하여 배치 구성
print (images.shape) # torch.Size([32, 3, 224, 224])
print (labels.shape) # torch.Size([32])
전체 동작 흐름
1. 데이터셋 생성
dataset = DogvsCatDataset(file_list, transform)
→ __init__ 호출: 파일 목록 저장, 라벨 생성
2. DataLoader 생성
dataloader = DataLoader(dataset, batch_size=32)
→ __len__ 호출: 배치 개수 계산
3. 학습 루프
for batch in dataloader:
→ __getitem__(idx) 32번 호출
→ 각 샘플을 배치로 collate
→ 모델에 전달
핵심 포인트
메서드 호출 시점 횟수 목적 __init__객체 생성 시 1번 초기화, 메타정보 준비 __len__len() 호출 시필요 시 데이터셋 크기 반환 __getitem__배치 구성 시 매우 많음 개별 샘플 로드 효율성 : __init__에서 무거운 작업(라벨 생성)을 미리 하고, __getitem__에서는 빠른 인덱싱만 수행하는 것이 일반적인 패턴입니다.