用于推理的多语言模型
原文链接:
huggingface.co/docs/transformers/v4.37.2/en/multilingual
🤗 Transformers 中有几个多语言模型,它们的推理用法与单语模型不同。不过,并非所有多语言模型的用法都不同。一些模型,如bert-base-multilingual-uncased,可以像单语模型一样使用。本指南将向您展示如何使用推理中用法不同的多语言模型。
XLM
XLM 有十个不同的检查点,其中只有一个是单语的。剩下的九个模型检查点可以分为两类:使用语言嵌入和不使用语言嵌入的检查点。
带有语言嵌入的 XLM
以下 XLM 模型使用语言嵌入来指定推理中使用的语言:
xlm-mlm-ende-1024
(掩码语言建模,英语-德语)xlm-mlm-enfr-1024
(掩码语言建模,英语-法语)xlm-mlm-enro-1024
(掩码语言建模,英语-罗马尼亚语)xlm-mlm-xnli15-1024
(掩码语言建模,XNLI 语言)xlm-mlm-tlm-xnli15-1024
(掩码语言建模+翻译,XNLI 语言)xlm-clm-enfr-1024
(因果语言建模,英语-法语)xlm-clm-ende-1024
(因果语言建模,英语-德语)
语言嵌入表示为与传递给模型的input_ids
相同形状的张量。这些张量中的值取决于使用的语言,并由标记器的lang2id
和id2lang
属性识别。
在这个示例中,加载xlm-clm-enfr-1024
检查点(因果语言建模,英语-法语):
>>> import torch >>> from transformers import XLMTokenizer, XLMWithLMHeadModel >>> tokenizer = XLMTokenizer.from_pretrained("xlm-clm-enfr-1024") >>> model = XLMWithLMHeadModel.from_pretrained("xlm-clm-enfr-1024")
标记器的lang2id
属性显示了该模型的语言及其 ID:
>>> print(tokenizer.lang2id) {'en': 0, 'fr': 1
接下来,创建一个示例输入:
>>> input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")]) # batch size of 1
将语言 ID 设置为"en"
,并用它来定义语言嵌入。语言嵌入是一个填充了0
的张量,因为这是英语的语言 ID。这个张量应该与input_ids
的大小相同。
>>> language_id = tokenizer.lang2id["en"] # 0 >>> langs = torch.tensor([language_id] * input_ids.shape[1]) # torch.tensor([0, 0, 0, ..., 0]) >>> # We reshape it to be of size (batch_size, sequence_length) >>> langs = langs.view(1, -1) # is now of shape [1, sequence_length] (we have a batch size of 1)
现在您可以将input_ids
和语言嵌入传递给模型:
>>> outputs = model(input_ids, langs=langs)
run_generation.py脚本可以使用xlm-clm
检查点生成带有语言嵌入的文本。
没有语言嵌入的 XLM
以下 XLM 模型在推理过程中不需要语言嵌入:
xlm-mlm-17-1280
(掩码语言建模,17 种语言)xlm-mlm-100-1280
(掩码语言建模,100 种语言)
这些模型用于通用句子表示,不同于之前的 XLM 检查点。
BERT
以下 BERT 模型可用于多语言任务:
bert-base-multilingual-uncased
(掩码语言建模+下一句预测,102 种语言)bert-base-multilingual-cased
(掩码语言建模+下一句预测,104 种语言)
这些模型在推理过程中不需要语言嵌入。它们应该根据上下文识别语言并相应地推断。
XLM-RoBERTa
以下 XLM-RoBERTa 模型可用于多语言任务:
xlm-roberta-base
(掩码语言建模,100 种语言)xlm-roberta-large
(掩码语言建模,100 种语言)
XLM-RoBERTa 在 100 种语言中新创建和清理的 2.5TB CommonCrawl 数据上进行了训练。在分类、序列标记和问题回答等下游任务上,它比以前发布的多语言模型如 mBERT 或 XLM 提供了强大的性能提升。
M2M100
以下 M2M100 模型可用于多语言翻译:
facebook/m2m100_418M
(翻译)facebook/m2m100_1.2B
(翻译)
在这个示例中,加载facebook/m2m100_418M
检查点以将中文翻译成英文。您可以在标记器中设置源语言:
>>> from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer >>> en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger." >>> chinese_text = "不要插手巫師的事務, 因為他們是微妙的, 很快就會發怒." >>> tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100_418M", src_lang="zh") >>> model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100_418M")
对文本进行标记化:
>>> encoded_zh = tokenizer(chinese_text, return_tensors="pt")
M2M100 强制将目标语言 ID 作为第一个生成的标记以翻译为目标语言。在generate
方法中将forced_bos_token_id
设置为en
以翻译为英语:
>>> generated_tokens = model.generate(**encoded_zh, forced_bos_token_id=tokenizer.get_lang_id("en")) >>> tokenizer.batch_decode(generated_tokens, skip_special_tokens=True) 'Do not interfere with the matters of the witches, because they are delicate and will soon be angry.'
MBart
以下 MBart 模型可用于多语言翻译:
facebook/mbart-large-50-one-to-many-mmt
(一对多多语言机器翻译,50 种语言)facebook/mbart-large-50-many-to-many-mmt
(多对多多语言机器翻译,50 种语言)facebook/mbart-large-50-many-to-one-mmt
(多对一多语言机器翻译,50 种语言)facebook/mbart-large-50
(多语言翻译,50 种语言)facebook/mbart-large-cc25
在此示例中,加载facebook/mbart-large-50-many-to-many-mmt
检查点以将芬兰语翻译为英语。您可以在标记器中设置源语言:
>>> from transformers import AutoTokenizer, AutoModelForSeq2SeqLM >>> en_text = "Do not meddle in the affairs of wizards, for they are subtle and quick to anger." >>> fi_text = "Älä sekaannu velhojen asioihin, sillä ne ovat hienovaraisia ja nopeasti vihaisia." >>> tokenizer = AutoTokenizer.from_pretrained("facebook/mbart-large-50-many-to-many-mmt", src_lang="fi_FI") >>> model = AutoModelForSeq2SeqLM.from_pretrained("facebook/mbart-large-50-many-to-many-mmt")
对文本进行标记化:
>>> encoded_en = tokenizer(en_text, return_tensors="pt")
MBart 强制将目标语言 ID 作为第一个生成的标记以翻译为目标语言。在generate
方法中将forced_bos_token_id
设置为en
以翻译为英语:
>>> generated_tokens = model.generate(**encoded_en, forced_bos_token_id=tokenizer.lang_code_to_id["en_XX"]) >>> tokenizer.batch_decode(generated_tokens, skip_special_tokens=True) "Don't interfere with the wizard's affairs, because they are subtle, will soon get angry."
如果您正在使用facebook/mbart-large-50-many-to-one-mmt
检查点,则不需要强制目标语言 ID 作为第一个生成的标记,否则用法相同。
创建自定义架构
原文链接:
huggingface.co/docs/transformers/v4.37.2/en/create_a_model
AutoClass
会自动推断模型架构并下载预训练配置和权重。通常,我们建议使用AutoClass
生成与检查点无关的代码。但是,希望对特定模型参数有更多控制的用户可以从几个基类创建一个自定义🤗 Transformers 模型。这对于任何对研究、训练或实验🤗 Transformers 模型感兴趣的人特别有用。在本指南中,深入了解如何创建一个自定义模型而不使用AutoClass
。学习如何:
- 加载并自定义模型配置。
- 创建模型架构。
- 为文本创建慢速和快速分词器。
- 为视觉任务创建图像处理器。
- 为音频任务创建特征提取器。
- 为多模态任务创建处理器。
配置
configuration 指的是模型的特定属性。每个模型配置都有不同的属性;例如,所有 NLP 模型都共有hidden_size
、num_attention_heads
、num_hidden_layers
和vocab_size
属性。这些属性指定了构建模型所需的注意力头或隐藏层的数量。
通过访问 DistilBertConfig 来查看其属性,进一步了解 DistilBERT:
>>> from transformers import DistilBertConfig >>> config = DistilBertConfig() >>> print(config) DistilBertConfig { "activation": "gelu", "attention_dropout": 0.1, "dim": 768, "dropout": 0.1, "hidden_dim": 3072, "initializer_range": 0.02, "max_position_embeddings": 512, "model_type": "distilbert", "n_heads": 12, "n_layers": 6, "pad_token_id": 0, "qa_dropout": 0.1, "seq_classif_dropout": 0.2, "sinusoidal_pos_embds": false, "transformers_version": "4.16.2", "vocab_size": 30522 }
DistilBertConfig 显示了用于构建基本 DistilBertModel 的所有默认属性。所有属性都是可定制的,为实验创造了空间。例如,您可以自定义一个默认模型:
- 使用
activation
参数尝试不同的激活函数。 - 使用
attention_dropout
参数为注意力概率设置更高的 dropout 比率。
>>> my_config = DistilBertConfig(activation="relu", attention_dropout=0.4) >>> print(my_config) DistilBertConfig { "activation": "relu", "attention_dropout": 0.4, "dim": 768, "dropout": 0.1, "hidden_dim": 3072, "initializer_range": 0.02, "max_position_embeddings": 512, "model_type": "distilbert", "n_heads": 12, "n_layers": 6, "pad_token_id": 0, "qa_dropout": 0.1, "seq_classif_dropout": 0.2, "sinusoidal_pos_embds": false, "transformers_version": "4.16.2", "vocab_size": 30522 }
预训练模型属性可以在 from_pretrained()函数中修改:
>>> my_config = DistilBertConfig.from_pretrained("distilbert-base-uncased", activation="relu", attention_dropout=0.4)
一旦您满意您的模型配置,您可以用 save_pretrained()保存它。您的配置文件将以 JSON 文件的形式存储在指定的保存目录中:
>>> my_config.save_pretrained(save_directory="./your_model_save_path")
要重用配置文件,请使用 from_pretrained()加载它:
>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")
您还可以将配置文件保存为字典,甚至只保存自定义配置属性与默认配置属性之间的差异!查看 configuration 文档以获取更多详细信息。
模型
下一步是创建一个 model。模型 - 也宽泛地称为架构 - 定义了每个层正在做什么以及正在发生的操作。像num_hidden_layers
这样的配置属性用于定义架构。每个模型都共享基类 PreTrainedModel 和一些常见方法,如调整输入嵌入和修剪自注意力头。此外,所有模型也是torch.nn.Module
、tf.keras.Model
或flax.linen.Module
的子类。这意味着模型与各自框架的使用是兼容的。
Pytorch 隐藏 Pytorch 内容
将您的自定义配置属性加载到模型中:
>>> from transformers import DistilBertModel >>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json") >>> model = DistilBertModel(my_config)
这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您无法将此模型用于任何有用的目的。训练是一个昂贵且耗时的过程。通常最好使用预训练模型以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。
使用 from_pretrained()创建一个预训练模型:
>>> model = DistilBertModel.from_pretrained("distilbert-base-uncased")
当加载预训练权重时,如果模型由🤗 Transformers 提供,则默认模型配置会自动加载。但是,如果您愿意,仍然可以替换 - 一些或全部 - 默认模型配置属性为您自己的属性:
>>> model = DistilBertModel.from_pretrained("distilbert-base-uncased", config=my_config)
TensorFlow 隐藏 TensorFlow 内容
将您的自定义配置属性加载到模型中:
>>> from transformers import TFDistilBertModel >>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/my_config.json") >>> tf_model = TFDistilBertModel(my_config)
这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您无法将此模型用于任何有用的目的。训练是一个昂贵且耗时的过程。通常最好使用预训练模型以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。
使用 from_pretrained()创建一个预训练模型:
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert-base-uncased")
当加载预训练权重时,如果模型由🤗 Transformers 提供,则默认模型配置会自动加载。但是,如果您愿意,仍然可以替换 - 一些或全部 - 默认模型配置属性为您自己的属性:
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert-base-uncased", config=my_config)
模型头
此时,您有一个输出隐藏状态的基础 DistilBERT 模型。隐藏状态作为输入传递给模型头,以产生最终输出。只要模型支持任务(即,您不能将 DistilBERT 用于像翻译这样的序列到序列任务),🤗 Transformers 为每个任务提供不同的模型头。
Pytorch 隐藏 Pytorch 内容
例如,DistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在汇总输出之上的线性层。
>>> from transformers import DistilBertForSequenceClassification >>> model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")
通过切换到不同的模型头轻松地为另一个任务重用此检查点。对于问答任务,您将使用 DistilBertForQuestionAnswering 模型头。问答头类似于序列分类头,只是它是在隐藏状态输出之上的线性层。
>>> from transformers import DistilBertForQuestionAnswering >>> model = DistilBertForQuestionAnswering.from_pretrained("distilbert-base-uncased")
TensorFlow 隐藏 TensorFlow 内容
例如,TFDistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在汇总输出之上的线性层。
>>> from transformers import TFDistilBertForSequenceClassification >>> tf_model = TFDistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")
通过切换到不同的模型头轻松地为另一个任务重用此检查点。对于问答任务,您将使用 TFDistilBertForQuestionAnswering 模型头。问答头类似于序列分类头,只是它是在隐藏状态输出之上的线性层。
>>> from transformers import TFDistilBertForQuestionAnswering >>> tf_model = TFDistilBertForQuestionAnswering.from_pretrained("distilbert-base-uncased")
Tokenizer
在使用模型处理文本数据之前,您需要的最后一个基类是 tokenizer 将原始文本转换为张量。您可以使用🤗 Transformers 的两种类型的 tokenizer:
- PreTrainedTokenizer:一个 tokenizer 的 Python 实现。
- PreTrainedTokenizerFast:来自我们基于 Rust 的🤗 Tokenizer库的一个分词器。这种分词器类型速度明显更快 - 特别是在批量分词时 - 这是由于其 Rust 实现。快速分词器还提供了额外的方法,比如偏移映射,将标记映射到它们的原始单词或字符。
两种分词器都支持常见方法,如编码和解码、添加新标记和管理特殊标记。
并非每个模型都支持快速分词器。查看这个 table 以检查模型是否支持快速分词器。
如果您训练了自己的分词器,可以从您的vocabulary文件创建一个:
>>> from transformers import DistilBertTokenizer >>> my_tokenizer = DistilBertTokenizer(vocab_file="my_vocab_file.txt", do_lower_case=False, padding_side="left")
重要的是要记住,自定义分词器的词汇表与预训练模型的分词器生成的词汇表是不同的。如果您使用预训练模型,则需要使用预训练模型的词汇表,否则输入将没有意义。使用 DistilBertTokenizer 类创建一个带有预训练模型词汇表的分词器:
>>> from transformers import DistilBertTokenizer >>> slow_tokenizer = DistilBertTokenizer.from_pretrained("distilbert-base-uncased")
使用 DistilBertTokenizerFast 类创建一个快速分词器:
>>> from transformers import DistilBertTokenizerFast >>> fast_tokenizer = DistilBertTokenizerFast.from_pretrained("distilbert-base-uncased")
默认情况下,AutoTokenizer 将尝试加载一个快速分词器。您可以通过在from_pretrained
中设置use_fast=False
来禁用此行为。
图像处理器
图像处理器处理视觉输入。它继承自基础 ImageProcessingMixin 类。
要使用,创建一个与您正在使用的模型相关联的图像处理器。例如,如果您正在使用 ViT 进行图像分类,则创建一个默认的 ViTImageProcessor:
>>> from transformers import ViTImageProcessor >>> vit_extractor = ViTImageProcessor() >>> print(vit_extractor) ViTImageProcessor { "do_normalize": true, "do_resize": true, "image_processor_type": "ViTImageProcessor", "image_mean": [ 0.5, 0.5, 0.5 ], "image_std": [ 0.5, 0.5, 0.5 ], "resample": 2, "size": 224 }
如果您不需要任何自定义,只需使用from_pretrained
方法加载模型的默认图像处理器参数。
修改任何 ViTImageProcessor 参数以创建您自定义的图像处理器:
>>> from transformers import ViTImageProcessor >>> my_vit_extractor = ViTImageProcessor(resample="PIL.Image.BOX", do_normalize=False, image_mean=[0.3, 0.3, 0.3]) >>> print(my_vit_extractor) ViTImageProcessor { "do_normalize": false, "do_resize": true, "image_processor_type": "ViTImageProcessor", "image_mean": [ 0.3, 0.3, 0.3 ], "image_std": [ 0.5, 0.5, 0.5 ], "resample": "PIL.Image.BOX", "size": 224 }
Transformers 4.37 中文文档(七)(2)https://developer.aliyun.com/article/1564149