728x90

 SentencePiece는 pre-tokenization을 필요로 하지 않는 tokenizer의 하나로, 어떤 언어에도 자유롭게 적용될 수 있고 속도도 굉장히 빠르기 때문에 NLP에서 널리 사용되는 tokenizer이다. 이번 글에서는 SentencePiece가 무엇인지와 함께 이를 어떻게 활용할 수 있는지 에 대한 예시 코드도 함께 살펴보겠다.

SentencePiecie

설명

 SetencePiece는 간단하게 말하면 기존에 존재하던 unigram, BPE와 같은 tokenizer들을 모든 언어에 대해 적용이 가능하도록 generalize하고 약간의 추가적인 기능들을 더해서 구현한 것이다. 특별히 새로운 알고리즘을 제시했다기보다는, 기존의 tokenizer들을 좀 더 사용하기 편하고 성능이 좋게 개선했다고 생각하면 되겠다. SentencePiece는 다음과 같은 특성들을 가진다.

  1. Pre-tokenization을 필요로 하지 않는다. 기존의 tokenizer들은 영어를 기준으로 학습되었다면 영어가 띄어쓰기를 기반으로 해서 단어들이 대부분 분리되기 때문에, 띄어쓰기가 없는 일본어나 중국어와 같은 언어들에는 적용될 수 없다는 한계점을 가지고 있었다. 하지만 SentencePiece는 띄어쓰기를 다른 알파벳 혹은 글자처럼 하나의 character로 취급한다. 그렇기 떄문에 모든 종류의 언어에 대해 general하게 적용이 가능하고, pre-tokenization이 필요하지 않다는 장점을 가진다.
  2. Character-coverage 설정이 가능하다. 영어의 경우에는 알파벳의 개수가 30개 내외로 적기 때문에 괜챃지만, 중국어나 일본어와 같은 문자들의 경우에는 굉장히 많은 종류의 한자를 포함하고 있고, 이에 따라 엄청나게 많은 개수의 character들을 다 다루어야 해서 tokenizer를 학습하는 데에 시간이 오래 걸린다는 한계점을 가진다. 하지만 SentencePiece는 모든 character를 다 고려하는 것이 아닌, 빈도에 따라 상위 99%의 character들만 고려하는 등의 옵션을 주는 것이 가능하다.
  3. Subword generalzation이 가능하다. 우리가 학습한 tokenizer가 항상 완벽하다면 좋겠지만, 이것이 overfitting되어 있을 가능성을 배제할 수는 없다. 그렇기 때문에 SentencePiece에서는 우리가 학습한 tokenizer에서 나올 수 있는 token들만을 사용하는 것이 아니라, 가끔은 다른 token들도 샘플링하면서 사용하여 overfitting하는 것이 가능하다. 
  4. 속도가 빠르다. 직접 구현해보면 알겠지만, 알고리즘이 굉장히 최적화되어 있어서 같은 BPE와 unigram을 실행하더라도 굉장히 빠른 속도를 보여준다.

 이러한 장점들 때문에 SentencePiece는 NLP에서 널리 쓰이는 tokenizer로 자리매김하였다.

예시

 SentencePiece는 구글에서 제공하는 다음 library를 활용해서 쉽게 구현할 수 있다.

학습

우선, 우리가 학습을 원하는 데이터셋에 대해서 다음 코드를 활용해서 spm model과 token들을 학습한다.

import sentencepiece as spm

spm.SentencePieceTrainer.Train('--input=$train_data_path --model_prefix=$output_file_name --vocab_size=$vocab_size --model_type=$model_type --control_symbols=$control_symbols')

위 Train 함수 안에 들어갈 수 있는 중요한 parameter들을 살펴 보면 다음과 같다.

  • input: 우리가 학습해야 하는 training dataset의 경로
  • model_prefix: SentencePiece의 학습 결과 도출되는 결과 파일 (model 파일과 vocab 파일)의 이름
  • vocab_size: 결과로 만들어낼 token의 최종 개수
  • model_type: unigram, bpe, char, word 중 어떤 tokenizer를 활용해서 SentencePiece를 학습할 것인지 선택
  • control_symbols: 하나의 token으로 취급할 substring이 무엇인지 선택. 여기에서 선택된 character는 최종 substring으로 남고, merge되거나 나눠지지 않는다.

이렇게 SentencePiece를 학습하면, model file과 vocab file이 생성된다.

도출된 vocab file 예시

Tokenizing

 이제 위에서 학습한 model을 활용해서 실제 문장을 tokenize할 차례이다. 이를 위해서는 다음과 같은 코드를 활용한다.

sp = spm.SentencePieceProcessor(model_file=$model_file_path)
line = "Hello, I study graph neural networks."
print(sp.encode_as_pieces(line))
print(sp.encode_as_ids(line))

model_file 부분에는 우리가 위에서 만들어낸 model file의 경로를 입력한다. 그리고, 아래의 두 가지 함수는 다음과 같은 기능을 한다.

  • encode_as_pieces: 주어진 문장에 대해 tokenize를 한 결과 도출된 token들을 표시한다. 우리의 예시에서는 ['Hello', '_I', 'study', 'graph', 'neur', 'al', 'net', 'work', 's', '.'] 과 같은 token들이 도출될 것이다.
  • encode_as_ids: 주어진 문장에 대해 tokenize를 한 결과 도출된 token들의 id를 표시한다. 우리의 예시에서는 [13, 52, 464, 1, 67, 758, 76, 456, 234, 5090]과 같은 token id들이 도출될 것이다.

또한, 전체 token들의 개수를 도출하고 싶다면 다음과 같이 도출할 수 있다.

sp.GetPieceSize()

 

 이번 글에서는 SentencePiece가 무엇인지에 대해 알아보았다. SentencePiece가 정확하게 무엇을 하는 것인지 잘 설명되어 있는 글이 없어서 이해를 하기 어려워 약간 고생했기 때문에 이 글을 쓰게 되었다. 이렇게 간단한 NLP 글 시리즈가 끝났다!

References

1. https://github.com/google/sentencepiece

2. Kudo, T., & Richardson, J. (2018). Sentencepiece: A simple and language independent subword tokenizer and detokenizer for neural text processing. arXiv preprint arXiv:1808.06226.

300x250
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기