tokenizer介绍

在自然语言处理(NLP)领域,tokenizer 是一个重要的组件,它的主要作用是将文本字符串分割成更小的单位,这些单位通常被称为"标记"(tokens)。这些标记可以是单词、子词(subwords)、字符甚至是更复杂的结构。Tokenizer 的设计和实现对后续的 NLP 模型性能有着重要影响,因为它决定了模型如何理解和处理输入数据。

Tokenizer 的主要功能

  1. 分词(Tokenization):将连续的文本切分成独立的标记。例如,句子 "I love natural language processing" 可以被切分成 ["I", "love", "natural", "language", "processing"]。
  2. 规范化(Normalization):对文本进行标准化处理,比如转换为小写、去除标点符号等,以减少词汇的变异性。
  3. 特殊标记处理:添加一些特殊的标记,如开始标记(<s>)、结束标记(</s>)、未知词汇标记(<unk>)等,这些标记有助于模型更好地理解文本的结构和边界。

常见的 Tokenizer 类型

  1. 基于规则的 Tokenizer:使用预定义的规则或正则表达式来切分文本。例如,根据空格、标点符号等进行分词。
  2. 基于统计的 Tokenizer:利用统计方法来学习如何切分文本。例如,使用频率信息来决定哪些子词应该被合并为一个标记。
  3. 基于机器学习的 Tokenizer:训练一个模型来预测文本的最佳切分点。这种方法通常需要大量的标注数据。

应用场景

  • 机器翻译:将源语言文本切分成标记,然后由模型生成目标语言的翻译。
  • 情感分析:将评论或文本切分成标记,以便模型可以更好地理解其中的情感倾向。
  • 文本分类:将文档切分成标记,用于训练分类模型。
  • 命名实体识别:将文本切分成标记,以便模型可以识别出人名、地名等实体。

示例

假设我们有一个简单的句子:"Hello, how are you doing today?"

  • 基于规则的 Tokenizer 可能会将其切分成:["Hello", ",", "how", "are", "you", "doing", "today", "?"]
  • 基于统计的 Tokenizer 可能会根据频率信息将其切分成:["Hello", "how", "are", "you", "doing", "today", "?"]
  • 基于机器学习的 Tokenizer 可能会根据训练数据将其切分成:["Hello", "how", "are", "you", "doing", "today", "?"]

llama-tokenizer-jsWeb site created using create-react-apphttps://belladoreai.github.io/llama-tokenizer-js/example-demo/build/

主要介绍三种分词算法: BPE/wordpiece/unigram,以及分词工具sentencepiece

llama-tokenizer-js
https://belladoreai.github.io/llama-tokenizer-js/example-demo/build/

huggingface.co
https://huggingface.co/docs/transformers/v4.46.2/zh/main_classes/tokenizer

SentencePiece是什么

SentencePiece 是一个由 Google 开发的开源工具,旨在帮助构建高效的自然语言处理(NLP)模型。它是一个跨平台的库,可以在多种操作系统上运行,包括但不限于 Windows、Linux 和 macOS。SentencePiece 的主要功能是在不需要预先定义词汇表的情况下,自动从大规模文本数据中学习如何将文本切分为"子词单元"(subword units)。这种方法可以有效地处理未知词汇和低频词汇的问题,这对于提高自然语言处理模型的性能非常关键。

SentencePiece 的主要特点包括:

  • 无需预定义词汇表:传统的自然语言处理方法通常需要预先定义一个词汇表,这可能会导致遇到未登录词(即不在词汇表中的词)时的问题。SentencePiece 可以动态地学习词汇表,从而更好地处理这些未知词汇。
  • 子词单元:SentencePiece 使用一种称为"子词单元"的概念,即将单词分解为更小的单元。这种方式不仅可以有效地处理未知词汇,还能减少词汇表的大小,从而提高模型的效率。
  • 支持多种语言:无论是空白分隔的语言(如英语),还是非空白分隔的语言(如中文、日文),SentencePiece 都能够有效处理。
  • 灵活性:用户可以根据自己的需求调整分词策略,比如设置词块的最大长度、最小频率等参数。

应用场景

SentencePiece 被广泛应用于各种自然语言处理任务中,如机器翻译、情感分析、文本分类等。特别是对于那些需要处理大量文本数据的应用,SentencePiece 提供了一种高效且灵活的解决方案。此外,它也被用于构建大规模的语言模型,如 BERT、XLNet 等,以提高这些模型的泛化能力和处理未知词汇的能力。

BPE是什么

Byte Pair Encoding (BPE) 是一种用于自然语言处理的子词(subword)分割算法。BPE 通过迭代地合并最常见的字符对来生成词汇表,从而将单词拆分成更小的单元。这种方法特别适用于处理未知词汇和低频词汇,同时可以减少词汇表的大小,提高模型的效率和性能。

BPE 的工作原理

  1. 初始化:从原始文本中提取所有字符,并将每个单词视为一个字符序列。
  2. 统计频率:计算所有字符对(bigrams)的出现频率。
  3. 合并操作:选择频率最高的字符对,并将它们合并为一个新的子词单元。
  4. 更新:更新文本中的所有单词,将合并后的子词单元替换原来的字符对。
  5. 重复:重复上述步骤,直到达到预定的词汇表大小或没有更多的字符对可以合并。

Python 使用示例代码

下面是一个使用 sentencepiece 库实现 BPE 的示例代码。sentencepiece 是一个广泛使用的库,支持 BPE 和其他分词方法。

安装 sentencepiece

首先,你需要安装 sentencepiece 库。可以使用以下命令进行安装:

bash 复制代码
pip install sentencepiece
python 复制代码
import sentencepiece as spm

# 准备训练数据
with open('train.txt', 'w', encoding='utf-8') as f:
    f.write("Hello, how are you doing today?\n")
    f.write("I am fine, thank you.\n")
    f.write("Natural language processing is fascinating.\n")

# 训练 BPE 模型
spm.SentencePieceTrainer.train(input='train.txt', model_prefix='bpe', vocab_size=1000)

# 加载训练好的模型
sp = spm.SentencePieceProcessor(model_file='bpe.model')

# 测试分词
text = "Hello, how are you doing today?"
encoded = sp.encode(text, out_type=str)
print(f"Encoded: {encoded}")

decoded = sp.decode(encoded)
print(f"Decoded: {decoded}")

代码解释

  1. 准备训练数据 :创建一个包含训练文本的文件 train.txt
  2. 训练 BPE 模型 :使用 SentencePieceTrainer.train 方法训练 BPE 模型。input 参数指定训练数据文件,model_prefix 参数指定输出模型文件的前缀,vocab_size 参数指定词汇表的大小。
  3. 加载训练好的模型 :使用 SentencePieceProcessor 加载训练好的 BPE 模型。
  4. 测试分词:对一段文本进行编码(分词)和解码(还原)。

输出结果

bash 复制代码
Encoded: ['▁Hello', ',', '▁how', '▁are', '▁you', '▁doing', '▁today', '?']
Decoded: Hello, how are you doing today?

注意事项

  • 词汇表大小vocab_size 参数决定了最终词汇表的大小。较大的词汇表可以更好地捕捉文本中的细节,但也会增加模型的复杂度。
  • 模型文件 :训练完成后,会生成两个文件:bpe.modelbpe.vocab。前者是模型文件,后者是词汇表文件

WordPiece是什么

WordPiece 是另一种常用的子词(subword)分割算法,与 Byte Pair Encoding (BPE) 类似,但有一些不同之处。WordPiece 也是通过迭代地合并常见的字符对来生成词汇表,但它在选择合并字符对时使用了概率模型,确保生成的词汇表在训练数据上的覆盖率最大化。

WordPiece 的工作原理

  1. 初始化:从原始文本中提取所有字符,并将每个单词视为一个字符序列。
  2. 统计频率:计算所有字符对(bigrams)的出现频率。
  3. 合并操作:选择使词汇表在训练数据上的覆盖率最大的字符对,并将它们合并为一个新的子词单元。
  4. 更新:更新文本中的所有单词,将合并后的子词单元替换原来的字符对。
  5. 重复:重复上述步骤,直到达到预定的词汇表大小或没有更多的字符对可以合并。

Python 使用示例代码

下面是一个使用 transformers 库实现 WordPiece 的示例代码。transformers 是 Hugging Face 开发的一个广泛使用的库,支持多种预训练模型及其分词器。

安装 transformers

首先,你需要安装 transformers 库。可以使用以下命令进行安装:

bash 复制代码
pip install transformers
python 复制代码
from transformers import BertTokenizer

# 初始化 BERT 的 WordPiece 分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

# 测试分词
text = "Hello, how are you doing today?"
tokens = tokenizer.tokenize(text)
print(f"Tokens: {tokens}")

# 编码为模型输入
input_ids = tokenizer.encode(text, add_special_tokens=True)
print(f"Input IDs: {input_ids}")

# 解码回原始文本
decoded_text = tokenizer.decode(input_ids)
print(f"Decoded Text: {decoded_text}")

代码解释

  1. 初始化 WordPiece 分词器 :使用 BertTokenizer.from_pretrained 方法加载预训练的 BERT 模型的 WordPiece 分词器。这里使用的是 bert-base-uncased,这是一个不区分大小写的 BERT 模型。
  2. 测试分词:对一段文本进行分词,得到子词单元的列表。
  3. 编码为模型输入 :将文本编码为模型可以接受的输入格式,add_special_tokens=True 表示添加特殊的标记,如 [CLS][SEP]
  4. 解码回原始文本:将编码后的输入解码回原始文本。

输出结果

bash 复制代码
Tokens: ['hello', ',', 'how', 'are', 'you', 'doing', 'today', '?']
Input IDs: [101, 3793, 1010, 2088, 2003, 2117, 2644, 1029, 102]
Decoded Text: [CLS] hello, how are you doing today? [SEP]

注意事项

  • 预训练模型transformers 库提供了多种预训练模型,每种模型都有对应的分词器。你可以根据需要选择不同的模型,如 bert-base-cased(区分大小写)或 roberta-base
  • 特殊标记add_special_tokens=True 参数会在编码时添加 [CLS][SEP] 等特殊标记,这些标记在 BERT 等模型中用于表示句子的开始和结束。
  • 词汇表大小:预训练模型的词汇表大小通常是固定的,但你可以通过训练自己的分词器来定制词汇表大小。

unigram是什么

Unigram Language Model 是一种基于单个词(或子词)的概率模型,常用于自然语言处理中的分词任务。与 Byte Pair Encoding (BPE) 和 WordPiece 不同,Unigram 模型通过优化词汇表中每个子词的频率分布来生成子词单元。Unigram 模型的目标是使生成的子词单元在训练数据上的概率最大化。

Unigram 的工作原理

  1. 初始化:从原始文本中提取所有字符,并将每个单词视为一个字符序列。
  2. 初始化词汇表:将所有字符作为初始词汇表。
  3. 优化过程:通过迭代地调整词汇表中的子词单元,使生成的子词单元在训练数据上的概率最大化。
  4. 更新:在每次迭代中,重新计算每个子词单元的概率,并根据这些概率调整词汇表。
  5. 终止条件:当达到预定的词汇表大小或收敛条件时,停止迭代。

Python 使用示例代码

下面是一个使用 sentencepiece 库实现 Unigram 分词的示例代码。sentencepiece 是一个广泛使用的库,支持多种分词方法,包括 Unigram。

安装 sentencepiece

首先,你需要安装 sentencepiece 库。可以使用以下命令进行安装:

bash 复制代码
pip install sentencepiece
python 复制代码
import sentencepiece as spm

# 准备训练数据
with open('train.txt', 'w', encoding='utf-8') as f:
    f.write("Hello, how are you doing today?\n")
    f.write("I am fine, thank you.\n")
    f.write("Natural language processing is fascinating.\n")

# 训练 Unigram 模型
spm.SentencePieceTrainer.train(
    input='train.txt',
    model_prefix='unigram',
    vocab_size=1000,
    model_type='unigram'
)

# 加载训练好的模型
sp = spm.SentencePieceProcessor(model_file='unigram.model')

# 测试分词
text = "Hello, how are you doing today?"
encoded = sp.encode(text, out_type=str)
print(f"Encoded: {encoded}")

decoded = sp.decode(encoded)
print(f"Decoded: {decoded}")

代码解释

  1. 准备训练数据 :创建一个包含训练文本的文件 train.txt
  2. 训练 Unigram 模型 :使用 SentencePieceTrainer.train 方法训练 Unigram 模型。input 参数指定训练数据文件,model_prefix 参数指定输出模型文件的前缀,vocab_size 参数指定词汇表的大小,model_type 参数指定使用 Unigram 模型。
  3. 加载训练好的模型 :使用 SentencePieceProcessor 加载训练好的 Unigram 模型。
  4. 测试分词:对一段文本进行编码(分词)和解码(还原)。

输出结果

bash 复制代码
Encoded: ['▁Hello', ',', '▁how', '▁are', '▁you', '▁doing', '▁today', '?']
Decoded: Hello, how are you doing today?

注意事项

  • 词汇表大小vocab_size 参数决定了最终词汇表的大小。较大的词汇表可以更好地捕捉文本中的细节,但也会增加模型的复杂度。
  • 模型文件 :训练完成后,会生成两个文件:unigram.modelunigram.vocab。前者是模型文件,后者是词汇表文件。
  • 模型类型model_type 参数可以设置为 unigrambpechar,分别对应 Unigram、BPE 和字符级别的分词方法。
相关推荐
阿里云大数据AI技术42 分钟前
PAI Model Gallery 支持云上一键部署 Qwen3 全尺寸模型
人工智能·llm
changzz20085 小时前
低配置电脑预训练minimind的实践
llm·大语言模型·minimind·低配置
thesky12345620 小时前
llama factory怎么命令行推理图片
深度学习·llama
量子位21 小时前
图像编辑开源新 SOTA,来自多模态卷王阶跃!大模型行业正步入「多模态时间」
人工智能·llm
智泊AI1 天前
别再吹通用型Al Agent了!其实真实业务都是Workflow
llm
free慢1 天前
用好大模型-提示词工程
llm
GPUStack1 天前
GPUStack v0.5:模型Catalog、图生图功能上线,多维优化全面提升产品能力与使用体验
ai·大模型·llm·genai·gpu集群
Goboy1 天前
Cursor 玩转 百度 AppBuilder
llm·cursor·mcp
AI蜗牛车2 天前
【LLM+Code】Windsurf Agent 模式Prompt&Tools详细解读
ai·大模型·llm·agent
Ann2 天前
Prompt Engineering:如何让大模型按要求“工作”
人工智能·llm