[논문 리뷰] SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing

조민서·2024년 1월 18일
0

NLP

목록 보기
4/8

https://arxiv.org/pdf/1808.06226.pdf
https://github.com/google/sentencepiece

BEiT에서 언어 토큰화 툴로 사용한 SentencePiece이다.
python에 간단히 pip로 다운받아 사용가능 하다.

Abstract

언어에 관계없는 subword tokenizer/detokenizer
subword tokenizer들은 대부분 pre-tokenized된 데이터셋으로부터 학습했다. 하지만 Sentence Piece는 raw sentences로 부터 바로 학습 가능하다.

1. Introduction

띄어쓰기 단위로 대부분 구별 가능한 영어/유럽쪽 언어와 다르게 한/중/일 아시아쪽 언어는 띄어쓰기가 필요없는 부분이 있다.
기존 방식들은 언어마다 규칙을 찾아 하드코딩을 해주는 방식이었지만,

Byte-pair-encoding(BPE), unigram language model을 활용하여 언어에 관계없이, raw-sentences로부터 학습 가능한 구조를 만들었다.

2. System Overview

Normalizer, Trainer, Encoder, Decoder 4개로 이루어져 있다.

Normalizer

Unicode 형태 글자들을 canonical form으로 바꿔준다.

Trainer

normalized corpus로부터 모델을 학습시킨다.
모델 종류는 선택 가능하다.

Encoder

Normalizer를 돌려주고, subword 단위로 토큰화해서 Trainer에 넘겨주는 녀석

Decoder

다시 text로 바꿔준다.

단어를 id-mapping방식을 이용해 encode-decode한다.
Hello world. <-> 151 88 21 887 6
->Encode
<-Decode

3. Library Design

기존 방식은 띄어쓰기가 필요한지, 없는지 구분할 수 없었다.
Hello world. -> [Hello] [world] [.]
면 hello와 world사이엔 띄어쓰기가 들어가야 한다는건 알지만 world와 .사이는 들어가면 안되니까 애매해진다.
다른 언어는 더더욱 그렇다.

Encoder Decoder가 서로의 inverse operation이 되도록
Decode(Encode(Normalize(text))) = Normalize(text)
구현 했고, 이걸 여기서 lossless tokenization이라고 부를 것이다.

띄어쓰기를 _ 로 바꿔서 보는걸 포함해 모든 글자들을 Unicode로 보고 input text를 아래 예시처럼 arbitrary subword 단위로 쪼갠다.

heap구조를 사용해 기존 BPE 알고리즘에서 O(N2)O(N^2)이던 시간을 O(Nlog(N))O(Nlog(N))으로 줄였고,

id mapping 할 때 vocab_size를 학습시 입력으로 받아 그때그때 설정 할 수 있고
Unknown symbol: EOS </s> , padding <pad> 같은 애들은 따로 설정 가능하다.

Normalizing에서 기본적으로는 Unicode NFKC를 사용하는데 커스터마이징도 가능하다.

https://wikidocs.net/86657
위키독스에 한글로 설명된 실습 해보자

IMDB 영화리뷰 데이터셋을 불러와 학습을 위한 txt파일로 저장해 준다.

train_df = pd.read_csv('C:/nlp_datas/IMDB Dataset.csv')
train_df['review']
with open('imdb_review.txt','w',encoding='utf8') as f:
    f.write('\n'.join(train_df['review']))

학습 파라미터로 txt파일명, 생성될 파일 이름, vocab_size, model type등을 지정해 준다.

spm.SentencePieceTrainer.Train(
    '--input=imdb_review.txt --model_prefix=imdb\
    --vocab_size=5000 --model_type=bpe --max_sentence_length=9999')

학습된 모델을 불러와 Encoding Decoding해보자

sp = spm.SentencePieceProcessor()
vocab_file = 'imdb.model'
sp.Load(vocab_file)

Encoding

lines = ['This is very fun','He was crying']
for line in lines:
    print(line)
    print(sp.encode_as_pieces(line))
    print(sp.encode_as_ids(line))
    print()

This is very fun
['▁This', '▁is', '▁very', '▁fun']
[280, 43, 270, 411]

He was crying
['▁He', '▁was', '▁cry', 'ing']
[490, 84, 2625, 20]


Decoding

sp.DecodeIds([280,43,270,411])

'This is very fun'

총정리

쓰기 굉장히 편하고 언어 구별 없다는 점에서 장점이 큰 것 같다.

이제 정수 인코딩 했으니 BEiT에 집어넣을때는 One-hot으로 바꿔서 한건지, 그대로 썼는지 또 알아보자.

0개의 댓글