35GB 텍스트 데이터로 토크나이저를 학습하였습니다.
from datasets import load_dataset
from tokenizers import ByteLevelBPETokenizer
tokenizer = ByteLevelBPETokenizer(unicode_normalizer="nfkc", trim_offsets=True)
ds = load_dataset("Bingsu/my-korean-training-corpus", use_auth_token=True)
# 공개된 데이터를 사용할 경우
# ds = load_dataset("cc100", lang="ko") # 50GB
# 이 데이터는 35GB이고, 데이터가 너무 많으면 컴퓨터가 터져서 일부만 사용했습니다.
ds_sample = ds["train"].train_test_split(0.35, seed=20220819)["test"]
def gen_text(batch_size: int = 5000):
for i in range(0, len(ds_sample), batch_size):
yield ds_sample[i : i + batch_size]["text"]
tokenizer.train_from_iterator(
gen_text(),
vocab_size=50265,
min_frequency=2,
special_tokens=[
"<s>",
"<pad>",
"</s>",
"<unk>",
"<mask>",
],
)
tokenizer.save("my_tokenizer.json")
# tokenizer.save_model(".", "my_tokenizer")
기본적인 틀은 https://huggingface.co/blog/how-to-train를 참고하였습니다.
tokenizer = ByteLevelBPETokenizer(unicode_normalizer="nfkc", trim_offsets=True)
unicode_normalizer는 paust/pko-t5-base와 유니코드 관련 문서를 참고하였습니다. 원본 roberta-base모델에는 이 옵션이 있지 않습니다. 참고: [유니코드] 한글 인코딩 개념과 발생하는 문제점 정리
ds = load_dataset("Bingsu/my-korean-training-corpus", use_auth_token=True)
이 datasets 저장소에는 Aihub와 모두의 말뭉치 등에서 수집한 텍스트가 있습니다. 라이센스상 공개할 수 없어 밑에 주석으로 다른 공개 데이터셋을 넣어놓았습니다.
def gen_text(batch_size: int = 5000):
for i in range(0, len(ds_sample), batch_size):
yield ds_sample[i : i + batch_size]["text"]
tokenizer.train_from_iterator(
gen_text(),
vocab_size=50265,
min_frequency=2,
special_tokens=[
"<s>",
"<pad>",
"</s>",
"<unk>",
"<mask>",
],
)
그리고 훈련.
vocab_size는 roberta-base와 같은 크기입니다.
텍스트를 제공하는 이터레이터를 만들고, .train_from_iterator
로 훈련합니다.
special_tokens에 들어가는 항목은 순서도 중요합니다.
i5-12600 non-k cpu로 약 7시간이 소요되었습니다.
훈련이 완료된 토크나이저를 다시 불러와, 토크나이저의 post-processor를 변경해줍니다.
from tokenizers import Tokenizer
from tokenizers.processors import RobertaProcessing
tokenizer = Tokenizer.from_file("my_tokenizer.json")
tokenizer.post_processor = RobertaProcessing(
("</s>", tokenizer.token_to_id("</s>")),
("<s>", tokenizer.token_to_id("<s>")),
add_prefix_space=False,
)
tokenizer.save("my_tokenizer2.json")
add_prefix_space=False옵션은 roberta-base를 그대로 따라하기 위한 것입니다. 설정하지 않으면 기본값 True가 사용됩니다.
from transformers import RobertaTokenizerFast
rt = RobertaTokenizerFast(tokenizer_file="tokenizer.json")
그리고 RobertaTokenizerFast
클래스로 불러옵니다. 다른 Fast 토크나이저로 불러와도 상관없습니다.
rt.save_pretrained("./my_tokenizer")
토크나이저를 저장해준 뒤
생성된 폴더의 tokenizer_config.json
파일을 열어 "model_max_length": 512,
를 추가합니다.
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Bingsu/BBPE_tokenizer_test")
끝!