Transformers 文档
分词器
并获得增强的文档体验
开始使用
分词器
分词器将文本转换为数字数组,即张量,作为文本模型的输入。分词算法有几种,但它们都有相同的目的。根据一些规则将文本分割成更小的词或子词(标记),并将其转换为数字(输入 ID)。Transformers 分词器还会返回一个注意力掩码,以指示哪些标记应该被关注。
在分词器摘要文档中了解最流行的分词算法。
调用from_pretrained()从 Hugging Face Hub 或本地目录加载分词器及其配置。预训练的分词器保存在tokenizer.model文件中,其中包含所有相关的词汇文件。
将字符串文本传递给分词器,以返回输入 ID 和注意力掩码,并设置框架张量类型,使用 return_tensors
参数返回。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
无论使用哪种分词器,请确保分词器词汇表与预训练模型的分词器词汇表相同。如果您使用自定义分词器且其词汇表与预训练模型分词器的词汇表不同,这一点尤其重要。
本指南简要概述了分词器类以及如何使用它预处理文本。
分词器类
所有分词器都继承自PreTrainedTokenizerBase类,该类为所有分词器提供了通用方法,例如from_pretrained()和batch_decode()。有两种主要的分词器类建立在基类之上。
- PreTrainedTokenizer是 Python 实现,例如LlamaTokenizer。
- PreTrainedTokenizerFast是来自Tokenizers库的基于 Rust 的快速实现,例如LlamaTokenizerFast。
有两种加载分词器的方法,使用AutoTokenizer或特定于模型的分词器。
AutoClass API 是一种快速简便的加载分词器的方法,无需了解是提供 Python 还是 Rust 实现。默认情况下,AutoTokenizer 会尝试加载一个快速分词器(如果可用),否则会加载 Python 实现。
使用from_pretrained()加载分词器。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library.", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
通过将其词汇表文件传递给from_pretrained()来加载您自己的分词器。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("./model_directory/my_vocab_file.txt")
多模态分词器
除了文本标记,多模态分词器还包含来自其他模态的标记,作为其属性的一部分,以便于访问。
要将这些特殊标记添加到分词器,请将它们作为字典传递给from_pretrained()中的extra_special_tokens
参数。下面的示例将image_token
添加到视觉-语言模型。
保存分词器,以便您可以直接访问image_token
、boi_token
和eoi_token
并重复使用它。
vision_tokenizer = AutoTokenizer.from_pretrained(
"llava-hf/llava-1.5-7b-hf",
extra_special_tokens={"image_token": "<image>", "boi_token": "<image_start>", "eoi_token": "<image_end>"}
)
print(vision_tokenizer.image_token, vision_tokenizer.image_token_id)
("<image>", 32000)
vision_tokenizer.save_pretrained("./path/to/tokenizer")
快速分词器
PreTrainedTokenizerFast或*快速分词器*是来自Tokenizers库的基于 Rust 的分词器。它在批量分词方面明显更快,并且与基于 Python 的分词器相比提供了额外的对齐方法。
AutoTokenizer如果支持,会自动加载一个快速分词器。否则,您需要显式加载快速分词器。
本节将向您展示如何训练一个快速分词器并在 Transformers 中重用它。
要训练字节对编码 (BPE) 分词器,请创建一个Tokenizer
和BpeTrainer
类,并定义未知标记和特殊标记。
from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
tokenizer = Tokenizer(BPE(unk_token="[UNK]"))
trainer = BpeTrainer(special_tokens=["[UNK]", "[CLS]", "[SEP]", "[PAD]", "[MASK]"])
在Whitespace
上分割标记,以创建不相互重叠的标记。
from tokenizers.pre_tokenizers import Whitespace
tokenizer.pre_tokenizer = Whitespace()
在文本文件和训练器上调用train
以开始训练。
files = [...] tokenizer.train(files, trainer)
使用save
将分词器配置和词汇表保存到 JSON 文件。
tokenizer.save("tokenizer.json")
现在,您可以将分词器对象传递给PreTrainedTokenizerFast中的tokenizer_object
参数,从而在 Transformers 中加载和重用它。
from transformers import PreTrainedTokenizerFast
fast_tokenizer = PreTrainedTokenizerFast(tokenizer_object=tokenizer)
要从其 JSON 文件加载已保存的分词器,请将文件路径传递给PreTrainedTokenizerFast中的tokenizer_file
参数。
from transformers import PreTrainedTokenizerFast
fast_tokenizer = PreTrainedTokenizerFast(tokenizer_file="tokenizer.json")
tiktoken
tiktoken 是 OpenAI 的一种字节对编码 (BPE) 分词器。它包含几种分词方案或编码,用于文本如何进行分词。
目前,tiktoken 已经训练并发布了两个模型:GPT2 和 Llama3。Transformers 支持带有 tokenizer.model tiktoken 文件的模型。tiktoken 文件会自动转换为 Transformers 基于 Rust 的 PreTrainedTokenizerFast。
在from_pretrained()中添加subfolder
参数以指定tokenizer.model
tiktoken 文件的位置。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct", subfolder="original")
创建 tiktoken 分词器
tiktoken tokenizer.model
文件不包含关于附加标记或模式字符串的信息。如果这些很重要,请将分词器转换为 tokenizer.json
(PreTrainedTokenizerFast 的适当格式)。
使用tiktoken.get_encoding函数生成 tiktoken tokenizer.model
文件,并使用convert_tiktoken_to_fast将其转换为tokenizer.json
。
from transformers.integrations.tiktoken import convert_tiktoken_to_fast
from tiktoken import get_encoding
# Load your custom encoding or the one provided by OpenAI
encoding = get_encoding("gpt2")
convert_tiktoken_to_fast(encoding, "config/save/dir")
生成的tokenizer.json
文件保存到指定目录,并使用from_pretrained()加载。
tokenizer = PreTrainedTokenizerFast.from_pretrained("config/save/dir")
预处理
Transformers 模型期望输入是 PyTorch、TensorFlow 或 NumPy 张量。分词器的作用是将文本预处理为这些张量。使用return_tensors
参数指定要返回的框架张量类型。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google/gemma-2-2b")
tokenizer("We are very happy to show you the 🤗 Transformers library.", return_tensors="pt")
{'input_ids': tensor([[ 2, 1734, 708, 1508, 4915, 577, 1500, 692, 573,
156808, 128149, 9581, 235265]]),
'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
}
将文本转换为输入 ID 的分词过程分为两步。
在第一步中,通过tokenize()函数将字符串文本分割成标记。文本的分割方式取决于分词算法。
tokens = tokenizer.tokenize("We are very happy to show you the 🤗 Transformers library")
print(tokens)
['We', '▁are', '▁very', '▁happy', '▁to', '▁show', '▁you', '▁the', '▁🤗', '▁Transformers', '▁library']
Gemma 使用SentencePiece分词器,它用下划线_
替换空格。
在分词器演练场中可视化不同分词器的工作方式。
特殊标记
特殊标记为模型提供了关于文本的一些额外信息。
例如,如果您比较直接将文本传递给分词器和从convert_tokens_to_ids()获得的标记,您会注意到添加了一些额外的标记。
model_inputs = tokenizer("We are very happy to show you the 🤗 Transformers library.")
[2, 1734, 708, 1508, 4915, 577, 1500, 692, 573, 156808, 128149, 9581]
tokenizer.convert_tokens_to_ids(tokens)
[1734, 708, 1508, 4915, 577, 1500, 692, 573, 156808, 128149, 9581]
当您解码() ID 时,您会看到字符串开头有<bos>
。这用于向模型指示句子的开头。
print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))
'<bos>We are very happy to show you the 🤗 Transformers library.'
'We are very happy to show you the 🤗 Transformers library'
并非所有模型都需要特殊标记,但如果需要,分词器会自动添加它们。
批量分词
预处理*批次*文本比一次处理一个句子更快、更高效。快速分词器尤其擅长并行化分词。
将字符串文本列表传递给分词器。
batch_sentences = [
"But what about second breakfast?",
"Don't think he knows about second breakfast, Pip.",
"What about elevensies?",
]
encoded_inputs = tokenizer(batch_sentences, return_tensors="pt")
print(encoded_inputs)
{
'input_ids':
[[2, 1860, 1212, 1105, 2257, 14457, 235336],
[2, 4454, 235303, 235251, 1742, 693, 9242, 1105, 2257, 14457, 235269, 48782, 235265],
[2, 1841, 1105, 29754, 37453, 235336]],
'attention_mask': [[1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1]]
}
填充
在填充和截断指南中了解更多填充策略。
在上面的输出中,input_ids
的长度不同。这是一个问题,因为 Transformers 期望它们的长度相同,以便可以打包成批次。长度不等的序列无法批量处理。
填充会添加一个特殊的*填充标记*,以确保所有序列的长度相同。设置padding=True
会将序列填充到批次中最长序列的长度。
encoded_inputs = tokenizer(batch_sentences, padding=True, return_tensors="pt")
print(encoded_inputs)
分词器将特殊填充标记0
添加到左侧(左填充),因为 Gemma 和通用 LLM 没有训练以从填充标记继续生成。
截断
在填充和截断指南中了解更多截断策略。
模型只能处理特定长度的序列。如果尝试处理超出模型处理能力的序列,它会崩溃。
截断会从序列中移除标记,以确保它不超过最大长度。设置truncation=True
会将序列截断到模型接受的最大长度。您还可以使用max_length
参数自行设置最大长度。
encoded_inputs = tokenizer(batch_sentences, max_length=8, truncation=True, return_tensors="pt")
print(encoded_inputs)