Tokenization介绍
Contents
序言
在谈到 Large Language Model(LLM)大模型时,离不开的一个概念就是 token,因为几乎所有生成式的大模型服务商基本都通过 token 数量来计费。第一次接触 token 的时候,我以为 token 是一个字或者一个单词,但实际使用时二者又不是完全相等的关系,这篇博客就主要看下 token 究竟什么,并介绍了当前生成式大语言模型所用的BPE算法。
从 Tokenization 说起
一篇文章在输入给大模型之前,首先需要经过 Tokenization,也即将输入的句子转为 token 序列。
为什么需要 Tokenization
对文本进行 tokenization 的原因是为了让计算机能够理解一句话背后所代表的含义。
为了让计算机能理解,一种简单的方式是,人工预定义一些句子并直接设定计算机要做出的反应。
|
|
但人类的语言丰富多变,这种方式显然是不现实的。但无论语言如何多变,其背后一定存在着某些规则,否则人类也无法理解语言背后的含义。所以我们也想让机器知道这些规则,通过这些规则来解析句子,进而理解句子背后的含义。
对于一门语言来说,主要组成部分包括语音、单词和语法,其中单词是组成句子的基本单元,语法则是语言如何组织单词的规则。所以如果计算机只处理文本,并且理解了单词含义及对应的语法规则,理解人类语言就成为了可能。
Tokenization 所做的就是第一步,将句子拆分成单词,让计算机学习单词的含义。
如何做 Tokenization
我们先看英文的情况,对于英文来说,天然的用空格作为了单词与单词之间的间隔符,所以很容易想到的就是使用空格进行分词。
|
|
使用空格分词后,可得到如下的词表:
|
|
这种分词方法非常简单,但问题也很明显:
- 这种处理方式会要求计算机要有一个非常巨大的词表,并且每当出现新的单词时,都要加入到词表中,否则计算就无法处理。例如计算机无法识别到 dataset 是 data 和 set 的组合、无法学习到 she’s、he’s、it’s 背后的’s 缩写。
- 无法处理无分割符的语言,如中文、日文等。
既然无法单词粒度太粗,那我们可以将粒度拆的再细点。无论是什么语言,在计算机中都是特定格式的字符序列,如 ascii、utf-8 等。所以我们可以将 token 的粒度拆分到字符维度。得到
|
|
相比于单词唯独来说,使用字符维度的 token 方法可以更好的处理未知的词汇,而且也可以处理无分隔符的语言。
但这种划分方式也有其缺点,首先就是生成的 token 太多了,越多的 token 所需的计算量越大。其次就是在字符维度,计算机无法学习到其本身的语义信息。
所以科研人员开始寻找一种介于单词和字符中间的一种 token 方式,subword tokenization,这是目前主流大语言模型所使用的 token 方式。
subword tokenization
subword tokenization 是为了解决,word 级别词表过大的问题,及字符级别输入过长且无语义的问题。其主要步骤是,将单词拆成一些更有意义的单元。例如,-ing,un-,-ily,-ed,-’s 等等。这样,当遇到未知的单词时,也可处理,例如如果词表中有 foot 和 ball,遇到 football 时,可以将其拆分成 foot-和-ball 两个 token。
使用这种方式,不需要将每一个遇到的单词都加到词表中,解决了词表过大的问题;同时,单词又没有拆分出非常多 token 且每个 token 都有一定的语义信息,解决了字符级别序列特别长且无语义的问题。
目前 subword tokenization 的主要方式有三种:BPE (GPT-2), WordPiece (BERT), and Unigram (T5)
BPE
bpe 是构建一个词汇表,词汇表中是可能出现的字词。
BPE 是一种起源于文本压缩的算法,现在被用于大模型训练中,期望用最少的 token 表示更多文本。
BPE 处理英文文本的主要步骤如下:
- 将文库按空格分词,在每个单词的后面拼接一个特殊 token
</s>
,单词内的每个字符都作为一个单独的 token,构建出基础的词库 - 统计词库内每个 token 出现的次数
- 计算每个单词内相邻两个 token 出现的频率,选出最高的 token pair 加入到词库中,合并单词内的 token pair
- 重复 2-3 步
在每个单词末尾添加一个特殊 token 的原因是,在英文语境下,同一个 sub-word 在词尾和其他位置可能有不同的含义。例如 easiest 中的 st 和 star 中的 st。
代码实现如下
|
|
输出为:
|
|
基于这个初始词表,统计每个出现次数最多的两个相邻token
|
|
|
|
统计这个词表中出现次数最多的token pair为(‘h’, ’e’),出现了4次,这就是一个merge rule,将其引用到原始词表中
|
|
|
|
不断重复统计-合并的步骤一定次数,即可得到最终的词表,最终代码如下:
|
|
在对语料库学习后,即可对句子进行编解码。编码的过程就是先将所有token按长度从大到小排列,然后对句子进行编码。
|
|
|
|
而解码的过程就非常简单了,将句子按</s>
分割后,将每个token合并即可。