본문 바로가기
Artificial Intelligence/21. PyTorch

[PYTORCH] CSV 파일을 읽어 데이터셋으로 만드는 7가지 방법과 성능 해결 가이드

by Papa Martino V 2026. 3. 25.
728x90

CSV 데이터셋
CSV(Comma-Separated Values) 데이터셋

 

대부분의 정형 데이터는 CSV(Comma-Separated Values) 포맷으로 저장되어 있습니다. 하지만 수십 GB에 달하는 거대한 CSV 파일을 단순히 리스트로 불러와 모델에 입력하면 메모리 부족(OOM) 현상이나 데이터 로딩 병목이 발생하게 됩니다. 본 가이드에서는 PandasPyTorch Dataset의 결합을 통해 메모리 효율성을 극대화하고, 실제 프로덕션 환경에서 바로 사용 가능한 7가지 데이터셋 빌드 패턴을 상세히 다룹니다.


1. CSV 데이터셋 로딩의 기술적 설계와 차이점 분석

단순히 CSV를 읽는 것을 넘어, PyTorch 파이프라인으로 통합할 때는 Eager Loading(한꺼번에 로드)과 Lazy Loading(필요할 때 로드)의 차이를 명확히 이해해야 합니다. 데이터의 크기와 RAM 용량에 따라 최적의 전략을 선택하는 것이 전문 엔지니어의 핵심 역량입니다.

2. 데이터 로딩 전략별 장점 및 리소스 영향도 비교

CSV 파일 크기에 따른 데이터셋 구현 방식의 차이를 표로 정리하였습니다.

구현 방식 주요 사용 라이브러리 메모리 점유율 데이터 접근 속도 권장 데이터 크기
In-Memory (Pandas 기반) Pandas + Dataset 매우 높음 매우 빠름 (O(1)) RAM의 50% 미만
Chunk-based (Lazy) Pandas (Chunk) + Dataset 낮음 보통 (디스크 I/O 발생) RAM 용량 초과 시
Streaming (Iterative) csv module / IterableDataset 최소 느림 (순차 접근 위주) 수십 GB 이상의 거대 파일
Pre-compiled (바이너리) NumPy Memmap / HDF5 최적 매우 빠름 고속 학습이 필요한 경우

3. 실무 즉시 적용 가능한 CSV 데이터셋 Example 7가지

단순 회귀 분석부터 복잡한 전처리가 포함된 케이스까지, 실무에서 마주치는 7가지 해결 코드를 제시합니다.

Example 1: 표준 Pandas 기반 CSV 데이터셋 제작 방법

가장 일반적인 형태의 구현체로, 학습 시작 시 모든 데이터를 메모리에 올립니다.

import pandas as pd
import torch
from torch.utils.data import Dataset

class StandardCSVDataset(Dataset):
    def __init__(self, csv_file):
        self.data = pd.read_csv(csv_file)
        # 피처와 레이블 분리 (마지막 열이 레이블인 경우)
        self.x = self.data.iloc[:, :-1].values
        self.y = self.data.iloc[:, -1].values

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        return torch.tensor(self.x[idx], dtype=torch.float32), \
               torch.tensor(self.y[idx], dtype=torch.long)
        

Example 2: 거대 CSV를 위한 Lazy Loading (On-the-fly) 해결

메모리가 부족할 때 인덱스 호출 시점에만 행을 읽어오는 방식입니다.

class LazyCSVDataset(Dataset):
    def __init__(self, csv_file):
        self.csv_file = csv_file
        self.total_rows = sum(1 for _ in open(csv_file)) - 1 # 헤더 제외

    def __len__(self):
        return self.total_rows

    def __getitem__(self, idx):
        # 특정 행만 스킵하며 읽기 (성능은 Pandas 단일 로드보다 느림)
        row = pd.read_csv(self.csv_file, skiprows=idx+1, nrows=1, header=None)
        data = torch.tensor(row.values, dtype=torch.float32)
        return data[0, :-1], data[0, -1].long()
        

Example 3: 범주형 데이터 인코딩이 포함된 데이터셋

CSV 내부의 문자열 데이터를 수치형 텐서로 자동 변환하는 방법입니다.

class CategoricalCSVDataset(Dataset):
    def __init__(self, csv_file):
        df = pd.read_csv(csv_file)
        # 범주형 데이터를 코드로 변환
        df['category'] = df['category'].astype('category').cat.codes
        self.x = torch.tensor(df[['feature1', 'feature2']].values, dtype=torch.float32)
        self.y = torch.tensor(df['category'].values, dtype=torch.long)

    def __len__(self):
        return len(self.x)

    def __getitem__(self, idx):
        return self.x[idx], self.y[idx]
        

Example 4: 스케일링(Normalization)이 통합된 데이터셋

from sklearn.preprocessing import StandardScaler

class ScaledCSVDataset(Dataset):
    def __init__(self, csv_file):
        df = pd.read_csv(csv_file)
        scaler = StandardScaler()
        self.x = scaler.fit_transform(df.iloc[:, :-1].values)
        self.y = df.iloc[:, -1].values

    def __getitem__(self, idx):
        return torch.tensor(self.x[idx], dtype=torch.float32), torch.tensor(self.y[idx])
        

Example 5: 다중 CSV 파일을 하나로 묶는 방법 (Concat)

import glob

class MultiFileCSVDataset(Dataset):
    def __init__(self, folder_path):
        all_files = glob.glob(folder_path + "/*.csv")
        self.df = pd.concat((pd.read_csv(f) for f in all_files), ignore_index=True)

    def __len__(self):
        return len(self.df)
        

Example 6: 누락된 값(NaN) 처리 해결 전략

class CleanCSVDataset(Dataset):
    def __init__(self, csv_file):
        df = pd.read_csv(csv_file)
        # 결측치를 평균값으로 채움
        df = df.fillna(df.mean())
        self.data = torch.tensor(df.values, dtype=torch.float32)
        

Example 7: IterableDataset을 이용한 스트리밍 로드

수십 GB의 CSV를 한 줄씩 처리하여 메모리 점유율을 1MB 미만으로 유지합니다.

from torch.utils.data import IterableDataset
import csv

class CSVStreamer(IterableDataset):
    def __init__(self, file_path):
        self.file_path = file_path

    def __iter__(self):
        with open(self.file_path, 'r') as f:
            reader = csv.reader(f)
            next(reader) # 헤더 스킵
            for row in reader:
                yield torch.tensor([float(i) for i in row], dtype=torch.float32)
        

4. CSV 처리 성능을 높이는 3가지 전문 최적화 팁

  1. 데이터 타입 명시: pd.read_csv 호출 시 dtype 옵션을 사용하여 메모리 소모가 큰 float64 대신 float32를 명시하십시오.
  2. 엔진 선택: 대용량 CSV의 경우 engine='pyarrow'를 사용하면 로딩 속도가 비약적으로 빨라집니다.
  3. 이진 포맷 변환: 빈번한 학습이 필요하다면 CSV를 한 번만 읽어 .npy 또는 .parquet 파일로 저장한 뒤 Dataset에서 로드하는 것이 가장 효율적입니다.

5. 결론: 견고한 데이터셋이 모델 학습의 안정성을 만든다

PyTorch에서 CSV 데이터를 다루는 방법은 단순한 코딩을 넘어 시스템의 리소스를 어떻게 설계하느냐의 문제입니다. Lazy Loading을 통해 메모리 한계를 극복하고, Pandas의 강력한 정제 기능을 활용하여 텐서로 변환하는 과정을 표준화하십시오. 본 가이드의 7가지 해결 예제가 귀하의 딥러닝 프로젝트를 한 단계 더 높은 수준으로 끌어올릴 것입니다.

내용 출처 및 기술 참조

  • PyTorch Official Documentation: "Writing Custom Datasets" Section
  • Pandas User Guide: "Enhancing Performance with CSV Loading"
  • "Python for Data Analysis" (Wes McKinney, 3rd Edition)
728x90