Transformers 文档

分词器

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始

分词器

分词器将文本转换为数字数组(称为张量),这是文本模型的输入。有几种分词器算法,但它们都具有相同的目的。根据一些规则将文本拆分为更小的单词或子词(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()。有两个主要的分词器类构建在基类之上。

有两种方法可以加载分词器,使用 AutoTokenizer 或模型特定的分词器。

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_tokenboi_tokeneoi_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) 分词器,请创建一个 TokenizerBpeTrainer 类,并定义未知 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.jsonPreTrainedTokenizerFast 的适当格式)。

使用 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 过程分两个步骤完成。

1. 分词
2. 将 token 转换为 id
3. 将 id 解码为文本

在第一步中,文本字符串通过 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)
< > 在 GitHub 上更新