-
Notifications
You must be signed in to change notification settings - Fork 19
[statistics] sentencepiece and unigram language model
Myungchul Shin edited this page Oct 25, 2020
·
17 revisions
-
paper : Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates
-
git : sentencepiece
-
training algorithm
-
MakeSeedSentencePieces
- suffix array를 이용해서 빈도수 2회 이상 sub-string을 추출
- 모든 character는 전부 포함. default score는 단어(문장)의 빈도수
- sub-string의 character-wise coverage를 default score로 설정
-
RunEStep
-
PopulateNodes
- sentence에 대해 현재 piece를 가지고 lattice 생성
-
PopulateMarginal
- 현재 lattice에서 alpha, beta variable 계산
- token w에 대한 p(w)를 alpha, beta를 이용해서 계산하고
expected
에 저장 - marginal Z 계산
- 이 Z 값은 objective로 누적됨
-
Viterbi
- 현재 lattice에서 best probable segmentation path를 viterbi algorithm으로 찾음
- 이 path의 길이는 ntokens로 누적됨
- 현재 lattice에서 best probable segmentation path를 viterbi algorithm으로 찾음
-
PopulateNodes
-
RunMStep
- E step에서 계산된 expected 값의 전체 sum을 계산.
- token w에 대한 score update
- w.second = Digamma(w.second) - Digamma(sum)
-
PruneSentencePieces
- token w의 loss 순으로 정렬해서 top n%만 남기고 버리는 방식
- token w의 loss는 w가 piece에서 제거되는 경우, likelihood L 값의 변화량으로 정의되는데, 크면 클수록 중요한 token이라고 생각할 수 있음
- 위 과정을 반복하면서, 원하는 사전 사이즈로 줄어들었다면 중지
-
MakeSeedSentencePieces
-
unigram language model
- PopulateMarginal()에서 alpha, beta를 계산하는 방식에서 token들 사이 independent 가정이 들어가 있음. 즉, unigram language model.
- 위와 같은 학습 알고리즘은 HMM(Hidden Markov Model)의 학습 알고리즘과 매우 유사.(transition 제외)
-
encoding
-
spm_export_vocab_main.cc
- 학습된 piece는 vocab 형태로 export, binary model file은 별도 저장
word1 \t score1 word2 \t score2 ...
-
Encode
- model loading이 완료된 이후, 입력된 sentence에 대해서 PopulateNodes() -> Viterbi() -> results
- 즉, tokenizing 할때, lattice를 빌드하고 viterbi algorithm을 적용
- 간단한 테스트 방법
-
spm_export_vocab_main.cc
-
BPE, WordPiece vs SentencePiece
-
BPE
- 모든 단어를 character 단위 symbol로 분리하고, 가장 고빈도 symbol pair를 찾아서 병합하는 과정을 반복
- 병합할때, symbol pair가 rule이 되는 방식
- 실제 BPE 적용할때는 merge rule, vocab 필요
- 입력된 word를 character 단위 symbol로 분리
- merge rule 적용 안될때까지 진행
-
WordPiece
- language model likelihood를 최대하시키도록 학습
- training 자세한 내용은 Japanese and Korean voice search
- BPE와 비슷하지만 vocab 형태의 결과물만 있으면 segmentation 가능
- BPE 학습 과정은 forward 방식, 즉, vocab가 늘어나는 방향. SentencePiece는 큰 vocab에서 원하는 size까지 줄이는 backward 방식.
- BPE는 word를 character 단위로 나눈 다음, merge rule/vocab 참조해서 병합. SentencePiece는 lattice를 만들고 viterbi decoding을 하는 방식.
-
Byte Pair Encoding is Suboptimal for Language Model Pretraining
- unigram lm(sentencepiece에서 사용)이 bpe보다 더 좋다는 논문.
-
BPE
-
BPEmb: Embedding based on BPE
- paper: BPEmb: Tokenization-free Pre-trained Subword Embeddings in 275 Languages
- git: bpemb
- tokenization: sentencepiece에 구현된 BPE를 사용
- embedding training: Glove 사용
-
huggingface's tokenizers
- git: tokenizers
- tokenizer type: ByteLevelBPETokenizer, BPETokenizer, SentencePieceBPETokenizer, BertWordPieceTokenizer
- train script(BertWordPieceTokenizer)
- train test
>>> from tokenizers import BertWordPieceTokenizer
>>> tokenizer = BertWordPieceTokenizer()
>>> tokenizer.train(["input.txt"], vocab_size=20000)
[00:06:50] input.txt █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 1.01GB / 1.01GB
[00:00:06] Tokenize words █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 391777 / 391777
[00:00:06] Count pairs █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 391777 / 391777
[00:00:18] Compute merges █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████ 19647 / 19647
>>> tokenizer.save('./', 'bert-cased-20000')
['./bert-cased-20000-vocab.txt']