Transformers 文档

ByT5

ByT5

概述

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中提出。

论文的摘要如下:

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

该模型由patrickvonplaten贡献。原始代码可以在这里找到。

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

由于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 是在跨度掩码去噪任务上训练的。然而,由于模型直接处理字符,预训练任务略有不同。让我们破坏输入句子"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

transformers.ByT5Tokenizer

< >

( eos_token = '' unk_token = '' pad_token = '' extra_ids = 125 additional_special_tokens = None **kwargs )

参数

  • eos_token (str, optional, defaults to "</s>") — The end of sequence token.

    在使用特殊标记构建序列时,这不是用于序列结束的标记。 使用的标记是sep_token

  • unk_token (str, 可选, 默认为 "") — 未知标记。不在词汇表中的标记无法转换为ID,而是设置为这个标记。
  • pad_token (str, optional, defaults to "") — 用于填充的标记,例如在批处理不同长度的序列时使用。
  • extra_ids (int, optional, 默认为 125) — 在词汇表末尾添加一些额外的 id,用作哨兵。这些令牌可以访问为“id{%d}>”,其中“{%d}”是 0 到 extra_ids-1 之间的数字。额外的令牌从词汇表的末尾开始索引到开头(“”是词汇表中的最后一个令牌,类似于 ByT5 预处理,请参见 这里)。
  • additional_special_tokens (List[str], optional) — 分词器使用的额外特殊标记。

构建一个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]) — 特殊令牌将被添加到的ID列表。
  • token_ids_1 (List[int], optional) — 可选的第二个序列对的ID列表。

返回

List[int]

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

通过连接和添加特殊标记,从序列或序列对构建序列分类任务的模型输入。序列的格式如下:

  • 单个序列: X
  • 序列对:A B

convert_tokens_to_string

< >

( tokens )

将一系列标记(字符串)转换为单个字符串。

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], optional) — 可选的第二个序列对的ID列表。

返回

List[int]

零的列表。

从传递给序列对分类任务的两个序列中创建一个掩码。ByT5不使用标记类型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], optional) — 可选的第二个序列对的ID列表。
  • already_has_special_tokens (bool, optional, defaults to False) — 是否已经为模型格式化了带有特殊标记的标记列表。

返回

List[int]

一个整数列表,范围在[0, 1]:1表示特殊标记,0表示序列标记。

从没有添加特殊标记的标记列表中检索序列ID。当使用标记器的prepare_for_model方法添加特殊标记时,会调用此方法。

查看 ByT5Tokenizer 获取所有详细信息。

< > Update on GitHub