19.06.07
본 글은 https://wikidocs.net/book/2155을 참고하여 작성되었음을 밝힙니다.
핵심키워드
- 단어 분리(Subword Segmentation)
- OOV(Out-Of-Vocabulary)
- UNK(Unkown Word)
- BPE(Byte Pair Encoding)
단어 분리(Subword Segmentation)
언어 모델(Language Model), 기계 번역(Neural Machine Translation) 등. 결국 머신 러닝을 이용한 자연어 처리의 목표는 기계가 사람만큼, 또는 사람 이상의 성능을 내는 것을 기대하는 것이다. 그런데 아무리 많은 단어들을 기계에게 학습시켜도, 기계에게 세상의 모든 단어를 다 알려줄 수는 없다. 그리고 아직 배운 적이 없는 단어 앞에서 기계는 대처할 수 없다. 게다가 사실 기계에게 많은 단어를 알려주려고 하면 할 수록, 즉 기계가 학습하는 단어가 많으면 많을수록 그 만큼 계산 비용도 늘어나는 부담이 있다.
단어 분리(Subword Segmentation)는 기계가 아직 배운 적이 없는 단어더라도 마치 배운 것처럼 대처할 수 있도록 도와주는 기법 중 하나이다. 이 방법은 이제 기계 번역 등에서 주요 전처리로 사용되고 있다.
뒤에서 예제로도 자주 언급되겠지만, 기계가 알고있는 단어들의 집합을 단어 집합(Vocabulary)이라고 한다. 그리고 기계가 미처 배우지 못하여 기계가 모르는 단어들을 OOV(Out-Of-Vocabulary) 또는 UNK(Unkown Word)라고 한다.
즉, 기계가 모르는 단어에 대처하지 못하는 상황이 오면 이 상황을 OOV 문제라고 언급한다. 지금부터 단어 분리를 통해 OOV 문제를 해결할 수 있는 이유와, 대표적인 단어 분리 방법인 BPE(Byte Pair Encoding) 알고리즘에 대해서 학습한다.
1. 단어 분리(Subword Segmentation)가 의미 있는 이유
단어 분리(Subword segmentation) 작업은 하나의 단어는 의미있는 여러 단어들의 조합으로 구성된 경우가 많기 때문에, 단어를 여러 단어로 분리해보겠다는 전처리 작업이다. 실제로, 언어의 특성에 따라 영어권 언어나 한국어는 단어 분리를 시도했을 때 어느정도 의미있는 단위로 나누는 것이 가능하다.
2. WPM(Word Piece Model)
WPM(Word Piece Model)은 하나의 단어를 내부 단어(Subword Unit)들로 분리하는 단어 분리 모델이다.
실제로 2016년에 구글이 낸 논문(Google’s Neural Machine Translation System : Bridging the Gap between Human and Machine Translation [Wo at el.2016])에서 구글은 자신들의 구글 번역기에서 WPM이 어떻게 수행되는지에 대해서 기술했다.
WPM을 수행하기 이전의 문장:
Jet makers feud over seat width with big orders at stake
WPM을 수행한 결과(wordpieces) :
_J et _makers _fe ud _over _seat _width _with _big _orders _at _stake
Jet는 J와 et로 나누어졌으며, feud는 fe와 ud로 나누어진 것을 볼 수 있다. WPM은 입력 문장에서 기존에 존재하던 띄어쓰기는 언더바로 치환하고, 단어는 내부단어(subword)로 통계에 기반하여 띄어쓰기로 분리한다.
기존의 띄어쓰기를 언더바로 치환하는 이유는 차후 다시 문장 복원을 위한 장치이다. WPM의 결과로 나온 문장을 보면, 기존에 없던 띄어쓰기가 추가되어 내부 단어(subwords)들을 구분하는 구분자 역할을 하고 있으므로 본래의 띄어쓰기를 언더바로 치환해놓지 않으면, 기존 문장으로 복원할 수가 없다.
WPM이 수행된 결과로부터 다시 수행 전의 결과로 돌리는 방법은 현재 있는 띄어쓰기를 전부 삭제하여 내부 단어들을 다시 하나의 단어로 연결시키고, 언더바를 다시 띄어쓰기로 바꾸면 된다.
3. BPE(Byte Pair Encoding) 알고리즘
구글의 WPM에는 BPE(Byte Pair Encoding) 알고리즘이 사용되었다. BPE 알고리즘 자체는 1994년에 제안된 알고리즘이지만 Neural Machine Translation of Rare Word with Subword Units [Sennrich at el.2015]라는 논문에서 최초로 기계 번역을 위해 BPE 알고리즘을 통해 단어 분리(Subword Segmentation)를 사용할 것을 제안했다. 그리고 현재는 자연어 처리를 위한 주요 전처리 방법으로 사용되고 있다.
아래 코드는 해당 논문에서 예제로서 사용된 BPE 알고리즘의 코드이다.
import re, collectionsdef get_stats(vocab):
pairs = collections.defaultdict(int)
for word, freq in vocab.items():
symbols = word.split()
for i in range(len(symbols)-1):
pairs[symbols[i],symbols[i+1]] += freq
return pairsdef merge_vocab(pair, v_in):
v_out = {}
bigram = re.escape(' '.join(pair))
p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
for word in v_in:
w_out = p.sub(''.join(pair), word)
v_out[w_out] = v_in[word]
return v_outvocab = {'l o w </w>' : 5,
'l o w e r </w>' : 2,
'n e w e s t </w>':6,
'w i d e s t </w>':3
}num_merges = 10for i in range(num_merges):
print(vocab)
pairs = get_stats(vocab)
best = max(pairs, key=pairs.get)
vocab = merge_vocab(best, vocab)
print('best :', best)
print('')#### 출력 결과 ####
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}
best : ('e', 's')
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w es t </w>': 6, 'w i d es t </w>': 3}
best : ('es', 't')
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est </w>': 6, 'w i d est </w>': 3}
best : ('est', '</w>')
{'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w est</w>': 6, 'w i d est</w>': 3}
best : ('l', 'o')
{'lo w </w>': 5, 'lo w e r </w>': 2, 'n e w est</w>': 6, 'w i d est</w>': 3}
best : ('lo', 'w')
{'low </w>': 5, 'low e r </w>': 2, 'n e w est</w>': 6, 'w i d est</w>': 3}
best : ('n', 'e')
{'low </w>': 5, 'low e r </w>': 2, 'ne w est</w>': 6, 'w i d est</w>': 3}
best : ('ne', 'w')
{'low </w>': 5, 'low e r </w>': 2, 'new est</w>': 6, 'w i d est</w>': 3}
best : ('new', 'est</w>')
{'low </w>': 5, 'low e r </w>': 2, 'newest</w>': 6, 'w i d est</w>': 3}
best : ('low', '</w>')
{'low</w>': 5, 'low e r </w>': 2, 'newest</w>': 6, 'w i d est</w>': 3}
best : ('w', 'i')
BPE 알고리즘의 기본 원리는 가장 많이 등장한 문자열에 대하여 병합하는 작업을 반복하는 데, 원하는 단어 집합의 크기. 즉, 단어의 갯수가 될 때까지 이 작업을 반복한다.