Code N Solve ๐: Google Colab์์ Transformers ๋ชจ๋ธ ํ์ต ์ ๋ฐ์ํ๋ ์ค๋ฅ ํด๊ฒฐ ๊ฐ์ด๋
Transformer ๊ธฐ๋ฐ NLP ๋ชจ๋ธ์ Google Colab์์ ํ์ตํ๋ ๋์ค ์ด๋ณด์๊ฐ ๊ฒช์ ์ ์๋ ๋ค์ํ ์ค๋ฅ์ ๋ํด ์ ๋ฆฌํด๋ณด์๋ค.
ํนํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๋ฌธ์ , ํ์ผ ๊ฒฝ๋ก ์ค์ , ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ๋ฌธ์ ๋ฑ ๋ค์ํ ์ค๋ฅ๋ฅผ ์ดํดํ๊ณ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์.
Google Colab ํ๊ฒฝ ์ดํดํ๊ธฐ
Google Colab์ด๋?
Google Colab(Colaboratory)์ ๊ตฌ๊ธ์ด ์ ๊ณตํ๋ ํด๋ผ์ฐ๋ ๊ธฐ๋ฐ Jupyter ๋ ธํธ๋ถ ํ๊ฒฝ์ด๋ค. ๋ก์ปฌ์ ์๋ฌด๊ฒ๋ ์ค์นํ์ง ์์๋ ๋ธ๋ผ์ฐ์ ์์ Python ์ฝ๋๋ฅผ ์คํํ๊ณ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ํ์ตํ ์ ์๋ค.
ํนํ GPU๋ฅผ ๋ฌด๋ฃ๋ก ์ ๊ณตํ์ฌ ๋๊ท๋ชจ ๋ฐ์ดํฐ์ ์ ์ฒ๋ฆฌํ๊ณ ๋ฅ๋ฌ๋ ๋ชจ๋ธ์ ํ์ตํ๋ ๋ฐ ํฐ ์ฅ์ ์ ๊ฐ์ง๊ณ ์๋ค.
๋ฌด๋ฃ ํ๋ vs Pro ํ๋
| ํญ๋ชฉ | ๋ฌด๋ฃ (Free) | Pro | Pro+ |
|---|---|---|---|
| GPU | T4 (๋๋ค ํ ๋น) | T4, V100, A100 | A100 ์ฐ์ |
| RAM | ์ฝ 12GB | ์ฝ 25GB | ์ฝ 52GB |
| ์ธ์ ์ ์ง | ์ต๋ 12์๊ฐ | ์ต๋ 24์๊ฐ | ์ต๋ 24์๊ฐ |
| ์ ํด ํ์์์ | ์ฝ 90๋ถ | ์ฝ 90๋ถ | ์ฝ 90๋ถ |
| ๋์คํฌ | ์ฝ 78GB | ์ฝ 166GB | ์ฝ 166GB |
| ๊ฐ๊ฒฉ | ๋ฌด๋ฃ | ์ ~$10 | ์ ~$50 |
GPU ํ ๋น ๋ฐฉ๋ฒ
# ํ์ฌ GPU ํ์ธ
import torch
print(torch.cuda.is_available()) # True๋ฉด GPU ์ฌ์ฉ ๊ฐ๋ฅ
print(torch.cuda.get_device_name(0)) # GPU ์ด๋ฆ ์ถ๋ ฅ
# ๋ฐํ์ โ ๋ฐํ์ ์ ํ ๋ณ๊ฒฝ โ GPU ์ ํColab ๋ฉ๋ด: ๋ฐํ์ โ ๋ฐํ์ ์ ํ ๋ณ๊ฒฝ โ ํ๋์จ์ด ๊ฐ์๊ธฐ โ GPU
์ธ์ ์ ํ ๋ฐ ์ฃผ์์ฌํญ
- ์ธ์ ํ์์์: ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ๊ฑฐ๋ ํญ์ ๋นํ์ฑํํ๋ฉด ์ฝ 90๋ถ ํ ์ธ์ ์ด ๋๊ธด๋ค
- ๋ฐํ์ ์ฌ์์: ์ธ์ ์ด ๋๊ธฐ๋ฉด ์ค์นํ ํจํค์ง, ๋ณ์, ํ์ต ์ํ๊ฐ ๋ชจ๋ ์ด๊ธฐํ๋๋ค
- ํ์ผ ํ๋ฐ์ฑ: Colab์
/content๋๋ ํฐ๋ฆฌ์ ์ ์ฅํ ํ์ผ์ ์ธ์ ์ข ๋ฃ ์ ์ญ์ ๋๋ค - Google Drive ์ฐ๋: ์๊ตฌ ์ ์ฅ์ด ํ์ํ ํ์ผ์ ๋ฐ๋์ Google Drive์ ์ ์ฅํด์ผ ํ๋ค
Hugging Face Transformers ํ์ดํ๋ผ์ธ ์ ์ฒด ํ๋ฆ
Hugging Face Transformers1๋ BERT, GPT, RoBERTa, T5 ๋ฑ ์์ฒ ๊ฐ์ ์ฌ์ ํ์ต(pretrained) ๋ชจ๋ธ์ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
๋ชจ๋ธ ํ์ธํ๋(fine-tuning)์ ์ ์ฒด ํ๋ฆ์ ๋ค์๊ณผ ๊ฐ๋ค.
๋ฌธ์ 1: ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ์ค๋ฅ โ sklearn๊ณผ datasets
Google Colab์์ Transformers ๋ชจ๋ธ ํ์ต์ ์์ํ๋ ค๋ฉด Hugging Face transformers, torch, datasets ๋ฑ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ๋ค.
ํ์ง๋ง sklearn์ ์ค์นํ ๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
ValueError: metadata-generation-failed
Encountered error while generating package metadata.
See above for output.
note: This is an issue with the package mentioned above, not pip.
hint: See above for details.์์ธ ๋ถ์
sklearn์ ์ค์ ํจํค์ง ์ด๋ฆ์ด ์๋๋ค.
Python ํจํค์ง ์ธ๋ฑ์ค(PyPI)์์ ์ค์ ํจํค์ง ์ด๋ฆ์ scikit-learn์ด๋ค.
sklearn์ด๋ผ๋ ์ด๋ฆ์ ๋ณ๋ ํจํค์ง๊ฐ ์กด์ฌํ๋๋ฐ, ์ด๊ฒ์ ๊ตฌ๋ฒ์ ๋ํผ ํจํค์ง๋ก ํ์ฌ๋ ์ ๋๋ก ์ค์น๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.
์ฆ, pip install sklearn์ ์คํํ๋ฉด scikit-learn์ด ์๋ ๋ค๋ฅธ (๋ถ์์ ํ) ํจํค์ง๋ฅผ ์ค์นํ๋ ค๊ณ ์๋ํด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
# ์๋ชป๋ ๋ฐฉ๋ฒ
!pip install sklearn
# ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ
!pip install -U scikit-learn์ ์ฒด ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ ๋ฒ์ ์ค์น:
!pip install transformers torch datasets scikit-learn evaluate accelerate๊ฐ ํจํค์ง์ ์ญํ :
| ํจํค์ง | ์ฉ๋ |
|---|---|
transformers |
BERT ๋ฑ ์ฌ์ ํ์ต ๋ชจ๋ธ ๋ก๋ ๋ฐ ํ์ธํ๋ |
torch |
๋ฅ๋ฌ๋ ์ฐ์ฐ ๋ฐฑ์๋ (PyTorch) |
datasets |
HuggingFace ๋ฐ์ดํฐ์ ๋ก๋ ๋ฐ ์ฒ๋ฆฌ |
scikit-learn |
ํ๊ฐ ์งํ ๊ณ์ฐ (accuracy, f1 ๋ฑ) |
evaluate |
HuggingFace ๊ณต์ ํ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
accelerate |
๋ถ์ฐ ํ์ต, ํผํฉ ์ ๋ฐ๋(fp16) ์ง์ |
๋ฌธ์ 2: Google Drive ํ์ผ ๊ฒฝ๋ก ์ค์ ๋ฌธ์ 4
๋ฐ์ดํฐ์
์ Colab์์ ์ฌ์ฉํ๋ ค๋ฉด Google Drive์ ์ ์ฅ๋ ํ์ผ์ Colab์ ์ฐ๊ฒฐํด์ผ ํ๋ค.
Drive๋ฅผ ๋ง์ดํธํ์ง ์์ผ๋ฉด FileNotFoundError ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
FileNotFoundError: [Errno 2] No such file or directory: '/content/drive/MyDrive/Dataset/Dataset.json'์์ธ ๋ถ์
Colab ์ธ์
์ /content ๋๋ ํฐ๋ฆฌ๋ Colab VM์ ๋ก์ปฌ ์ ์ฅ์๋ค.
Google Drive๋ ๋ณ๋์ ์ ์ฅ ๊ณต๊ฐ์ด๋ฉฐ, ๋ช
์์ ์ผ๋ก ๋ง์ดํธํด์ผ๋ง /content/drive ๊ฒฝ๋ก๋ก ์ ๊ทผ ๊ฐ๋ฅํ๋ค.
๋ํ ์ธ์
์ด ์ฌ์์๋๋ฉด ๋ง์ดํธ๊ฐ ํด์ ๋๋ฏ๋ก ๋งค๋ฒ ๋ค์ ๋ง์ดํธํด์ผ ํ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
from google.colab import drive
drive.mount('/content/drive')์คํํ๋ฉด ๊ตฌ๊ธ ๊ณ์ ์ธ์ฆ์ ์์ฒญํ๋ ํ์
์ด ๋ํ๋๋ค. ์ธ์ฆ ์๋ฃ ํ /content/drive/MyDrive/์์ ํ์ผ์ ์ ๊ทผํ ์ ์๋ค.
import pandas as pd
# Google Drive์์ ํ์ผ ์ฝ๊ธฐ
file_path = "/content/drive/MyDrive/Dataset/Dataset.json"
data = pd.read_json(file_path, lines=True)
print(data.head())
print(f"๋ฐ์ดํฐ ํฌ๊ธฐ: {data.shape}")Google Drive ๊ฒฝ๋ก ๊ตฌ์กฐ
/content/drive/
MyDrive/ โ ๋ด ๋๋ผ์ด๋ธ (๋ณธ์ธ ํ์ผ)
Dataset/
Dataset.json
Shareddrives/ โ ๊ณต์ ๋๋ผ์ด๋ธ (ํ ๋๋ผ์ด๋ธ)ํ์ผ ํ์ธ ๋ฐฉ๋ฒ
import os
# ๊ฒฝ๋ก ์กด์ฌ ํ์ธ
path = "/content/drive/MyDrive/Dataset"
if os.path.exists(path):
print("ํด๋ ์กด์ฌ")
print(os.listdir(path))
else:
print("๊ฒฝ๋ก ์์ โ Drive ๋ง์ดํธ ํ์ธ ํ์")๋ฌธ์ 3: Transformers ๋ชจ๋ธ ํ์ต ์ ๋ฐ์ดํฐ ํจ๋ฉ ์ค๋ฅ2
๋ชจ๋ธ ํ์ต ์ค ๋ฐฐ์น ๋ฐ์ดํฐ์ ๊ธธ์ด๊ฐ ์ผ์ ํ์ง ์์ผ๋ฉด ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
ValueError: expected sequence of length 128 at dim 1 (got 97)
# ๋๋
RuntimeError: stack expects each tensor to be equal size, but got [128] at entry 0 and [97] at entry 1์์ธ ๋ถ์
Transformer ๋ชจ๋ธ์ ์
๋ ฅ ์ํ์ค์ ๊ธธ์ด๊ฐ ๋ฐฐ์น ๋ด์์ ๋์ผํด์ผ ํ๋ค.
์์ฐ์ด ํ
์คํธ๋ ๋ฌธ์ฅ๋ง๋ค ๊ธธ์ด๊ฐ ๋ค๋ฅด๋ฏ๋ก, ์งง์ ๋ฌธ์ฅ์๋ ํจ๋ฉ([PAD] ํ ํฐ)์ ์ถ๊ฐํด ๊ธธ์ด๋ฅผ ๋ง์ถฐ์ผ ํ๋ค.
ํ ํฌ๋์ด์ง ๋จ๊ณ์์ padding=True๋ฅผ ์ค์ ํ๋๋ผ๋, ๊ฐ ์ํ์ ๊ฐ๋ณ๋ก ์ฒ๋ฆฌํ๋ฉด ๋ฐฐ์น๋ก ๋ฌถ์ ๋ ํฌ๊ธฐ๊ฐ ๋ง์ง ์์ ์ ์๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
DataCollatorWithPadding์ ์ฌ์ฉํ๋ฉด ๋ฐฐ์น๋ฅผ ๊ตฌ์ฑํ ๋ ๋์ ์ผ๋ก ํจ๋ฉ์ ์ ์ฉํ๋ค.
from transformers import DataCollatorWithPadding
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=data_collator, # ์๋ ํจ๋ฉ ์ถ๊ฐ
)Dynamic Padding์ ์ฅ์ : ๋ฐฐ์น ๋ด์์ ๊ฐ์ฅ ๊ธด ์ํ์ค์ ๋ง์ถฐ ํจ๋ฉํ๋ฏ๋ก, ๋ถํ์ํ ํจ๋ฉ์ ์ต์ํํด ํ์ต ์๋๋ฅผ ๋์ธ๋ค.
# ์ ์ฒด ํ ํฌ๋์ด์ง ์์
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("klue/bert-base")
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True, # ์ต๋ ๊ธธ์ด ์ด๊ณผ ์ ์๋ฆ
max_length=128, # ์ต๋ ํ ํฐ ๊ธธ์ด
# padding์ ์ฌ๊ธฐ์ ํ์ง ์๊ณ DataCollator์์ ๋์ ์ผ๋ก ์ฒ๋ฆฌ
)
tokenized_dataset = dataset.map(tokenize_function, batched=True)๋ฌธ์ 4: ๋ชจ๋ธ ํ์ต ์ wandb ๋ก๊ทธ์ธ ์์ฒญ5
Hugging Face Trainer๋ ๊ธฐ๋ณธ์ ์ผ๋ก Weights & Biases(wandb)๋ฅผ ์ฌ์ฉํด ํ์ต ๊ณผ์ ์ ์ถ์ ํ๋ ค ํ๋ค.
์ฒ์ ์คํ ์ ๋ค์๊ณผ ๊ฐ์ ์
๋ ฅ ํ๋กฌํํธ๊ฐ ๋ํ๋๋ค.
wandb: (1) Create a W&B account
wandb: (2) Use an existing W&B account
wandb: (3) Don't visualize my results
wandb: Enter your choice:Colab์์ ์ ์ด ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ๋ฉ์ถ๋ ๊ฒฝ์ฐ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
report_to="none"์ผ๋ก wandb๋ฅผ ๋นํ์ฑํํ๋ค.
from transformers import TrainingArguments
training_args = TrainingArguments(
output_dir="./results",
evaluation_strategy="epoch",
per_device_train_batch_size=8,
per_device_eval_batch_size=8,
num_train_epochs=3,
weight_decay=0.01,
report_to="none" # wandb ๋นํ์ฑํ
)๋๋ ํ๊ฒฝ ๋ณ์๋ก ์ค์ :
import os
os.environ["WANDB_DISABLED"] = "true"wandb๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธ ํ ํ ํฐ์ ์ค์ ํ๋ค:
import wandb
wandb.login(key="your_api_key_here")๋ฌธ์ 5: CUDA Out of Memory ์ค๋ฅ
๋ฌธ์ ์ํฉ
RuntimeError: CUDA out of memory. Tried to allocate 2.00 GiB
(GPU 0; 14.76 GiB total capacity; 12.54 GiB already allocated;
1.20 GiB free; 12.67 GiB reserved in total by PyTorch)์์ธ ๋ถ์
GPU ๋ฉ๋ชจ๋ฆฌ(VRAM)๊ฐ ๋ถ์กฑํ ๋ ๋ฐ์ํ๋ค. ์ฃผ์ ์์ธ:
- ๋ฐฐ์น ์ฌ์ด์ฆ๊ฐ ๋๋ฌด ํผ: ๋ฐฐ์น ํ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ํ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ VRAM์ ์ด๊ณผ
- ์ํ์ค ๊ธธ์ด๊ฐ ๋๋ฌด ๊น: ํ ํฐ ๊ธธ์ด๊ฐ ๊ธธ์๋ก Attention ๊ณ์ฐ์ ํ์ํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ๊ณฑ์ผ๋ก ์ฆ๊ฐ
- ๋ชจ๋ธ์ด ๋๋ฌด ํผ: ํ๋ผ๋ฏธํฐ ์๊ฐ ๋ง์ ๋ชจ๋ธ (BERT-large, GPT-2 ๋ฑ)
- ์ด์ ์คํ์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋์ง ์์: ์ด์ ์ ์์ ๋ชจ๋ธ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋จ์ ์์
ํด๊ฒฐ ๋ฐฉ๋ฒ
1. ๋ฐฐ์น ์ฌ์ด์ฆ ์ค์ด๊ธฐ + Gradient Accumulation
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=4, # 8 โ 4๋ก ์ค์
gradient_accumulation_steps=4, # 4๋ฒ ๋์ ํด์ ์ค์ง์ ์ผ๋ก ๋ฐฐ์น 16 ํจ๊ณผ
per_device_eval_batch_size=8,
num_train_epochs=3,
report_to="none",
)gradient_accumulation_steps=4๋ฅผ ์ค์ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์์ผ๋ก๋ ๋ฐฐ์น 4๊ฐ์ฉ ์ฒ๋ฆฌํ์ง๋ง, 4๋ฒ accumulate ํ์ ๊ฐ์ค์น๋ฅผ ์
๋ฐ์ดํธํ๋ฏ๋ก ์ค์ง์ ์ธ ๋ฐฐ์น ํฌ๊ธฐ๋ 16์ด๋ค.
2. Gradient Checkpointing ํ์ฑํ
training_args = TrainingArguments(
output_dir="./results",
per_device_train_batch_size=4,
gradient_checkpointing=True, # ์ค๊ฐ activation์ ์ ์ฅํ์ง ์๊ณ ์ฌ๊ณ์ฐ
fp16=True, # 16๋นํธ ๋ถ๋์์์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ ๋ฐ ์ ์ฝ
report_to="none",
)gradient_checkpointing=True๋ Forward pass ์ค๊ฐ ๊ฒฐ๊ณผ(activation)๋ฅผ ์ ์ฅํ์ง ์๊ณ , backward pass ์ ํ์ํ ๋ ์ฌ๊ณ์ฐํ๋ค.
์๋๋ ์ฝ 20~30% ๋๋ ค์ง์ง๋ง ๋ฉ๋ชจ๋ฆฌ๋ ํฌ๊ฒ ์ ์ฝ๋๋ค.
3. ํผํฉ ์ ๋ฐ๋(Mixed Precision) ํ์ต
training_args = TrainingArguments(
output_dir="./results",
fp16=True, # float32 โ float16 (๋ฉ๋ชจ๋ฆฌ ์ ๋ฐ, ์๋ 1.5~2๋ฐฐ)
# bf16=True, # A100 GPU์์๋ bfloat16์ด ๋ ์์ ์
report_to="none",
)4. ์ด์ ์ธ์ ๋ฉ๋ชจ๋ฆฌ ํด์
import torch
import gc
# GPU ์บ์ ๋น์ฐ๊ธฐ
torch.cuda.empty_cache()
# Python ๊ฐ๋น์ง ์ปฌ๋ ํฐ ์คํ
gc.collect()
# ํ์ฌ GPU ๋ฉ๋ชจ๋ฆฌ ์ํ ํ์ธ
print(f"ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ: {torch.cuda.memory_allocated() / 1024**3:.2f} GB")
print(f"์บ์๋ ๋ฉ๋ชจ๋ฆฌ: {torch.cuda.memory_reserved() / 1024**3:.2f} GB")๋ฌธ์ 6: ์ธ์ ์ฐ๊ฒฐ ๋๊น์ผ๋ก ์ธํ ํ์ต ์ค๋จ
๋ฌธ์ ์ํฉ
๋ฌด๋ฃ Colab์์ ์ฅ์๊ฐ ํ์ตํ๋ค๊ฐ ์ธ์ ์ด ๋๊ธฐ๋ฉด ํ์ต ์งํ ์ํฉ์ด ๋ชจ๋ ์ฌ๋ผ์ง๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ: ์ฒดํฌํฌ์ธํธ ์ ์ฅ ์ ๋ต
์ฒดํฌํฌ์ธํธ๋ฅผ Google Drive์ ์ ์ฅํด, ์ธ์ ์ด ๋๊ฒจ๋ ์ด์ด์ ํ์ตํ ์ ์๋๋ก ํ๋ค.
from google.colab import drive
drive.mount('/content/drive')
training_args = TrainingArguments(
# Google Drive์ ์ฒดํฌํฌ์ธํธ ์ ์ฅ
output_dir="/content/drive/MyDrive/model_checkpoints",
# ๋งค ์ํญ๋ง๋ค ์ ์ฅ
save_strategy="epoch",
evaluation_strategy="epoch",
# ์ต๋ 3๊ฐ ์ฒดํฌํฌ์ธํธ๋ง ๋ณด๊ด (๋์คํฌ ์ ์ฝ)
save_total_limit=3,
# ๊ฐ์ฅ ์ข์ ๋ชจ๋ธ ์๋ ์ ํ
load_best_model_at_end=True,
metric_for_best_model="f1",
report_to="none",
)์ฒดํฌํฌ์ธํธ์์ ์ด์ด ํ์ตํ๊ธฐ
์ธ์ ์ด ๋๊ธด ํ ๋ค์ ์์ํ ๋:
# ๋ง์ง๋ง ์ฒดํฌํฌ์ธํธ ๊ฒฝ๋ก ํ์ธ
import os
checkpoint_dir = "/content/drive/MyDrive/model_checkpoints"
checkpoints = [d for d in os.listdir(checkpoint_dir) if d.startswith("checkpoint")]
latest_checkpoint = sorted(checkpoints)[-1]
checkpoint_path = os.path.join(checkpoint_dir, latest_checkpoint)
print(f"์ด์ด ํ์ตํ ์ฒดํฌํฌ์ธํธ: {checkpoint_path}")
# ์ฒดํฌํฌ์ธํธ์์ ์ด์ด ํ์ต
trainer.train(resume_from_checkpoint=checkpoint_path)Colab ์ธ์ ์ ์ง ๊ฟํ
๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ์ฝ์(F12)์์ ๋ค์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ์๋ ์ฌ์ฐ๊ฒฐ์ ์๋ํ๋ค (๋น๊ณต์์ ์ธ ๋ฐฉ๋ฒ):
// ๋ธ๋ผ์ฐ์ ์ฝ์์์ ์คํ
function ClickConnect(){
console.log("์ฐ๊ฒฐ ์ ์ง ํด๋ฆญ");
document.querySelector("colab-connect-button").click()
}
setInterval(ClickConnect, 60000) // 1๋ถ๋ง๋ค ์คํ๋จ, ์ด ๋ฐฉ๋ฒ์ Colab ์ ์ฑ ์ ๋ฐ๋ผ ๋์ํ์ง ์์ ์ ์๋ค. ๊ฐ์ฅ ํ์คํ ๋ฐฉ๋ฒ์ ์ฒดํฌํฌ์ธํธ๋ฅผ ์์ฃผ ์ ์ฅํ๋ ๊ฒ์ด๋ค.
๋ฌธ์ 7: Tokenizer์ Model ๋ถ์ผ์น ์ค๋ฅ
๋ฌธ์ ์ํฉ
ValueError: You are trying to use a fast tokenizer, which is not supported by this model.
# ๋๋
RuntimeError: The size of tensor a (30522) must match the size of tensor b (32000)
at non-singleton dimension 1์์ธ ๋ถ์
ํ ํฌ๋์ด์ ์ ๋ชจ๋ธ์ ์ดํ(vocabulary) ํฌ๊ธฐ๊ฐ ๋ค๋ฅผ ๋ ๋ฐ์ํ๋ค. ์๋ฅผ ๋ค์ด BERT ์๋ฌธ ๋ชจ๋ธ์ ์ดํ ํฌ๊ธฐ๋ 30,522๊ฐ์ธ๋ฐ, LLaMA ๋ชจ๋ธ์ 32,000๊ฐ๋ค. ์๋ก ๋ค๋ฅธ ์ฌ์ ํ์ต ๋ชจ๋ธ์ ํ ํฌ๋์ด์ ์ ๋ชจ๋ธ ๊ฐ์ค์น๋ฅผ ์์ด ์ฌ์ฉํ๋ฉด ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
ํญ์ ๊ฐ์ ๋ชจ๋ธ ์ด๋ฆ์ผ๋ก ํ ํฌ๋์ด์ ์ ๋ชจ๋ธ์ ํจ๊ป ๋ก๋ํด์ผ ํ๋ค.
from transformers import AutoTokenizer, AutoModelForSequenceClassification
model_name = "klue/bert-base" # ๋์ผํ ๋ชจ๋ธ ์ด๋ฆ ์ฌ์ฉ
# ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ: ๊ฐ์ ์ด๋ฆ์ผ๋ก ๋ก๋
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=2 # ๋ถ๋ฅํ ํด๋์ค ์
)
# ์๋ชป๋ ๋ฐฉ๋ฒ: ๋ค๋ฅธ ๋ชจ๋ธ์ ํ ํฌ๋์ด์ ์ฌ์ฉ
# tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") # ์๋ฌธ BERT
# model = AutoModelForSequenceClassification.from_pretrained("klue/bert-base") # ํ๊ตญ์ด BERTํ๊ตญ์ด NLP์์ ์์ฃผ ์ฌ์ฉํ๋ ๋ชจ๋ธ ๋ชฉ๋ก:
| ๋ชจ๋ธ | ํน์ง |
|---|---|
klue/bert-base |
ํ๊ตญ์ด ํนํ BERT, KLUE ๋ฒค์น๋งํฌ |
snunlp/KR-ELECTRA-discriminator |
ํ๊ตญ์ด ELECTRA, ๋น ๋ฅธ ํ์ธํ๋ |
monologg/koelectra-base-v3-discriminator |
KoELECTRA v3 |
beomi/kcbert-base |
KcBERT (์ปค๋ฎค๋ํฐ ํ ์คํธ ํ์ต) |
๋ฌธ์ 8: ๋ฐ์ดํฐ์ ํ์ ์ค๋ฅ (Dataset format, column names)
๋ฌธ์ ์ํฉ
KeyError: 'label'
# ๋๋
ValueError: The model did not return a loss from the inputs,
only the following keys: logits. For reference, the inputs it received are: input_ids, attention_mask.์์ธ ๋ถ์
HuggingFace Trainer๋ ํ์ต ๋ฐ์ดํฐ์
์ ํน์ ์ปฌ๋ผ ์ด๋ฆ์ด ์์ ๊ฒ์ ๊ธฐ๋ํ๋ค.
- ๋ ์ด๋ธ ์ปฌ๋ผ ์ด๋ฆ์ด
label๋๋labels์ฌ์ผ ํ๋ค. - ์
๋ ฅ ์ปฌ๋ผ์
input_ids,attention_mask๋ฑ ํ ํฌ๋์ด์ ์ถ๋ ฅ ํค์ ์ผ์นํด์ผ ํ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
import pandas as pd
from datasets import Dataset
# ์๋ณธ ๋ฐ์ดํฐ (์ปฌ๋ผ๋ช
์ด ๋ค๋ฅผ ์ ์์)
df = pd.DataFrame({
"review": ["์ ๋ง ์ข์์", "๋ณ๋ก์์", "๊ด์ฐฎ๋ค์"],
"sentiment": [1, 0, 1]
})
# ์ปฌ๋ผ๋ช
์ Trainer๊ฐ ๊ธฐ๋ํ๋ ์ด๋ฆ์ผ๋ก ๋ณ๊ฒฝ
df = df.rename(columns={
"review": "text",
"sentiment": "label"
})
# Pandas DataFrame์ HuggingFace Dataset์ผ๋ก ๋ณํ
dataset = Dataset.from_pandas(df)
print(dataset)
# Dataset({
# features: ['text', 'label'],
# num_rows: 3
# })ํ์ต/๊ฒ์ฆ ์ธํธ ๋ถ๋ฆฌ
from datasets import Dataset, DatasetDict
# 80/20 ๋ถ๋ฆฌ
split = dataset.train_test_split(test_size=0.2, seed=42)
dataset_dict = DatasetDict({
"train": split["train"],
"test": split["test"],
})
print(dataset_dict)ํ ํฌ๋์ด์ง ํ ๋ถํ์ํ ์ปฌ๋ผ ์ ๊ฑฐ
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True,
max_length=128,
)
tokenized_dataset = dataset_dict.map(
tokenize_function,
batched=True,
remove_columns=["text"], # ์๋ณธ ํ
์คํธ ์ปฌ๋ผ ์ ๊ฑฐ (Trainer๊ฐ ๋ชจ๋ฅด๋ ์ปฌ๋ผ ์ ๊ฑฐ)
)
print(tokenized_dataset["train"].column_names)
# ['label', 'input_ids', 'attention_mask', 'token_type_ids']Colab์์ ํจ์จ์ ์ผ๋ก ํ์ตํ๋ ํ ์ ๋ฆฌ
1. ๋ฐํ์ ์ ์ง
Colab์ ํญ์ด ๋นํ์ฑํ๋๊ฑฐ๋ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ์ผ๋ฉด ์ธ์ ์ด ๋๊ธด๋ค. ํ์ต ์ค์๋ Colab ํญ์ ํ์ฑ ์ํ๋ก ์ ์งํด์ผ ํ๋ค.
# ํ์ต ์ค ์งํ ์ํฉ ์ถ๋ ฅ์ผ๋ก "ํ์ฑ ์ํ" ์ ํธ ๋ณด๋ด๊ธฐ
from transformers import TrainerCallback
class ProgressCallback(TrainerCallback):
def on_epoch_end(self, args, state, control, **kwargs):
print(f"์ํญ {state.epoch:.0f}/{args.num_train_epochs} ์๋ฃ")
print(f"ํ์ฌ ์์ค: {state.log_history[-1].get('loss', 'N/A')}")2. Google Drive์ ๋ชจ๋ธ ์ ์ฅ
# ํ์ต ์๋ฃ ํ Drive์ ์ ์ฅ
save_path = "/content/drive/MyDrive/my_model"
model.save_pretrained(save_path)
tokenizer.save_pretrained(save_path)
print(f"๋ชจ๋ธ ์ ์ฅ ์๋ฃ: {save_path}")3. ๋ฐฐ์น ํฌ๊ธฐ ์๋ ํ์
# GPU ๋ฉ๋ชจ๋ฆฌ์ ๋ง๋ ์ต๋ ๋ฐฐ์น ํฌ๊ธฐ ์ฐพ๊ธฐ
def find_max_batch_size(model, tokenizer, start=32):
batch_size = start
while batch_size > 1:
try:
# ํ
์คํธ ๋ฐฐ์น๋ก Forward pass ์๋
inputs = tokenizer(
["ํ
์คํธ ๋ฌธ์ฅ"] * batch_size,
return_tensors="pt",
padding=True,
truncation=True,
max_length=128
).to("cuda")
with torch.no_grad():
model(**inputs)
print(f"๋ฐฐ์น ํฌ๊ธฐ {batch_size}: ์ฑ๊ณต")
return batch_size
except RuntimeError:
batch_size //= 2
print(f"OOM ๋ฐ์ โ ๋ฐฐ์น ํฌ๊ธฐ {batch_size}๋ก ์ค์")
torch.cuda.empty_cache()
return 14. GPU ์ฌ์ฉ๋ฅ ๋ชจ๋ํฐ๋ง
# ์ค์๊ฐ GPU ๋ฉ๋ชจ๋ฆฌ ํ์ธ
def print_gpu_status():
if torch.cuda.is_available():
allocated = torch.cuda.memory_allocated() / 1024**3
reserved = torch.cuda.memory_reserved() / 1024**3
total = torch.cuda.get_device_properties(0).total_memory / 1024**3
print(f"GPU ๋ฉ๋ชจ๋ฆฌ โ ์ฌ์ฉ: {allocated:.2f}GB / ์บ์: {reserved:.2f}GB / ์ด: {total:.2f}GB")
else:
print("GPU ์์ (CPU ๋ชจ๋)")
print_gpu_status()์ ์ฒด ํ์ต ์ฝ๋ ์์ : ๊ฐ์ฑ ๋ถ์ ๋ชจ๋ธ ํ์ธํ๋
ํ๊ตญ์ด ์ํ ๋ฆฌ๋ทฐ ๋ฐ์ดํฐ์ ์ผ๋ก ๊ธ์ /๋ถ์ ๊ฐ์ฑ ๋ถ์ ๋ชจ๋ธ์ ํ์ธํ๋ํ๋ ์ ์ฒด ์ฝ๋๋ค.
# ===== 1. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น =====
# !pip install transformers torch datasets scikit-learn evaluate accelerate
# ===== 2. ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฌํธ =====
import os
import torch
import numpy as np
import pandas as pd
from datasets import Dataset, DatasetDict
from transformers import (
AutoTokenizer,
AutoModelForSequenceClassification,
TrainingArguments,
Trainer,
DataCollatorWithPadding,
)
import evaluate
# ===== 3. Google Drive ๋ง์ดํธ =====
from google.colab import drive
drive.mount('/content/drive')
# ===== 4. GPU ํ์ธ =====
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"์ฌ์ฉ ๋๋ฐ์ด์ค: {device}")
if device == "cuda":
print(f"GPU: {torch.cuda.get_device_name(0)}")
# ===== 5. ๋ฐ์ดํฐ ์ค๋น =====
# ์์: Naver ์ํ ๋ฆฌ๋ทฐ ๋ฐ์ดํฐ์
# ์ค์ ๋ก๋ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ HuggingFace datasets์์ ๋ก๋
file_path = "/content/drive/MyDrive/Dataset/nsmc_train.txt"
try:
df = pd.read_csv(file_path, sep="\t")
df = df.dropna() # ๊ฒฐ์ธก๊ฐ ์ ๊ฑฐ
df = df.rename(columns={"document": "text", "label": "label"})
print(f"๋ฐ์ดํฐ ๋ก๋ ์๋ฃ: {df.shape}")
print(df.head())
except FileNotFoundError:
# ์ํ ๋ฐ์ดํฐ๋ก ๋์ฒด
print("ํ์ผ ์์ โ ์ํ ๋ฐ์ดํฐ ์ฌ์ฉ")
df = pd.DataFrame({
"text": [
"์ ๋ง ์ฌ๋ฏธ์๋ ์ํ์์ด์", "๋ณ๋ก์์ด์ ์๊ฐ ๋ญ๋น",
"์ต๊ณ ์ ์ํ์
๋๋ค", "๊ธฐ๋ ์ดํ์์ต๋๋ค",
"๊ฐ๋ ฅ ์ถ์ฒํฉ๋๋ค", "๋ค์๋ ์ ๋ณผ ๊ฑฐ์์",
],
"label": [1, 0, 1, 0, 1, 0]
})
# ===== 6. Dataset ๊ฐ์ฒด ์์ฑ ๋ฐ ๋ถ๋ฆฌ =====
dataset = Dataset.from_pandas(df[["text", "label"]])
split = dataset.train_test_split(test_size=0.1, seed=42)
dataset_dict = DatasetDict({
"train": split["train"],
"validation": split["test"],
})
print(f"ํ์ต: {len(dataset_dict['train'])}๊ฐ, ๊ฒ์ฆ: {len(dataset_dict['validation'])}๊ฐ")
# ===== 7. ํ ํฌ๋์ด์ ๋ฐ ๋ชจ๋ธ ๋ก๋ =====
model_name = "klue/bert-base"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
model_name,
num_labels=2,
)
model = model.to(device)
# ===== 8. ํ ํฌ๋์ด์ง =====
def tokenize_function(examples):
return tokenizer(
examples["text"],
truncation=True,
max_length=128,
)
tokenized_dataset = dataset_dict.map(
tokenize_function,
batched=True,
remove_columns=["text"],
)
print("ํ ํฌ๋์ด์ง ์๋ฃ")
print(tokenized_dataset)
# ===== 9. Data Collator ์ค์ =====
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
# ===== 10. ํ๊ฐ ํจ์ ์ค์ =====
accuracy_metric = evaluate.load("accuracy")
f1_metric = evaluate.load("f1")
def compute_metrics(eval_pred):
logits, labels = eval_pred
predictions = np.argmax(logits, axis=-1)
accuracy = accuracy_metric.compute(
predictions=predictions, references=labels
)["accuracy"]
f1 = f1_metric.compute(
predictions=predictions, references=labels, average="binary"
)["f1"]
return {"accuracy": accuracy, "f1": f1}
# ===== 11. ํ์ต ์ค์ =====
output_dir = "/content/drive/MyDrive/sentiment_model"
training_args = TrainingArguments(
output_dir=output_dir,
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=32,
learning_rate=2e-5,
weight_decay=0.01,
warmup_ratio=0.1,
evaluation_strategy="epoch",
save_strategy="epoch",
load_best_model_at_end=True,
metric_for_best_model="f1",
fp16=(device == "cuda"), # GPU์์๋ง fp16 ์ฌ์ฉ
gradient_accumulation_steps=2,
save_total_limit=2,
report_to="none", # wandb ๋นํ์ฑํ
logging_steps=50,
)
# ===== 12. Trainer ์ด๊ธฐํ ๋ฐ ํ์ต =====
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset["train"],
eval_dataset=tokenized_dataset["validation"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
print("ํ์ต ์์!")
trainer.train()
# ===== 13. ์ต์ข
ํ๊ฐ =====
results = trainer.evaluate()
print(f"\n์ต์ข
ํ๊ฐ ๊ฒฐ๊ณผ:")
print(f" Accuracy: {results['eval_accuracy']:.4f}")
print(f" F1 Score: {results['eval_f1']:.4f}")๋ชจ๋ธ ์ ์ฅ ๋ฐ ๋ถ๋ฌ์ค๊ธฐ
# ===== ๋ชจ๋ธ ์ ์ฅ =====
save_path = "/content/drive/MyDrive/sentiment_model_final"
# ๋ชจ๋ธ ๊ฐ์ค์น ์ ์ฅ
model.save_pretrained(save_path)
# ํ ํฌ๋์ด์ ์ ์ฅ (์ถ๋ก ์ ํ์)
tokenizer.save_pretrained(save_path)
print(f"๋ชจ๋ธ ์ ์ฅ ์๋ฃ: {save_path}")
print(f"์ ์ฅ๋ ํ์ผ: {os.listdir(save_path)}")
# ['config.json', 'model.safetensors', 'tokenizer.json', 'tokenizer_config.json', ...]
# ===== ๋ชจ๋ธ ๋ถ๋ฌ์ค๊ธฐ =====
from transformers import pipeline
# ์ ์ฅ๋ ๋ชจ๋ธ๋ก ํ์ดํ๋ผ์ธ ์์ฑ
classifier = pipeline(
"text-classification",
model=save_path,
tokenizer=save_path,
device=0 if device == "cuda" else -1,
)
# ์ถ๋ก ํ
์คํธ
test_texts = [
"์ด ์ํ ์ ๋ง ๊ฐ๋์ ์ด์์ด์!",
"๋์ด ์๊น์ด ์ํ์์ต๋๋ค.",
"๋ฐฐ์ฐ๋ค ์ฐ๊ธฐ๊ฐ ์ต๊ณ ์์ด์.",
]
for text in test_texts:
result = classifier(text)
label = "๊ธ์ " if result[0]["label"] == "LABEL_1" else "๋ถ์ "
score = result[0]["score"]
print(f"'{text}' โ {label} ({score:.2%})")Hugging Face Hub์ ์ ๋ก๋ํ๊ธฐ
ํ์ตํ ๋ชจ๋ธ์ Hugging Face Hub์ ๊ณต์ ํ๋ฉด ๋ค๋ฅธ ์ฌ๋๋ค๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
# ===== Hub์ ์
๋ก๋ =====
from huggingface_hub import notebook_login
# HuggingFace ๋ก๊ทธ์ธ (ํ ํฐ ํ์: https://huggingface.co/settings/tokens)
notebook_login()
# ๋ชจ๋ธ ์
๋ก๋
model.push_to_hub("your-username/klue-bert-sentiment")
tokenizer.push_to_hub("your-username/klue-bert-sentiment")
print("HuggingFace Hub ์
๋ก๋ ์๋ฃ!")
print("๋ชจ๋ธ ์ฃผ์: https://huggingface.co/your-username/klue-bert-sentiment")์ ๋ก๋ ํ ๋ค๋ฅธ ์ฌ๋์ด ํ ์ค๋ก ์ฌ์ฉ ๊ฐ๋ฅ:
from transformers import pipeline
classifier = pipeline(
"text-classification",
model="your-username/klue-bert-sentiment"
)
result = classifier("์ ๋ง ์ฌ๋ฏธ์๋ ์ํ์์ด์!")๊ฒฐ๋ก
Google Colab์์ Transformers ๋ชจ๋ธ์ ํ์ตํ๋ฉด์ ๋ฐ์ํ๋ ์ฃผ์ ์ค๋ฅ๋ค๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํ๋ค.
ํต์ฌ ์ฒดํฌ๋ฆฌ์คํธ
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น:
sklearn๋์scikit-learn์ฌ์ฉ - ํ์ผ ๊ฒฝ๋ก: Google Drive ๋ง์ดํธ ํ
/content/drive/MyDrive/๊ฒฝ๋ก ์ฌ์ฉ - ๋ฐ์ดํฐ ํจ๋ฉ:
DataCollatorWithPadding์ผ๋ก ๋์ ํจ๋ฉ ์ฒ๋ฆฌ - wandb ๋นํ์ฑํ:
report_to="none"์ค์ - OOM ์ค๋ฅ: ๋ฐฐ์น ์ฌ์ด์ฆ ์ค์ด๊ธฐ +
gradient_accumulation_steps+fp16=True - ์ธ์
๋๊น: ์ฒดํฌํฌ์ธํธ๋ฅผ Google Drive์ ์ ์ฅํ๊ณ
resume_from_checkpointํ์ฉ - ํ ํฌ๋์ด์ ๋ถ์ผ์น: ๋ชจ๋ธ๊ณผ ํ ํฌ๋์ด์ ๋ฅผ ํญ์ ๊ฐ์
model_name์ผ๋ก ๋ก๋ - ๋ฐ์ดํฐ์
ํ์: ์ปฌ๋ผ๋ช
์
text,label๋ก ํต์ผํ๊ณ ๋ถํ์ํ ์ปฌ๋ผ ์ ๊ฑฐ
๊ฐ ๋จ๊ณ์์ ๋ฐ์ํ ์ ์๋ ๋ฌธ์ ๋ค์ ์ดํดํ๊ณ ์ด๋ฅผ ํด๊ฒฐํด ๋๊ฐ๋ฉด, Colab ํ๊ฒฝ์์ ํจ์จ์ ์ผ๋ก ๋ชจ๋ธ์ ํ์ต์ํฌ ์ ์๋ค.
