<출처 및 참고자료>
https://huggingface.co/learn/nlp-course/en/chapter3/4?fw=pt
A full training - Hugging Face NLP Course
Now we’ll see how to achieve the same results as we did in the last section without using the Trainer class. Again, we assume you have done the data processing in section 2. Here is a short summary covering everything you will need: Before actually writi
huggingface.co
0. 정리
- NLP목적에 맞게 모델을 불러와서 사용(분류, 생성 등)
- 전체 코드를 제시하고 코드 설명
- 기본적인 Pytorch 사용법 알고 있어야 함.
- 데이터셋의 구조(형태)가 중요함.
- torch.utils.data.Dataset 으로 pytorch 데이터셋 만드는 법을 알고 있어야 함(자신만의 데이터셋으로 훈련)
- 변경내용
1) 데이터셋: 예제 코드의 데이터를 사용하여 torch.utils.data.Dataset로 변경후 Dataloader 함수를 이용
2) 평가함수: sklearn(사이킷 런) 사용
1. 전체코드 및 설명
- 허깅페이스 NLP Course에 제시된 코드
from datasets import load_dataset #예제 데이터 셋
from transformers import AutoTokenizer, DataCollatorWithPadding
checkpoint = "bert-base-uncased" #사용할 언어모델
#tokenizer 정의
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
#데이터셋 로드
raw_datasets = load_dataset("glue", "mrpc")
#데이터셋 불러오기 및 백터화
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) #동적패딩적용 배치당 가장 긴 문자열 기준
#데이터 전처리 과정
# 1. model에게 필요없는 열 삭제
tokenized_datasets = tokenized_datasets.remove_columns(["sentence1", "sentence2", "idx"])
# 2. label => labels 모델에 입력할때에는 labels로
tokenized_datasets = tokenized_datasets.rename_column("label", "labels")
# 3. Pytorch 텐서로 변경
tokenized_datasets.set_format("torch")
tokenized_datasets["train"].column_names
#Dataloader
#Pytorch는 Dataloader를 통해서 데이터 입력
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)
# DataLoader가 올바르게 되었는지 검사
for batch in train_dataloader:
break
{k: v.shape for k, v in batch.items()}
#모델 불러오기
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2) #이진분류
#model 작동여부 테스트
outputs = model(**batch)
print(outputs.loss, outputs.logits.shape)
#Optimizer 설정
from transformers import AdamW
optimizer = AdamW(model.parameters(), lr=5e-5)
#스케줄러 설정
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)
#gpu로 학습
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()} #gpu로 데이터 올려놓음
outputs = model(**batch)
loss = outputs.loss
loss.backward()
optimizer.step()
lr_scheduler.step()
optimizer.zero_grad()
progress_bar.update(1)
#평가
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()} #gpu 사용을 위한 코드 model이 gpu를 사용하기 때문에 데이터도 gpu 로
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()
2. 자신의 데이터로 fine-tuning
- 모델에 들어가는 데이터의 형태를 맞추어 주면 됨(가장 중요)
- 아래와 같이 Dataset 모듈을 사용해서 데이터셋 정의
from torch.utils.data import Dataset
class MyMapDataset(Dataset):
#데이터셋 정의(초기화) (A)
def __init__(self, data):
self.data = data
#데이터셋 길이(B)
def __len__(self):
return len(self.data)
#출력 (C)
def __getitem__(self, index):
return {'input_ids': self.data['input_ids'][index],
'token_type_ids': self.data['token_type_ids'][index],
'attention_mask': self.data['attention_mask'][index],
'label': self.data['label'][index]}
- 최종코드 수정
from datasets import load_dataset
from transformers import AutoTokenizer, DataCollatorWithPadding
checkpoint = "bert-base-uncased"
#tokenizer 정의
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
#데이터셋 로드
raw_datasets = load_dataset("glue", "mrpc")
"""
수정부분 시작
- 모델에 들어가는 데이터셋 형태를 잘 맞춰 주어야 함.
- lable -> labels로 수정
- train_data와 valid_data를 함수로 변경하거나, TestDataset 클래스의 __init__에 정의해도 됨.
"""
#데이터셋 전처리
train_data = {'input_ids': [],
'token_type_ids': [],
'attention_mask': [],
'labels': []}
for i in range(len(raw_datasets['train'])):
tokenize = tokenizer(raw_datasets['train']['sentence1'][i], raw_datasets['train']['sentence2'][i], truncation=True)
train_data['input_ids'].append(tokenize['input_ids'])
train_data['token_type_ids'].append(tokenize['token_type_ids'])
train_data['attention_mask'].append(tokenize['attention_mask'])
train_data['labels'].append(raw_datasets['train']['label'][i])
valid_data = {'input_ids': [],
'token_type_ids': [],
'attention_mask': [],
'labels': []}
for i in range(len(raw_datasets['validation'])):
tokenize = tokenizer(raw_datasets['validation']['sentence1'][i], raw_datasets['validation']['sentence2'][i], truncation=True)
valid_data['input_ids'].append(tokenize['input_ids'])
valid_data['token_type_ids'].append(tokenize['token_type_ids'])
valid_data['attention_mask'].append(tokenize['attention_mask'])
valid_data['labels'].append(raw_datasets['validation']['label'][i])
from torch.utils.data import Dataset
class TestDataset(Dataset):
def __init__(self, data):
self.data = data
def __len__(self):
return len(self.data['labels'])
def __getitem__(self, index):
return {'input_ids': self.data['input_ids'][index],
'token_type_ids': self.data['token_type_ids'][index],
'attention_mask': self.data['attention_mask'][index],
'labels': self.data['labels'][index]}
train_dataset = TestDataset(train_data)
eval_dataset = TestDataset(valid_data)
"""
수정부분 종료
"""
data_collator = DataCollatorWithPadding(tokenizer=tokenizer)
#Dataloader
from torch.utils.data import DataLoader
train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=8, collate_fn=data_collator)
eval_dataloader = DataLoader(eval_dataset, batch_size=8, collate_fn=data_collator)
#모델 불러오기
from transformers import AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)
#Optimizer 설정
from transformers import AdamW
optimizer = AdamW(model.parameters(), lr=5e-5)
# 스케줄러 설정
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
)
#GPU사용
import torch
device = torch.device("cuda") if torch.cuda.is_available() else torch.device('cpu')
model.to(device)
#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)
"""
수정부분
- 정확도와 f1_score를 sklearn을 사용해서 표현
"""
#정확도 및 f1값 저장
from sklearn.metrics import accuracy_score, f1_score
accuracy = 0
f1 = 0
#평가모드
model.eval()
for batch in eval_dataloader:
batch = {k: v.to(device) for k, v in batch.items()} #gpu 사용을 위한 코드 model이 gpu를 사용하기 때문에 데이터도 gpu 로
with torch.no_grad():
outputs = model(**batch)
logits = outputs.logits
predictions = torch.argmax(logits, dim=-1)
#모델이 GPU에서 작동하고 데이터가 GPU에 있기 때문에 CPU로 옮기는 과정이 필요함
acc = accuracy_score(batch['labels'].to(torch.device('cpu')), predictions.to(torch.device('cpu')))
accuracy += acc
f = f1_score(batch['labels'].to(torch.device('cpu')), predictions.to(torch.device('cpu')))
f1 += f
accuracy /= len(eval_dataloader)
f1 /= len(eval_dataloader)
#정확도와 f1출력
print("Accuracy: ", accuracy, "\n", "F1_Score: ", f1)
'NLP > Hugging Face' 카테고리의 다른 글
HuggingFace(허깅페이스) 모델 Fine-Tuning(Trainer 사용) (0) | 2023.06.16 |
---|---|
허깅페이스 pipeline 사용법 (0) | 2023.04.03 |