[NLP] Tokenizer

hyunsooo·2021년 7월 29일
0

컴퓨터가 자연어(한국어,영어...)를 학습할 수 있도록 수치화하는 것을 워드 임베딩(word embedding)이라고 한다. word embedding을 수행하기 전에 어떠한 말뭉치데이터(Corpus)들을 다양한 기준을 가지고 분류 하는 행위를 토큰화(Tokenization)라고 하며 토큰화를 해주는 것을 Tokenizer라고 한다.

Tokenizaion

- character level

character 단위로 토큰화를 하는 방법은 한국어에서 가,나,다...와 같이 한 글자단위로 토큰화를 하거나, ㄱ,ㄴ... / ㅏ,ㅑ.. 와 같이 자음,모음으로 토큰화 방법을 말한다.

중국어(한자)의 경우는 characeter level로 토큰화를 해도 한 글자가 고유한 의미를 가지지만
한국어의 경우, 한 글자가 어떤 것을 의미하는 경우는 극히 드물고 고유한 의미를 표현하는 것은 아니기 때문에 한국어에 적용하는것은 적절하지 않은 방식이다.

- space(word) level

한 문장내에서 띄어쓰기를 기준으로 토큰화를 하는 방식이다.
영어의 경우 공백을 기준으로 토큰화를 해도 단어별로 토큰화가 되지만( 몇몇 예외는 존재 ), 한국어의 경우 조사나 어미와 같은 다양한 문장구조가 존재하기 때문에 문제가 발생한다. 예를 들어, ( 컴퓨터를, 컴퓨터가, 컴퓨터는 ) 모두 컴퓨터를 의미하지만 뒤에 붙는 조사때문에 각각 다른 단어로 저장되기 때문에 학습이 잘 되지 않는 상황이 발생하기도 한다. "컴퓨터에는"이라는 단어가 등장하면 기계가 모르는 단어이기 때문에 OOV ( Out - Of - Vocabulary ) 문제가 발생한다. 또한 큰 말뭉치를 word 단위로 분절하면 매우 큰 vocab을 사용해야 하기 때문에 메모리 문제를 야기할 수 있다.

- subword level

subword단위로 토큰화를 하는 것은 하나의 단어를 더 작은 단위의 의미있는 여러 서브워드로 나누는 작업이다. 이 과정으로 OOV 문제와 희귀 단어, 신조어와 같은 문제를 완화 할 수 있다. " 자주 등장하는 단어는 그대로 두고, 자주 등장하지 않는 단어는 의미 있는 서브 워드 토큰들로 분절한다. "
( 컴퓨터를, 컴퓨터가, 컴퓨터는, 노트북에는 ) 이라는 단어는
[ 컴퓨터 + 를 , 컴퓨터 + 가 , 컴퓨터 + 는, 노트북 + 에는 ] 과 같이 subword로 분리한다.

( 컴퓨터, 를, 가, 는, 노트북, 에는 )과 같이 사전이 만들어졌을 경우,
space level에서 생긴 문제인 "컴퓨터에는"이 등장할 때, 학습한 vocabulary안에 컴퓨터와 에는이 존재하기 때문에 문제를 해결할 수 있다.

- vocab

위에서 등장하는 vocab은 토큰화한 단어들을 모아둔 사전이라고 볼 수 있다.

- special token

문장의 시작[SOS]이나 끝[EOS], 마스킹된 위치[MASK], 두개의 문장을 구분하는 토큰 [SEP] 등을 의미한다.



BPE ( Byte Pair Encoding )

BPE알고리즘은 데이터 압축 알고리즘으로 byte단위의 pair(쌍)을 묶어서 데이터를 압축하는 과정이다. 이 알고리즘을 자연어 처리 분야에 적용하여 토큰화하는 방법으로 사용되고 있다.

  • 기존의 BPE 방법
aaabdaaabac 라는 문자열이 있을때 바이트( 문자열에서는 글자로 이해 )단위의 쌍을
하나의 바이트(글자)로 바꿔주는 과정이다. 기본적으로 가장 자주 등장하고 있는 
글자의 쌍 ( byte pair )를 찾아 압축한다.

1. aa의 글자쌍 (byte pair)이 가장 빈도수가 높다.

aaabdaaabac

aa를 Z로 치환하여

ZabdZabac로 

2. ab 글자쌍이 가장 빈도수가 높다.

ab를 Y로 치환하여

ZYdZYac

3. ZY가 가장 빈도수가 높다.

ZY를 X로 치환하여

XdXac

4. 더 이상 병합할 쌍이 없으므로 최종 결과가 된다.
  • 자연어 처리에 적용한 BPE

BPE는 훈련데이터를 단어 단위로 나누는 Pre - tokenize과정을 거쳐야한다.
이런 Pre-tokenize는 단순하게 공백 단위로 할 수 있고, 다양한 규칙기반으로 할 수 있다.

  1. 모든 단어들을 글자(chracter)단위로 분리한다.

    low , lower , newest , widest 라는 4개의 단어가 존재할 때 ( 빈도수 포함 )

    dic = {
    l o w : 5,
    l o w e r : 2,
    n e w e s t : 6,
    w i d e s t : 3
    }

    이 때의 vocab(사전)의 집합은 아래처럼 구성되어 진다.

    vocab = { l, o, w , e , r, n, w, s, t, i, d }

  1. BPE 알고리즘을 적용하는데 몇 회를 반복할 것인지는 사용자가 정한다. ( 10회라고 가정 )
  • 반복1회 )

    • 위의 dictionary에서 가장 빈도수가 높은 글자쌍 ( 유니그램쌍 )은 (e,s)이다.

      e와s를 -> es로 통합

      dic = {
      l o w : 5,
      l o w e r : 2,
      n e w es t : 6,
      w i d es t : 3
      }

      vocab = { l, o, w , e , r, n, w, s, t, i, d , es }

  • 반복2회 )

    - 위의 dict에서 가장 빈도수가 높은 유니그램쌍은 (es,t)이다.
    es와 t -> est로 통합

    dic = {
    l o w : 5,
    l o w e r : 2,
    n e w est : 6,
    w i d est : 3
    }

    vocab = { l, o, w , e , r, n, w, s, t, i, d , es , est }

    .
    .
    .

  • 위와 같은 과정을 사용자가 정한 횟수만큼 진행한다.

  • 반복10회 )

    dic = {
    low : 5,
    low e r : 2,
    newest : 6,
    widest : 3
    }

    vocab = { l, o, w , e , r, n, w, s, t, i, d , es , est, lo, low, ne, new, newest, wi, wid, widest }

    새로운 단어 " lowest"가 등장하면 lowest는 vocab안에 있는 low + est로 분리되어지고,
    OOV 문제에서 완화될 수 있다.



실제 코드에서의 단어 집합은

단어맨 끝에 /w의 특수문자가 붙어 있고 저 특수문자도 분리될 때 똑같이 사용된다.



Wordpiece Model

WPM는 BPE을 변형한 알고리즘이다. wordpiece는 BPE와 마찬가지로 vocab을 코퍼스 내의 등장한 char로 구성을 시작으로 사용자가 지정한 회수만큼 병합하는 방식으로 훈련된다. 가장 큰 차이 점은 BPE는 빈도수에 기반하여 가장 많이 등장한 쌍을 병합하는 것과 달리, 병합되었을 때 코퍼스의 우도(Likelihood,가능도)를 가장 높이는 쌍을 병합한다. 즉 주어진 데이터에 따라 모델이 달라진다는 의미이다.
wordpiece는 BPE와 마찬가지로 vocab을 코퍼스 내의 등장한 char로 구성을 시작으로 사용자가 지정한 회수만큼 병합하는 방식으로 훈련된다.

우도

Tip
확률함수는 이미 알고있는 모수(고정됨)를 확률함수를 통해 확률을 얻는 것이다.
예를들어) 동전을 10번 던져서 앞면이 7번 나올 확률을 구하면
10C7 0.5^7 0.5^3 으로 구한다. 여기서 중요한것은 모수(앞면이 나올 확률, 0.5)를 우리가 이미 알고있고 고정해 놓고 계산을 한 것이다. ( 모수는 모집단을 대표하는 값이라고 생각한다. )

우도는 가능도를 얻는 것으로, 데이터에서 우도함수를 통해 데이터를 가장 잘표현하는 값 ! 즉,모수를 구하는 것이다.
예를들어) 동전던지기 처럼 이항분포에서의 우도함수는 확률질량함수와 같다. 하지만 시행횟수와 성공횟수를 10과 7로 고정해 놓고 모수 p를 0.1부터 1사이의 아무 값을 넣고 계산하여 가장 높은 모수를 얻는다. n,x를 10과7로 고정해놓은 상태에서의 p값이 가장 큰 경우는 p=0.7, 즉 앞면이 나올 확률이 0.5일때보다 0.7일때가 이 데이터를 가장 잘 성명한다고 볼 수 있다.
이렇게 우도함수를 이용해 모수를 추정하는 방식을 최대우도 추정법이라고 한다.
우도함수는 확률함수가 아니므로 총합이 1이되지 않는 것에 주의한다.

Unigram

Unigram은 BPE, WPM과 달리 모든 Pre-Tokenized와 subword에서 점차 vocab을 줄여나가는 방식으로 진행된다. Unigram은 sentencepiece에서 자주 사용되는 알고리즘이다.

Unigram은 주어진 corpus와 현재 vocab에 대한 Loss를 측정하고 각각의 subword에 대해 해당 subword가 corpus에서 제거되었을 때, loss가 얼마나 증가하는지를 측정한다.

결과적으로 loss를 가장 조금 증가시키는 p개의 토큰을 제거한다.
( p는 보통 전체 사전 크기의 10~20%로 설정한다. )

Unigram은 해당 과정을 사용자가 원하는 크기를 지니게 될 때 까지 반복하며 기본 char들은 사전에서 제거되지 않고 유지되어야 한다.

BPE나 WPM은 토큰의 우선 순위대로 토크나이즈를 실행하기 때문에 항상 똑같은 토큰을 얻을 수 있는데 Unigram은 vocab을 구축할 때, 각 토큰의 확률 값들을 함께 저장하기 때문에 최적의 조합을 선택할 수 있다.

vocab = [ 'a' : 확률 , 'b' : 확률 , 'p' : 확률, 'l' : 확률, 'e' : 확률, 'ap' :확률 , 'app' : 확률 ]

"apple "를 토큰화하는 방법은 [ 'a', 'p' ,'p', 'l', 'e' ] , [ 'ap', 'p' , 'l', 'e' ] , [ 'app', 'l', 'e' ] 와 같이 나눠질 수 있고 이 중 가장 높은 확률을 지니는 조합을 선택한다.

확률을 가짐으로 훈련할 때 loss를 정의하는 값이 될 수 있다.

SentencePiece

위의 방법들과 달리 SentencePiece는 사전 토큰화 ( Pre-tokenized )없이 단어 토큰화를 수행한다.

모든 언어들은 공백을 기준으로 나눌 수 있는게 아니기 때문에 위의 방법들은 어느 언어에서나 적용할 수 없었고 이 문제를 해결하기 위해 소개된 방법이 SentencePiece이다.

공백을 underbar "_"로 표현하고 이 공백을 포함한 모든 char를 활용하여, BPE 또는 Unigram을 적용하여 사전을 구축한다.

"_"캐릭터를 사용하는 이유는 해당 스페셜 토큰 덕분에 나눠진 텍스트를 병합하는 과정이 쉬워지기 때문이다.

"풋사과가 먹고 싶다. ---> "_풋사과가 _먹고 _싶다." ---> "_풋, 사과,가, _먹고 , _싶다"
반대로 병합할 때는 모든 토큰을 붙여준 후, _토큰만 공백으로 바꿔주면 된다.

profile
지식 공유

0개의 댓글