对SentencePiece的一些疑问

问题描述 投票:0回答:1

最近在学习Google的SentencePiece时遇到了一些问题。

  • BPE、WordPiece 和 Unigram 都是常见的子词算法,那么 SentencePiece 和它们之间的关系是什么呢?有的教程说SentencePiece也是一个subword算法,有的教程说SentencePiece是上述subword算法的实现。
  • SentencePiece 在预处理中似乎只用特殊下划线替换空格。如果没有预分词阶段,那么如何应用需要预分词的subword算法,例如BPE和Unigram?

我自己的理解:

  • 我更倾向于认为SentencePiece是BPE和Unigram等子词算法的实现。因为如果SentencePiece也被归类为子词算法,为什么还会有SentencePiece+BPE、SentencePiece+Unigram这样的表达方式?
  • SentencePiece 支持 BPE、Unigram 等算法,但这些算法显然需要预分词化。 SentencePiece 不需要预先标记化。这有点冲突吗?
tokenize sentencepiece byte-pair-encoding
1个回答
0
投票

几天前我也有同样的问题,所以我做了一些研究,这是我的答案(可能100%正确,也可能不是100%正确,但可能会有所帮助):

  1. sentencepeice 论文从未明确表示他们不会为 BPE 进行预标记。他们只是说一些语言,如中文、日文等,不能基于空格进行预标记,因此我们需要一种算法来处理这些语言,而不必担心手写规则。
  2. 我检查了 Transformer 库中的 SentencePieceBPETokenizer 模块。该模块有一个名为 pre_tokenizer.pre_tokenize_str 的函数,它实现了句子预标记器(使用 _ 表示空格)并查看下面的输出:
from tokenizers import SentencePieceBPETokenizer
tokenizer = SentencePieceBPETokenizer()
tokenizer.pre_tokenizer.pre_tokenize_str("こんにちは世界")
>>> [('▁こんにちは世界', (0, 7))]

由于这句话中没有分隔符(顺便说一句,它是“Hello World”),因此它不会对其进行预标记,而只是将整个句子视为单个标记,并可能将这个标记发送到 BPE 算法。

tokenizer.pre_tokenizer.pre_tokenize_str("Hello world.")
>>> [('▁Hello', (0, 5)), ('▁world.', (5, 12))]
tokenizer.pre_tokenizer.pre_tokenize_str("Hello   world.")
>>> [('▁Hello', (0, 5)), ('▁', (5, 6)), ('▁', (6, 7)), ('▁world.', (7, 14))]

看看它是如何根据空格对句子进行预标记的?唯一的区别是它保留了空白信息,而天真的空白预标记器(或任何其他预标记器)可能会丢失这些信息。根据我从论文中了解到的内容,这是该句子的唯一优势,它通过保持空白信息完整来使编码和解码无损。

我希望这是有道理的。

参考:

  1. 这篇文章的评论部分可能会有所帮助:https://www.reddit.com/r/MachineLearning/comments/rprmq3/d_sentencepiece_wordpiece_bpe_which_tokenizer_is/
© www.soinside.com 2019 - 2024. All rights reserved.