Transformers 文档

分词器

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

分词器

分词器将文本转换为数字数组,即张量,作为文本模型的输入。分词算法有几种,但它们都有相同的目的。根据一些规则将文本分割成更小的词或子词(标记),并将其转换为数字(输入 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()。有两种主要的分词器类建立在基类之上。

有两种加载分词器的方法,使用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")

多模态分词器

除了文本标记,多模态分词器还包含来自其他模态的标记,作为其属性的一部分,以便于访问。

要将这些特殊标记添加到分词器,请将它们作为字典传递给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类,并定义未知标记和特殊标记。

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.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 的分词过程分为两步。

1. 分词
2. 将标记转换为 ID
3. 将 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)
< > 在 GitHub 上更新