SentencePiece论文阅读
1. 论文
1.1 基本使用
-
SentencePiece
是用于NLP训练中对句子进行token化的工具,跟语言无关, SentencePiece中包含了byte-pairencoding(BPE)
和unigram language model
两种切分subword的算法。 -
SentencePiece
中包含有四个部分:- Normalizer: 规一化操作,类似Unicode把字符转为统一格式。
- Trainer: 从规一化后的语料中学习subword的切分模型。
- Encoder: 对应预处理时的tokenization操作,把句子转为对应的subword或id。
- Decoder: 对应后处理时的detokenization操作,把subword或id还原为原有句子
示例如下:
% spm_train −−input=data/input.txt
−−model_prefix=spm −−vocab_size=1000
% echo "Hello world." | spm_encode
−−model=spm.model
_He ll o _world .
% echo "Hello world." | spm_encode
−−model=spm.model −−output_format=id
151 88 21 887 6
% echo "_He ll o _world ." |
spm_decode −−model=spm.model
Hello world.
% echo "151 88 21 887 6" |
spm_decode −−model=spm.model
−−input_format=id
Hello world.
1.2 设计
-
SentencePiece中的Encoder和Decoder相互对应,公式定义为
Decode(Encode(Normalize(text))) = Normalize(text)
。也被称为lossless tokenization
。 -
SentencePiece计算高效,BPE每轮需要
O(N^2)
的计算量,但SentencePiece实现时使用了二叉堆(优先队列),使得效率降为了O(N*log(N))
。 -
SentencePiece词id的管理使用
--vocab_size=<size>
, 相比BPE中使用合并次数的定义更通用。内置了一些词id,例如:unknown symbol(), BOS (), EOS ()和padding(). -
SentencePiece默认的规一化采用了
Unicode NFKC
, 在使用spm_train
时指定规一化类型--normalization_rule_name=nfkc
, 也支持自定义规一化操作--normalization_rule_tsv=<file>
, 例如把unicode编码[U+41 U+302 U+300]转为U+1EA64。
-
SentencePiece使用是自包含的,所有的模型参数、规则、状态都被编码到了model文件中
-
提供了即时使用的Python、C++等API,例如:
// c++
#include <sentencepiece_processor.h>
#include <sentencepiece_trainer.h>
SentencePieceTrainer::Train(
"--input=input.txt "
"--model_prefix=spm "
"--vocab_size=1000");
SentencePieceProcessor sp;
sp.Load("spm.model");
std::vector<std::string> pieces;
sp.Encode("Hello world.", &pieces);
std::vector<int> ids;
sp.Encode("Hello world.", &ids);
std::string text;
sp.Decode({151, 88, 21, 887, 6}, &text);
# python
import sentencepiece as spm
params = (’--input=input.txt ’
’--model_prefix=spm ’
’--vocab_size=1000’)
spm.SentencePieceTrainer.Train(params)
sp = spm.SentencePieceProcessor()
sp.Load(’spm.model’)
print(sp.EncodeAsPieces(’Hello world.’))
print(sp.EncodeAsIds(’Hello world.’))
print(sp.DecodeIds([151, 88, 21, 887, 6]))
2. 代码
代码参考:https://github.com/google/sentencepiece