어휘 집합 구축 및 토큰화 하기

Yerin·2022년 1월 3일
0
post-thumbnail

해당 글은 <Do it! BERT와 GPT로 배우는 자연어 처리> 책을 읽고 정리한 글입니다.

앞에서 본 이론을 바탕으로 허깅페이스 tokenizers 라이브러리를 활용해 BPE 기반의 토크나이저를 만들어보자.
BPE는 자주 등장하는 문자열을 토큰으로 인식해, 이를 기반으로 토큰화를 수행하는 기법이다.

어휘 집합 구축하기

BPE 기반 토크나이저를 사용하려면 가장 먼저 어휘 집합을 구축해야한다.

말뭉치 내려받기 및 전처리

오픈소스 파이썬 패키지 코포라를 활용해 BPE 수행 대상 말뭉치를 내려받고 전처리를 한다.
실습용 말뭉치는 박은정님이 공개한 네이버 영화 리뷰 NSMC이다.

from Korpora import Korpora
nsmc = Korpora.load("nsmc", force_download=True)

이제 NSMC에 포함된 영화 리뷰들을 순수 텍스트 형태로 지정된 디렉토리에 저장한다.

import os
def write_lines(path, lines):
    with open(path, 'w', encoding='utf-8') as f:
        for line in lines:
            f.write(f'{line}\n')

write_lines("/root/train.txt", nsmc.train.get_all_texts())
write_lines("/root/test.txt", nsmc.test.get_all_texts())

GPT 토크나이저 구축

앞 절에서 설명한 문자 단위가 아닌 유니코드 바이트 수준으로 어휘 집합을 구축하고 토큰화를 수행할 것이다.
즉 어휘 집합 구축 대상 말뭉치를 모두 유니코드 바이트로 변환하고 이들을 문자 취급해 가장 자주 등장한 문자열을 병합하는 방식으로 어휘 집합을 만든다는 의미이다.

바이트 수준 BPE 어휘 집합 구축 결과를 저장해 둘 디렉토리를 구글 드라이브 계정 내에 만든다.

import os
os.makedirs("/gdrive/My Drive/nlpbook/bbpe", exist_ok=True)

다음 코드를 실행하여 바이트 수준 BPE 어휘 집합을 구축한다.

from tokenizers import ByteLevelBPETokenizer
bytebpe_tokenizer = ByteLevelBPETokenizer()
bytebpe_tokenizer.train(
    files=["/root/train.txt", "/root/test.txt"],
    vocab_size=10000,
    special_tokens=["[PAD]"]
)
bytebpe_tokenizer.save_model("/gdrive/My Drive/nlpbook/bbpe")

위 코드의 결과로 vocab.json(바이트 수준 BPE의 어휘 집합), merge.txt(바이그램 쌍의 병합 우선 순위) 가 생성된다.

토큰화 하기

GPT 입력값 만들기

입력값을 만들기 위해 토크나이저를 준비해야 한다.
어휘 집합 구축 실습에서 만든 바이트 기준 BPE 어휘 집합(vocab.json)과 바이그램 쌍의 우선순위(merge.txt)를 불러오자.

from transformers import GPT2Tokenizer
tokenizer_gpt = GPT2Tokenizer.from_pretrained("/gdrive/My Drive/nlpbook/bbpe")
tokenizer_gpt.pad_token = "[PAD]"

이제 예시 문장 3개를 바이트 수준 BPE 토크나이저로 토큰화 하자.

sentences = [
    "아 더빙.. 진짜 짜증나네요 목소리",
    "흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나",
    "별루 였다..",
]
tokenized_sentences = [tokenizer_gpt.tokenize(sentence) for sentence in sentences]

tokenized_sentences를 출력해보면 아래와 같이 알 수 없는 문자열로 구성되어 있음을 알 수 있다. 이는 바이트 기준 BPE를 적용했기 때문이다.

['ìķĦ', 'ĠëįĶë¹Ļ', '..', 'Ġì§Ħì§ľ', 'Ġì§ľì¦ĿëĤĺ', 'ëĦ¤ìļĶ', 'Ġ목ìĨĮ리'], ['íĿł', '...', 'íı¬ìĬ¤íĦ°', 'ë³´ê³ł', 'Ġì´ĪëĶ©', 'ìĺģíĻĶ', 'ì¤Ħ', '....', 'ìĺ¤ë²Ħ', 'ìĹ°ê¸°', 'ì¡°ì°¨', 'Ġê°Ģë³į', 'ì§Ģ', 'ĠìķĬ', '구ëĤĺ'], ['ë³Ħ루', 'Ġìĺ', 'Ģëĭ¤', '..']]

이제 본격적으로 실제 모델에 입력값을 넣어보자.

batch_inputs = tokenizer_gpt(
    sentences,
    padding="max_length",
    max_length=12,
    truncation=True,
)

위 코드의 결과로 input_ids와 attention_mask 두 개의 값이 만들어 진다.

input_ids

[[334, 2338, 263, 581, 4055, 464, 3808, 0, 0, 0, 0, 0],
 [3693, 336, 2876, 758, 2883, 356, 806, 422, 9875, 875, 2960, 7292],
 [4957, 451, 3653, 263, 0, 0, 0, 0, 0, 0, 0, 0]]

토큰화 결과를 가지고 각 토큰을 인덱스로 바꾼 것이다.

attention_mask

[[1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]]

일반 토큰이 자리한 곳(1)과 패딩 토큰이 자리한 곳(0)을 구분해 알려주는 장치이다.


이 부분을 학습하는데 있어서 조금 어려움이 있었다.
아직 이해가 덜 된 부분도 있어 추후 허깅페이스 토크나이저 공식 문서를 통해 학습할 예정이다.
https://huggingface.co/docs/tokenizers/python/latest/

profile
재밌는 코딩 공부

0개의 댓글