한국어를 위한 KoBERT 사용기

Nina·2022년 11월 5일
0

그동안 댓글 데이터를 처리할 일이 많다보니 KcBERT를 사용할 일이 많고 정작 KoBERT로 데이터 처리를 해본 적이 없었다.

아무 생각 없이 이번에도 KcBERT로 테스크 진행하고 있었는데 생각해보니 KoBERT를 사용해도 될 데이터라 이번 기회에 KoBERT로 모델을 바꿔 실험을 진행해 보았다.

Huggingface에서 두 모델을 제공하고 있으니, 모델만 바꿔 끼면 되겠지라고 안일하게 생각했는데..

그게 아니었다는..
게다가 2021년 11월부터 서버에 문제가 생기면서 그동안 잘 돌아가던 Kobert 코드도 잘 안되는 듯 하다. (지금 검색으로 찾을 수 있는 코드 중 대부분은 바뀌기 전 코드)

암튼 각설하고 huggingface KoBERT 돌리는 코드를 공유한다.

huggingface transformer를 설치하고, KoBERT의 경우 토크나이저 사용을 하려면 sentencepice도 설치를 해줘야 한다.

!pip install transformers
!pip install sentencepiece

KcBERT의 경우 transfomer 모듈에서 바로 가져와서 쓸 수 있지만(!!) KoBERT는 공식 깃에서 토크나이저 관련 파일을 받아줘야 한다.

!pip install 'git+https://github.com/SKTBrain/KoBERT.git#egg=kobert_tokenizer&subdirectory=kobert_hf'

이 과정을 거치고 나서야 huggingface에서 모델과 토크나이저를 가져올 수 있다. huggingface에서 Kobert는 'skt/kobert-base-v1' 모델명으로 불러온다.

from kobert_tokenizer import KoBERTTokenizer
from transformers import BertModel

from transformers import AdamW
from transformers.optimization import get_cosine_schedule_with_warmup
tokenizer = KoBERTTokenizer.from_pretrained('skt/kobert-base-v1', last_hidden_states=True)
model = BertModel.from_pretrained('skt/kobert-base-v1', return_dict=False)

토크나이저가 잘 동작하는지 확인을 해보니 다행히 잘 나온다.

inputs = tokenizer("목차를 봤을 때 기억에 오래 남아요", return_tensors="pt")

{'input_ids': tensor([[   2, 2068, 7389, 6116, 2421, 7088, 1844, 1291, 6896, 3422, 1420, 6999,
            3]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

모델 지정해주고~

import torch.nn as nn
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence

class Bert(nn.Module):
    def __init__(
            self,
            model_name,
            n_classes,
            hidden_size,
            n_layers,
            dropout_p,
    ):
        self.model_name = model_name
        self.n_class = n_classes
        self.hidden_size = hidden_size
        self.n_layers = n_layers
        self.dropout_p = dropout_p

        super().__init__()

        self.bertmodel = BertModel.from_pretrained(self.model_name,  output_attentions = True, output_hidden_states=True)

        self.classifier = nn.Sequential(
            nn.Dropout(p=dropout_p),
            nn.Linear(self.bertmodel.config.hidden_size, self.n_class)
        )

    def forward(self, x):
       
        # |x| = (batch_size, length)
        # encoder_layer= self.bertmodel(x, attention_mask)
        pooled_output = self.bertmodel(x)[1]
      
        x = self.classifier(pooled_output)

        return x

잘 물려서 돌아가는 것까지 확인 :)

model = bert(
            'skt/kobert-base-v1',
            3,
            hidden_size = 100,
            n_layers = 3,
            dropout_p =.25,
        )
encoding = tokenizer("나는 할 수 있다", return_tensors="pt")

x= encoding['input_ids']

outputs = model(x)
print(outputs)

<참고>

KcBERT 공식 깃허브

KoBERT 공식 깃허브

profile
언어를 사랑하고 독서를 즐겨하며 자연어처리를 공부합니다.

1개의 댓글

comment-user-thumbnail
2023년 5월 3일

혹시 python 버전이랑 transformers, sentencepiece 버전 알 수 있을까요.

답글 달기