※ tokenization이란?
토큰화(tokenization)란 문장을 토큰으로 나누는 과정으로 수행대상에 따라 다음 세 방법이 있다.
- 문자
- 단어
- 서브워드
§ 문자 단위 토큰화
- 한글 위주로 표현된 데이터로 언어 모델을 만든다 하자.
한글 음절 수는 1만1172개이므로 알파벳, 숫자 등을 고려 해도 어휘 집합 크기는 최대 1만5000개를 넘기 어렵다.
게다가 해당 언어의 모든 문자를 어휘 집합에 포함하므로 미등록 토큰(unknown token) 문제로부터 자유롭다.
미등록 토큰이란 어휘 집합에 없는 토큰이다. (주로 신조어 등에서 발생)
하지만 문자 단위로 토큰화를 수행할 경우 단점도 있는데, 각 문자 토큰은 의미 있는 단위가 되기 어려운데, 예를 들어 어제와 어미간의 어의 구분이 모호해지는 것처럼 단점이 존재한다.
어제 카페 갔었어 > 어 / 제 / 카 / 페 / 갔 / 었 / 어
어제 카페 갔었는데요 > 어 / 제 / 카 / 페 / 갔 / 었 / 는 / 데 / 요
뿐만 아니라 문자 단위 토큰화는 앞의 단어 단위와 비교할 때 분석 결과인 토큰 시퀀스의 길이가 상대적으로 길어졌음을 확인할 수 있다. 언어 모델에 입력할 토큰 시퀀스가 길면 모델이 해당 문장을 학습하기가 어려워지고 결과적으로 성능이 떨어지게 된다.
§ 단어(어절) 단위 토큰화
- 가장 쉽게 생각해보면 공백으로 분리할 수 있다.
어제 카페 갔었어 > 어제 / 카페 / 갔었어
어제 카페 갔었는데요 > 어제 / 카페 / 갔었는데요
공백으로 분리하면 별도의 토크나이저를 쓰지 않아도 된다는 장점이 있다.
다만, 어휘 집합의 크기가 매우 커질 수 있는데, 갔었어, 갔었는데요 처럼 표현이 살짝만 바뀌어도 모든 경우의 수가 어휘 집합에 포함돼야 하기 때문이다.
만약 학습된 토크나이저를 사용하면 어휘 집합의 크기가 커지는 것을 조금 완화할 수는 있다.
예를 들어 같은 문장을 은전한닢으로 토큰화하면 다음과 같다.
예시가 적어서 효과가 도드라져 보이지는 않지만, 의미 있는 단위로, (예를 들면 갔었) 토큰화해 어휘 집합이 급격하게 커지는 것을 다소 막을 수 있다.
어제 카페 갔었어 > 어제 / 카페 / 갔었 / 어
어제 카페 갔었는데요 > 어제 / 카페 / 갔었 / 는데요
그렇지만 위 같은 토크나이저를 사용하더라도 어휘 집합 크기가 지나치게 커지는 것은 막기 어려운데, 보통 언어 하나로 모델을 구축할 때 어휘 집합 크기는 10만 개를 훌쩍 넘는 경우가 다반사이기에 어휘 집합 크기가 커지면 그만큼 모델 학습이 어려워질 수 있다.
§ 서브워드 단위 토큰화
- 단위 토큰화는 단어와 문자 단위 토큰화의 중간에 있는 형태로. 둘의 장점만을 취한 형태이다.
어휘 집합 크기가 지나치게 커지지 않으면서도 미등록 토큰 문제를 피하고,
분석된 토큰 시퀀스가 너무 길어지지 않게 한다.
- 대표적인 서브워드 단위 토큰화 기법이라면 바이트 페어 인코딩을 들 수 있는데 아래에서 소개하겠다.
※ Byte Pair Encoding Algorithm
- BPE는 정보를 압축하는 알고리즘으로 원래 제안된 것으로 데이터에서 최빈문자열을 병합해 압축하는 기법이다.
최근에는 자연어 처리모델에서 쓰이는 토큰화 기법이다.
GPT 모델은 BPE기법으로 토큰화를 수행
BERT모델은 BPE와 유사한 워드피스(wordpiece)를 토크나이저로 사용
예를 들어 다음과 같은 데이터가 있다고 가정하자.
- aaabdaaabac
BPE는 데이터에 등장한 글자(a, b, c, d)를 초기 사전으로 구성하며, 연속된 두 글자를 한 글자로 병합한다.
이 문자열에선 aa가 가장 많이 나타났으므로 이를 Z로 병합(치환)하면 다음과 같이 압축할 수 있다.
- ZabdZabac
이 문자열은 한번 더 압축 가능한데, ab가 가장 많이 나타났으므로 이를 Y로 병합(치환)한다.
- ZYdZYac
물론 ab 대신 Za를 병합할 수도 있지만 둘의 빈도수가 2로 같으므로 알파벳 순으로 앞선 ab를 먼저 병합한다.
ZY 역시 X로 병합할 수 있습니다. 이미 병합된 문자열 역시 한 번 더 병합할 수 있다는 얘기로 다음과 같다.
- XdXac
※ BPE 어휘집합 구축하기.
1. pre-tokenize 진행 (말뭉치를 준비 후 모든 문장을 공백으로 나눠줌. 물론 다른 기준으로 나눌 수도 있음)
2. pre-tokenize 진행 후 그 빈도를 모두 세어 초기 어휘 집합을 구한다.
3. 위의 어휘집합을 바이그램 쌍(토큰을 2개씩 묶어 나열)으로 만들고 바이그램 쌍을 합친다.
4. 가장 많이 등장한 바이그램쌍을 합쳐 집합에 추가 (위를 예로 들면 u, g를 합친 ug를 바이그램에 추가)
>> b / g / h / n / p / s / u / ug
이후 계속 사용자가 정한 크기 전까지 반복해서 진행.
5. 입력이 들어오면 입력을 문자단위로 분리 후 병합의 우선순위(by 빈도)에 따라 merge 진행.
만약 input으로 mug가 들어온다면?
따라서 출력은 다음과 같이 <unk>, ug로 나오며 <unk>는 unkown token(미등록 토큰)을 의미.
※ WordPiece.
BPE와 비슷하지만 빈도를 기준으로 merge를 진행하는 BPE와는 달리
Wordpiece는 likelihood를 기준으로 likelihood가 높은 쌍을 merge한다.
병합후보 A, B에 대해 워드피스의 병합기준 식은 다음과 같다.
이 식의 값이 높은 값을 기준으로 병합을 진행하며
n은 전체 글자수를 가리키고 a, b, ab는 각각의 문자열의 빈도수를 뜻한다.
즉, a,b는 각각의 문자가 등장할 확률이고 ab는 ab가 연이어 등장할 확률이다.
'A.I > 자연어 처리' 카테고리의 다른 글
self.NLP(3-2). Transformer with pytorch (0) | 2023.06.30 |
---|---|
self.NLP(3-1). Pytorch 기본설명. (0) | 2023.06.29 |
self.NLP(3). Transformer & etc. (0) | 2023.06.29 |
self.NLP(2). RNN의 한계와 Attention Mechanism (0) | 2023.06.29 |
self.NLP(0). 자연어 처리란? (0) | 2022.12.28 |