作者:Taku Kudo, John Richardson
时间:2018
一、完整代码
这里我们使用python代码进行实现
# 完整代码在这里 import tensorflow as tf import keras_nlp inputs = tf.data.Dataset.from_tensor_slices(["Drifting Along"]) proto = keras_nlp.tokenizers.compute_sentence_piece_proto(inputs, vocabulary_size=15, lowercase=True) tokenizer = keras_nlp.tokenizers.SentencePieceTokenizer(proto=proto) outputs = inputs.map(tokenizer) for output in outputs: print(output) # tf.Tensor([ 4 8 12 5 9 14 5 6 13 4 7 10 11 6 13], shape=(15,), dtype=int32)
二、论文解读
SentencePiece是一个用于基于文本生成的无监督文本分词器,基本上结合了所有的分词算法于一身,是一个端到端的工具,并且不依赖于语言;也就是说无论什么语言丢进去就能做分词处理;
2.1 问题
- 不同语言需要进行不同的预处理
一般来说,BPE
和Unigram
在处理tokenization的时候都需要文本已经经过了一次切割,以英文为例子:how are you
应该被切割成了['how', 'are', 'you']
;只有这样我们才能进行考虑单词的内部构造,因为BPE
和Unigram
都是基于subwords
的算法;现在的问题是,不是所有的语言其word都是以空格来进行分割的,对于中文来说,只能每个字符每个字符来切割,或者结合词表来切割;总结就是语言并不共享同一套预处理方式;
- 解码会存在不同,并不是无损的
以hello world.
为例子,假设得到的分割是['hello', 'world', '.']
,这里解码的时候会得到hello world .
,也就是在world
和.
之间多了一个空格,这是我们不想看到的
- 没有一个端到端的解决方案
BPE
,Unigram
并不能完整的解决问题,需要一个端到端的解决方案;
2.2 解决
- 把所有的字符都转化为
unicode
编码,包括空格
SentencePiece首先将所有文本的字符都转化为unicode
字符,这也就意味着不需要去考虑不同的语言,字符或者符号,都视为一致的;
SentencePiece
把空格看作一个基本符号
SentencePiece为了精细化的处理空格,其将空格
转为_
进行分割,比如hello world.
,其会分割为[hello],[_wor],[ld],[.]
,这样处理就我们可以在没有任何歧义的情况下去标记文本;
- 不仅实现端到端的方案,而且更快
SentencePiece利用了优先队列对算法进行加速,分词时间大幅缩减,可以利用其作为一个端到端的分词工具;
2.3 应用
这里要介绍的是这里采用的模型类别有四种,分别是BPE
,Unigram
,word
和char
;
其中word
和char
看字面意思就直到其是根据word
和char
来进行分词,前者根据空格转的_
来进行分词,而char
是根据每个unicode来进行分词;
这里要讨论的便是BPE
和Unigram
,其会对_
来进行分割,然后各自适配其算法,但是在这里假设是中文呢,预处理的时候会分割成以空格开头的长字符串,看作word
再进行subword
分析;要注意的是BPE
是小表变大表,Unigram
是大表转小表,由于在转化的过程中一般有限制,这里建立在对中文分词时使用Unigram
最好,这样会有长字符出现而不是统一都是单字符;
代码如下:
import tensorflow as tf import keras_nlp inputs = tf.data.Dataset.from_tensor_slices(["Drifting Along"]) proto = keras_nlp.tokenizers.compute_sentence_piece_proto(inputs, vocabulary_size=15, lowercase=True) tokenizer = keras_nlp.tokenizers.SentencePieceTokenizer(proto=proto) outputs = inputs.map(tokenizer) for output in outputs: print(output) # tf.Tensor([ 4 8 12 5 9 14 5 6 13 4 7 10 11 6 13], shape=(15,), dtype=int32)
三、总结
SentencePiece不应该看作一个分词算法,现有的分词算法貌似只有两种,BPE和Unigram,WordPiece和SentencePiece一样,其不过是做了一些改良;
SentencePiece NB!