일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 실기
- 성능
- dl
- ml 웹서빙
- 빅데이터분석기사
- qgis
- DASH
- 머신러닝
- ㅂ
- 예제소스
- webserving
- Kaggle
- 캐글
- 인공지능
- GPU
- CUDA
- 2유형
- fastapi
- K최근접이웃
- pytorch
- KNN
- 공간시각화
- streamlit
- 딥러닝
- 공간분석
- 3유형
- 1유형
- Ai
- QGIS설치
- gradio
- Today
- Total
에코프로.AI
[HuggingFace] Fine-tuning - 3 (A full training) 본문
A full training
이제 트레이너 클래스를 사용하지 않고 지난 섹션에서 했던 것과 동일한 결과를 얻는 방법을 살펴보겠습니다. 다시 한 번, 섹션 2에서 데이터 처리를 완료했다고 가정합니다. 다음은 필요한 모든 사항을 간략하게 요약한 것입니다.
from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding
raw_datasets = load_dataset("glue", "mrpc")
checkpoint = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
def tokenize_function(example):
return tokenizer(example["sentence1"], example["sentence2"], truncation=True)
tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
Prepare for training
실제로 훈련 루프를 작성하기 전에 몇 가지 객체를 정의해야 합니다. 첫 번째 객체는 배치 반복에 사용할 데이터 로더입니다. 하지만 이러한 데이터로더를 정의하기 전에, Trainer 가 자동으로 수행한 몇 가지 작업을 처리하기 위해 tokenized_datasets 에 약간의 후처리를 적용해야 합니다. 구체적으로는 다음과 같이 해야 합니다.
모델이 예상하지 않는 값에 해당하는 열을 제거합니다(예: sentence1및 sentence2열 ).
열 레이블의 이름을 레이블로 바꿉니다(모델이 인수의 이름을 레이블로 예상하므로).
데이터 세트의 형식을 설정하여 목록 대신 PyTorch 텐서를 반환하도록 합니다.
- 모델이 예상하지 않는 값에 해당하는 열(예: sentence1및 sentence2열)을 제거합니다.
- 열 이름을 label 에서 labels 로 바꿉니다 (모델이 인수의 이름을 label으로 예상하므로 )
- PyTorch 텐서를 반환하도록 데이터 세트의 형식을 설정합니다.
tokenized_datasets 에는 각 단계마다 하나의 메서드가 있습니다.
tokenized_datasets = tokenized_datasets.remove_columns(["sentence1", "sentence2", "idx"])
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")
tokenized_datasets.set_format("torch")
tokenized_datasets["train"].column_names
그런 다음 결과에 모델이 허용하는 열만 있는지 확인할 수 있습니다.
["attention_mask", "input_ids", "labels", "token_type_ids"]
이제 이 작업이 완료되었으므로 데이터 로더를 쉽게 정의할 수 있습니다.
from torch.utils.data import DataLoader
train_dataloader = DataLoader(
tokenized_datasets["train"], shuffle=True, batch_size=8, collate_fn=data_collator
)
eval_dataloader = DataLoader(
tokenized_datasets["validation"], batch_size=8, collate_fn=data_collator
)
데이터 처리에 오류가 없는지 빠르게 확인하기 위해 다음과 같이 배치를 검사할 수 있습니다.
for batch in train_dataloader:
break
{k: v.shape for k, v in batch.items()}
{'attention_mask': torch.Size([8, 65]),
'input_ids': torch.Size([8, 65]),
'labels': torch.Size([8]),
'token_type_ids': torch.Size([8, 65])}
훈련 데이터 로더에 shuffle=True 를 설정하고 배치 내에서 최대 길이로 패딩하기 때문에 실제 모양은 약간 다를 수 있다는 점에 유의하세요.
이제 데이터 전처리를 완전히 마쳤으니(모든 ML 실무자에게는 만족스럽지만 달성하기 어려운 목표입니다), 이제 모델로 넘어가 보겠습니다. 이전 섹션에서 했던 것과 똑같이 모델을 인스턴스화합니다:
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
훈련 중에 모든 것이 순조롭게 진행되도록 하기 위해 우리는 배치를 이 모델에 전달합니다.
outputs = model(**batch)
print(outputs.loss, outputs.logits.shape)
tensor(0.5441, grad_fn=<NllLossBackward>) torch.Size([8, 2])
모든 🤗 트랜스포머 모델은 레이블이 제공되면 손실을 반환하며, 로짓(배치의 각 입력에 대해 2개씩, 즉 8 x 2 크기의 텐서)도 가져옵니다.
트레이닝 루프를 작성할 준비가 거의 다 되었습니다! 최적화 도구와 학습 속도 스케줄러라는 두 가지가 빠졌을 뿐입니다. 트레이너가 수작업으로 수행하던 작업을 복제하려고 하므로 동일한 기본값을 사용하겠습니다. 트레이너가 사용하는 최적화 도구는 Adam과 동일하지만 가중치 감쇠 정규화에 약간의 변형이 있는 AdamW입니다(일리야 로쉬칠로프와 프랭크 후터의 "분리된 가중치 감쇠 정규화" 참조).
from transformers import AdamW
optimizer = AdamW(model.parameters(), lr=5e-5)
마지막으로, 기본적으로 사용되는 학습 속도 스케줄러는 최대값(5e-5)에서 0까지 선형적으로 감소하는 것입니다. 이를 제대로 정의하려면 실행하려는 에포크 수에 훈련 배치 수(훈련 데이터로더의 길이)를 곱한 값인 훈련 단계 수를 알아야 합니다. 트레이너는 기본적으로 3개의 에포크를 사용하므로 이를 따릅니다:
from transformers import get_scheduler
num_epochs = 3
num_training_steps = num_epochs * len(train_dataloader)
lr_scheduler = get_scheduler(
"linear",
optimizer=optimizer,
num_warmup_steps=0,
num_training_steps=num_training_steps,
)
print(num_training_steps)
1377
The training loop
마지막으로 한 가지 더: GPU를 사용할 수 있는 경우 GPU를 사용하고 싶을 것입니다(CPU에서는 훈련에 몇 분이 아닌 몇 시간이 걸릴 수 있습니다). 이를 위해 모델과 배치를 배치할 디바이스를 정의합니다:
import torch
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)
device
device(type='cuda')
이제 훈련할 준비가 되었습니다! 교육이 언제 완료되는지 알기 위해 tqdm 라이브러리를 사용하여 교육 단계 수 위에 진행률 표시줄을 추가합니다:
from tqdm.auto import tqdm
progress_bar = tqdm(range(num_training_steps))
model.train()
for epoch in range(num_epochs):
for batch in train_dataloader:
batch = {k: v.to(device) for k, v in batch.items()}
outputs = model(**batch)
loss = outputs.loss
loss.backward()
optimizer.step()
lr_scheduler.step()
optimizer.zero_grad()
progress_bar.update(1)
트레이닝 루프의 핵심은 소개에 있는 것과 매우 유사하다는 것을 알 수 있습니다. 보고를 요청하지 않았으므로 이 학습 루프에서는 모델이 어떻게 작동하는지에 대한 정보를 알 수 없습니다. 이를 위해 평가 루프를 추가해야 합니다.
The evaluation loop
앞서 했던 것처럼 🤗 Evaluate 라이브러리에서 제공하는 메트릭을 사용하겠습니다. 이미 metric.compute() 메서드를 살펴봤지만, 메트릭은 실제로 add_batch() 메서드를 사용하여 예측 루프를 진행하면서 배치를 누적할 수 있습니다. 모든 배치를 누적한 후에는 metric.compute()를 사용하여 최종 결과를 얻을 수 있습니다. 이 모든 것을 평가 루프에서 구현하는 방법은 다음과 같습니다:
import evaluate
metric = evaluate.load("glue", "mrpc")
model.eval()
for batch in eval_dataloader:
batch = {k: v.to(device) for k, v in batch.items()}
with torch.no_grad():
outputs = model(**batch)
logits = outputs.logits
predictions = torch.argmax(logits, dim=-1)
metric.add_batch(predictions=predictions, references=batch["labels"])
metric.compute()
{'accuracy': 0.8431372549019608, 'f1': 0.8907849829351535}
다시 말하지만, 모델 헤드 초기화와 데이터 셔플링의 무작위성으로 인해 결과가 약간 다르겠지만 대략 비슷한 범위에 있을 것입니다.
[참고사이트] https://huggingface.co/learn/nlp-course/chapter3/4?fw=pt
끝~

'AI Tutorial' 카테고리의 다른 글
[CUDA] 2. pytorch에서 GPU를 사용하는 방법 (0) | 2025.01.08 |
---|---|
[HuggingFace] Fine-tuning - 1 (Processing the data) (1) | 2025.01.05 |
[CUDA] 1. 소개 및 설치 for windows(Feat. GTX 1650) (0) | 2025.01.03 |
[DeepLearning] 사전학습, 전이학습, RAG, 미세조정 (0) | 2025.01.03 |
[Hugging Face - 7] Putting it all together (모든 것을 종합하기) (1) | 2025.01.03 |