카테고리 없음

LLM tokenizer조사

codarchive 2023. 11. 27. 01:40

Tokenizer의 종류

Byte Pair Encoding (BPE):

서브워드 토크나이저 (한 단어를 더 작은 단위로 나누는 토크나이저)중 하나. 압축 알고리즘에서 파생된 토크나이저로, 연속적으로 가장 많이 등장한 글자의 쌍을 찾아서 하나의 글자로 병합하는 방식을 수행하는 방법.
예시로 어떤 텍스트에서 아래와 같이 {단어:빈도수}와 같이 모든 단어의 횟수를 세어 딕셔너리를 만들었다고 가정하자.

low : 5, lower : 2, newest : 6, widest : 3

그후 처음에는 글자(byte)로 구성된 vocabulary로 초기화를 한다.

# vocabulary
l, o, w, e, r, n, s, t, i, d

단어에서 앞뒤로 붙어나오는 byte pair의 갯수를 세어본다. 예를들면, low에서 (l,o),(o,w)와 같은 pair를 셀 수 있다. 그렇게 세어보면, (e,s) pair가 9회로 빈도수가 가장 높으니 (s,t쌍도 같은 9회이지만 먼저 나온 e,s쌍을 우선한다고 치자) vocabulary가 아래와 같이 업데이트 된다.

l, o, w, e, r, n, s, t, i, d, es

다시 위의 vocabulary의 pair를 단어에서 세어보면, (es, t)쌍이 9회로 가장 빈도수가 높기때문에, 다시 vocabulary가 아래와 같이 업데이트 된다.

l, o, w, e, r, n, s, t, i, d, es, est

이러한 식으로 n회 (사용자지정) 반복하면 빈도수가 가장 높은 pair가 계속 합쳐지며 vocabulary (토큰들의 집합)이 업데이트된다.
(참조:https://wikidocs.net/22592)

Wordpiece tokenization:

BPE와 아주 흡사하지만 합치는 기준이 조금 다름. wordpiece 토크나이저를 이용하여 구글이 BERT를 훈련하였다고 함. BPE는 pair의 빈도수를 세어 많으면 합치는데, wordpiece는 아래와 같은 스코어에 기준하여 합침.

예를 들어, (un, able)이라는 쌍의 빈도수가 높다고 하더라도, un과 able 각각의 빈도수가 아주 높다면 score가 낮아져서 합치지 않을 수 있음. 따라서 각각의 voca 출현 횟수에 비한 pair의 출현 횟수가 높은 비율이여야 합쳐짐.
(참조:https://huggingface.co/learn/nlp-course/chapter6/6?fw=pt, https://arxiv.org/pdf/1609.08144.pdf)

Unigram tokenization:

위의 두 tokenizer와 같이 subword tokenizer로서, subword의 probability를 고려하여 단어의 끊는 지점을 결정하는 방법이다. 문자로는 모호하니 예시를 살펴보면,

("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)

위와 같이 텍스트의 dictionary (단어수,빈도)가 모였다고 가정하자.
위의 단어들의 가능한 모든 substring을 나타내면 아래와 같다.

["h", "u", "g", "hu", "ug", "p", "pu", "n", "un", "b", "bu", "s", "hug", "gs", "ugs"]

(참고로 substring은 단어 전체를 빼고 연속하는 단어내의 부분집합들을 이야기한다. 예를들어, hug의 substring은 [’h’,’u’,’g’,’hu’,’ug’]이고, hugs의 substring은 [’h’,’u’,’g’,’s’,’hu’,’ug’,’gs’,’hug’,’ugs’]이다.)
위의 substring의 빈도수를 다시 세어서 (substring:빈도수)로 나타내면 아래와 같다.

("h", 15) ("u", 36) ("g", 20) ("hu", 15) ("ug", 20) ("p", 17) ("pu", 17) ("n", 16)
("un", 16) ("b", 4) ("bu", 4) ("s", 5) ("hug", 15) ("gs", 5) ("ugs", 5)

그럼 위의 (substring:빈도수)들을 모두 나열했으니, 확률을 구할 모든 준비가 된 것이다.
단어장의 pug는 어떠한 substring을 subword로 결정해야할지 구해보자.

위는 pug단어를 p,u,g라고 나눈다고 가정했을 때 확률이다.

위는 pug단어를 pu,g로 나눈다고 가정했을 때 확률이다.
단어 pug는 (p,u,g), (pu,g), (p,ug) 이렇게 세가지로 나눌 수 있는데 이 중에서 어떻게 나누는게 가장 합리적일까? (기대값이 높을까?)

["p", "u", "g"] : 0.000132
["p", "ug"] : 0.000805
["pu", "g"] : 0.000805

위와 같이 확률을 구해본 결과를 보면 (pu,g) 혹은 (p,ug) 로 나누는게 (p,u,g)로 나누는 것보다 합리적이라는 결론이 난다. 이렇게 단어들에 대하여 substring의 확률값을 모두 구해서 가장 높은 확률값의 substring을 subword로 확정짓는 것을 unigram tokenizer이다.

센텐스피스(sentencepiece)

위와 별개의 토크나이저 알고리즘이 아니라, 위의 BPE, unigram algorithm을 내장한 토크나이저. 다만 띄어쓰기를 모든 언어권에서 seperator로 쓰는게 아니기 때문에 (ex.일본어) 이러한 문제를 해결하기 위하여 문장에도 pretokenizer를 넣은 후에 위의 알고리즘을 통해 토크나이징을 실행한다고 함. 다만 pretokenizing은 어떻게 해결한지 조사 필요.


한국어 LLM에 들어간 tokenizer

  • polyglot-ko에는 vocabulary size를 30003개로 정한 morpheme-aware BPE를 사용하였다고 한다. 여기서 morpheme (형태소)의 분석은 MeCab을 통해 하였다고 쓰여있는데, 이러한 Mecab의 vocab을 그대로 tokenizer의 vocab으로 쓴 것인지 Mecab을 pretokenizer로 사용한 것인지 이 부분은 불분명.
  • polyglot-ko에 tokenizer.json파일이 형태를 보아 token vocabulary인듯한데, 인코딩을 여러방식으로 바꿔서 설정해보아도 깨져나와서 (한글 형태가 아님) 파악이 어려움.
  • 다만 같은 프로젝트의 연장선인 https://github.com/Beomi/KoAlpaca 의 토크나이저 형태를 inference예시 파일에서 확인해보면, llamatokenizer를 쓰고 있는데 이는 BPE 방식으로 형성된 vocabulary를 갖고 있다. 해당 vocabulary파일을 한국어가 깨지지 않는 버전으로 확보해보려 했으나 찾지 못함.
  • 다만 논문에서와 같이 30003개의 voca갯수를 가지고 있는 것으로 보아 MeCab으로 tokenizing을 실시한 것으로 생각됨.