NLLB
更新后的分词器行为
**免责声明:** 分词器的默认行为已在 2023 年 4 月修复,因此已更改。之前的版本在目标和源标记化的标记序列末尾添加了 `[self.eos_token_id, self.cur_lang_code]`。这是错误的,正如 NLLB 论文中提到的那样(第 48 页,6.1.1. 模型架构)
请注意,我们会在源序列前面加上源语言,这与之前在几项工作中所做的目标语言相反(Arivazhagan et al., 2019; Johnson et al., 2017)。这主要是因为我们优先考虑以轻微的监督性能成本优化我们模型在任何 200 种语言对上的零样本性能。
之前的行为
>>> from transformers import NllbTokenizer
>>> tokenizer = NllbTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
>>> tokenizer("How was your day?").input_ids
[13374, 1398, 4260, 4039, 248130, 2, 256047]
>>> # 2: '</s>'
>>> # 256047 : 'eng_Latn'
新行为
>>> from transformers import NllbTokenizer
>>> tokenizer = NllbTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
>>> tokenizer("How was your day?").input_ids
[256047, 13374, 1398, 4260, 4039, 248130, 2]
可以通过以下方式启用旧行为
>>> from transformers import NllbTokenizer
>>> tokenizer = NllbTokenizer.from_pretrained("facebook/nllb-200-distilled-600M", legacy_behaviour=True)
概述
NLLB 模型在 Marta R. Costa-jussà、James Cross、Onur Çelebi、Maha Elbayad、Kenneth Heafield、Kevin Heffernan、Elahe Kalbassi、Janice Lam、Daniel Licht、Jean Maillard、Anna Sun、Skyler Wang、Guillaume Wenzek、Al Youngblood、Bapi Akula、Loic Barrault、Gabriel Mejia Gonzalez、Prangthip Hansanti、John Hoffman、Semarley Jarrett、Kaushik Ram Sadagopan、Dirk Rowe、Shannon Spruit、Chau Tran、Pierre Andrews、Necip Fazil Ayan、Shruti Bhosale、Sergey Edunov、Angela Fan、Cynthia Gao、Vedanuj Goswami、Francisco Guzmán、Philipp Koehn、Alexandre Mourachko、Christophe Ropers、Safiyyah Saleem、Holger Schwenk 和 Jeff Wang 发表的 不落下任何语言:扩展以人为本的机器翻译 一文中提出。
该论文的摘要是:
在消除全球语言障碍的目标的推动下,机器翻译已成为当今人工智能研究的一个关键焦点。然而,这些努力都集中在少数几种语言上,而忽略了绝大多数主要是低资源语言。在确保安全、高质量的结果,同时兼顾道德因素的情况下,突破 200 种语言的障碍需要付出什么?在“不落下任何语言”中,我们首先通过与母语人士的探索性访谈,将对低资源语言翻译支持的需求置于背景中,从而应对这一挑战。然后,我们创建了旨在缩小低资源语言和高资源语言之间性能差距的数据集和模型。更具体地说,我们开发了一种基于稀疏门控专家混合的条件计算模型,该模型使用针对低资源语言量身定制的新颖有效的挖掘技术获得的数据进行训练。我们提出了多项架构和训练改进,以在对数千个任务进行训练时抵消过度拟合。至关重要的是,我们使用人工翻译的基准 Flores-200 评估了超过 40,000 个不同翻译方向的性能,并将人工评估与涵盖 Flores-200 中所有语言的新型毒性基准相结合,以评估翻译安全性。与之前最先进的技术相比,我们的模型实现了 44% 的 BLEU 改进,为实现通用翻译系统奠定了重要基础。
此实现包含发布时可用的密集模型。
稀疏模型 NLLB-MoE(专家混合)现已推出!更多详情请参见此处
此模型由 Lysandre 贡献。作者的代码可以在 此处 找到。
使用 NLLB 生成
生成目标文本时,将 `forced_bos_token_id` 设置为目标语言 ID。以下示例展示了如何使用 *facebook/nllb-200-distilled-600M* 模型将英语翻译成法语。
请注意,我们使用的是法语的 BCP-47 代码 `fra_Latn`。有关 Flores 200 数据集中所有 BCP-47 代码的列表,请参见此处。
>>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
>>> model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M")
>>> article = "UN Chief says there is no military solution in Syria"
>>> inputs = tokenizer(article, return_tensors="pt")
>>> translated_tokens = model.generate(
... **inputs, forced_bos_token_id=tokenizer.convert_tokens_to_ids("fra_Latn"), max_length=30
... )
>>> tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
Le chef de l'ONU dit qu'il n'y a pas de solution militaire en Syrie
从英语以外的任何其他语言生成
英语 (eng_Latn
) 被设置为默认的翻译源语言。要指定从其他语言进行翻译,您应该在分词器初始化的 src_lang
关键字参数中指定 BCP-47 代码。
请参阅以下从罗马尼亚语翻译成德语的示例
>>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained(
... "facebook/nllb-200-distilled-600M", token=True, src_lang="ron_Latn"
... )
>>> model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M", token=True)
>>> article = "Şeful ONU spune că nu există o soluţie militară în Siria"
>>> inputs = tokenizer(article, return_tensors="pt")
>>> translated_tokens = model.generate(
... **inputs, forced_bos_token_id=tokenizer.convert_tokens_to_ids("deu_Latn"), max_length=30
... )
>>> tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
UN-Chef sagt, es gibt keine militärische Lösung in Syrien
资源
NllbTokenizer
类 transformers.NllbTokenizer
< 源代码 >( vocab_file bos_token = '<s>' eos_token = '</s>' sep_token = '</s>' cls_token = '<s>' unk_token = '<unk>' pad_token = '<pad>' mask_token = '<mask>' tokenizer_file = None src_lang = None tgt_lang = None sp_model_kwargs: Optional = None additional_special_tokens = None legacy_behaviour = False **kwargs )
参数
- vocab_file (
str
) — 词汇表文件的路径。 - bos_token (
str
, 可选, 默认值为"<s>"
) — 预训练期间使用的序列开始标记。可以用作序列分类标记。使用特殊标记构建序列时,这不是用于序列开头的标记。使用的标记是
cls_token
。 - eos_token (
str
, 可选, 默认为"</s>"
) — 序列结束标记。使用特殊标记构建序列时,这不是用于序列结尾的标记。使用的标记是
sep_token
。 - sep_token (
str
, 可选, 默认为"</s>"
) — 分隔标记,用于从多个序列构建序列时,例如,用于序列分类的两个序列或用于问答的文本和问题。它还用作使用特殊标记构建的序列的最后一个标记。 - cls_token (
str
, 可选, 默认为"<s>"
) — 分类标记,在进行序列分类(对整个序列进行分类而不是对每个标记进行分类)时使用。它是使用特殊标记构建的序列的第一个标记。 - unk_token (
str
, 可选, 默认为"<unk>"
) — 未知标记。不在词汇表中的标记无法转换为 ID,而是设置为该标记。 - pad_token (
str
, 可选, 默认为"<pad>"
) — 用于填充的标记,例如,对不同长度的序列进行批处理时。 - mask_token (
str
, 可选, 默认为"<mask>"
) — 用于掩盖值的标记。这是使用掩码语言建模训练此模型时使用的标记。这是模型将尝试预测的标记。 - tokenizer_file (
str
, 可选) — 用于代替词汇文件的 tokenizer 文件的路径。 - src_lang (
str
, 可选) — 用作翻译源语言的语言。 - tgt_lang (
str
, 可选) — 用作翻译目标语言的语言。 - sp_model_kwargs (
Dict[str, str]
) — 要传递给模型初始化的其他关键字参数。
构造一个 NLLB 分词器。
改编自 RobertaTokenizer 和 XLNetTokenizer。 基于 SentencePiece。
对于源语言文档,分词方法是 <tokens> <eos> <language code>
,对于目标语言文档,分词方法是 `<language code>
示例
>>> from transformers import NllbTokenizer
>>> tokenizer = NllbTokenizer.from_pretrained(
... "facebook/nllb-200-distilled-600M", src_lang="eng_Latn", tgt_lang="fra_Latn"
... )
>>> example_english_phrase = " UN Chief Says There Is No Military Solution in Syria"
>>> expected_translation_french = "Le chef de l'ONU affirme qu'il n'y a pas de solution militaire en Syrie."
>>> inputs = tokenizer(example_english_phrase, text_target=expected_translation_french, return_tensors="pt")
build_inputs_with_special_tokens
< source >( token_ids_0: List token_ids_1: Optional = None ) → List[int]
通过连接序列并添加特殊标记,从一个序列或一对序列构建用于序列分类任务的模型输入。 NLLB 序列具有以下格式,其中 X
表示序列
input_ids
(对于编码器)X [eos, src_lang_code]
decoder_input_ids
: (对于解码器)X [eos, tgt_lang_code]
从不使用 BOS。 序列对不是预期的用例,但它们将在没有分隔符的情况下进行处理。
NllbTokenizerFast
类 transformers.NllbTokenizerFast
< source >( vocab_file = None tokenizer_file = None bos_token = '<s>' eos_token = '</s>' sep_token = '</s>' cls_token = '<s>' unk_token = '<unk>' pad_token = '<pad>' mask_token = '<mask>' src_lang = None tgt_lang = None additional_special_tokens = None legacy_behaviour = False **kwargs )
参数
- vocab_file (
str
) — 词汇表文件的路径。 - bos_token (
str
, 可选, 默认值"<s>"
) — 在预训练期间使用的序列开始标记。可以用作序列分类标记。使用特殊标记构建序列时,这不是用于序列开头的标记。使用的标记是
cls_token
。 - eos_token (
str
, 可选, 默认值"</s>"
) — 序列结束标记。使用特殊标记构建序列时,这不是用于序列结尾的标记。使用的标记是
sep_token
。 - sep_token (
str
,可选,默认为"</s>"
) — 分隔符标记,用于从多个序列构建序列时使用,例如用于序列分类的两个序列,或用于问答的文本和问题。它也用作使用特殊标记构建的序列的最后一个标记。 - cls_token (
str
,可选,默认为"<s>"
) — 分类符标记,用于执行序列分类(对整个序列进行分类,而不是对每个标记进行分类)时使用。它是使用特殊标记构建的序列的第一个标记。 - unk_token (
str
,可选,默认为"<unk>"
) — 未知标记。不在词汇表中的标记无法转换为 ID,并将设置为该标记。 - pad_token (
str
,可选,默认为"<pad>"
) — 用于填充的标记,例如在对不同长度的序列进行批处理时。 - mask_token (
str
,可选,默认为"<mask>"
) — 用于屏蔽值的标记。这是使用掩码语言建模训练此模型时使用的标记。这是模型将尝试预测的标记。 - tokenizer_file (
str
,可选) — 用于代替词汇表文件的 tokenizer 文件的路径。 - src_lang (
str
,可选) — 用作翻译源语言的语言。 - tgt_lang (
str
,可选) — 用作翻译目标语言的语言。
构造一个“快速”NLLB 分词器(由 HuggingFace 的 *tokenizers* 库支持)。基于 BPE。
此分词器继承自 PreTrainedTokenizerFast,其中包含大多数主要方法。用户应参考此超类以获取有关这些方法的更多信息。
对于源语言文档,分词方法是 <tokens> <eos> <language code>
,对于目标语言文档,分词方法是 `<language code>
示例
>>> from transformers import NllbTokenizerFast
>>> tokenizer = NllbTokenizerFast.from_pretrained(
... "facebook/nllb-200-distilled-600M", src_lang="eng_Latn", tgt_lang="fra_Latn"
... )
>>> example_english_phrase = " UN Chief Says There Is No Military Solution in Syria"
>>> expected_translation_french = "Le chef de l'ONU affirme qu'il n'y a pas de solution militaire en Syrie."
>>> inputs = tokenizer(example_english_phrase, text_target=expected_translation_french, return_tensors="pt")
build_inputs_with_special_tokens
< source >( token_ids_0: List token_ids_1: Optional = None ) → List[int]
通过连接和添加特殊标记,从序列或序列对构建模型输入,用于序列分类任务。 特殊标记取决于调用 set_lang。
NLLB 序列具有以下格式,其中 X
表示序列
input_ids
(对于编码器)X [eos, src_lang_code]
decoder_input_ids
: (对于解码器)X [eos, tgt_lang_code]
从不使用 BOS。 序列对不是预期的用例,但它们将在没有分隔符的情况下进行处理。
create_token_type_ids_from_sequences
< source >( token_ids_0: List token_ids_1: Optional = None ) → List[int]
从传递的两个序列中创建一个掩码,用于序列对分类任务。 nllb 不使用标记类型 ID,因此返回一个零列表。
将特殊标记重置为源语言设置。
- 在旧模式下:无前缀,后缀为 [eos, src_lang_code]。
- 在默认模式下:前缀为 [src_lang_code],后缀为 [eos]。
将特殊标记重置为目标语言设置。
- 在旧模式下:无前缀,后缀为 [eos, tgt_lang_code]。
- 在默认模式下:前缀为 [tgt_lang_code],后缀为 [eos]。
使用 Flash Attention 2
Flash Attention 2 是一种更快、更优化的注意力分数计算版本,它依赖于 cuda
内核。
安装
首先,检查您的硬件是否与 Flash Attention 2 兼容。您可以在官方文档中找到兼容硬件的最新列表。
接下来,安装最新版本的 Flash Attention 2。
pip install -U flash-attn --no-build-isolation
用法
要使用 Flash Attention 2 加载模型,我们可以将参数 attn_implementation="flash_attention_2"
传递给 .from_pretrained
。您可以使用 torch.float16
或 torch.bfloat16
精度。
>>> import torch
>>> from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
>>> model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M", torch_dtype=torch.float16, attn_implementation="flash_attention_2").to("cuda").eval()
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/nllb-200-distilled-600M")
>>> article = "Şeful ONU spune că nu există o soluţie militară în Siria"
>>> inputs = tokenizer(article, return_tensors="pt").to("cuda")
>>> translated_tokens = model.generate(
... **inputs, forced_bos_token_id=tokenizer.convert_tokens_to_ids("deu_Latn"), max_length=30
... )
>>> tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
"UN-Chef sagt, es gibt keine militärische Lösung in Syrien"
预期加速比
下图是一个预期加速比图,比较了原生实现和 Flash Attention 2 之间的纯推理时间。
使用缩放点积注意力 (SDPA)
PyTorch 在 torch.nn.functional
中包含一个原生缩放点积注意力 (SDPA) 运算符。此函数包含多个实现,可根据输入和使用的硬件应用。有关更多信息,请参阅官方文档或GPU 推理页面。
当实现可用时,SDPA 默认用于 torch>=2.1.1
,但您也可以在 from_pretrained()
中设置 attn_implementation="sdpa"
以显式请求使用 SDPA。
from transformers import AutoModelForSeq2SeqLM
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-distilled-600M", torch_dtype=torch.float16, attn_implementation="sdpa")
...
为了获得最佳加速,我们建议以半精度加载模型(例如 torch.float16
或 torch.bfloat16
)。