🤗

Transformers와 DeepSpeed로 새 BERT모델 굽기

Posted on Mon, May 17, 2021 NLP MLDL Framework

환경 준비

pip install torch
# 혹은 
# pip install torch==1.8.1+cu111 -f https://download.pytorch.org/whl/torch_stable.html
# 등등 CUDA 버전 맞춰서..
pip install transformers[deepspeed]
pip install git+https://github.com/huggingface/transformers
git clone https://github.com/huggingface/transformers
mv transformers/examples/pytorch/language-modeling/* .
rm -rf transformers
pip install -r requirements.txt

위와 같이 설치를 모두 진행해주면 OK.

💡

아래 학습은 RTX Titan * 1대, 그리고 RAM 128G, CPU 64c 이상의 환경에서 진행했습니다. 학습시 약 13GB의 VRam을 소모합니다.

모두 준비된 깃헙 Repo

아래 Github Repo를 clone해서 사용하셔도 됩니다. (다만 실행 시점 최신이 아닐 수 있음)

Beomi/transformers-language-modeling

Fork from https://github.com/huggingface/transformers/tree/86d5fb0b360e68de46d40265e7c707fe68c8015b/examples/pytorch/language-modeling at 2021.05.17. Fine-tuning (or training from scratch) the library models for language modeling on a text dataset for GPT, GPT-2, ALBERT, BERT, DistilBERT, RoBERTa, XLNet... GPT and GPT-2 are trained or fine-tuned using a causal language modeling (CLM) loss while ALBERT, BERT, DistilBERT and RoBERTa are trained or fine-tuned using a masked language modeling (MLM) loss.

데이터셋/Tokenizer 준비

이 부분은 각자 준비하는 것이 있을 테니.. 샘플로만 준비.

Dataset = KcBERT에서 일부 샘플링한 것

wget -O sampled_20190101_20200611_v2.txt https://www.dropbox.com/s/n8th7qnwpa1bt3r/sampled_20190101_20200611_v2.txt?dl=1

Tokenizer = KcELECTRA 것(huggingface model)

DeepSpeed Stage 2 = ZeRO-2

DeepSpeed Config 파일 준비(ZeRO-2)

아래 파일을 ds_zero2_1gpu.json 으로 만들어 저장해두자.

{
    "fp16": {
        "enabled": "auto",
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    },
    "optimizer": {
        "type": "AdamW",
        "params": {
            "lr": "auto",
            "betas": "auto",
            "eps": "auto",
            "weight_decay": "auto"
        }
    },
    "scheduler": {
        "type": "WarmupLR",
        "params": {
            "warmup_min_lr": "auto",
            "warmup_max_lr": "auto",
            "warmup_num_steps": "auto"
        }
    },
    "zero_optimization": {
        "stage": 2,
        "allgather_partitions": true,
        "allgather_bucket_size": 2e8,
        "overlap_comm": true,
        "reduce_scatter": true,
        "reduce_bucket_size": 2e8,
        "contiguous_gradients": true,
        "cpu_offload": true
    },
    "gradient_accumulation_steps": "auto",
    "gradient_clipping": "auto",
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto"
}

학습 커맨드 파일 준비(ZeRO-2)

💡

Batch Size(BS)만 적당히 조절해서 쓰자.

# export NCCL_IB_DISABLE=1
export BS=32
export NCCL_DEBUG=INFO

deepspeed run_mlm.py \
--seed 42 \
--model_type bert \
--tokenizer_name beomi/KcELECTRA-base \
--train_file ./sampled_20190101_20200611_v2.txt \
--num_train_epochs 2 \
--per_device_train_batch_size $BS \
--per_device_eval_batch_size $BS \
--do_train \
--output_dir ./test-bert-zero2 \
--fp16 \
--logging_first_step \
--max_seq_length 300 \
--deepspeed ./ds_zero2_1gpu.json  

위 스크립트를 sh 파일로 만들어 실행하거나 혹은 그대로 복사 & 붙여넣기를 해도 된다.

샘플 실행 로그(ZeRO-2)

ZeRO-2 BERT Train(with Sampled dataset) Output Log with NCCL_DEBUG=INFO

ZeRO-2 BERT Train(with Sampled dataset) Output Log with NCCL_DEBUG=INFO - ZeRO2_BERT_Sample_Log.txt

DeepSpeed Stage 3 = ZeRO-3

DeepSpeed Config 파일 준비(ZeRO-3)

아래 파일을 ds_zero3_1gpu.json 으로 만들어 저장해두자.

{
    "fp16": {
        "enabled": "auto",
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    },

    "optimizer": {
        "type": "AdamW",
        "params": {
            "lr": "auto",
            "betas": "auto",
            "eps": "auto",
            "weight_decay": "auto"
        }
    },

    "scheduler": {
        "type": "WarmupLR",
        "params": {
            "warmup_min_lr": "auto",
            "warmup_max_lr": "auto",
            "warmup_num_steps": "auto"
        }
    },

    "zero_optimization": {
        "stage": 3,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": true
        },
        "offload_param": {
            "device": "cpu",
            "pin_memory": true
        },
        "overlap_comm": true,
        "contiguous_gradients": true,
        "sub_group_size": 1e14,
        "reduce_bucket_size": "auto",
        "stage3_prefetch_bucket_size": "auto",
        "stage3_param_persistence_threshold": "auto",
        "stage3_max_live_parameters": 1e9,
        "stage3_max_reuse_distance": 1e9,
        "stage3_gather_fp16_weights_on_model_save": true
    },

    "gradient_accumulation_steps": "auto",
    "gradient_clipping": "auto",
    "steps_per_print": 2000,
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "wall_clock_breakdown": false
}

학습 커맨드 파일 준비(ZeRO-3)

💡

Batch Size(BS)만 적당히 조절해서 쓰자.

# export NCCL_IB_DISABLE=1
export BS=32
export NCCL_DEBUG=INFO

deepspeed run_mlm.py \
--seed 42 \
--model_type bert \
--tokenizer_name beomi/KcELECTRA-base \
--train_file ./sampled_20190101_20200611_v2.txt \
--num_train_epochs 2 \
--per_device_train_batch_size $BS \
--per_device_eval_batch_size $BS \
--do_train \
--output_dir ./test-bert-full \
--fp16 \
--logging_first_step \
--max_seq_length 300 \
--deepspeed ./ds_zero3_1gpu.json  

위 스크립트를 sh 파일로 만들어 실행하거나 혹은 그대로 복사 & 붙여넣기를 해도 된다.

샘플 실행 로그(ZeRO-3)

ZeRO-3 BERT Train(with Sampled dataset) Output Log with NCCL_DEBUG=INFO

ZeRO-3 BERT Train(with Sampled dataset) Output Log with NCCL_DEBUG=INFO - ZeRO3_BERT_Sample_Log.txt