Transformers 文档
分词器
并获得增强的文档体验
开始
分词器
分词器将文本转换为数字数组(称为张量),这是文本模型的输入。有几种分词器算法,但它们都具有相同的目的。根据一些规则将文本拆分为更小的单词或子词(token),并将它们转换为数字(输入 id)。Transformers 分词器还会返回一个注意力掩码,以指示应关注哪些 token。
在 分词器总结 文档中了解最流行的分词算法。
调用 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")
多模态分词器
除了文本 token 之外,多模态分词器还保存来自其他模态的 token,作为其属性的一部分,以便于访问。
要将这些特殊 token 添加到分词器,请将它们作为字典传递给 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
类,并定义未知 token 和特殊 token。
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]"])
在空格上拆分 token,以创建彼此不重叠的 token。
from tokenizers.pre_tokenizers import Whitespace
tokenizer.pre_tokenizer = Whitespace()
在文本文件和 trainer 上调用 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) 分词器。它包括几种 tokenization 方案或编码,用于说明如何对文本进行 tokenization。
目前有两个模型使用 tiktoken 训练和发布,GPT2 和 Llama3。Transformers 支持带有 tokenizer.model tiktoken 文件的模型。tiktoken 文件会自动转换为 Transformers 基于 Rust 的 PreTrainedTokenizerFast。
将 subfolder
参数添加到 from_pretrained() 以指定 tokenizer.model
tiktoken 文件所在的位置。
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct", subfolder="original")
创建 tiktoken 分词器
tiktoken tokenizer.model
文件不包含有关其他 token 或模式字符串的信息。如果这些很重要,请将分词器转换为 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 的 tokenization 过程分两个步骤完成。
在第一步中,文本字符串通过 tokenize() 函数拆分为 token。文本的拆分方式取决于 tokenization 算法。
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 分词器,该分词器将空格替换为下划线 _
。
在 Tokenizer Playground 中可视化不同分词器的工作方式。
特殊 token
特殊 token 为模型提供有关文本的一些额外信息。
例如,如果你比较直接将文本传递给分词器以及从 convert_tokens_to_ids() 获取的 token,你会注意到添加了一些额外的 token。
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]
当你 decode() 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'
并非所有模型都需要特殊 token,但如果需要,分词器会自动添加它们。
批量分词
一次预处理一批文本而不是单个句子更快更有效。快速分词器尤其擅长并行化分词。
将文本字符串列表传递给分词器。
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 希望它们的长度相同,以便可以将它们打包成批次。长度不均匀的序列无法批量处理。
填充添加一个特殊的填充 token,以确保所有序列都具有相同的长度。设置 padding=True
将序列填充到批次中最长序列的长度。
encoded_inputs = tokenizer(batch_sentences, padding=True, return_tensors="pt")
print(encoded_inputs)
分词器将特殊的填充 token 0
添加到左侧(左填充),因为 Gemma 和 LLM 通常没有经过训练以从填充 token 继续生成。
截断
在 填充和截断 指南中了解有关其他截断策略的信息。
模型只能处理一定长度的序列。如果你尝试处理的序列长度超过模型可以处理的长度,则会崩溃。
截断从序列中删除 token,以确保它不超过最大长度。设置 truncation=True
将序列截断为模型接受的最大长度。你还可以使用 max_length
参数自行设置最大长度。
encoded_inputs = tokenizer(batch_sentences, max_length=8, truncation=True, return_tensors="pt")
print(encoded_inputs)