LLM基础|最初的最初——分词器详解(只需看这篇就够!)

一、引言

自然语言处理(NLP)领域,分词和嵌入是非常重要的两个步骤,它们能够将自然语言转换为机器能够理解和识别的表示(Embedding)。只有在将自然语言转化为机器能够理解和识别的表示之后,才有之后各种学习和处理。 

在NLP发展过程中,分词和嵌入也在随之不断地进步和发展。这篇文章就围绕什么是分词器、主流的分词器的原理来展开讲解。

二、什么是分词器(Tokenizer)

计算机是无法直接理解自然语言的文本,我们需要进行文本预处理 ,而最重要的第一步就是分词(Tokenization)。

那什么是分词?一个典型的分词过程如下图所示:

分词这个过程,是将输入的整个文本,根据分词规则,将整个文本拆成一个个小词;每一个小词都有一个自己对应的index(或者向量),从而做到将整段文本转换成一个仅包含数字的序列。

其中,执行分词的算法模型称为分词器(Tokenizer) ,划分好的一个个词称为 Token。

Tokenizer 允许使用两种方法向量化一个文本语料库:

1. 将每个token转化为一个整数序列(每个整数都是词典中标记的索引);

2; 将每个token转化为一个向量,其中每个token对应的向量可以是二进制值、词频、TF-IDF权重等。

三、主流分词器

在理解了分词的过程后,tokenzier的功能可以总结为:

1. 将文本切分成token;

2. 将切分好的文本数值化,并输入至后续模型;

为了更高效地分词以及实现后续的任务,我们希望分词器尽可能地让每个token向量蕴含更多有用的信息,然后再把这些向量输入到算法模型中。

但是在实际的分词实现过程中,往往会遇到的问题是:文本的词太多了 。如果把所有的词都放入tokenizer中,这不现实,也不高效。

因此,为了方便后续算法模型训练,我们会选取出频率 (也可能是其它的权重)最高的若干个词组成一个词表(Vocabulary),从而根据这个词表再来对文本进行分词。

根据这个原则,有很多的分词方法衍生出来,帮助NLP模型更高效地理解、处理文本。这篇文章就古典分词法、子词分词法(Subword Tokenization)、BPE 和BBPE、WordPiece、Unigram这些分词法来进行详细介绍。

3.1 古典分词法

古典分词法,也是最基础的分词法,包括基于word和基于character的分词方法。

3.1.1 基于词的(word-based)分词法

基于词的(word-based) tokenizer,通常很容易设置和使用,只需几条规则(例如,基于空格分词,基于标点符号分词),并且通常会产生不错的结果。

一个典型的基于词的分词过程如下所示:

基于词的古典分词法,优点缺点都很鲜明:

优点:

  • 确实很容易理解,也易于操作;

缺点:

  • 这种分词法会得到非常大的“词汇表”,其中词汇表由语料库中拥有的独立标记的总数定义(这个数量是不可详尽的)。

  • 对于未在词表中出现的词(Out Of Vocabulary, OOV ),模型将无法处理(未知符号标记为 [UNK])。
  • 词表中的低频词在模型训无法得到训练(因为词表大小有限,太大的话会影响效率)。
  • 很多语言难以用空格进行分词,例如英语单词的多种形态,"look"衍生出的"looks", "looking", "looked",其实都是一个意思,但是在词表中却被当作不同的词处理,模型也无法通过"old", "older","oldest"之间的关系学到另外的形容词之间的关系。这一方面增加了训练冗余,另一方面也造成了大词汇量问题。

3.1.2 基于字符的(Character-based)分词法

基于字符的标记器(tokenizer)将文本拆分为字符,而不是单词。

一个典型的基于字符的分词过程如下所示:

这有两个主要好处:

  • 词汇量要小得多。
  • 词汇外(未知)标记(token)要少得多,因为每个单词都可以从字符构建。

这种分词方法虽然能解决 OOV 问题,也避免了大词汇量问题,但缺点也十分明显:

  • 粒度太细(一个词会被分成很多个字符),每个token的信息密度低。
  • 训练花费的成本太高;解码效率很低。
  • 在某些语言中,由于现在表示是基于字符而不是单词。每个字符本身并没有多大意义。

3.2 基于子词的分词方法(Subword Tokenization)

在分析完基于词和基于字符的古典分词法的优缺点之后,我们自然希望通过某种方式结合两种分词法分优点,并尽可能地克制缺点,但问题是,到底怎么做才能实现强强联合呢?

我们都知道,随着 BERT 算法的横空出世,NLP 中的很多领域都被颠覆性的改变了,BERT 也成为了一个非常主流的 NLP 算法。由于 BERT 的特性,要求分词方法也必须作出改变。从此,基于子词的分词方法(Subword Tokenization)诞生了 ,该算法现在已经成为一种标配。

基于子词的分词方法(Subword Tokenization) ,简称为 Subword 算法,意思就是把词切成更小的一块一块的子词,这些子词本身也具有一定的语义:

  • 高频词依旧切分成完整的整词

  • 低频词被切分成有意义的子词,例如 dogs => [dog, ##s]

这种方法的目的是通过一个有限的词表 来解决所有单词的分词问题,同时尽可能将结果中词汇表的数目降到最低。例如,可以用更小的sub-word组成更大的词,例如:

“unfortunately” = “un ” + “for ” + “tun ” + “ate ” + “ly ”。

可以看到,有点类似英语中的词根词缀拼词法,其中的这些小片段又可以用来构造其他词。可见这样做,既可以降低词表的大小,同时对相近词也能更好地处理。

这种方法在土耳其语等粘着型语言(agglutinative languages)中特别有用,可以通过将子词串在一起来形成(几乎)任意长的复杂词。

Subword 相较于传统分词方法的优点:

  • 学习到词之间的关系:传统分词法不利于模型学习词缀之间的关系,例如模型无法学习到“old”, “older”, and “oldest”之间的关系。
  • 平衡 OOV 问题:传统分词法无法很好的处理未知或罕见的词汇(OOV 问题),而基于字符的分词法作为 OOV 的解决方法又有粒度太细的问题;subword分词法可以通过“拼词”的方式处理很多罕见的词汇,其粒度在词与字符之间,能够较好的平衡 OOV 问题。

目前有三种主流的 Subword 算法,它们分别是:Byte Pair Encoding (BPE)、WordPiece 和 Unigram Language Model。

3.2.1 字节对编码(BPE, Byte Pair Encoding)

字节对编码(BPE)最初被开发为一种压缩文本的算法,后来在预训练 GPT 模型时被 OpenAI 用于分词。发展到现在,许多 Transformer 模型都使用它,包括 GPT、GPT-2、RoBERTa、BART 和 DeBERT;许多的开源LLM模型使用的也是BPE或者BPE的改进分词法,例如Llama系列、Mistral、Qwen等。

BPE分词算法的过程如下:

  1. 准备足够大的训练语料,并确定期望的词表大小;
  2. 在每个单词末尾添加后缀 </w> (用于标明词尾),统计每个单词出现的频率;例如,low的频率为 5,那么我们将其改写为"low </w>" : 5

    注:停止符 </w> 的意义在于标明词尾。为什么需要标明词尾呢?举例来说:st不加 </w> 可以出现在词首,如star;加了</w>之后表明该子词位于词尾,如west </w>,二者意义截然不同。
  3. 将语料库中所有单词拆分为单个字符,用所有单个字符建立最初的词典,并统计每个字符的频率(这一步和基于字符的分词法类似);
  4. 在语料上统计单词内相邻单元对的频数,选取频数最高的单元对合并成新的Subword单元;
  5. 重复第3步直到达到第1步设定的Subword词表大小或下一个最高频数为1。

我们用一个例子来更进一步地说明BPE的大致过程:

1. 第一步,准备语料库。我们以以下这段话为例:FloydHub is the fastest way to build, train and deploy deep learning models. Build deep learning models in the cloud. Train deep learning models.

2. 加后缀,统计词汇频率:

WORD FREQUENCY WORD FREQUENCY
deep </w> 3 build </w> 1
learning <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值