반응형
15.3 파이토치를 이용한 미세조정학습
del model
del trainer
torch.cuda.empty_cache()
from torch.utils.data import DataLoader
train_loader = DataLoader(train_dataset, shuffle=True, batch_size=8)
from transformers import BertModel
bert_model = BertModel.from_pretrained('bert-base-uncased')
# BERT를 포함한 신경망 모형
class MyModel(torch.nn.Module):
def __init__(self, pretrained_model, token_size, num_labels):
super(MyModel, self).__init__()
self.token_size = token_size
self.num_labels = num_labels
self.pretrained_model = pretrained_model
# 분류기 정의
self.classifier = torch.nn.Linear(self.token_size, self.num_labels)
def forward(self, inputs):
# BERT 모형에 입력을 넣고 출력을 받음
outputs = self.pretrained_model(**inputs)
# BERT 출력에서 CLS 토큰에 해당하는 부분만 가져옴
bert_clf_token = outputs.last_hidden_state[:,0,:]
return self.classifier(bert_clf_token)
# token_size는 BERT 토큰과 동일, bert_model.config.hidden_size로 알 수 있음
model = MyModel(bert_model, num_labels=2, token_size=bert_model.config.hidden_size)
from transformers import AdamW
import torch.nn.functional as F
import time
# GPU 가속을 사용할 수 있으면 device를 cuda로 설정하고, 아니면 cpu로 설정
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device) # 모형을 GPU로 복사
model.train() # 학습모드로 전환
optim = AdamW(model.parameters(), lr=5e-5) # 옵티마이저를 트랜스포머가 제공하는 AdamW로 설정
criterion = torch.nn.CrossEntropyLoss() # 멀티클래스이므로 크로스 엔트로피를 손실함수로 사용
start = time.time() # 시작시간 기록
num_epochs = 4 # 학습 epoch를 4회로 설정
for epoch in range(num_epochs):
total_epoch_loss = 0 # epoch의 총 loss 초기화
for step, batch in enumerate(train_loader):
optim.zero_grad() # 그래디언트 초기화
# 배치에서 label을 제외한 입력만 추출하여 GPU로 복사
inputs = {k: v.to(device) for k, v in batch.items() if k != 'labels'}
labels = batch['labels'].to(device) # 배치에서 라벨을 추출하여 GPU로 복사
outputs = model(inputs) # 모형으로 결과 예측
# 두 클래스에 대해 예측하고 각각 비교해야 하므로 labels에 대해 원핫인코딩을 적용한 후에 손실을 게산
loss = criterion(outputs, F.one_hot(labels, num_classes=2).float()) # loss 계산
if (step+1) % 100 == 0: # 100 배치마다 경과한 시간과 loss를 출력
elapsed = time.time() - start
print('Epoch %d, batch %d, elapsed time: %.2f, loss: %.4f' % (epoch+1, step+1, elapsed, loss))
total_epoch_loss += loss
loss.backward() # 그래디언트 계산
optim.step() # 가중치 업데이트
avg_epoch_loss = total_epoch_loss / len(train_loader) # epoch의 평균 loss 계산
print('Average loss for epoch %d: %.4f' % (epoch+1, avg_epoch_loss))
"""
Epoch 1, batch 100, elapsed time: 39.77, loss: 0.5169
Epoch 1, batch 200, elapsed time: 80.67, loss: 0.3300
Average loss for epoch 1: 0.5417
Epoch 2, batch 100, elapsed time: 121.59, loss: 0.5303
Epoch 2, batch 200, elapsed time: 162.57, loss: 0.1188
Average loss for epoch 2: 0.2969
Epoch 3, batch 100, elapsed time: 203.50, loss: 0.0132
Epoch 3, batch 200, elapsed time: 244.48, loss: 0.0130
Average loss for epoch 3: 0.1258
Epoch 4, batch 100, elapsed time: 285.65, loss: 0.0095
Epoch 4, batch 200, elapsed time: 327.03, loss: 0.0188
Average loss for epoch 4: 0.1103
"""
from datasets import load_metric
test_loader = DataLoader(test_dataset, batch_size=16)
metric= load_metric("accuracy")
model.eval()
for batch in test_loader:
inputs = {k: v.to(device) for k, v in batch.items() if k != 'labels'}
labels = batch['labels'].to(device)
with torch.no_grad(): # 학습할 필요가 없으므로 그래디언트 계산을 끔
outputs = model(inputs)
#print(outputs)
predictions = torch.argmax(outputs, dim=-1)
metric.add_batch(predictions=predictions, references=labels)
metric.compute()
"""
{'accuracy': 0.8825}
"""
※ 해당 내용은 <파이썬 텍스트 마이닝 완벽 가이드>의 내용을 토대로 학습하며 정리한 내용입니다.
반응형
'텍스트 마이닝' 카테고리의 다른 글
한국어 문서에 대한 BERT 활용 (2) (0) | 2023.08.06 |
---|---|
한국어 문서에 대한 BERT 활용 (1) (0) | 2023.08.05 |
BERT 사전학습 모형에 대한 미세조정학습 (2) (0) | 2023.08.03 |
BERT 사전학습 모형에 대한 미세조정학습 (1) (0) | 2023.08.02 |
BERT의 이해와 간단한 활용 (2) (0) | 2023.08.01 |