Patrick's 데이터 세상
Transformer Encoder 카테고리 분류 개발 후기 - 1. Tokenizer 본문
Transformer Encoder 카테고리 분류 개발 후기 - 1. Tokenizer
patrick610 2022. 2. 27. 17:42
그동안 회사에서 작업했던 30개 카테고리 class 분류 모델 개발 과정 및 삽질 과정을 기록하려고 한다.
전체 프로세스에 대한 공유 목적이자 다시 공부하려는 목적이기도 하다.
https://github.com/hipster4020/category_classification
GitHub - hipster4020/category_classification: 뉴스 카테고리 분류
뉴스 카테고리 분류. Contribute to hipster4020/category_classification development by creating an account on GitHub.
github.com
👉🏻 작업 환경
GPU type | NVIDIA GeForce RTX 3090 |
CPU count | 48 |
GPU count | 4 |
CUDA Version | 11.4 |
Python Version | 3.6.9 |
OS | Docker tensorflow - Ubuntu |
👉🏻 Issue
해당 분류 모델의 목적은 스크랩된 뉴스 본문 기사를 30개 클래스 카테고리로 분류하는 것이었다.
클래스는 각 기사당 최대 3개까지 예측하기 위해 30개 클래스에 대해 모두 각각의 0~1까지 범위의 확률을 낼 수 있도록 각각의 class에 sigmoid를 적용하여 예측값이 0.8 이상인 값 중 3개를 추출하고 1개도 없으면 etc로 분류하였다.
따라서, 각 기사 당 predict label은 1~3개가 된다.
모델은 Transformer의 self-attn과 feedforward network로 구성된 EncoderLayer모델을 활용하였다.
Tokenizer는 뉴스 기사 데이터를 Huggingface Tokenizer의 BPE 모델로 별도로 학습한 모델을 사용한다.
👉🏻 Tokenizer
GitHub - hipster4020/category_classification: 뉴스 카테고리 분류
뉴스 카테고리 분류. Contribute to hipster4020/category_classification development by creating an account on GitHub.
github.com
Tokenizer 작업은 jupyter notebook으로 진행하였다.
• load data
import json
import re
from pprint import pprint
def load_jsonl(input_path) -> list:
data = []
with open(input_path, "r", encoding="utf-8") as f:
for line in f:
data.append(json.loads(line.rstrip("\n|\r")))
return data
data = load_jsonl('../../data/category.json')
json 타입으로 구성된 뉴스 본문 데이터를 불러와 list 타입으로 담는 작업
vocab_size = 24000
user_defined_symbols = ["<pad>", "<unk>", "<cls>", "<sep>", "<mask>", "<bos>", "<eos>", "<tsep>", "<name>", "<url>"]
user_defined_symbols += ["<unk0>", "<unk1>", "<unk2>", "<unk3>", "<unk4>", "<unk5>", "<unk6>", "<unk7>", "<unk8>", "<unk9>"]
unused_token_num = 100
unused_list = [f"<unused{i}>" for i in range(unused_token_num)]
user_defined_symbols += unused_list
pprint(user_defined_symbols)
vocabulary size를 24000으로 설정하고, 사용자 정의 토큰에 <pad>, <unk>, <cls>, <sep>, <mask>, <bos>, <eos>, <tsep>, <name>, <url>
<unk0>, <unk1>, <unk2>, <unk3>, <unk4>, <unk5>, <unk6>, <unk7>, <unk8>, <unk9>를 지정.
추가로 <unused> 토큰을 0~99까지 100개 사용자 정의 토큰에 추가하였다.
• train
from tokenizers import Tokenizer
from tokenizers.models import BPE
tokenizer = Tokenizer(BPE(unk_token="<unk>"))
pretrained 된 tokenizer 말고 직접 train 해서 쓸 것이기 때문에 import 된 Huggingface의 Tokenizer, models를 활용하여 BPE 학습을 진행한다.
from tokenizers import normalizers
from tokenizers.normalizers import NFKC, BertNormalizer
n1 = NFKC()
n2 = BertNormalizer(
clean_text=False,
handle_chinese_chars=False,
strip_accents=False,
lowercase=False,
)
tokenizer.normalizer = normalizers.Sequence([n1, n2])
NFKC : NFKC 유니코드로 정규화 진행
BertNormalizer : Bert 모델 Normalizer 사용
from tokenizers import pre_tokenizers
from tokenizers.pre_tokenizers import Metaspace
tokenizer.pre_tokenizer = pre_tokenizers.Sequence([Metaspace(replacement="_", add_prefix_space=True
)
]
)
pre_tokenizers.Sequence : 공백을 분할하고 특수 문자 "_"로 대체하는 Metaspace로 사전 토큰화
def gen():
for row in data:
yield processing(row['content'])
from tokenizers.trainers import BpeTrainer
trainer = BpeTrainer(vocab_size=vocab_size,
special_tokens=user_defined_symbols,
)
tokenizer.train_from_iterator(gen(), trainer)
tokenizer.model.save("temp")
trainers.BpeTrainer : BpeTrainer로 config 값 세팅(vocab_size : 24000 , user_defined_symbols : 위에 정의한 사용자 정의 토큰)
tokenizer.train_from_iterator : list 뉴스데이터와 trainer로 train 진행
tokenizer.model.save("temp") : 모델 저장
output = tokenizer.encode("본 고안은 이러한 특성을 이용해 사용한다.")
print(output.ids)
tokenizer.decode(output.ids)
from tokenizers import decoders
tokenizer.decoder = decoders.BPEDecoder(suffix='_')
tokenizer.decode(output.ids)
trained tokenizer에 test encoding 후 decoding 진행하면 정상적으로 결과 출력된다.
• convert transformers tokenizer and save
from transformers import GPT2TokenizerFast
fast_tokenizer = GPT2TokenizerFast(tokenizer_object=tokenizer)
fast_tokenizer.pad_token = "<pad>"
fast_tokenizer.unk_token = "<unk>"
fast_tokenizer.cls_token = "<cls>"
fast_tokenizer.sep_token = "<sep>"
fast_tokenizer.mask_token = "<mask>"
fast_tokenizer.bos_token = "<bos>"
fast_tokenizer.eos_token = "<eos>"
special_tokens_dict = {'additional_special_tokens': user_defined_symbols}
fast_tokenizer.add_special_tokens(special_tokens_dict)
새로 정의한 GPT2TokenizerFast에 padding, unknown, cls, sep, mask, bos, eos 토큰을 추가하고, 스페셜 토큰 사전에 사용자 정의 토큰을 추가한다.
fast_tokenizer.decode(fast_tokenizer.encode("본 고안은 이러한 특성을 이용해 사용한다."))
fast_tokenizer.save_pretrained("tokenizer")
테스트 문장 출력 확인 후 tokenizer save.
👉🏻 정리
huggingface BPE 학습한 모델을 GPT2TokenizerFast로 load하여 Transformer Encoder 모델에 사용할 준비를 마쳤다.
2부에서 Transformer 모델, Finetuning에 대해 다루려고 한다
Components — tokenizers documentation
When building a Tokenizer, you can attach various types of components to this Tokenizer in order to customize its behavior. This page lists most provided components. PostProcessor After the whole pipeline, we sometimes want to insert some special tokens be
huggingface.co
'Deep Learning > 프로젝트 후기' 카테고리의 다른 글
2024년 회고록 (4) | 2024.12.31 |
---|---|
카피라이터 광고 문구 생성모델 학습 후기 (2) | 2023.08.11 |
국내 유통대기업 성격유형별 문체 특성 기반 맞춤형 광고 메시지 생성 모델 재구현 프로젝트 (0) | 2023.05.15 |
koELECTRA with Active Learning 감성 분류 개발 후기 (0) | 2022.06.09 |
Transformer Encoder 카테고리 분류 개발 후기 - 2. train (0) | 2022.03.05 |