文章提出了一种子词分词方法,针对包括中文、日文、各种拉丁语等不同语言都可以进行通用的无监督学习。文章提出的分词方法SentencePiece
SentencePiece包含4个组成部分
已有的分词器针对以下场景往往需要手动添加规则:如将"Hello World.“分割成[Hello][World][.]之后,如果复原会在标点符号之前增加一个空格:“Hello World .”,这就造成了detokenization的不可逆性。针对中文、日文的句子,同一句话之间没有空格,detokenizer也很难对分割后的序列还原。为此文章将Decoder按照如下方式学习,使得Decoder为一个可逆的过程: D e c o d e r ( E n c o d e r ( N o r m a l i z e ( T e x t ) ) ) = N o r m a l i z e ( T e x t ) Decoder(Encoder(Normalize(Text))) = Normalize(Text) Decoder(Encoder(Normalize(Text)))=Normalize(Text),文章称此为Lossless Tokenization。Lossless Tokenization会将输入视为Unicode字符(包含空格),然后先将句子分割成随机的子词序列,其中由”_“代替空格,如果单个单词被拆分,则非首字母的单词要以@@开头标记,如"world"如被分割则需标记为"wor"和”@@ld"。detokenization阶段我们只需通过detok = ''.join(tokens.replace('_', ' ‘))
还原至原始句子。
文章还提出了一些API的其它功能,这里笔者就不一一细述。
文章的github里面附了一个超详细的官方介绍笔记本SentencePiece的python全部操作示例代码链接,感兴趣的读者可以去详细阅读。这里笔者附送一个中文/英文示例(很多网上找到的都跑不通,这里亲测有效)
!wget https://raw.githubusercontent.com/google/sentencepiece/master/data/botchan.txt
import sentencepiece as spm # 测过跑不通
由于上述链接失效,笔者自己在代码的文件夹下构建了一个同名的txt文件(测过其它名字会报错,应该是做了一些处理吧,由于源码是C++也没怎么看),然后在里面粘贴一些中文/英文文本即可。
import os
import sentencepiece as spm
# kwargs
spm.SentencePieceTrainer.train(
sentence_reader=open(os.path.join(os.getcwd(), 'botchan.txt'), 'r'),
model_prefix='my', vocab_size=900)
上述传参方法等价于下述指令字符执行代码
# 传入指令字符串
spm.SentencePieceTrainer.train(
'--input=botchan.txt --model_prefix=m --vocab_size=900')
笔者随便测试了几百行中文文本,如此小的样本分词效果竟然真得很可以!
文章提出了基于Lossless Tokenization的分词器SentencePiece,不同于其它现存的分词器,SentencePiece无需指定语言,一套系统通吃!而且操作简单,效果很好(我宣布SentencePiece即将成为笔者下一个project的工具!)。
SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing
SentencePiece的python全部操作示例代码链接