딥러닝 이야기 / Bidirectional Encoder Representations from Transformers (BERT) / 3. Pre-trained BERT Fine-tuning을 통한 Google Play Store Apps 리뷰 감성 분류

Pre-trained BERT Fine-tuning을 통한 Google Play Store Apps 리뷰 감성 분류

작성자: 여행 초짜
작성일: 2022.12.28

시작하기 앞서 틀린 부분이 있을 수 있으니, 틀린 부분이 있다면 지적해주시면 감사하겠습니다.

이전글에서는 BERT를 pre-training 하는 코드에 대해 설명하였습니다. 이번글에서는 간편하게 Hugging Face API를 이용하여 pre-trained BERT를 가져오는 코드와 이 모델을 fine-tuning 하는 방법을 알아보겠습니다. 본 글에서는 Googe Play Store Apps 리뷰 데이터를 바탕으로 pre-trained BERT를 fine-tuning하여 감성 분류 모델을 학습합니다. 코드의 구현은 python의 PyTorch를 이용하였습니다.

그리고 BERT에 대한 설명은 이전글을 참고하시기 바랍니다. 본 글에서 설명하는 BERT fine-tuning 코드는 GitHub에 올려놓았으니 아래 링크를 참고하시기 바랍니다(본 글에서는 Hugging Face API 사용과 모델의 fine-tuning에 초점을 맞추고 있기 때문에 사용 데이터, 데이터 전처리, 토크나이저 학습 등 학습을 위한 전체 코드는 아래 GitHub 링크를 참고하시기 바랍니다).

오늘의 컨텐츠입니다.

  1. Pre-trained BERT 가져오기
  2. BERT Fine-tuning
  3. BERT 감성 분류 모델 학습 결과

감성 분류를 위한 Pre-trained BERT Fine-tuning

Pre-trained BERT 가져오기

여기서는 Hugging Face를 이용하여 pre-trained BERT를 가져오는 코드를 살펴보겠습니다. 먼저 Hugging Face를 사용하기 위해서는 아래 코드를 실행해서 transformers 모듈을 설치해야 합니다.

 # terminal
pip install transformers



이제는 Hugging Face API를 통해 pre-trained BERT를 가져오는 코드입니다.

Pre-trained BERT

import torch
import torch.nn as nn
from transformers import BertModel


# BERT
class BERT(nn.Module):
    def __init__(self, config, device):
        super(BERT, self).__init__()
        self.pretrained_model = config.pretrained_model
        self.n_class = config.n_class
        self.device = device
        
        self.model = BertModel.from_pretrained(self.pretrained_model)
        self.fc = nn.Linear(self.model.config.hidden_size, self.n_class)
        self.pos_ids = torch.arange(config.max_len).to(device)


    def forward(self, x, attn_mask):
        batch_size = x.size(0)
        pos_ids = self.pos_ids.expand(batch_size, -1)

        output = self.model(input_ids=x, attention_mask=attn_mask, position_ids=pos_ids)
        output = self.fc(output['pooler_output'])

        return output

  • 10번째 줄: Hugging Face에서 pre-trained BERT를 불러올 모델의 종류(e.g. bert-base-uncased, bert-base-cased).
  • 11번째 줄: 감성 분류 label 개수. 본 코드에서는 부정, 중립, 긍정의 3개.
  • 14번째 줄: Hugging Face의 pre-trained BERT 불러오는 부분.
  • 15번째 줄: 감성 분류를 위한 fully-connected layer.
  • 16, 21번째 줄: Positional embedding을 위해 position 값을 1 x max_len → batch_size x max_len으로 변환.
  • 23 ~ 24번째 줄: 리뷰 데이터가 모델에 들어간 후, 감성 분류를 위해 fully-connected layer를 거치는 부분.

BERT Fine-tuning

이제 pre-trained BERT를 fine-tuning하는 코드를 살펴보겠습니다. 아래 코드에 self. 이라고 나와있는 부분은 GitHub 코드에 보면 알겠지만 학습하는 코드가 class 내부의 변수이기 때문에 있는 것입니다. 여기서는 무시해도 좋습니다.

그리고 아래 학습 코드는 실제 학습 코드를 간소화한 것입니다. Scheduler 등 전체 학습 코드는 GitHub 코드를 참고하면 됩니다.

self.model = BERT(self.config, self.device).to(self.device)
self.criterion = nn.CrossEntropyLoss()
self.optimizer = optim.Adam(self.model.parameters(), lr=self.lr)

self.model.train()

for i, (x, label, attn_mask) in enumerate(self.dataloaders['train']):
    x, label, attn_mask = x.to(self.device), label.to(self.device), attn_mask.to(self.device)
    self.optimizer.zero_grad()

    with torch.set_grad_enabled(phase=='train'):
        output = self.model(x, attn_mask)
        loss = self.criterion(output, label)
        loss.backward()
        self.optimizer.step()

학습에 필요한 것들 선언
먼저 위에 코드에서 정의한 모델을 불러오고 학습에 필요한 loss function, optimizer 등을 선언하는 부분입니다.

  • 1 ~ 3번째 줄: Loss function, BERT 모델 및 optimizer 선언.

모델 학습
  • 5 ~ 13번째 줄: Cross entropy loss를 이용하여 모델 학습하는 부분(label: 0, 1, 2).
  • 14 ~ 15번째 줄: Loss를 계산하고 모델을 업데이트 하는 부분.

BERT 감성 분류 모델 학습 결과

이제 train/validation set의 loss 및 accuracy history와 validation set의 최대의 accuracy일 때 모델의 선정해 test set의 accuracy 결과를 살펴보겠습니다. 여기에 더하여 accuracy보다 더 자세하게 test set의 각각의 label에 대해 precision, recall 등의 결과도 추가로 살펴보겠습니다. 마지막으로 test set 리뷰 샘플에 대해 긍정/중립/부정을 어떻게 예측하는지 ground truth label과 비교해보겠습니다.

Train/validation Set Loss History

Loss history


Train/validation Set Accuracy History

Accuracy history


Validation set accuracy가 가장 높았던 11 epoch 모델을 test set에 적용한 결과

  • Test set accuracy: 0.86


Test Set Result Statistics

                  precision    recall  f1-score   support

        negative       0.84      0.92      0.88       514
        mediocre       0.84      0.77      0.81       529
        positive       0.91      0.90      0.90       533

        accuracy                           0.86      1576
       macro avg       0.86      0.86      0.86      1576
    weighted avg       0.86      0.86      0.86      1576

Test set 통계 시각화 결과



Test Set 감성 분류 결과 샘플

# Sample 1
review: [CLS] i had paid once for this app and had login to it. now i have another mobile and want to use my acount on this device, but this app asket to pay first before login. should i pay each time i change my device? [SEP]
gt    : negative
pred  : negative


# Sample 2
review: [CLS] i got this app to track my medication and it's perfect! i can set up how i want to take each medicine ( yes / no or quantity ), see the start date and adherence in the summary view, and even track side effects and effectiveness each day then see them in a chronological list in the sunmary. and the best part is that it's not tied to some medical database! added bonus : i can track real to - dos as well. overall, love this app! [SEP]
gt    : positive
pred  : positive


# Sample 3
review: [CLS] great app [SEP]
gt    : positive
pred  : positive




지금까지 Hugging Face API를 통해 pre-treined BERT를 불러와서 Google Play Store Apps 리뷰 감성 데이터를 바탕으로 fine-tuning하여 감성 분류 모델을 학습해보았습니다. 학습 과정에 대한 전체 코드와 학습에 필요한 데이터는 GitHub에 있으니 참고하시면 될 것 같습니다.

다음에는 BERT 뿐 아니라 transformer 기반의 다른 언어 모델을 소개하겠습니다.

태그 #BERT #감성분류 #HuggingFace #fine-tuning
⟨ 이전글
WikiSplit을 이용한 BERT Pre-training