허니비 honeybee 2023. 1. 2. 14:53

단어에서 subword 란 말 그대로 더 작은 단위의 의미들이다. 예를 들어 "집중" 이라는 한글 단어는 모은다는 뜻이 있는 "집" 그리고 가운데를 뜻하는 "중" 으로 이루어져 있다. 영어의 경우도 Concentrate 는 con/centr/ate 의 세 가지 뜻으로 구성된 단어들이 대부분이다. 

 

따라서 이런 작은 의미 단위로 분절할 수 있다면 학습이 더 유리해지나, 이를 위해서는 subword 를 나눠둔 사전이 필요하다. 오늘은 이 subword 사전을 만들어내기 위한 여러가지 방법들을 알아보고, 간단한 실습을 해보도록 하겠다. 

 

 

 

 

1. Byte Pair Encoding 알고리즘 

 

압축 알고리즘? 이라고 불리는 이 알고리즘은 subword 사전을 생성해내는 알고리즘이다. 학습 코퍼스를 활용해 모델을 학습시킨 후 학습/테스트 코퍼스에 알고리즘을 적용하는 방법이란다. 이 방법을 쓰면 희소성을 효과적으로 낮출 수 있고, Oov도 없앨 수 있다 (예를 들어 아랍 문자는 한국어 학습을 한 모델의 경우 당연히 인식하지 못한다..) 

 

 


 

 

2. BPE Training

 

그럼 모델 작동 원리에 대해 간단히 알아보겠다. 우선 모델이 작동하는 순서는 다음과 같다

 

 

- Training

1. 단어 사전 생성

2. 단어 분절 후 pair 별 빈도 카운트

3. 최빈 pair 를 골라 merge

4. pair 빈도 카운트 업데이트

5. 반복 

 

ex) Apple 의 pair 는

 

(A,p)

(p,p)

(p,l)

(l,e)

.

.

.

등등

 

 

 

이 방식으로 best pair 를 업데이트해줌

 

 

이후에 merge 를 실행하고 나면 최종적으로는 단어들이 어떻게 분절되는지 알 수 있게 됨 


 

 

 

3. 유의사항

 

- 이 알고리즘은 예제에서 알아본 것 처럼 단어 세트의 빈도를 가지고 subword 사전을 만들어주는 거기 때문에 학습 set 과 test set 에서 쓰이는 단어들의 도메인이 어느정도 일치해야 한다는 한계를 가진다. 

 

-입력 데이터가 Oov 에 발생할 경우 UNK 토큰으로 치환해 모델에 입력하자

 

-그러나 이전 단어들을 기반으로 다음 단어를 예측하는 task 에서는 치명적으로 작동할 수 있다 

 

- 대신 모르는 단어지만 subword 분절을 통해 의미를 유추해 볼 수 있다 (약간.. 신조어같은거.. 버카충? 버스카드충전의 줄임말이라고 함... 알고 계셨나요?ㅎ 저의 경우,  ~충 으로 끝나면 보통 비하하는 뜻의 어떤 사람을 뜻하던데.. 이렇게 유추했는데 이 알고리즘을 쓰면 특이하게 쪼개지는 걸 보고 전자로 잘 예측할 수 있었을지도?) 

 

- 그러나! 한국어의 경우에는 띄어쓰기가 제멋대로인 경우가 많기 때문에 바로 subword segmentation 을 적용하는건 위험하다. 따라서 형태소 분석기를 통한 tokenization 을 진행한 후, subword segmentation을 적용하자. 

 


4. 모듈

 

파이썬에서 현재 subword 를 구현가능한 모델 요렇게 두가지가 있는데 두번째거가 구글에서 만든 최신형(?) 모듈이란다

 

 

https://github.com/rsennrich/subword-nmt

 

GitHub - rsennrich/subword-nmt: Unsupervised Word Segmentation for Neural Machine Translation and Text Generation

Unsupervised Word Segmentation for Neural Machine Translation and Text Generation - GitHub - rsennrich/subword-nmt: Unsupervised Word Segmentation for Neural Machine Translation and Text Generation

github.com

 

https://github.com/google/sentencepiece

 

GitHub - google/sentencepiece: Unsupervised text tokenizer for Neural Network-based text generation.

Unsupervised text tokenizer for Neural Network-based text generation. - GitHub - google/sentencepiece: Unsupervised text tokenizer for Neural Network-based text generation.

github.com

 


 

 

 

5. 실습

 

이 코드를 py 파일로 저장해서 파일에 적용시키면 된다 

import sys

STR = '▁'

if __name__ == "__main__":
    ref_fn = sys.argv[1]

    f = open(ref_fn, 'r')

    for ref in f:
        ref_tokens = ref.strip().split(' ')
        input_line = sys.stdin.readline().strip()

        if input_line != "":
            tokens = input_line.split(' ')

            idx = 0
            buf = []

            # We assume that stdin has more tokens than reference input.
            for ref_token in ref_tokens:
                tmp_buf = []

                while idx < len(tokens):
                    if tokens[idx].strip() == '':
                        idx += 1
                        continue

                    tmp_buf += [tokens[idx]]
                    idx += 1

                    if ''.join(tmp_buf) == ref_token:
                        break

                if len(tmp_buf) > 0:
                    buf += [STR + tmp_buf[0].strip()] + tmp_buf[1:]

            sys.stdout.write(' '.join(buf) + '\n')
        else:
            sys.stdout.write('\n')

    f.close()

 

 

 

 

728x90