페이지

2025년 4월 28일 월요일

IMDb 데이터셋의 label 열이 DistilBERT 모델 forward() 함수의 labels 인자로 전달되는 과정

IMDb 데이터셋의 label 열이 DistilBERT 모델 forward() 함수의 labels 인자로 전달되는 과정

1. 개요

허깅 페이스의 Transformers 라이브러리를 사용하여 모델을 훈련할 때 데이터셋의 label 항목이 어떤 과정을 거쳐 모델의 forward(..., labels, ...) 메소드로 전달되는지 설명합니다.

  • IMDb 데이터셋에서 추출한 한 개의 데이터 예시

    {
        "text": "I love sci-fi...",
        "label": 0
    }
    
  • DistilBertForSequenceClassification 클래스의 forward() 메소드

    transformers/models/distilbert/modeling_distilbert.py

    def forward(
        ...,
        labels: Optional[torch.LongTensor] = None,
        ...
    )-> Union[SequenceClassifierOutput, Tuple[torch.Tensor, ...]]:
        ...
    

이 문서에서는 IMDb 데이터셋과 DistilBertForSequenceClassification 모델을 사용하여 설명하지만 특정 데이터셋과 모델에만 해당하는 것은 아닙니다.

이 문서에서 등장하는 주요 API는 다음과 같습니다.

  • datasets.default_data_collator
  • class datasets.Dataset
  • class datasets.DatasetDict
  • class transformers.DataCollatorWithPadding
  • class transformers.DistilBertForSequenceClassification
  • class transformers.Trainer

2. 트레이너 (Trainer)

2.1. Trainer.__init()__

  • 데이터 콜레이터를 인자로 받아들이는 Trainer 객체 생성

    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=tokenized_imdb["train"],
        eval_dataset=tokenized_imdb["test"],
        processing_class=tokenizer,
        data_collator=data_collator,
        compute_metrics=compute_metrics,
    )
    
  • Trainer 클래스의 생성자에서 사용자 지정 데이터 콜레이터를 쓸 것인지, 아니면 기본 데이터 콜레이터를 쓸 것인지 결정

    transformers/trainer.py

    class Trainer:
        def __init__(self, ..., data_collator, ...):
            ...
            default_collator = (
                DataCollatorWithPadding(processing_class)
                if processing_class is not None
                and isinstance(processing_class, (PreTrainedTokenizerBase, SequenceFeatureExtractor))
                else default_data_collator
            )
            self.data_collator = data_collator if data_collator is not None else default_collator
            ...
    

2.2. Trainer.train()

  • 훈련 과정에서 배치 데이터를 얻기 위하여 __init__() 메소드 내에서 정했던 데이터 콜레이터를 이용

    transformers/trainer.py

    class Trainer:
        ...
        def train(self, ...):
            ...
            find_executable_batch_size(self._inner_training_loop, ...)
            ...
        
        def _inner_training_loop(self, batch_size=None, ...):
            ...
            train_dataloader = self.get_train_dataloader()
            ...
            for epoch in range(epochs_trained, num_train_epochs):
                epoch_dataloader = train_dataloader
                ...
                epoch_iterator = iter(epoch_dataloader)
                ...
                for _ in range(total_updates):
                    batch_samples, num_items_in_batch = self.get_batch_samples(epoch_iterator, num_batches, args.device)
                    ...
                    for i, inputs in enumerate(batch_samples):
                        ...
                        tr_loss_step = self.training_step(model, inputs, num_items_in_batch)
                        ...
            ...
        
        def get_train_dataloader(self) -> DataLoader:
            ...
            data_collator = self.data_collator
            ...
            
        def training_step(self, model, inputs, ...) -> torch.Tensor:
            ...
            loss = self.compute_loss(model, inputs, num_items_in_batch=num_items_in_batch)
            ...
    
        def compute_loss(self, model, inputs, ...)
            ...
            outputs = model(**inputs)
            ...
            return (loss, outputs) if return_outputs else loss
    

3. 데이터 콜레이터 (Data Collator)

데이터 콜레이터는 데이터셋으로부터 배치 크기의 데이터를 추출하여 반환하는 역할을 수행합니다. 트레이너는 훈련 과정에서 데이터를 공급받기 위하여 응용 프로그램에서 직접 생성하여 지정한 데이터 콜레이터를 사용하거나, 그렇지 않으면 기본 데이터 콜레이터를 사용합니다.

Transformers 라이브러리는 다음 세 종류의 기본 데이터 콜레이터를 구현하고 있습니다.

  • PyTorch - torch_default_data_collator
  • TensorFlow - tf_default_data_collator
  • NumPy - numpy_default_data_collator

3.1. 데이터 콜레이터를 직접 생성하여 지정하는 경우

  • DataCollatorWithPadding 객체를 생성하여 Trainer 객체 생성 시 인자로 전달

    data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
    
    trainer = Trainer(
        ...
        data_collator=data_collator,
        ...
    )
    
    trainer.train()
    
  • DataCollatorWithPadding 객체 호출 시 label 항목을 labels로 변경

    transformers/data/data_collator.py

    class DataCollatorWithPadding:
        def __call__(self, ...):
            batch = pad_without_fast_tokenizer_warning(...)
            if "label" in batch:
                batch["labels"] = batch["label"]
    	        del batch["label"]
            if "label_ids" in batch:
                batch["labels"] = batch["label_ids"]
                del batch["label_ids"]
    	    return batch
    

3.2. 데이터 콜레이터를 지정하지 않는 경우

  • Trainer 객체 생성 시 data_collator 파라미터 지정하지 않음

    trainer = Trainer(
        ...
        data_collator=None,
        ...
    )
    
  • PyTorch의 경우 torch_default_data_collator() 함수 호출 시 label 항목을 labels로 변경

    def torch_default_data_collator():
        ...
        if "label" in ...:
    	    ...
            batch["labels"] = torch.tensor([f["label"] for f in features], dtype=dtype)
    

4. 정리

  • 데이터 콜레이터가 데이터셋의 label 항목을 labels 항목으로 변경하고 트레이너가 labels 항목을 모델의 forward(..., labels, ...) 메소드 인자로 전달합니다.

Written with StackEdit.

2025년 4월 22일 화요일

DistilBERT + KorQuAD MLM 훈련 소요 시간 비교 (RTX 4090, T4, A100)

DistilBERT + KorQuAD MLM 훈련 소요 시간 비교 (RTX 4090, T4, A100)

개요

BERT 계열 언어 모델 중 하나인 DistilBERT(논문)로 미세 조정 훈련을 수행할 때 NVIDIA GPU 모델에 따라 훈련에 걸리는 시간이 어떻게 달라지는지 궁금했습니다.

실험에 사용한 모델과 데이터셋은 다음과 같습니다.

미세 조정 훈련은 아래의 작업을 목표로 하였습니다.

그리고 훈련 소요 시간 비교를 위해 사용한 NVIDIA GPU 모델은 아래 표와 같습니다.

모델 CUDA 코어 수 Tensor 코어 수 메모리 출시 시점 실험 머신 유형
RTX 4090 16,384개 512개 (4세대) 24GB GDDR6X 2022년 데스크톱 PC
T4 2,560개 320개 (2세대) 16GB GDDR6 2018년 GCP의 VM 인스턴스
A100 (40GB 기준) 6,912개 432개 (3세대) 40GB HBM2 2020년 GCP의 VM 인스턴스

RTX 4090은 PC에 장착된 것으로, T4와 A100은 GCP의 VM 인스턴스에 연결된 것으로 사용해서 환경의 차이가 있고, 또한 소요 시간에 영향을 미치는 다른 요인들도 있긴 하지만 GPU 간 소요 시간 차이를 대략적으로 확인하는 데에는 중요한 요소가 아닌 것으로 간주하였습니다.

실험 결과

실험을 위해 사용한 파이썬 스크립트 파일은 여기에 있습니다.

사전 작업:

  • 파이썬 패키지 설치: pip install datasets transformers accelerate
  • 스크립트 소스 코드에서 epochs 수정: epochs = 4.0

model.train() 소요 시간 (1회 테스트):

실험 머신 유형 GPU 소요 시간 (단위: 초)
데스크톱 PC RTX 4090 (24GB) 0:19:33
GCP의 VM 인스턴스 T4 (16GB) 1:57:01
GCP의 VM 인스턴스 A100 (40GB) 0:27:09

Written with StackEdit.

2025년 4월 21일 월요일

GCP에서 딥러닝을 위한 VM 인스턴스 생성

GCP에서 딥러닝을 위한 VM 인스턴스 생성

구글 클라우드 플랫폼(Google Cloud Platform, GCP)에 딥러닝 환경을 구축하고 이를 통해 실습할 수 있는 방법에 대해 설명합니다.

이 문서에서 다루는 주요 내용은 다음과 같습니다.

  1. 딥러닝을 위한 VM 인스턴스 생성 과정
  2. 로컬 컴퓨터에서 VM 인스턴스에 연결하는 과정
  3. 로컬 컴퓨터에서 JupyterLab에 연결하는 과정

1. 브라우저에서 Google Cloud Console 연결

  1. 브라우저로 Google Cloud Console에 연결하고 로그인
  2. 프로젝트 선택하고 프로젝트 ID 확인
    • 프로젝트 ID: my_project

2. “Deep Learning VM” 이미지로 VM 인스턴스 생성

  1. 좌측 상단 탐색 메뉴에서 Marketplace 항목 선택
  2. 검색 창에 "deep learning vm"을 입력하고 엔터
  3. 검색 결과에서 아래 항목 클릭
    • Deep Learning VM - Google Click to Deploy - 가상 머신
      • OS: Debian 10 또는 11
  4. 실행 버튼 클릭
  5. 아래와 같이 입력 또는 선택 (항목별 값은 각자의 상황에 맞게 변경)
    • 배포 구성 예시 1 (예상 월별 총액 KRW 859,668/월)
      • Deployment
        • Deployment name: deeplearning-1
        • Zone: asia-northeast3-b
        • Machien type: GPU
          • GPU 유형: NVIDIA T4
          • GPU 수: 1
          • 머신 유형: n1-highmem-8(vCPU 8개, 코어 4개, 메모리 52GB)
          • Framework: PyTorch 2.4 (CUDA 12.4, Python 3.10)
      • GPU
        • Checked: Install NVIDIA GPU driver automatically on first startup?
      • Access to the Jupyter Lab
        • Checked: Enable access to JupyterLab via URL instead of SSH. (Beta)
      • Boot Disk
        • Boot disk type: SSD Persistent Disk
        • Boot disk size in GB: 1024
      • Networking
        • 네트워크 인터페이스: default
    • 배포 구성 예시 2 (예상 월별 총액 KRW 3,162,624/월)
      • Deployment
        • Deployment name: deeplearning-2
        • Zone: asia-northeast3-b
        • Machien type: GPU
          • GPU 유형: NVIDIA A100 40GB
          • GPU 수: 1
          • 머신 유형: a2-highgpu-1g(vCPU 12개, 코어 6개, 메모리 85GB)
          • Framework: PyTorch 2.4 (CUDA 12.4, Python 3.10)
      • GPU
        • Checked: Install NVIDIA GPU driver automatically on first startup?
      • Access to the Jupyter Lab
        • Checked: Enable access to JupyterLab via URL instead of SSH. (Beta)
      • Boot Disk
        • Boot disk type: SSD Persistent Disk
        • Boot disk size in GB: 1024
      • Networking
        • 네트워크 인터페이스: default
  6. 배포 버튼 클릭 (배포 완료까지 약 3~ 5분 소요)
  7. 좌측 상단 탐색 메뉴에서 VM 인스턴스 항목 선택
  8. 배포한 인스턴스 deeplearning-1-vm 또는 deeplearning-2-vm 클릭하여 세부 정보 확인

3. SSH로 VM 연결하기

3.1. 브라우저에서 SSH를 통해 연결

  1. Google Cloud Console 좌측 상단 탐색 메뉴에서 VM 인스턴스 항목 선택
  2. 인스턴스 목록에서 deeplearning-1-vm 항목의 SSH 옆에 있는 펼침 메뉴 클릭
  3. 펼침 메뉴에서 브라우저 창에서 열기 항목 클릭
  4. 브라우저 창으로 열린 터미널에서 쉘 명령어를 실행하거나 파일 업로드/다운로드 작업 수행

3.2. Cloud Shell에서 gcloud CLI로 SSH 연결

  1. Google Cloud Console 우측 상단 아이콘 메뉴에서 Cloud Shell 활성화 항목 선택
  2. Shell 창에서 gcloud compute ssh deeplearning-1-vm 명령 실행
    • 터미널 프로그램이 실행되면서 VM 인스턴스에 연결함
  3. 터미널 창에서 쉘 명령어를 실행

3.3. 로컬 컴퓨터에서 gcloud CLI로 SSH 연결

  1. gcloud CLI 설치
    • SSH 클라이언트 프로그램(예: PuTTY)을 실행하고자 하는 컴퓨터에서 gcloud CLI 설치
  2. Google Cloud SDK Shell 실행
    • Windows의 경우 전체 프로그램 목록에서 Google Cloud SDK Shell 항목 클릭
  3. SSH 연결
    • Google Cloud SDK Shell 창에서 아래와 같이 명령 실행
      gcloud compute ssh \
          --project my_project \
          --zone asia-northeast3-b \
          deeplearning-1-vm \
          -- -L 8080:localhost:8080
      
      PuTTY 터미널 프로그램이 실행되면서 VM 인스턴스에 연결함
  4. PuTTY 터미널 창에서 쉘 명령어를 실행

4. JupyterLab 연결하기

Deep Learning VM 이미지로 생성한 인스턴스를 시작하면 JupyterLab 세션이 초기화됩니다.

4.1. SSH 포트 전달을 통한 JupyterLab 연결

  1. Cloud Shell 또는 로컬 컴퓨터의 Google Cloud SDK Shell에서 Google Cloud CLI를 사용하여 다음 명령어 실행
    gcloud compute ssh \
        --project my_project \
        --zone asia-northeast3-b \
        deeplearning-1-vm
        -- -L 8080:localhost:8080
    
  2. 로컬 브라우저를 통해 http://localhost:8080 열기
    • Cloud Shell 터미널의 경우 우측 상단 웹 미리보기 아이콘 클릭
  3. JupyterLab에서 노트북을 생성하고 실행합니다.

5. 참고 문서

Written with StackEdit.

잠들기 전의 나와 잠에서 깬 나는 이어지는 나인가?

잠들기 전의 나와 잠에서 깬 나는 이어지는 나인가? 이 글에서, 개체-A: 잠들기 전의 나 개체-B: 잠에서 깬 나 (개체-A의 일부 세포 변화) 의식 이전(transfer) t2 시점에 개체-A의 의식...