Transformers 文档

ByT5

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

ByT5

PyTorch TensorFlow Flax

概述

ByT5 模型由 Linting Xue、Aditya Barua、Noah Constant、Rami Al-Rfou、Sharan Narang、Mihir Kale、Adam Roberts、Colin Raffel 在 ByT5: Towards a token-free future with pre-trained byte-to-byte models 中提出。

该论文的摘要如下:

大多数广泛使用的预训练语言模型都基于与词或子词单元对应的 token 序列进行操作。将文本编码为 token 序列需要一个分词器,该分词器通常作为独立于模型的工件创建。直接对原始文本(字节或字符)进行操作的无 token 模型具有许多优点:它们可以开箱即用地处理任何语言的文本,它们对噪声更鲁棒,并且通过移除复杂且容易出错的文本预处理流程来最大限度地减少技术债务。由于字节或字符序列比 token 序列更长,因此过去关于无 token 模型的工作通常引入新的模型架构,旨在分摊直接操作原始文本的成本。在本文中,我们展示了标准的 Transformer 架构可以通过最少的修改来处理字节序列。我们仔细地描述了参数数量、训练 FLOP 和推理速度方面的权衡,并表明字节级模型与其 token 级对应模型相比具有竞争力。我们还证明了字节级模型对噪声的鲁棒性明显更强,并且在对拼写和发音敏感的任务上表现更好。作为我们贡献的一部分,我们发布了一组新的基于 T5 架构的预训练字节级 Transformer 模型,以及我们在实验中使用的所有代码和数据。

此模型由 patrickvonplaten 贡献。 原始代码可以在 此处 找到。

ByT5 的架构基于 T5v1.1 模型,有关 API 参考,请参阅 T5v1.1 的文档页面。 它们仅在如何为模型准备输入方面有所不同,请参阅下面的代码示例。

由于 ByT5 是以无监督方式预训练的,因此在单任务微调期间使用任务前缀没有实际优势。 如果您正在进行多任务微调,则应使用前缀。

使用示例

ByT5 基于原始 UTF-8 字节工作,因此无需分词器即可使用

>>> from transformers import T5ForConditionalGeneration
>>> import torch

>>> model = T5ForConditionalGeneration.from_pretrained("google/byt5-small")

>>> num_special_tokens = 3
>>> # Model has 3 special tokens which take up the input ids 0,1,2 of ByT5.
>>> # => Need to shift utf-8 character encodings by 3 before passing ids to model.

>>> input_ids = torch.tensor([list("Life is like a box of chocolates.".encode("utf-8"))]) + num_special_tokens

>>> labels = torch.tensor([list("La vie est comme une boîte de chocolat.".encode("utf-8"))]) + num_special_tokens

>>> loss = model(input_ids, labels=labels).loss
>>> loss.item()
2.66

但是,对于批量推理和训练,建议使用分词器

>>> from transformers import T5ForConditionalGeneration, AutoTokenizer

>>> model = T5ForConditionalGeneration.from_pretrained("google/byt5-small")
>>> tokenizer = AutoTokenizer.from_pretrained("google/byt5-small")

>>> model_inputs = tokenizer(
...     ["Life is like a box of chocolates.", "Today is Monday."], padding="longest", return_tensors="pt"
... )
>>> labels_dict = tokenizer(
...     ["La vie est comme une boîte de chocolat.", "Aujourd'hui c'est lundi."], padding="longest", return_tensors="pt"
... )
>>> labels = labels_dict.input_ids

>>> loss = model(**model_inputs, labels=labels).loss
>>> loss.item()
17.9

T5 类似,ByT5 也在 span-mask 去噪任务上进行了训练。 但是,由于该模型直接基于字符工作,因此预训练任务略有不同。 让我们破坏输入句子 "The dog chases a ball in the park." 的一些字符,并要求 ByT5 为我们预测它们。

>>> from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
>>> import torch

>>> tokenizer = AutoTokenizer.from_pretrained("google/byt5-base")
>>> model = AutoModelForSeq2SeqLM.from_pretrained("google/byt5-base")

>>> input_ids_prompt = "The dog chases a ball in the park."
>>> input_ids = tokenizer(input_ids_prompt).input_ids

>>> # Note that we cannot add "{extra_id_...}" to the string directly
>>> # as the Byte tokenizer would incorrectly merge the tokens
>>> # For ByT5, we need to work directly on the character level
>>> # Contrary to T5, ByT5 does not use sentinel tokens for masking, but instead
>>> # uses final utf character ids.
>>> # UTF-8 is represented by 8 bits and ByT5 has 3 special tokens.
>>> # => There are 2**8+2 = 259 input ids and mask tokens count down from index 258.
>>> # => mask to "The dog [258]a ball [257]park."

>>> input_ids = torch.tensor([input_ids[:8] + [258] + input_ids[14:21] + [257] + input_ids[28:]])
>>> input_ids
tensor([[ 87, 107, 104,  35, 103, 114, 106,  35, 258,  35, 100,  35, 101, 100, 111, 111, 257,  35, 115, 100, 117, 110,  49,   1]])

>>> # ByT5 produces only one char at a time so we need to produce many more output characters here -> set `max_length=100`.
>>> output_ids = model.generate(input_ids, max_length=100)[0].tolist()
>>> output_ids
[0, 258, 108, 118,  35, 119, 107, 104,  35, 114, 113, 104,  35, 122, 107, 114,  35, 103, 114, 104, 118, 257,  35, 108, 113,  35, 119, 107, 104,  35, 103, 108, 118, 102, 114, 256, 108, 113,  35, 119, 107, 104, 35, 115, 100, 117, 110,  49,  35,  87, 107, 104,  35, 103, 114, 106, 35, 108, 118,  35, 119, 107, 104,  35, 114, 113, 104,  35, 122, 107, 114,  35, 103, 114, 104, 118,  35, 100,  35, 101, 100, 111, 111,  35, 108, 113, 255,  35, 108, 113,  35, 119, 107, 104,  35, 115, 100, 117, 110,  49]

>>> # ^- Note how 258 descends to 257, 256, 255

>>> # Now we need to split on the sentinel tokens, let's write a short loop for this
>>> output_ids_list = []
>>> start_token = 0
>>> sentinel_token = 258
>>> while sentinel_token in output_ids:
...     split_idx = output_ids.index(sentinel_token)
...     output_ids_list.append(output_ids[start_token:split_idx])
...     start_token = split_idx
...     sentinel_token -= 1

>>> output_ids_list.append(output_ids[start_token:])
>>> output_string = tokenizer.batch_decode(output_ids_list)
>>> output_string
['<pad>', 'is the one who does', ' in the disco', 'in the park. The dog is the one who does a ball in', ' in the park.']

ByT5Tokenizer

class transformers.ByT5Tokenizer

< >

( eos_token = '</s>' unk_token = '<unk>' pad_token = '<pad>' extra_ids = 125 additional_special_tokens = None **kwargs )

参数

  • eos_token (str, 可选, 默认为 "</s>") — 序列结束 token。

    当使用特殊 token 构建序列时,这不是用于序列结束的 token。 使用的 token 是 sep_token

  • unk_token (str, 可选, 默认为 "<unk>") — 未知 token。 词汇表中不存在的 token 无法转换为 ID,而是设置为此 token。
  • pad_token (str, 可选, 默认为 "<pad>") — 用于填充的 token,例如在批量处理不同长度的序列时。
  • extra_ids (int, 可选, 默认为 125) — 添加许多额外的 ID,添加到词汇表的末尾,用作哨兵。 这些 token 可以通过 “” 访问,其中 “{%d}” 是介于 0 和 extra_ids-1 之间的数字。 额外 token 从词汇表的末尾索引到开头(“” 是词汇表中的最后一个 token,如 ByT5 预处理中所见 此处)。
  • additional_special_tokens (List[str], 可选) — 分词器使用的其他特殊 token。

构建 ByT5 分词器。 ByT5 简单地使用原始字节 utf-8 编码。

此分词器继承自 PreTrainedTokenizer,其中包含大多数主要方法。 用户应参考此超类以获取有关这些方法的更多信息。

build_inputs_with_special_tokens

< >

( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) List[int]

参数

  • token_ids_0 (List[int]) — 将向其添加特殊 token 的 ID 列表。
  • token_ids_1 (List[int], 可选) — 用于序列对的可选的第二个 ID 列表。

返回值

List[int]

带有适当特殊 token 的 输入 ID 列表。

通过连接并添加特殊 token,从序列或序列对构建用于序列分类任务的模型输入。 序列具有以下格式

  • 单个序列: X </s>
  • 序列对: A </s> B </s>

convert_tokens_to_string

< >

( tokens )

将 token(字符串)序列转换为单个字符串。

create_token_type_ids_from_sequences

< >

( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None ) List[int]

参数

  • token_ids_0 (List[int]) — ID 列表。
  • token_ids_1 (List[int], 可选) — 用于序列对的可选的第二个 ID 列表。

返回值

List[int]

零列表。

从传递的两个序列创建一个掩码,用于序列对分类任务。 ByT5 不使用 token 类型 ID,因此返回零列表。

get_special_tokens_mask

< >

( token_ids_0: typing.List[int] token_ids_1: typing.Optional[typing.List[int]] = None already_has_special_tokens: bool = False ) List[int]

参数

  • token_ids_0 (List[int]) — ID 列表。
  • token_ids_1 (List[int], 可选) — 用于序列对的可选的第二个 ID 列表。
  • already_has_special_tokens (bool, 可选, 默认为 False) — token 列表是否已使用模型的特殊 token 格式化。

返回值

List[int]

范围 [0, 1] 中的整数列表:1 表示特殊 token,0 表示序列 token。

从没有添加特殊 token 的 token 列表中检索序列 ID。 当使用分词器的 prepare_for_model 方法添加特殊 token 时,将调用此方法。

有关所有详细信息,请参阅 ByT5Tokenizer

< > 在 GitHub 上更新