최근 인공지능 분야에서는 자연어 처리(NLP)가 중요한 도전 과제가 되었으며, BERT(Bidirectional Encoder Representations from Transformers)와 같은 모델이 이 분야의 혁신을 이끌어왔습니다. BERT 모델은 단어의 맥락을 양방향으로 이해할 수 있는 기능을 제공하며, 이는 더욱 정교한 방법으로 자연어 문제를 해결할 수 있게 합니다. 본 강좌에서는 허깅페이스의 트랜스포머 라이브러리를 활용하여 BERT 모델을 설정하고, 앙상블 학습을 구현하는 방법에 대해 자세히 알아보겠습니다.
1. BERT 앙상블 학습이란?
앙상블 학습은 여러 모델의 예측 결과를 결합하여 최종 예측을 만드는 방법론입니다. 여러 모델의 예측치를 평균하거나, 다수결의 원칙(Get majority vote)으로 결정하는 방식으로, 이는 단일 모델의 편향을 줄이고, 일반화 성능을 향상시키는 데 도움을 줍니다. BERT와 같은 강력한 언어 모델을 앙상블하여 활용하는 것은 모델의 학습 성능과 예측 성능을 극대화하는 효과를 가져올 수 있습니다.
2. 환경 설정
허깅페이스의 트랜스포머 라이브러리를 사용하기 위해서는 먼저 관련 패키지를 설치해야 합니다. 다음 명령어를 통해 설치할 수 있습니다.
pip install transformers torch
이외에 필요한 라이브러리로는 데이터 처리를 위한 pandas
와 모델 성능 평가를 위한 scikit-learn
을 사용할 예정입니다.
pip install pandas scikit-learn
3. 데이터 준비
이번 강좌에서는 영화 리뷰 감성 분석 데이터셋을 사용할 것입니다. 이 데이터셋은 리뷰와 감성 레이블이 포함되어 있으며, 긍정적 또는 부정적인 리뷰로 구분됩니다. 데이터셋은 pandas를 사용하여 불러올 수 있습니다.
import pandas as pd
# 데이터셋 로드
data = pd.read_csv('movie_reviews.csv')
print(data.head())
4. BERT 모델 설정
허깅페이스의 트랜스포머 라이브러리를 사용하여 BERT 모델을 설정합니다. BERT를 사용하기 위해서는 먼저 모델을 로드하고, 토크나이저를 설정하여 입력 데이터를 처리해야 합니다.
from transformers import BertTokenizer, BertForSequenceClassification
import torch
# BERT 모델과 토크나이저 로드
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# 입력 데이터 토크나이징
def tokenize_data(sentences):
return tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')
# 예시로 첫 번째 문장을 토크나이징
tokens = tokenize_data(data['review'].tolist())
print(tokens) # 토크나이즈된 데이터 확인
5. 데이터 전처리
모델 학습을 위하여 데이터 전처리가 필요합니다. 각 리뷰는 토큰화되며, 이를 모델이 인식할 수 있는 포맷으로 변환해야 합니다. 또한, 배치 사이즈를 설정하여 GPU에서 학습 속도를 향상시킵니다.
from torch.utils.data import DataLoader, TensorDataset
# 입력 데이터와 레이블 설정
inputs = tokens['input_ids']
attn_masks = tokens['attention_mask']
labels = torch.tensor(data['label'].tolist())
# 텐서 데이터셋 생성
dataset = TensorDataset(inputs, attn_masks, labels)
# 데이터 로더 설정
batch_size = 16
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
6. 모델 학습
BERT 모델을 학습하기 위해서는 옵티마이저와 손실 함수를 설정해야 합니다. 여기서는 AdamW 옵티마이저를 사용합니다. 모델 학습을 위한 손실 함수는 CrossEntropyLoss를 사용합니다.
from transformers import AdamW
from torch import nn
# 옵티마이저 설정
optimizer = AdamW(model.parameters(), lr=5e-5)
# 손실 함수 설정
loss_fn = nn.CrossEntropyLoss()
# 모델 훈련을 위한 함수 작성
def train_model(dataloader, model, optimizer, loss_fn, epochs=3):
model.train()
for epoch in range(epochs):
total_loss = 0
for batch in dataloader:
input_ids, attention_masks, labels = batch
# 모델에 데이터 전송
input_ids = input_ids.to('cuda')
attention_masks = attention_masks.to('cuda')
labels = labels.to('cuda')
# 기울기 초기화
optimizer.zero_grad()
# 모델 예측
outputs = model(input_ids, token_type_ids=None, attention_mask=attention_masks)
loss = loss_fn(outputs.logits, labels)
# 손실 계산 및 역전파
total_loss += loss.item()
loss.backward()
optimizer.step()
print(f'Epoch: {epoch+1}, Loss: {total_loss/len(dataloader)}')
# 모델 학습 호출
train_model(dataloader, model.to('cuda'), optimizer, loss_fn)
7. 앙상블 모델 설정
이제 기본적인 BERT 모델을 설정했으니, 여러 개의 BERT 모델을 앙상블하여 성능을 향상시키겠습니다. 여기서는 두 개의 BERT 모델을 학습하고, 예측 결과를 평균하여 최종 예측을 만들겠습니다.
def create_ensemble_model(num_models=2):
models = []
for _ in range(num_models):
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2).to('cuda')
models.append(model)
return models
# 앙상블 모델 생성
ensemble_models = create_ensemble_model()
8. 앙상블 학습 및 예측
앙상블된 모델들을 학습하고, 테스트 데이터에 대해 예측을 수행한 후, 결과를 평균하여 최종 예측을 생성합니다.
def train_ensemble(models, dataloader, optimizer, loss_fn, epochs=3):
for model in models:
train_model(dataloader, model, optimizer, loss_fn, epochs)
def ensemble_predict(models, input_ids, attention_masks):
preds = []
for model in models:
model.eval()
with torch.no_grad():
outputs = model(input_ids, attention_mask=attention_masks)
preds.append(outputs.logits)
return sum(preds) / len(preds)
# 앙상블 모델 학습
train_ensemble(ensemble_models, dataloader, optimizer, loss_fn)
# 예시로 첫 번째 문장 예측
inputs = tokenize_data([data['review'].iloc[0]])
average_logits = ensemble_predict(ensemble_models, inputs['input_ids'].to('cuda'), inputs['attention_mask'].to('cuda'))
predictions = torch.argmax(average_logits, dim=1)
print(f'Predicted label: {predictions}') # 예측 결과 확인
9. 모델 성능 평가
마지막으로, 테스트 데이터셋에 대한 모델의 성능을 평가해 보겠습니다. 정확도, 정밀도, 재현율 등을 측정하여 성능을 검토합니다.
from sklearn.metrics import accuracy_score, classification_report
# 테스트 데이터 로드
test_data = pd.read_csv('movie_reviews_test.csv')
test_tokens = tokenize_data(test_data['review'].tolist())
test_inputs = test_tokens['input_ids'].to('cuda')
test_masks = test_tokens['attention_mask'].to('cuda')
# 앙상블 예측
test_logits = ensemble_predict(ensemble_models, test_inputs, test_masks)
test_predictions = torch.argmax(test_logits, axis=1)
# 정확도 및 평가 지표 출력
accuracy = accuracy_score(test_data['label'].tolist(), test_predictions.cpu())
report = classification_report(test_data['label'].tolist(), test_predictions.cpu())
print(f'Accuracy: {accuracy}\n')
print(report)
결론
이번 강좌에서는 BERT 모델을 활용하여 자연어 처리 문제를 해결하는 방법과, 여러 모델을 앙상블하여 성능을 향상시키는 방법에 대해 알아보았습니다. 허깅페이스의 트랜스포머 라이브러리를 통해 BERT 모델을 손쉽게 적용할 수 있으며, 사용자 맞춤형 앙상블 모델링을 통해 더욱 강력한 성능을 기대할 수 있습니다. 앞으로도 다양한 자연어 처리 문제에 대해 이와 같은 기술을 활용해 나가기를 바랍니다.