누가누가 잘하나! 대화체와 합이 잘 맞는 Tokenizer를 찾아보자! - Dialog-BERT 만들기 2편

What is the Best Tokenizer for Dialogue (How to build Dialog-BERT: Part #2)

이주홍 | 2019년 07월 16일

지난 “카톡 데이터는 어떻게 정제할 수 있을까? - Dialog-BERT 만들기 1편“에서는 Dialog-BERT를 학습시키기 위한 자연어 데이터 전처리에 대해서 소개했었습니다. 이번에는 전처리에 이어서 한국어 모델링의 본격적인 시작인 Tokenizer에 대해서 얘기해볼까 합니다. 한국어를 위한 다양한 Tokenizer를 알아보고, 특히 대화체와 가장 합이 잘 맞는 Tokenizer가 무엇인지 실험을 통해 알아 보겠습니다.

Table of Contents

  1. Introduction
    1. 왜 Tokenize를 해야 할까요?
    2. 한국어 대화체에 적절한 Tokenizer는 무엇일까요?
  2. Tokenizers
    1. 공백 기반 Tokenizer
    2. 형태소 분석기 기반 Tokenizer
    3. BPE 기반 Tokenizer
  3. Experiments
    1. Tokenizer 후보
    2. Tokenizing Speed & OOV Rate
    3. Subtask #1: Language Modeling
    4. Subtask #2: Intent Classification
  4. Discussion
  5. Conclusion
  6. Reference

1. Introduction

왜 Tokenize를 해야 할까요?

우리가 매일 사용하는 자연어(natural language)는 사람은 이해할 수 있지만, 숫자 밖에 모르는 모델은 이를 바로 이해할 수 없습니다. 따라서 자연어를 모델에게 가르치려면 숫자로 나타낸 데이터 (numerical data)로 바꾸어 주어야 합니다. 분류, 번역, 추론 등 대부분의 NLP 테스크 데이터는 문장의 형태로 존재를 하는데, 이런 문장들은 너무나 다양하고 사실상 무한대에 가깝기 때문에 각각을 숫자로 매핑(mapping)하는 것은 불가능합니다. 그래서 보통 유한한 단어(word) 혹은 글자(character) 단위로 문장을 쪼개고 각각을 숫자로 매핑시켜서 sequence 모델링을 합니다. 이때 각각의 쪼개진 단위를 token이라고 하고, 문장을 적절한 token으로 자르는 작업을 tokenize라고 합니다.

그렇다면 tokenize는 어떻게 하는 게 좋은 것일까요? 이상적인 tokenize 결과는 각 token이 의미 단위로 적절히 쪼개지는 것이라고 할 수 있습니다. 적절한 의미 단위의 Tokenize을 위해 간단히 공백을 기준으로 자를 수도 있고 형태소 분석기를 이용해서 문법적 의미 단위를 잡아낼 수도 있을 것입니다. 또한 최근에는 Subword Unit의 통계 정보를 기반으로 한 Word Piece Model (Sennrich et al., 2016) 도 많이 사용되고 있습니다.

한국어 대화체에 적절한 Tokenizer는 무엇일까요?

영어와 한국어는 의미 단위를 구분하는 데이터 처리 관점에서 많은 차이점이 있습니다. 영어는 띄어쓰기 단위로 각 단어가 비교적 명확한 의미를 갖기 때문에 구분이 쉽지만, 한국어는 조사와 어미의 변형으로 인해 의미 단위를 쉽게 구분하기 어렵습니다. 예시를 통해 알아보겠습니다.

한국어는 하나의 단어에 대해서 다양한 변형이 일어나는데 비해 영어는 여러 단어를 이용해 의미적 변형이 일어난다. (a), (b): 다양한 조사, (b): 다양한 어미의 변형.

위의 그림에서 (a)는 한국어의 특징 중 하나인 조사의 다양성을 보여주는 예시입니다. 그림에서 알 수 있듯이 조사는 명사 뒤에 붙어서 의존적으로 사용됩니다. 반면, (a)를 영어로 대응시킨 (b)의 경우 “is”, “to”, “with” 등과 같이 별개의 단어가 공백을 사이에 두고 붙습니다. (c)와 (d)는 어미의 변형에 대한 예시이며, 이 역시 한국어는 어근 “먹”에 대해서 어미들이 의존적으로 붙어서 변형이되는데 비해 영어는 어근 “eat”에 다른 단어(“to”, “have”)가 공백으로 구분되어 붙거나 비교적 규칙적인 변형(-ing, -en, -ed)이 이루어집니다. 언뜻 보았을 때는 큰 차이라고 생각되지 않지만 데이터 처리 / 모델링 관점에서 보면 큰 차이가 있습니다. 간단한 모델링을 위해 문장을 공백 단위로 tokenize하고 이를 숫자로 매핑시킨다고 했을 때, (a)의 단어들은 조사까지가 하나의 token이 되어 모두 서로 다른 숫자로 매핑될 것입니다. “핑퐁은”은 1, “핑퐁이”는 2, “핑퐁을”은 3 … 과 같이 매핑이 되는데 모델에게 1번 단어인 “핑퐁은”과 2번 단어인 “핑퐁이”는 서로 굉장히 유사한 의미를 지님에도 불구하고 전혀 관련이 없는 다른 단어로 인식됩니다. 반면 (b)는 모든 “Pingpong”과 앞뒤에 붙은 단어들이 서로 다른 token으로 분리되고 “Pingpong”은 모두 하나의 숫자로 매핑할 수 있고 모델 역시 이를 모두 같은 의미로 인식할 수 있습니다. (c)와 (d)도 마찬가지입니다.

위와 같은 이유로 한국어의 경우 각각의 변형이 사실 굉장히 유사한 의미를 가진다는 것을 학습을 통해 알아가야 하는데 모든 변형에 대한 의미를 충분히 학습한다는 것은 사실상 불가능에 가깝습니다. 또한 저런 변형을 모두 포함시키려면 매우 큰 사전이 필요하게 됩니다. NLP 모델링에서 사전이 커지게 되면 모델의 크기가 커질 뿐더러 학습이 잘 이루어지지 않게 됩니다. 반면 영어는 이런 문제가 상대적으로 덜하기 때문에 특별한 tokenizer를 쓰지 않고 단순히 공백(white space)으로 tokenize를 후 모델링을 해도 충분히 효과적이고 많은 연구들이 이를 기반으로 진행되어 왔습니다. 따라서, 효과적인 한국어 모델링을 위해서 tokenizer는 매우 중요하고 최신의 복잡한 모델을 사용하는 것보다 성능을 더 크게 올릴 수도 있는 요소입니다. 특히, 핑퐁에서 다루고 있는 카톡 데이터는 수많은 오타와 띄어쓰기 오류가 있고 더욱 다양한 변형과 생략이 있기 때문에, 이를 기반으로 Dialog-BERT를 학습시키는데 있어서 tokenizer가 더욱 중요한 역할을 합니다. 그렇다면 Dialog-BERT를 학습시키는데 어떤 토크나이저가 가장 좋을지 다양한 실험을 통해서 알아보겠습니다.

2. Tokenizers

실험에 앞서 대상이 될 tokenizer를 먼저 알아보겠습니다. 가장 간단한 공백 기준의 tokenizer와 형태소 분석기 기반 tokenizer, 그리고 Word Piece Model로 대표되는 Byte Pair Encoding (BPE) 기반의 tokenizer가 있습니다. 각각이 어떤 특징을 갖고 있는지, 또 그들 간에 어떤 차이가 있을지 살펴보겠습니다.

공백 기반 Tokenizer

말 그대로 공백을 기준으로 문장을 잘라내는 것입니다. 가장 빠르고 심플합니다. 영어 데이터는 1. Introduction 에서 언급했듯이 공백으로 문장을 분리해도 의미 단위로 잘 나뉩니다. 하지만 한국어에서는 조사, 어미 변형으로 인해 의미가 잘 분리되지 않기 때문에 모델의 성능 저하를 야기합니다. 이런 문제는 핑퐁에서 다루는 카톡 데이터와 같이 대화/채팅체의 자연어 데이터에서 더욱 심화됩니다.

형태소 분석기 기반 Tokenizer

형태소 분석기이란 형태소를 비롯한 어근(stem), 접두사(prefix) / 접미사(suffix), 품사(POS; part-of-speech) 등의 다양한 언어적 속성에 대한 문법 구조를 파악하는 것입니다 [원문]. 아래의 예시와 같이 형태소 분석기는 문장의 문법적 구조를 파악하여 조사나 어미에 대한 tokenize를 할 수 있습니다.

나는 밥을 먹는다 -> 나/NP + 는/JX + 밥/NNG + 을/JKO + 먹/VV + 는다/EC

위의 결과의 각 token을 연결한 [“나”, “는”, “밥”, “을”, “먹”, “는다”] 를 모델의 인풋으로 사용하게 됩니다. POS tag를 추가적인 인풋으로 사용할 수도 있습니다. 이런 형태소 분석기를 이용하기 위해 한국어 NLP 파이썬 패키지인 KoNLPy 를 이용할 수 있습니다. 해당 패키지를 통해 Mecab, Kkma, Komoran 등의 형태소 분석기를 사용할 수 있으며 각 형태소 분석기의 성능 비교에 대한 포스트 를 참고하시면 사용하시는데 도움이 될 것 같습니다. 이와 함께 카카오에서 최근 공개한 Khaiii 를 통해서도 형태소 분석을 할 수 있습니다.

하지만 이런 형태소 분석기 기반 tokenizer는 몇 가지 문제점이 있습니다. 첫 번째는 형태소 분석 결과가 100% 확실한 것이 아니라는 것입니다. 형태소 분석기는 보통 기존에 구축된 사전을 기반으로 확률적 예측을 하기 때문에 띄어쓰기 오류, 오타, 신조어 등이 포함될 경우 아래의 예시와 같이 잘못된 분석 결과가 나올 수 있습니다.

어제 ㄹㅇ 갑분싸 ㅋㅋㅋ -> 어제/MAG + ㄹ/NNG + ㅇ/UNKNOWN + 갑/NNG + 분/XSN + 싸/VA+EF + ㅋㅋㅋ/IC

두 번째 문제점은 속도가 느리다는 점입니다. 형태소 분석기는 사전에 대한 로딩 시간과 형태소 분석을 위한 확률적 계산에 상당한 시간이 소요됩니다. 이러한 소요시간은 문자의 개수에 따라서 기하급수적으로 증가할 수 있습니다.

문자의 개수에 따른 소요시간 (출처: KoNLPy - 형태소 분석 및 품사 태깅)

마지막 세 번째는 Out-of-Vocabulary(OOV) 문제입니다. OOV 문제란 학습(train)할 때 보지 못했던 새로운 단어가 테스트(test) 단계에서 등장하여 모델이 해당 단어의 의미를 알 수 없게 되는 것입니다. 사전에 크기가 한정적이기 때문에 모든 단어를 포함할 수 없게 되고 따라서 사전에 포함되지 못한 단어는 모두 unknown token (“<UNK>“)으로 치환되는 것이죠.

word_dict = {"<UNK>": 0, "안녕": 1, "나": 2, "는": 3, "이야": 4}
sentence = ["안녕", "나", "는", "핑퐁", "이야"]
input_sequence = [1, 2, 3, 0, 4]  # "핑퐁" -> "<UNK>" -> index: 0

예를 들어, 학습 데이터로부터 위와 같은 단어 사전 word_dict 를 구축했다고 가정해보겠습니다. 이때 sentence 와 같은 tokenize 된 문장이 input으로 주어졌을 때, “핑퐁” 이란 단어는 word_dict 에 존재하지 않기 때문에 “<UNK>” 로 치환이 되고 최종적으로 input_sequence 와 같이 numerical한 input이 모델에 들어가게 됩니다. 이 경우 당연히 모델은 “핑퐁”이라는 단어를 모델링할 수가 없게 되는 것입니다. 따라서 이런 OOV의 비율이 커질수록 input 문장을 모델이 이해하기 어렵게 되어 학습이 잘 안되고 성능이 떨어지게 됩니다.

BPE 기반 Tokenizer

이런 OOV 문제를 해결하기 위해서 최근에는 데이터 압축 기법인 BPE 알고리즘 (Gage, 1994) 을 기반으로 Subword Unit에 대한 사전을 만드는 (Sennrich et al., 2016), (Wu et al., 2016), (Kudo and Richardson, 2018) 등의 기법이 많이 활용되고 있습니다. 이 기법들을 간단히 설명하자면, 빈도수가 높은 Subword Unit들을 병합시켜나가면서 최종적으로 자주 나오는 단어는 그 자체를 그대로 저장하고 덜 나오는 단어는 subword로 나누어서 저장하므로서 효율적인 사전 관리를 통해 OOV를 줄이는 목적을 갖고 있습니다. 확실히 이런 BPE 기반 tokenizer들이 굉장히 낮은 OOV를 보이며 접두사, 접미사가 비교적 규칙적으로 잘 활용되는 영어의 경우 좋은 효과를 보입니다. 하지만 한글에 경우 워낙 변형이 다양하기 때문에 잘 동작하지 않을 수도 있다는 한계점이 있습니다.

3. Experiments

Tokenizer 후보

모든 tokenizer를 실험해볼 수 없었기에 형태소 분석기 기반 tokenizer로 많이 활용되는 1) Mecab 형태소 분석기와 BPE 기반 tokenizer 중 오픈소스로 잘 관리된 2) SentencePiece를 대표적으로 다루어보았습니다. 카카오 형태소 분석기 Khaiii나 확률 기반의 Cohesion tokenizer 도 간단히 실험을 진행하였으나, 위의 두 tokenizer에 비해서 속도(아래 Tokenizing Speed & OOV Rate 챕터 참조)나 정확도 면에서 다소 부족하다고 판단하여 실험은 Mecab과 SentencePiece에 대해서만 진행을 하였습니다. 그리고 사전의 크기에 따른 성능 변화 및 OOV 차이를 확인하기 위해, 30000, 50000, 100000의 크기를 갖는 사전을 기반으로 각 tokenizer를 생성하였습니다. 즉, Mecab과 SentencePiece가 각각 3가지의 사전 크기에 대한 variation을 가져서 총 6개의 tokenizer를 비교하게 됩니다.

데이터 및 실험 환경

Tokenizer 준비 프로세스

핑퐁 내부적으로 구축되어 있는 약 1억 개의 카톡 채팅 데이터를 사용하였습니다. 이 데이터를 Mecab과 SentencePiece는 각각 다른 방식으로 이용합니다. 먼저 Mecab은 이미 완성된 형태소 분석기 형태로 배포되기 때문에 바로 tokenize가 가능합니다. 따라서 카톡 데이터를 Mecab을 통해 모두 tokenize하고 최빈(most frequent) N 단어 사전을 구축합니다. 반면 SentencePiece tokenizer의 경우 tokenizer 자체를 새로 학습을 시켜야 하고 이때 사전의 크기도 정해져야 합니다. 따라서 카톡 데이터로 사전 크기가 N 인 SentencePiece tokenizer를 카톡 데이터를 이용해서 학습시킵니다. SentencePiece의 경우 초기에 정한 크기 N 대로 사전이 구축되기 때문에 별도의 사전 구축 작업을 진행하지 않습니다.

Tokenizer에 대한 준비를 마친 뒤, 비로소 각 tokenizer의 성능을 평가할 수 있습니다. 하지만 tokenize가 잘 되었는지를 자동으로 평가할만한 metric이 마땅히 없기 때문에 tokenizer의 성능을 정량적으로 평가하는 것이 쉬운 일이 아닙니다. 정성적으로 사람이 보기에 의미 단위로 알맞게 나뉘었는지 평가해볼 수는 있지만, 사람이 보기 좋은 데이터를 쓴다고 모델의 성능이 반드시 올라가는 것이 아니기에 정성적 기준으로 모든 것을 판단하기에는 무리가 있을 수 있습니다. 따라서 저희는 tokenizer에 따른 subtask 모델의 성능 변화에 대한 실험을 진행하였습니다. 단순히 tokenize에 대한 성능 뿐아니라 실제로 tokenize 결과를 모델이 얼마나 잘 이해하고 학습하는지 확인해보는 것입니다. Subtask로는 token이 적절히 의미 단위로 끊어져 있는지 확인할 수 있고 unsupervised learning이 가능한 Language Modeling과 language understanding의 대표적인 테스크이자 자체적으로 구축해둔 데이터가 존재하는 Intent Classification을 선정하였습니다.

Tokenizing Speed & OOV Rate

Subtask 평가에 앞서 먼저 각 tokenizer 별로 OOV 비율과 tokenizing 속도를 비교해보았습니다. 저희가 다루고 있는 채팅 데이터는 띄어쓰기 오류, 오타, 신조어 등이 많이 포함하고 있기 때문에 OOV 문제가 심화될 수 있어서 이 부분을 필수적으로 체크해보았습니다. 또한 저희가 만들고 있는 일상대화 시스템은 사용자와 실시간으로 대화를 주고 받기 때문에 처리 속도에 비교적 민감한 편이기 때문에 tokenizing speed 역시 체크해보았습니다.

Tokenizer Out-of-Vocabulary Tokenizing Speed (sample/sec)
SentencePiece-30000 0.12 % 132632.42
SentencePiece-50000 0.13 % 131353.65
SentencePiece-100000 0.14 % 129670.69
Mecab-30000 0.62 % 47035.73
Mecab-50000 0.20 % 46795.35
Mecab-100000 0.04 % 46085.86
Khaiii - 4444.43

각 tokenizer 별 결과는 위의 표와 같습니다. 우선 SentencePiece는 알려진대로 사전의 크기와 관계없이 아주 낮은 OOV 비율을 보이고 있습니다. 하지만 예상과 달리 Mecab의 OOV 비율도 상당히 낮다는 것을 알 수 있었습니다. 개인적으로 OOV 비율이 낮게 나온 것이 일상대화에 생각보다 많은 단어를 사용되지 않기 때문이지 않을까라고 생각합니다. 띄어쓰기 오류나 오타, 신조어가 많이 있다고 하더라도 일상대화에서 우리가 사용하는 단어는 의외로 아주 다양하지는 않다는 것입니다. 오히려 많이 사용하는 데이터 중 하나인 Wikipedia 데이터는 평소에 잘 안쓰는 표현, 단어들로 서술이 많이 되어있기 때문에 OOV 비율이 더 높았고, 때문에 Mecab과 같은 형태소 분석기 기반의 tokenizer를 사용하면 OOV가 높다고 널리 알려지게 된 것이 아닌가 생각하였습니다. 속도 측면에서는 SentencePiece가 나름 빠르다고 알려진 Mecab보다 2배 이상 빠랐습니다. 반면 Khaiii는 Mecab보다 10배 이상, SentencePiece보다 30배 이상 느린 속도를 보였습니다. 이런 이유로 Khaiii는 이후 Subtask에 대한 실험을 더 진행하지 않았습니다.

결론적으로 SentencePiece가 OOV도 적고 속도도 빠르지만, Mecab도 그에 크게 뒤쳐지지 않는 성능을 보였습니다. 또한 뒤의 4. Discussion 에서 얘기하겠지만 정성적으로 봤을 때 SentencePiece보다 Mecab이 오히려 의미 단위로 더 잘 tokenize하고 있는 것처럼 보이기 때문에 Mecab도 충분히 좋고 Subtask 성능을 봐야 어떤 것이 더 좋은지 판단할 수 있다고 생각하였습니다.

Subtask #1: Language Modeling

첫 번째 subtask는 input token sequence에 대해 다음에 어떤 token이 나올지를 예측하는 문제인 Language Modeling입니다. 가장 대표적인 NLP 테스크이기도 하면서 각각의 token을 예측하기 때문에 tokenizing이 성능에 많은 영향을 미칠 것이라고 보았습니다. 또한 unsupervised learning이 가능하다는 장점이 있기도 하였습니다. Tokenizer의 사전 구축 및 학습에 사용하였던 데이터를 제외한 약 1000만 개의 문장을 통해서 학습을 진행하였습니다.

Tokenizer Perplexity
SentencePiece-30000 252.7571
SentencePiece-50000 325.1923
SentencePiece-100000 460.4182
Mecab-30000 69.8147
Mecab-50000 73.1414
Mecab-100000 74.9851

Language Model의 평가 metric으로 주로 사용하는 perplexity 를 통해 성능을 평가하였습니다. 위의 표와 같은 결과를 얻을 수 있었으며, Mecab이 SentencePiece보다 좋은 성능을 보였습니다. Language Model은 token 하나하나가 의미를 잘 지니고 있을 때 아무래도 좋은 성능을 보일 수 밖에 없습니다. 이런 점에서 Mecab은 형태소 분석을 기반으로 하기 때문에 비교적 확실한 의미 단위의 token이 생성되는데 비해 SentencePiece는 data-driven하게 그저 확률에 기반하여 tokenize를 하기 때문에 token이 이상하게 짤리는 경우가 있었고, 여기서 성능 차이가 생기지 않았나 싶습니다.

Subtask #2: Intent Classification

두 번째 subtask는 Intent Classification입니다. Intent Classification은 language understanding, 특히 dialogue의 발화에 대한 이해에 있어서 매우 중요한 테스크입니다. 입력 문장에 대해 총 45개의 intent class 중 하나로 분류를 하는 문제이며 평가 metric은 accuracy를 사용합니다.

Tokenizer Accuracy
SentencePiece-30000 77.140 %
SentencePiece-50000 76.385 %
SentencePiece-100000 74.995 %
Mecab-30000 76.570 %
Mecab-50000 75.270 %
Mecab-100000 74.735 %

위의 표와 같은 결과를 얻을 수 있었으며, SentencePiece가 Mecab에 비해 약간의 차이로 좀 더 좋은 성능을 보였습니다. 다만 차이가 그리 크지 않고 데이터 크기(약 2MB)가 아주 크지 않기 때문에 단순히 성능만으로 어떤 tokenizer가 더 좋다고 판단하는데는 무리가 있다고 생각합니다. 다만 Language Modeling 테스크에서 안좋은 성능을 보였던 SentencePiece가 classification 테스크에서는 더 좋은 성능을 보였다는 점에서 충분히 한국어 데이터에서도 Subword Unit에 대한 tokenize가 효과가 있다는 것을 알 수 있었습니다.

4. Discussion

Tokenize가 잘 되었는지를 단순히 성능으로만 판단하기에는 무리가 있습니다. 해당 테스크에 우연히 피팅되어 좋은 결과가 나왔을 수 있기 때문입니다. 보다 확실한 판단을 위해서 성능과 함께 tokenize 된 문장을 봤을 때 의미 단위로 잘 분리가 되었는지를 확인할 필요가 있습니다. 아래의 표는 Origin Sentence에 대해 SentencePiece Tokenizer와 Mecab Tokenizer로 tokenize했을 때의 결과입니다.

# Origin Sentence SentencePiece Tokenizer Mecab Tokenizer
1 엄청 빨리끝나는거같네 엄청 V 빨리끝나 V 는거같네 엄청 V 빨리 V 끝나 V 는 V 거 V 같 V 네
2 차량운행할때 불편하겠다 조심해요 차량 V V V 할때 V 불편하겠다 V 조심해요 차량 V 운행 V 할 V 때 V 불편 V 하 V 겠 V 다 V 조심 V 해요
3 출석부르기전에 들어가면 되지않을까 출석 V 부르 V 기전에 V 들어가면 V 되지않을까 출석 V 부르 V V V V 들어가 V 면 V 되 V 지 V 않 V 을까
4 잘못될까무섭고 잘못 V 될 V 까 V V V 고 잘못 V 될까 V 무섭 V 고
5 피스타치오향 약간 새로운맛이야 V 스타 V V V 향 V 약간 V 새로운 V 맛이야 피스타치오 V 향 V 약간 V 새로운 V 맛 V 이 V 야
6 후리스따뜻해? 후리스 V 따뜻해 V ? V 리스 V 따뜻 V 해 V ?
7 응 당직은 칼퇴 응 V 당직 V 은 V 칼퇴 응 V 당직 V 은 V V
8 자꾸자꾸 심쿵하네 자꾸자꾸 V 심쿵 V 하네 자꾸 V 자꾸 V V V 하 V 네
9 칭구들이랑 가죠 뭐 칭구들이랑 V 가죠 V 뭐 V V V 이랑 V 가 V 죠 V 뭐

Origin Sentence는 실제 채팅과 유사하게 띄어쓰기 오류, 오타, 신조어 등이 포함되어 있습니다. 1 ~ 4 번 문장의 경우 띄어쓰기가 올바르게 이루어지지 않은 문장에 대한 경우입니다. Mecab의 경우 형태소 분석을 통해 문법적 구조와 형태소 단위를 잘 잡아낸 것을 보실 수 있습니다. 반면 SentencePiece는 “빨리끝나”, “차량”+”운”+”행”, “부르”+”기전에” 등과 같이 의미 단위로 tokenize를 잘못한다는 것을 확인할 수 있습니다. 5번의 “피스타치오”의 경우 학습 데이터에 많은 빈도로 등장하지 않기 때문에 SentencePiece는 이를 “피”+”스타”+”치”+”오”라고 분리하지만 Mecab은 사전에 “피스타치오”가 있기 때문에 이를 하나의 token으로 묶을 수가 있었습니다. 6 ~ 9 번 문장은 신조어와 오타에 관련된 케이스입니다. “후리스”, “칼퇴”, “심쿵”, “칭구들”은 신조어 및 오타 단어들인데 이 경우 SentencePiece는 올바르게 tokenize를 하였지만, Mecab은 해당 단어들이 사전에 없기 때문에 처리를 하지 못하고 더 잘게 단위를 나누는 모습을 볼 수 있습니다.

5. Conclusion

지금까지 한국어, 채팅 데이터에 대한 특성을 살펴보고 이에 적합한 tokenizer를 실험을 통해 알아보았습니다. 크게 SentencePiece tokenizer와 Mecab tokenizer, 2가지 tokenizer를 살펴보았으며, 둘 다 각자의 장점과 한계를 갖고 있다는 사실을 알 수 있었습니다.

결론적으로 핑퐁은 Dialog-BERT를 위한 tokenizer로 Mecab을 채택 했습니다. 처음에는 그냥 SentencePiece와 같은 최신의 유명한 tokenizer를 쓰면 되지 않을까 하는 생각을 갖고 있었습니다. 하지만 우리가 다루는 데이터의 특성을 파악하고 각 tokenizer의 장단점 이해 및 성능 평가를 통해서 가장 적합한 tokenizer를 찾을 수 있었습니다. Subtask 중 좀 더 비중이 크고 신뢰할만한 Language Modeling 테스크의 성능이 더 좋았으며, 정성적 평가에 있어서도 SentencePiece 보다 의미 단위로 문장을 잘 나누었다고 보았습니다. 다만 신조어나 오타에 취약한 문제가 여전히 남아있습니다. 먼저 신조어 문제를 해결하기 위해서 Mecab의 사용자 사전에 신조어, 이모티콘, “ㅋㅋ”와 같은 자모음 단어 등을 추가하였습니다. 오타의 경우는 현재는 처리하지 않지만 tokenize에 앞서 오타 수정(Typo Correction) 모듈을 추가하여 해결을 해볼 계획입니다.

이렇게 Dialog-BERT 만들기 1, 2편을 통해 normalize와 tokenize 과정을 마쳤습니다! 여기까지가 모델 학습에 앞선 데이터 처리 과정이었고 이제 본격적으로 다음 편에서 Dialog-BERT 학습에 대해 알아보겠습니다.

6. Reference