一、SentencePiece 简介SentencePiece 在大模型领域主要用于文本的 分词 和 编码。1、分词是将文本分割成一个个独立的词语或符号。传统的中文分词方法，例如 BMM 分词、隐马尔可夫(H M M ) 分词，都是基于规则的，需要人工制定分词规则。而 SentencePiece 则是基于 无监督学习 的，它可以自动学习文本的语义和结构，并根据学习结果进行分词。2、编码是将分词后的词语或符号转换为数字形式，以便计算机能够处理。SentencePiece 使用了一种称为 字节对编码 的方法，它可以将每个词语或符号编码成一个或多个字节。字节对编码的优点是能够有效地利用空间，并且可以将词语或符号之间的关系编码到编码中。3、优势：SentencePiece 在大模型领域具有以下优势：分词效果好，能够准确地识别词语和符号的边界。编码效率高，能够节省空间。能够将词语或符号之间的关系编码到编码中，有利于模型学习。因此，SentencePiece 已经被广泛应用于各大模型，例如 Google 的 BERT、GPT-3，以及阿里巴巴的 M6 等。简单来说，SentencePiece 就是大模型领域的一个 分词和编码工具。它可以帮助大模型更好地理解和处理文本。4、自监督训练原理SentencePiece 的自监督训练模型原理是通过 无监督学习 的方式，学习文本的语义和结构，并根据学习结果进行分词和编码。具体来说，SentencePiece 的训练过程可以分为以下几个步骤：数据准备：首先需要准备一个文本语料库，语料库中的文本可以是任何类型，例如新闻文章、书籍、代码等。模型训练：使用无监督学习算法训练 SentencePiece 模型，模型的输入是文本语料库，输出是分词后的文本。模型评估：使用评估指标评估模型的性能，例如分词准确率、召回率等。SentencePiece 使用的无监督学习算法是一种称为 Masked Language Modeling (MLM) 的算法。MLM 的基本思想是：将文本中的部分词语或符号进行遮蔽，然后让模型预测被遮蔽的词语或符号。通过这种方式，模型可以学习文本的语义和结构。在 SentencePiece 中，MLM 的具体实现如下：随机选择文本中的部分词语或符号进行遮蔽。将被遮蔽的词语或符号替换为一个特殊符号，例如 [MASK]。将处理后的文本输入模型，让模型预测被遮蔽的词语或符号。通过这种方式，模型可以学习到被遮蔽词语或符号与周围词语或符号之间的关系，从而提高分词和编码的准确性。SentencePiece 的自监督训练模型具有以下优势：不需要人工制定分词规则，能够自动学习文本的语义和结构。分词效果好，能够准确地识别词语和符号的边界。编码效率高，能够节省空间。SentencePiece 的自监督训练模型已经被广泛应用于各大模型，例如 Google 的 BERT、GPT-3，以及阿里巴巴的 M6 等。二、TikToken 简介Tiktoken 的功能与 SentencePiece 类似，都是用于文本的 分词 和 编码。Tiktoken 是一个基于 BPE 算法的 快速分词器，它专门针对 GPT-4 和 ChatGPT 等大模型进行了优化。Tiktoken 的主要特点如下：速度快：Tiktoken 的分词速度比 SentencePiece 快很多，可以满足大模型训练和推理的需求。效果好：Tiktoken 的分词效果与 SentencePiece 相当，能够准确地识别词语和符号的边界。易用性：Tiktoken 提供了简单的 API 接口，方便使用。Tiktoken 与 SentencePiece 的主要区别 如下：分词算法：Tiktoken 使用 BPE 算法进行分词，而 SentencePiece 使用的是无监督学习算法。速度：Tiktoken 的分词速度比 SentencePiece 快很多。模型：Tiktoken 专门针对 GPT-4 和 ChatGPT 等大模型进行了优化，而 SentencePiece 则是通用的。速度探究所以大家一定对为什么这么快很好奇，查阅tictoken的源码得知，tictoken对CoreBPE类进行了基于RUST的重写，包括真·多线程，regex，缓存caching，哈希各个方面的优化，具体的下面逐一解释：3.1 regex优化正则是耗时的大头，解决办法是用一些不那么花哨的方法，比如用 regex crate可解析的形式的regex要比寻常方法快3倍以上。一旦明确了使用crate可解析的regex，可以选择用regex crate 或者 fancy_regex crateregex crate 和 fancy_regex crate也有相互关系，fancy_regex使用的re.find_it会竞争re的可变缓存空间，造成性能下降，而regex的find_iter有不同的代码路径，不会造成这个问题。为此，通过给绝大部分的regex线程做一个克隆线程来避免。3.2 threadingrayon并没有比python自带的threads和释放GIL的情况下快，所以直接用python线程计数等来完成threads这里我多说一下，python自带的GIL是指如果没有额外操作，只是使用了类似：3.3 cachingtokenizer中使用LRU cache是很有必要的，可以加速查找速度，作者使用了RWLock来保护cache安全，对于RWLock，全称是"reader-writer spin lock"，和普通的spinlock不同，它对"read"和"write"的操作进行了区分。如果当前没有writer，那么多个reader可以同时获取这个rwlock。如果当前没有任何的reader，那么一个writer可以获取这个rwlock。3.4 hash作者使用了FxHashMap替代传统的HashMap达到了一定的性能提升，简单说明一下，FxHashMap的散列算法质量不高，但速度非常快，特别是对整数键而言，并且发现它的性能优于rustc内的所有其他散列算法。以上就是tictoken进行的性能优化。
一、 背景与基础在使用GPT BERT模型输入词语常常会先进行tokenize ，tokenize具体目标与粒度是什么呢？tokenize也有许多类别及优缺点，这篇文章总结一下各个方法及实际案例。tokenize的目标是把输入的文本流，切分成一个个子串，每个子串相对有完整的语义，便于学习embedding表达和后续模型的使用。二、切分粒度tokenize有三种粒度：word/subword/char1.词粒度-word词粒度的切分就跟人类平时理解文本原理一样，常常用一些工具来完成，例如英文的NLTK、SpaCy，中文的jieba、LTP等。举个栗子：英文live in New York ------> live / in / New York /中文在纽约生活 -----> 在 / 纽约 / 生活词粒度的切分能够非常好地保留完整语义信息，但是如果出现拼写错误、英文中的缩写等情况，鲁棒性一般。另一方面，词切分会产生非常巨大的词表，而且这都不能确保不会出现out of vocabulary问题。2.字粒度-char-字符粒度字粒度最早应该是2015年Karpathy[1]提出，简单说英文就是以字母为单位（对于大小写不敏感的任务，甚至可以先转小写再切分），中文就是以字为单位，举个栗子，英文live in New York -----> l / i / v /e / i / n / N / e / w / Y / o / r /k中文在纽约生活 -----> 在 / 纽 / 约 / 生 / 活可以看出，字粒度的切分很好地解决了词粒度的缺陷，鲁棒性增强、词表大大减小。但另一方面，也会带来一些麻烦：「毫无意义」：一个字母或一个单字本质上并没有任何语义意义；「增加输入计算压力」：减小词表的代价就是输入长度大大增加，从而输入计算变得更耗时耗力；如果词粒度不理想，而且字粒度似乎也有自己的问题，那么还有什么替代方法呢？Here comes subword tokenization。3.Subword粒度我们需要的tokenization需要满足：它能够在不需要无限词汇表的情况下处理缺失的标记，即通过有限的已知单词列表来处理无限的潜在词汇。此外，我们不希望将所有内容分解为单个字符的额外复杂性，因为字符级别可能会丢失单词级别的一些含义和语义细节。为此，我们需要考虑如何重新利用『小』单词来创建『大』单词。subword tokenization不转换最常见的单词，而是将稀有单词分解成有意义的子词单元。如果unfriendly被标记为一个稀有词，它将被分解为un-friendly-ly，这些单位都是有意义的单位，un的意思是相反的，friend是一个名词，ly则变成副词。这里的挑战是如何进行细分，我们如何获得un-friend-ly而不是unfr-ien-dly。NLP最火的网红 Transformer 和 BERT 就是Subword的带盐人，来看个它们做tokenization的栗子，I have a new GPU ----> [’i’, ’have’, ’a’, ’new’, ’gp’, ’##u’, ’.’]subword粒度切分算法又有一下几种：1.BPE2.WordPiece3.ULM(unigram LM)SentencePiece集成了两种subword算法，BPE和UniLM， WordPiece 则是谷歌内部的子词包，没对外公开参考：1.https://cloud.tencent.com/developer/article/18656892.https://zhuanlan.zhihu.com/p/340473354