[파이썬]KoBERT로 다중 분류 모델 만들기 - 코드

Seolini·2021년 6월 24일
15

Chatbot

목록 보기
3/5
post-thumbnail

(※22.10.20수정 - KoBERT 예제 외의 제가 작성한 코드를 동일하게 인용하시는 분들은 꼭 출처 남겨주시면 감사하겠습니다💖)

지난번 글에서는 'BERT' 모델에 대한 이론을 정리하고, BERT를 이용하여 한국어 대화를 이진 분류하는 모델을 만들었던 프로젝트(+코드)에 대해 살펴보았다. 그러면서 마지막에 KoBERT에 대한 소개를 잠깐 했었는데, 이번 글에서는 KoBERT를 이용해 다중분류 모델을 만들었던 프로젝트에 대해 글을 적어보려고 한다!
(👉블로그👈에 프로젝트를 소개했었는데, 전체적인 코드에 대해서도 설명하지만 현재 글보다 간소화된 글이긴 하다. 프로젝트다운 글이니 가볍게 읽을 수 있으니 한번 읽어봐도 좋을 것 같다ㅎ.ㅎ)

한편, ⭐프로젝트⭐에 대해 설명하자면, KoBERT를 이용하여 한국어 문장을 여러 클래스로 분류하는 모델을 만드는 것인데, 공포, 놀람, 분노, 슬픔, 중립, 행복, 혐오와 같은 감정이 느껴지는 짧은 대화 텍스트를 각각 어떠한 감정의 텍스트인지 분류하는 모델을 만드는 것이다. 예를 들어 "앗 깜작이야!" 라는 문장을 입력하면 '놀람'이라는 클래스로 예측을 하도록 학습시키는 것이다. 대충 이러한 다중 분류 모델을 만드는 프로젝트였는데, 하나씩 코드를 보며 살펴보도록 하자!


그 전에! 잠깐 KoBERT에 대해 알아보도록 하자🐱‍🏍🐱‍🏍


KoBERT란?

BERT는 약 33억 개의 단어로 pretrain 되어 있는 기계번역 모델이다. 하지만 외국에서 만든 것이다 보니 영어에 대해 정확도가 높지 한국어에 대해서는 영어보다 정확도가 떨어진다. 따라서 좋은 알고리즘을 갖고 있는 BERT 모델을 한국어에도 잘 활용할 수 있도록 만들어진 것 중에 하나가 바로 KoBERT이다. 즉, 한국어 버전의 BERT인 것인데 구글링을 해보면 한국어 버전의 BERT가 여러 개 있었고, 오픈소스로 공유되어 있는 것을 쉽게 찾을 수 있다. 근데 그중 K0BERT가 많이 알려져 있는 것 같다.

이러한 KoBERT는 SKTBrain에서 공개한 기계번역 모델인데, KoBERT 개발자의 개발 리뷰기를 보면 BERT를 기반으로 하는 대화엔진 개발을 위해 KoBERT 학습을 시작하게 되었다고 한다. 이처럼 KoBERT는 BERT 모델에서 한국어 데이터를 추가로 학습시킨 모델로, 한국어 위키에서 5백만개의 문장과 54백만개의 단어를 학습시킨 모델이다. 따라서 한국어 데이터에 대해서도 높은 정확도를 낼 수 있다고 한다.

아무튼, KoBERT는 한국어 버전의 BERT이기 때문에 BERT의 구조를 갖는다. 따라서 BERT에 대한 기본적인 이해가 필요한데, BERT에 대한 이론적인 내용은 이 글에 정리되어 있다. BERT의 알고리즘이 기존에 생각했던 신경망과는 다른 알고리즘(Attention 이용)이라 상식을 위해서라도 알아두면 좋을 것 같다..! 중요하다고 생각되는 내용 위주로 쉽게 작성해서 읽는데 어렵진 않을 것이다(아마도ㅎ).

(👉BERT에 대해서 간단하게 설명하자면 BERT(Bidirectional Encoder Representations from Transformers)는 2018년 구글에서 발표된 기계번역 모델로, 그 성능을 인정받은 모델이다. 이러한 BERT의 큰 특징은 방대한 양의 데이터(약 33억개 단어)로 먼저 학습(pretrain)되었다는 것과, 자신의 사용 목적에 따라 파인튜닝(finetuning)이 가능하다는 점이다. 따라서 output layer만 추가로 달아주면 원하는 결과를 출력해내는 기계번역 모델을 만들어 낼 수 있다.)


Project Description

앞에서 언급했듯이, KoBERT를 이용한 프로젝트는 바로, 한국어 대화 문장을 7가지의 감정(기쁨, 슬픔, 놀람, 분노, 공포, 혐오, 중립)으로 분류하는 모델을 학습시키는 것이다.

코드는 KoBERT 깃허브에 있는 네이버 영화평 이중분류 예시 코드를 바탕으로 작성하였다. 데이터셋을 변경하고 전처리하고, 모델 파라미터를 설정에서 class 수를 변경해주는 것 이외에는 코드가 크게 변경되는 것이 없다! 전체 코드는 깃허브(관리x)에 ipynb 파일로 올려둘 예정이다

한편, 학습 데이터는 AIHUB에서 오픈되어 있는 '한국어 감정 정보가 포함된 단발성 대화 데이터셋'을 다운받아 사용하였다. 해당 데이터는 SNS 글 및 온라인 댓글에 대한 웹 크롤링을 실시한 약 38,600개의 문장으로, 각 문장에 대해 7개 감정(기쁨, 슬픔, 놀람, 분노, 공포, 혐오, 중립)에 대해 레이블링이 수행되어 있다. 아래 이미지는 데이터의 일부분을 캡쳐한 것이다.
(※23.05수정 - 현재 AIHUB에 해당 데이터가 내려가 있어서 블로그에 업로드 해두었으니 필요하시면 다운받으시기 바랍니다! https://blog.naver.com/seolin43/223102584267 )

이제 코드를 살펴보고자 할텐데, 코드는 Colab에서 작성되었고, GPU로 설정해준 뒤 수행하였다.
그 외 셋팅 및 파라미터는 다음과 같다.

  • Python >= 3.6
  • PyTorch >= 1.70
  • Transformers = 3.0.2
  • Colab
  • batch size = 64
  • epochs = 10

Transformers의 경우 3.0.2로 해주어야 에러가 나지 않는다. batch size나 epochs는 변경 가능하다.


1.Colab 환경 설정

Colab에서 코드를 작성했기 때문에 필요한 라이브러리와 모듈을 설치하고, 깃허브에서 KoBERT 파일을 로드해주어야 한다.

!pip install mxnet
!pip install gluonnlp pandas tqdm
!pip install sentencepiece
!pip install transformers==3.0.2
!pip install torch
#깃허브에서 KoBERT 파일 로드
!pip install git+https://git@github.com/SKTBrain/KoBERT.git@master
import torch
from torch import nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import gluonnlp as nlp
import numpy as np
from tqdm import tqdm, tqdm_notebook
#kobert
from kobert.utils import get_tokenizer
from kobert.pytorch_kobert import get_pytorch_kobert_model

#transformers
from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup
#GPU 사용
device = torch.device("cuda:0")
#BERT 모델, Vocabulary 불러오기
bertmodel, vocab = get_pytorch_kobert_model()

2.데이터셋 전처리

필요한 모듈을 설치하고 나면 이제 한국어 대화 데이터셋을 가져와야 한다. AIHUB에서 필요한 데이터를 파일로 다운받았고, 구글 드라이브에 업로드해놓았다. 이제 코랩과 구글 드라이브를 연동해서 로드하면 된다.

#구글드라이브 연동
from google.colab import drive
drive.mount('/content/drive')

위 코드를 실행한 뒤, 링크가 나오면 해당 링크에 들어가서 알파벳과 숫자로 되어 있는 코드를 복사한 뒤 입력창에 붙여넣기 해주면 연동이 된다.

그리고 파일이 있는 폴더 경로를 입력하여 데이터 프레임의 형태로 가져와준다.

import pandas as pd
chatbot_data = pd.read_excel('/content/drive/MyDrive/챗봇/한국어_단발성_대화_데이터셋.xlsx')

'chatbot_data'라는 이름의 데이터프레임으로 데이터를 가져왔다. len(chatbot_data)를 입력하여 실행하면 38594가 나오는데, 이는 한국어 대화 문장이 총 38,594개가 있다는 것이다.

여기서 10개의 데이터를 랜덤으로 출력해보았다.

chatbot_data.sample(n=10)

랜덤으로 출력된 데이터를 보면 첫 번째 컬럼 'Sentence'에는 한국어 대화 텍스트 데이터가 있고, 두 번째 컬럼인 'Emotion'에 어떠한 감정인지 레이블링 되어 있다. 그 옆으로는 NaN 값을 가지는 칼럼들이 있는데 이를 없애주고, 7가지의 감정 단어를 숫자로 변경하도록 하겠다.

chatbot_data.loc[(chatbot_data['Emotion'] == "공포"), 'Emotion'] = 0  #공포 => 0
chatbot_data.loc[(chatbot_data['Emotion'] == "놀람"), 'Emotion'] = 1  #놀람 => 1
chatbot_data.loc[(chatbot_data['Emotion'] == "분노"), 'Emotion'] = 2  #분노 => 2
chatbot_data.loc[(chatbot_data['Emotion'] == "슬픔"), 'Emotion'] = 3  #슬픔 => 3
chatbot_data.loc[(chatbot_data['Emotion'] == "중립"), 'Emotion'] = 4  #중립 => 4
chatbot_data.loc[(chatbot_data['Emotion'] == "행복"), 'Emotion'] = 5  #행복 => 5
chatbot_data.loc[(chatbot_data['Emotion'] == "혐오"), 'Emotion'] = 6  #혐오 => 6

data_list = []
for q, label in zip(chatbot_data['Sentence'], chatbot_data['Emotion'])  :
    data = []
    data.append(q)
    data.append(str(label))

    data_list.append(data)

위 코드를 입력하고 실행하면 각 문장과 숫자로 라벨링된 값이 'data_list'에 저장이 되는데, 몇 개를 출력해보겠다.

print(data_list[0])
print(data_list[6000])
print(data_list[12000])
print(data_list[18000])
print(data_list[24000])
print(data_list[30000])
print(data_list[-1])

>>['언니 동생으로 부르는게 맞는 일인가요..??', '0']
>>['기술적으로도 아직도 해체해서 다시 완벽히 돌려놓는게 어려운데 해체를한다고?', '1']
>>['당연히 그렇게 해야지 우리나라도 판매를 중단하라', '2']
>>['그거들은 뒤부터 미치겠어요...', '3']
>>['최악의 상황중 그나마 나은 방법이네. 기분은 잡치겠지만', '4']
>>['  요리하는것이 숙제하는것처럼 힘든저에게 용기나게 해주시고 할수 있을것같은 희망을 주셔서감사합니다!!', '5']
>>['와이프도 그렇고 댓글 다 볼텐데 이휘재 좀 하차 하라고 전해주세요', '6']

출력된 것을 보면 각 데이터셋이 ['sentence', 'class']의 형태로 이루어져 있음을 확인할 수 이고, 각 숫가 class로 잘 라벨링 되었음을 확인할 수 있다.


3.Train data & Test data

이제 기본적인 데이터셋이 준비가 되었다면, 모델에 학습시킬 train data와 모델을 평가할 test data로 나누어야 한다. Data를 나누는 것은 사이킷런에서 제공하는 train_test_split 라이브러리를 이용하며, 4:1 비율로 나누도록 하겠다.

#train & test 데이터로 나누기
from sklearn.model_selection import train_test_split
                                                         
dataset_train, dataset_test = train_test_split(data_list, test_size=0.25, random_state=0)
print(len(dataset_train))
print(len(dataset_test))

위 코드로 각 train data와 test data의 개수를 출력하면 각각 28945, 9649개가 출력된다. 숫자가 애매하긴 하지만 신경쓰진 않겠다ㅎ


4.KoBERT 입력 데이터로 만들기

데이터를 train data와 test data로 나누었다면 각 데이터가 KoBERT 모델의 입력으로 들어갈 수 있는 형태가 되도록 토큰화, 정수 인코딩, 패딩 등을 해주어야 한다. 예시 코드에 입력데이터의 형태가 되도록 해주는 클래스가 있어서 동일하게 코드를 작성해주었다.

class BERTDataset(Dataset):
    def __init__(self, dataset, sent_idx, label_idx, bert_tokenizer, max_len,
                 pad, pair):
        transform = nlp.data.BERTSentenceTransform(
            bert_tokenizer, max_seq_length=max_len, pad=pad, pair=pair)

        self.sentences = [transform([i[sent_idx]]) for i in dataset]
        self.labels = [np.int32(i[label_idx]) for i in dataset]

    def __getitem__(self, i):
        return (self.sentences[i] + (self.labels[i], ))

    def __len__(self):
        return (len(self.labels))

코드를 보면, 위에서 import 해주었던 BERTSentenceTransform 이라는 모듈을 사용한다. 그리고이 모듈을 통해 토큰화와 패딩이 이루어지는 것 같다. 우선 이 클래스를 정의해준다.

그리고나서 하이퍼 파라미터들을 조정해준다. Batch size는 64, epochs는 5, learning rate는 5e-5로 설정해주었다. 사실 파라미터의 값은 정답이 없고 가장 좋은 성능을 내는 값을 찾아가는 것이 좋다. 하지만 난 그냥 예시 코드에 있는 값들을 동일하게 설정해주었다.

# Setting parameters
max_len = 64
batch_size = 64
warmup_ratio = 0.1
num_epochs = 5
max_grad_norm = 1
log_interval = 200
learning_rate =  5e-5

그리고 이제 버트토크나이저와 위에서 정의한 클래스를 적용해 토큰화와 패딩을 해준다.

#토큰화
tokenizer = get_tokenizer()
tok = nlp.data.BERTSPTokenizer(tokenizer, vocab, lower=False)

data_train = BERTDataset(dataset_train, 0, 1, tok, max_len, True, False)
data_test = BERTDataset(dataset_test, 0, 1, tok, max_len, True, False)

※2022.08.16 수정사항※
이부분을 실행하면 runtime error로 nbest_size 관련 에러가 난다고 하는 분들이 있는데요, sentencepiece 라이브러리의 업데이트로 이슈가 생길 수 있다고 합니다~ 다시 런타임 재시작 + sentencepiece 라이브러리 업데이트 또는 재설치를 해보시고, sentencepiece의 버전이 0.1.6 이상, 0.1.96이하가 맞는지 확인해보시기 바랍니다!
=> 관련링크 : (https://github.com/SKTBrain/KoBERT/issues/89)

토큰화와 패딩이 잘 이루어져있는지 확인하기 위해 data_train[0]을 실행해보면 다음과 같은 값들이 출력될 것이다.

>>(array([   2, 1189,  517, 6188, 7245, 7063,  517,  463, 3486, 7836, 5966,
        1698,  517, 6188, 7245, 7063,  517,  463, 1281, 7870, 1801, 6885,
        7088, 5966, 1698, 5837, 5837,  517, 6188, 7245, 6398, 6037, 7063,
         517,  463,  517,  463,  517,  364,  517,  364,    3,    1,    1,
           1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
           1,    1,    1,    1,    1,    1,    1,    1,    1], dtype=int32),
 array(42, dtype=int32),
 array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       dtype=int32), 5)

출력값들을 보면 3개의 array가 출력되는데, 첫 번째는 패딩된 시퀀스, 두 번째는 길이와 타입에 대한 내용, 세 번재는 어텐션 마스크 시퀀스이다. 어텐션 마스크는 지난 BERT 프로젝트 글에서도 설명했었는데, BERT에 데이터가 입력되었을 때 어텐션 함수가 적용되어 연산이 된다. 이때 1로 패딩된 값들은 연산할 필요가 없기 때문에 연산을 하지 않아도 된다고 알려주는 데이터가 있어야 하는데 그게 바로 어텐션 마스크 시퀀스인 것이다. 이렇게 BERT나 KoBERT에는 어텐션 마스크 데이터도 함께 입력되어야 한다⭐

이제 마지막으로 아래 코드를 실행하여 torch 형식의 dataset을 만들어준다.

train_dataloader = torch.utils.data.DataLoader(data_train, batch_size=batch_size, num_workers=5)
test_dataloader = torch.utils.data.DataLoader(data_test, batch_size=batch_size, num_workers=5)

5.KoBERT 학습모델 만들기

학습시킬 KoBERT 모델을 만들어야 하는데, 아래 코드에서 다중분류할 클래스 수 만큼 num_classes 변수를 수정해주어야 한다. 이번 프로젝트에서는 7가지의 class를 분류하기 때문에 7로 입력해주었다.

class BERTClassifier(nn.Module):
    def __init__(self,
                 bert,
                 hidden_size = 768,
                 num_classes=7,   ##클래스 수 조정##
                 dr_rate=None,
                 params=None):
        super(BERTClassifier, self).__init__()
        self.bert = bert
        self.dr_rate = dr_rate
                 
        self.classifier = nn.Linear(hidden_size , num_classes)
        if dr_rate:
            self.dropout = nn.Dropout(p=dr_rate)
    
    def gen_attention_mask(self, token_ids, valid_length):
        attention_mask = torch.zeros_like(token_ids)
        for i, v in enumerate(valid_length):
            attention_mask[i][:v] = 1
        return attention_mask.float()

    def forward(self, token_ids, valid_length, segment_ids):
        attention_mask = self.gen_attention_mask(token_ids, valid_length)
        
        _, pooler = self.bert(input_ids = token_ids, token_type_ids = segment_ids.long(), attention_mask = attention_mask.float().to(token_ids.device))
        if self.dr_rate:
            out = self.dropout(pooler)
        return self.classifier(out)

그리고 아래 코드를 쭉 실행해주면 된다.

#BERT 모델 불러오기
model = BERTClassifier(bertmodel,  dr_rate=0.5).to(device)

#optimizer와 schedule 설정
no_decay = ['bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [
    {'params': [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay)], 'weight_decay': 0.01},
    {'params': [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay)], 'weight_decay': 0.0}
]

optimizer = AdamW(optimizer_grouped_parameters, lr=learning_rate)
loss_fn = nn.CrossEntropyLoss()

t_total = len(train_dataloader) * num_epochs
warmup_step = int(t_total * warmup_ratio)

scheduler = get_cosine_schedule_with_warmup(optimizer, num_warmup_steps=warmup_step, num_training_steps=t_total)

#정확도 측정을 위한 함수 정의
def calc_accuracy(X,Y):
    max_vals, max_indices = torch.max(X, 1)
    train_acc = (max_indices == Y).sum().data.cpu().numpy()/max_indices.size()[0]
    return train_acc
    
train_dataloader

6.KoBERT 모델 학습시키기

학습 데이터셋과 학습 모델 준비가 다 끝났다면 이제 아래 코드 실행을 통해 KoBERT 모델을 학습시켜준다.

for e in range(num_epochs):
    train_acc = 0.0
    test_acc = 0.0
    model.train()
    for batch_id, (token_ids, valid_length, segment_ids, label) in enumerate(tqdm_notebook(train_dataloader)):
        optimizer.zero_grad()
        token_ids = token_ids.long().to(device)
        segment_ids = segment_ids.long().to(device)
        valid_length= valid_length
        label = label.long().to(device)
        out = model(token_ids, valid_length, segment_ids)
        loss = loss_fn(out, label)
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_grad_norm)
        optimizer.step()
        scheduler.step()  # Update learning rate schedule
        train_acc += calc_accuracy(out, label)
        if batch_id % log_interval == 0:
            print("epoch {} batch id {} loss {} train acc {}".format(e+1, batch_id+1, loss.data.cpu().numpy(), train_acc / (batch_id+1)))
    print("epoch {} train acc {}".format(e+1, train_acc / (batch_id+1)))
    
    model.eval()
    for batch_id, (token_ids, valid_length, segment_ids, label) in enumerate(tqdm_notebook(test_dataloader)):
        token_ids = token_ids.long().to(device)
        segment_ids = segment_ids.long().to(device)
        valid_length= valid_length
        label = label.long().to(device)
        out = model(token_ids, valid_length, segment_ids)
        test_acc += calc_accuracy(out, label)
    print("epoch {} test acc {}".format(e+1, test_acc / (batch_id+1)))

앞서 batch size를 64, epochs 를 10으로 지정한 뒤 학습한 결과, 약 2시간 이내의 시간이 소요되었다. dataset의 크기와 epochs의 수가 크지 않은 것 같은데 생각보다 시간이 많이 걸린 것 같다.

한편 그 결과, 마지막 epoch에서의 정확도 값은 다음가 같이 출력되었다.

출력된 정확도를 보면 학습 데이터에 대해선 0.96로 정확도가 아주 높게 나왔는데, 테스트 데이터에 대해선 정확도가 많이 떨어졌다😮🙄😲 왜 그런걸까.. 7가지의 텍스트 데이터셋이 잘 안 섞인걸까..? 7개 중 하나를 찍은 수준이라면 또 0.53보다는 훨씬 낮아야 하는데.. 아무튼 train set에 대해서는 정확도가 높게 나왔기 때문에 일단 새로운 문장에 대해 테스트를 해보기로 했다.


7.새로운 문장 테스트

새로운 문장을 테스트 할 때, 입력되는 문장을 KoBERT의 입력 형식으로 바꿔주는 코드를 작성해주어야 한다. 아래 코드를 작성하여 토큰화, 패딩, 텐서를 바꿔주고 예측을 하는 'predict' 함수를 만들어 주었다.

#토큰화
tokenizer = get_tokenizer()
tok = nlp.data.BERTSPTokenizer(tokenizer, vocab, lower=False)

def predict(predict_sentence):

    data = [predict_sentence, '0']
    dataset_another = [data]

    another_test = BERTDataset(dataset_another, 0, 1, tok, max_len, True, False)
    test_dataloader = torch.utils.data.DataLoader(another_test, batch_size=batch_size, num_workers=5)
    
    model.eval()

    for batch_id, (token_ids, valid_length, segment_ids, label) in enumerate(test_dataloader):
        token_ids = token_ids.long().to(device)
        segment_ids = segment_ids.long().to(device)

        valid_length= valid_length
        label = label.long().to(device)

        out = model(token_ids, valid_length, segment_ids)


        test_eval=[]
        for i in out:
            logits=i
            logits = logits.detach().cpu().numpy()

            if np.argmax(logits) == 0:
                test_eval.append("공포가")
            elif np.argmax(logits) == 1:
                test_eval.append("놀람이")
            elif np.argmax(logits) == 2:
                test_eval.append("분노가")
            elif np.argmax(logits) == 3:
                test_eval.append("슬픔이")
            elif np.argmax(logits) == 4:
                test_eval.append("중립이")
            elif np.argmax(logits) == 5:
                test_eval.append("행복이")
            elif np.argmax(logits) == 6:
                test_eval.append("혐오가")

        print(">> 입력하신 내용에서 " + test_eval[0] + " 느껴집니다.")

그리고 이제 질문을 무한반복하기 위한 코드를 작성해주고 실행해주면 된다!

#질문 무한반복하기! 0 입력시 종료
end = 1
while end == 1 :
    sentence = input("하고싶은 말을 입력해주세요 : ")
    if sentence == 0 :
        break
    predict(sentence)
    print("\n")

질문 결과는 다음과 같다.

최대한 다 다른 감정들이 출력될 수 있도록 문장을 입력해보았다.
그 결과 test dataset의 정확도에 대한 우려와는 다르게 생각보다 예측을 잘 해주었다! 100% 정확하다고는 할 수 없지만 대충 결이 비슷한 감정으로 출력되었다.


Result

KoBERT를 이용하여 한국어 대화 문장을 7가지의 감정으로 분류하는 모델을 만들고 학습시켜보았다. Test datasets에 대한 정확도가 높지 않았지만 새로운 문장을 입력하니 의외로 감정이 잘 예측되었다. 잘못 예측하더라도 적어도 기쁜 감정의 대화는 놀람이나 중립으로 예측되었지 공포, 슬픔과 같은 감정으로 예측되진 않았다. 반대로 놀람의 감정은 분노나 공포 정도로 예측되었다. 이를 통해 어느정도 대화의 긍정/부정에 대한 분류는 잘 예측되는 것 같다.

한편, 아쉬운 게 있다면 사실 감정 대화 데이터셋을 보면 레이블링이 완벽하게 되어있지 않다. 수정해주고 싶은 데이터와 애매한 감정의 데이터가 많았지만 3만개의 문장을 모조리 고칠 수는 없으니 하지 않았다. 아무튼 확실한 감정이 느껴지는 대화 데이터셋과 레이블링이 완벽하게 구축된다면 모델의 예측률을 훨씬 높일 수 있지 않을까 싶다!


이렇게 KoBERT에 대해 알아보고, KoBERT를 이용한 한국어 분류 모델 프로젝트에 대해 글을 적어봤는데, 쉽게 사용할 수 있어서 챗봇 등 기계번역 모델을 만들 때 매우 유용하지 않을까 싶다! 다음 글에서는 KoBERT, BERT 모델의 기본 베이스가 되는 Transformer를 이용하여 챗봇을 구현했던 프로젝트에 대해 글을 작성하도록 해야겠다.



profile
코드 문의는 언제나 환영입니다 :D 메일 답변이 빨라요! 댓글은 안봐요ㅠ💗

10개의 댓글

comment-user-thumbnail
2021년 12월 11일

💕코드와 관련하여 궁금한 건 메일 주시면 아는 선에서 빠르게 답변드립니다(댓글 안봅니다)💕

1개의 답글

좋은 튜토리얼을 주셔서 감사합니다 👏👏👏. KoBERT 모델을 사용할 때 F1, Precision, Recall 점수를 계산하는 방법을 보여주시겠어요?

답글 달기
comment-user-thumbnail
2022년 3월 12일

도움이 많이 되었습니다. 역시 좋은 자료가 있어야 좋은 자료가 나오는군요 ^^ 아무튼 저에게는 매우 좋은 튜토리얼 이었습니다. 많이 배우고 갑니다~~ 앞으로도 좋은 글 많이 부탁 드려요~

답글 달기
comment-user-thumbnail
2022년 4월 26일

KoBERT 모델을 사용할 때 F1, Precision, Recall 점수를 계산하는 방법을 알 수 있을까요?

1개의 답글
comment-user-thumbnail
2022년 11월 15일

너무 좋은 글 감사합니다~ KoBERT에 대해 막막했는데 도움이 많이 되었습니다!!

답글 달기
comment-user-thumbnail
2023년 5월 16일

올려주신글 너무 감사하게 잘 읽었습니다.
혹시 지금 코랩으로 실행보니깐 import gounnlp 부터 안되고 있는데 혹시 방법을 알고 계실까요?
4월말 까지는 너무 잘사용했는데 갑자기 코랩이 업데이트(python 10.0으로 업데이트)되더니 문제가 발생합니다.
python version: 3.6, 3.7, 3.8, 3.9 까지 진행 결과 오류가 발생합니다.

1개의 답글
comment-user-thumbnail
2023년 12월 19일

올려주신 글 정말 감사하게 잘 읽었습니다. 한 가지 여쭙고 싶은 것이 !pip install git+https://git@github.com/SKTBrain/KoBERT.git@master를 하려고 해도 onnxruntime과 torch가 requirement에 따른 예전 버전이 업데이트로 인해 없어져서 저 방식으로는 환경 세팅이 불가능하다고 나오는데 어떻게 조치하면 좋을까요? 저는 참고로 코랩에서 작업합니다.

답글 달기