前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Transformers 4.37 中文文档(七)

Transformers 4.37 中文文档(七)

作者头像
ApacheCN_飞龙
发布2024-06-26 14:47:08
1460
发布2024-06-26 14:47:08
举报
文章被收录于专栏:信数据得永生

原文:huggingface.co/docs/transformers

用于推理的多语言模型

原文链接: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相同形状的张量。这些张量中的值取决于使用的语言,并由标记器的lang2idid2lang属性识别。

在这个示例中,加载xlm-clm-enfr-1024检查点(因果语言建模,英语-法语):

代码语言:javascript
复制
>>> 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:

代码语言:javascript
复制
>>> print(tokenizer.lang2id)
{'en': 0, 'fr': 1}

接下来,创建一个示例输入:

代码语言:javascript
复制
>>> input_ids = torch.tensor([tokenizer.encode("Wikipedia was used to")])  # batch size of 1

将语言 ID 设置为"en",并用它来定义语言嵌入。语言嵌入是一个填充了0的张量,因为这是英语的语言 ID。这个张量应该与input_ids的大小相同。

代码语言:javascript
复制
>>> 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和语言嵌入传递给模型:

代码语言:javascript
复制
>>> 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检查点以将中文翻译成英文。您可以在标记器中设置源语言:

代码语言:javascript
复制
>>> 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")

对文本进行标记化:

代码语言:javascript
复制
>>> encoded_zh = tokenizer(chinese_text, return_tensors="pt")

M2M100 强制将目标语言 ID 作为第一个生成的标记以翻译为目标语言。在generate方法中将forced_bos_token_id设置为en以翻译为英语:

代码语言:javascript
复制
>>> 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检查点以将芬兰语翻译为英语。您可以在标记器中设置源语言:

代码语言:javascript
复制
>>> 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")

对文本进行标记化:

代码语言:javascript
复制
>>> encoded_en = tokenizer(en_text, return_tensors="pt")

MBart 强制将目标语言 ID 作为第一个生成的标记以翻译为目标语言。在generate方法中将forced_bos_token_id设置为en以翻译为英语:

代码语言:javascript
复制
>>> 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_sizenum_attention_headsnum_hidden_layersvocab_size属性。这些属性指定了构建模型所需的注意力头或隐藏层的数量。

通过访问 DistilBertConfig 来查看其属性,进一步了解 DistilBERT:

代码语言:javascript
复制
>>> 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 比率。
代码语言:javascript
复制
>>> 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()函数中修改:

代码语言:javascript
复制
>>> my_config = DistilBertConfig.from_pretrained("distilbert-base-uncased", activation="relu", attention_dropout=0.4)

一旦您满意您的模型配置,您可以用 save_pretrained()保存它。您的配置文件将以 JSON 文件的形式存储在指定的保存目录中:

代码语言:javascript
复制
>>> my_config.save_pretrained(save_directory="./your_model_save_path")

要重用配置文件,请使用 from_pretrained()加载它:

代码语言:javascript
复制
>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")

您还可以将配置文件保存为字典,甚至只保存自定义配置属性与默认配置属性之间的差异!查看 configuration 文档以获取更多详细信息。

模型

下一步是创建一个 model。模型 - 也宽泛地称为架构 - 定义了每个层正在做什么以及正在发生的操作。像num_hidden_layers这样的配置属性用于定义架构。每个模型都共享基类 PreTrainedModel 和一些常见方法,如调整输入嵌入和修剪自注意力头。此外,所有模型也是torch.nn.Moduletf.keras.Modelflax.linen.Module的子类。这意味着模型与各自框架的使用是兼容的。

Pytorch 隐藏 Pytorch 内容

将您的自定义配置属性加载到模型中:

代码语言:javascript
复制
>>> from transformers import DistilBertModel

>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/config.json")
>>> model = DistilBertModel(my_config)

这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您无法将此模型用于任何有用的目的。训练是一个昂贵且耗时的过程。通常最好使用预训练模型以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。

使用 from_pretrained()创建一个预训练模型:

代码语言:javascript
复制
>>> model = DistilBertModel.from_pretrained("distilbert-base-uncased")

当加载预训练权重时,如果模型由🤗 Transformers 提供,则默认模型配置会自动加载。但是,如果您愿意,仍然可以替换 - 一些或全部 - 默认模型配置属性为您自己的属性:

代码语言:javascript
复制
>>> model = DistilBertModel.from_pretrained("distilbert-base-uncased", config=my_config)

TensorFlow 隐藏 TensorFlow 内容

将您的自定义配置属性加载到模型中:

代码语言:javascript
复制
>>> from transformers import TFDistilBertModel

>>> my_config = DistilBertConfig.from_pretrained("./your_model_save_path/my_config.json")
>>> tf_model = TFDistilBertModel(my_config)

这将创建一个具有随机值而不是预训练权重的模型。在训练之前,您无法将此模型用于任何有用的目的。训练是一个昂贵且耗时的过程。通常最好使用预训练模型以更快地获得更好的结果,同时仅使用训练所需资源的一小部分。

使用 from_pretrained()创建一个预训练模型:

代码语言:javascript
复制
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert-base-uncased")

当加载预训练权重时,如果模型由🤗 Transformers 提供,则默认模型配置会自动加载。但是,如果您愿意,仍然可以替换 - 一些或全部 - 默认模型配置属性为您自己的属性:

代码语言:javascript
复制
>>> tf_model = TFDistilBertModel.from_pretrained("distilbert-base-uncased", config=my_config)
模型头

此时,您有一个输出隐藏状态的基础 DistilBERT 模型。隐藏状态作为输入传递给模型头,以产生最终输出。只要模型支持任务(即,您不能将 DistilBERT 用于像翻译这样的序列到序列任务),🤗 Transformers 为每个任务提供不同的模型头。

Pytorch 隐藏 Pytorch 内容

例如,DistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在汇总输出之上的线性层。

代码语言:javascript
复制
>>> from transformers import DistilBertForSequenceClassification

>>> model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")

通过切换到不同的模型头轻松地为另一个任务重用此检查点。对于问答任务,您将使用 DistilBertForQuestionAnswering 模型头。问答头类似于序列分类头,只是它是在隐藏状态输出之上的线性层。

代码语言:javascript
复制
>>> from transformers import DistilBertForQuestionAnswering

>>> model = DistilBertForQuestionAnswering.from_pretrained("distilbert-base-uncased")

TensorFlow 隐藏 TensorFlow 内容

例如,TFDistilBertForSequenceClassification 是一个带有序列分类头的基础 DistilBERT 模型。序列分类头是在汇总输出之上的线性层。

代码语言:javascript
复制
>>> from transformers import TFDistilBertForSequenceClassification

>>> tf_model = TFDistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")

通过切换到不同的模型头轻松地为另一个任务重用此检查点。对于问答任务,您将使用 TFDistilBertForQuestionAnswering 模型头。问答头类似于序列分类头,只是它是在隐藏状态输出之上的线性层。

代码语言:javascript
复制
>>> 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文件创建一个:

代码语言:javascript
复制
>>> from transformers import DistilBertTokenizer

>>> my_tokenizer = DistilBertTokenizer(vocab_file="my_vocab_file.txt", do_lower_case=False, padding_side="left")

重要的是要记住,自定义分词器的词汇表与预训练模型的分词器生成的词汇表是不同的。如果您使用预训练模型,则需要使用预训练模型的词汇表,否则输入将没有意义。使用 DistilBertTokenizer 类创建一个带有预训练模型词汇表的分词器:

代码语言:javascript
复制
>>> from transformers import DistilBertTokenizer

>>> slow_tokenizer = DistilBertTokenizer.from_pretrained("distilbert-base-uncased")

使用 DistilBertTokenizerFast 类创建一个快速分词器:

代码语言:javascript
复制
>>> from transformers import DistilBertTokenizerFast

>>> fast_tokenizer = DistilBertTokenizerFast.from_pretrained("distilbert-base-uncased")

默认情况下,AutoTokenizer 将尝试加载一个快速分词器。您可以通过在from_pretrained中设置use_fast=False来禁用此行为。

图像处理器

图像处理器处理视觉输入。它继承自基础 ImageProcessingMixin 类。

要使用,创建一个与您正在使用的模型相关联的图像处理器。例如,如果您正在使用 ViT 进行图像分类,则创建一个默认的 ViTImageProcessor:

代码语言:javascript
复制
>>> 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 参数以创建您自定义的图像处理器:

代码语言:javascript
复制
>>> 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
}

特征提取器

特征提取器处理音频输入。它继承自基础 FeatureExtractionMixin 类,并且还可以继承自 SequenceFeatureExtractor 类来处理音频输入。

要使用,创建一个与您正在使用的模型相关联的特征提取器。例如,如果您正在使用 Wav2Vec2 进行音频分类,则创建一个默认的 Wav2Vec2FeatureExtractor:

代码语言:javascript
复制
>>> from transformers import Wav2Vec2FeatureExtractor

>>> w2v2_extractor = Wav2Vec2FeatureExtractor()
>>> print(w2v2_extractor)
Wav2Vec2FeatureExtractor {
  "do_normalize": true,
  "feature_extractor_type": "Wav2Vec2FeatureExtractor",
  "feature_size": 1,
  "padding_side": "right",
  "padding_value": 0.0,
  "return_attention_mask": false,
  "sampling_rate": 16000
}

如果您不需要任何自定义,只需使用from_pretrained方法加载模型的默认特征提取器参数。

修改任何 Wav2Vec2FeatureExtractor 参数以创建您自定义的特征提取器:

代码语言:javascript
复制
>>> from transformers import Wav2Vec2FeatureExtractor

>>> w2v2_extractor = Wav2Vec2FeatureExtractor(sampling_rate=8000, do_normalize=False)
>>> print(w2v2_extractor)
Wav2Vec2FeatureExtractor {
  "do_normalize": false,
  "feature_extractor_type": "Wav2Vec2FeatureExtractor",
  "feature_size": 1,
  "padding_side": "right",
  "padding_value": 0.0,
  "return_attention_mask": false,
  "sampling_rate": 8000
}

处理器

对于支持多模态任务的模型,🤗 Transformers 提供了一个处理器类,方便地将处理类(如特征提取器和分词器)包装成一个单一对象。例如,让我们使用 Wav2Vec2Processor 来进行自动语音识别任务(ASR)。ASR 将音频转录为文本,因此您将需要一个特征提取器和一个分词器。

创建一个特征提取器来处理音频输入:

代码语言:javascript
复制
>>> from transformers import Wav2Vec2FeatureExtractor

>>> feature_extractor = Wav2Vec2FeatureExtractor(padding_value=1.0, do_normalize=True)

创建一个分词器来处理文本输入:

代码语言:javascript
复制
>>> from transformers import Wav2Vec2CTCTokenizer

>>> tokenizer = Wav2Vec2CTCTokenizer(vocab_file="my_vocab_file.txt")

将特征提取器和分词器组合在 Wav2Vec2Processor 中:

代码语言:javascript
复制
>>> from transformers import Wav2Vec2Processor

>>> processor = Wav2Vec2Processor(feature_extractor=feature_extractor, tokenizer=tokenizer)

通过两个基本类 - 配置和模型 - 以及额外的预处理类(分词器、图像处理器、特征提取器或处理器),您可以创建🤗 Transformers 支持的任何模型。这些基本类都是可配置的,允许您使用您想要的特定属性。您可以轻松设置一个用于训练的模型或修改现有的预训练模型进行微调。

构建自定义模型

原文链接:huggingface.co/docs/transformers/v4.37.2/en/custom_models

🤗 Transformers 库被设计为易于扩展。每个模型都完全在存储库的给定子文件夹中编码,没有抽象,因此您可以轻松复制一个建模文件并根据需要进行调整。

如果您正在编写全新的模型,从头开始可能更容易。在本教程中,我们将向您展示如何编写自定义模型及其配置,以便可以在 Transformers 中使用,并且您可以与社区共享(以及它所依赖的代码),以便任何人都可以使用它,即使它不在🤗 Transformers 库中。我们将看到如何在 transformers 上构建并扩展框架,使用您的钩子和自定义代码。

我们将在 ResNet 模型上说明所有这些,通过将timm 库的 ResNet 类包装到 PreTrainedModel 中。

编写自定义配置

在深入研究模型之前,让我们先编写其配置。模型的配置是一个对象,其中包含构建模型所需的所有信息。正如我们将在下一节中看到的,模型只能接受一个config进行初始化,因此我们确实需要该对象尽可能完整。

在我们的示例中,我们将获取 ResNet 类的一些参数,可能需要进行调整。然后,不同的配置将给我们不同类型的可能的 ResNets。然后我们只需存储这些参数,之前检查其中一些参数的有效性。

代码语言:javascript
复制
from transformers import PretrainedConfig
from typing import List

class ResnetConfig(PretrainedConfig):
    model_type = "resnet"

    def __init__( self,
        block_type="bottleneck",
        layers: List[int] = [3, 4, 6, 3],
        num_classes: int = 1000,
        input_channels: int = 3,
        cardinality: int = 1,
        base_width: int = 64,
        stem_width: int = 64,
        stem_type: str = "",
        avg_down: bool = False,
        **kwargs, ):
        if block_type not in ["basic", "bottleneck"]:
            raise ValueError(f"`block_type` must be 'basic' or bottleneck', got {block_type}.")
        if stem_type not in ["", "deep", "deep-tiered"]:
            raise ValueError(f"`stem_type` must be '', 'deep' or 'deep-tiered', got {stem_type}.")

        self.block_type = block_type
        self.layers = layers
        self.num_classes = num_classes
        self.input_channels = input_channels
        self.cardinality = cardinality
        self.base_width = base_width
        self.stem_width = stem_width
        self.stem_type = stem_type
        self.avg_down = avg_down
        super().__init__(**kwargs)

编写自定义配置时需要记住的三个重要事项如下:

  • 您必须继承自PretrainedConfig
  • 您的PretrainedConfig__init__必须接受任何 kwargs,
  • 这些kwargs需要传递给超类__init__

继承是为了确保您从🤗 Transformers 库中获得所有功能,而另外两个约束来自于PretrainedConfig拥有比您设置的字段更多。当使用from_pretrained方法重新加载配置时,这些字段需要被您的配置接受,然后发送到超类。

为您的配置定义model_type(这里model_type="resnet")不是强制性的,除非您希望将您的模型注册到自动类(请参见最后一节)。

完成后,您可以像处理库中任何其他模型配置一样轻松创建和保存您的配置。以下是我们如何创建一个 resnet50d 配置并保存它:

代码语言:javascript
复制
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d_config.save_pretrained("custom-resnet")

这将在custom-resnet文件夹内保存一个名为config.json的文件。然后,您可以使用from_pretrained方法重新加载您的配置:

代码语言:javascript
复制
resnet50d_config = ResnetConfig.from_pretrained("custom-resnet")

您还可以使用 PretrainedConfig 类的任何其他方法,例如 push_to_hub()直接将您的配置上传到 Hub。

编写自定义模型

现在我们有了 ResNet 配置,我们可以继续编写模型。实际上,我们将编写两个模型:一个从一批图像中提取隐藏特征的模型(类似于 BertModel),一个适用于图像分类的模型(类似于 BertForSequenceClassification)。

如前所述,我们将只编写模型的松散包装,以使示例简单化。在编写此类之前,我们需要做的唯一事情是将块类型与实际块类之间建立映射。然后通过将所有内容传递给ResNet类,从配置中定义模型:

代码语言:javascript
复制
from transformers import PreTrainedModel
from timm.models.resnet import BasicBlock, Bottleneck, ResNet
from .configuration_resnet import ResnetConfig

BLOCK_MAPPING = {"basic": BasicBlock, "bottleneck": Bottleneck}

class ResnetModel(PreTrainedModel):
    config_class = ResnetConfig

    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )

    def forward(self, tensor):
        return self.model.forward_features(tensor)

对于将对图像进行分类的模型,我们只需更改前向方法:

代码语言:javascript
复制
import torch

class ResnetModelForImageClassification(PreTrainedModel):
    config_class = ResnetConfig

    def __init__(self, config):
        super().__init__(config)
        block_layer = BLOCK_MAPPING[config.block_type]
        self.model = ResNet(
            block_layer,
            config.layers,
            num_classes=config.num_classes,
            in_chans=config.input_channels,
            cardinality=config.cardinality,
            base_width=config.base_width,
            stem_width=config.stem_width,
            stem_type=config.stem_type,
            avg_down=config.avg_down,
        )

    def forward(self, tensor, labels=None):
        logits = self.model(tensor)
        if labels is not None:
            loss = torch.nn.cross_entropy(logits, labels)
            return {"loss": loss, "logits": logits}
        return {"logits": logits}

在这两种情况下,请注意我们如何从PreTrainedModel继承并使用config调用超类初始化(有点像当您编写常规torch.nn.Module时)。设置config_class的行不是强制性的,除非您想将您的模型注册到自动类(请参见最后一节)。

如果您的模型与库中的模型非常相似,您可以重用与该模型相同的配置。

您可以让您的模型返回任何您想要的内容,但是像我们为ResnetModelForImageClassification所做的那样返回一个包含损失的字典,当传递标签时,将使您的模型可以直接在 Trainer 类中使用。只要您打算使用自己的训练循环或其他库进行训练,使用另一种输出格式也是可以的。

现在我们有了我们的模型类,让我们创建一个:

代码语言:javascript
复制
resnet50d = ResnetModelForImageClassification(resnet50d_config)

同样,您可以使用 PreTrainedModel 的任何方法,例如 save_pretrained()或 push_to_hub()。我们将在下一节中使用第二种方法,并看看如何将模型权重与我们模型的代码一起推送。但首先,让我们在模型中加载一些预训练权重。

在您自己的用例中,您可能会在自己的数据上训练自定义模型。为了在本教程中快速进行,我们将使用 resnet50d 的预训练版本。由于我们的模型只是它的一个包装器,所以转移这些权重将会很容易:

代码语言:javascript
复制
import timm

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

现在让我们看看如何确保在执行 save_pretrained()或 push_to_hub()时,模型的代码被保存。

将带有自定义代码的模型注册到自动类

如果您正在编写一个扩展🤗 Transformers 的库,您可能希望扩展自动类以包括您自己的模型。这与将代码推送到 Hub 不同,用户需要导入您的库才能获取自定义模型(与自动从 Hub 下载模型代码相反)。

只要您的配置具有与现有模型类型不同的model_type属性,并且您的模型类具有正确的config_class属性,您就可以像这样将它们添加到自动类中:

代码语言:javascript
复制
from transformers import AutoConfig, AutoModel, AutoModelForImageClassification

AutoConfig.register("resnet", ResnetConfig)
AutoModel.register(ResnetConfig, ResnetModel)
AutoModelForImageClassification.register(ResnetConfig, ResnetModelForImageClassification)

注意,在将自定义配置注册到 AutoConfig 时使用的第一个参数需要与自定义配置的model_type匹配,并且在将自定义模型注册到任何自动模型类时使用的第一个参数需要与这些模型的config_class匹配。

将代码发送到 Hub

此 API 是实验性的,可能在下一个版本中有一些轻微的破坏性更改。

首先,请确保您的模型在一个.py文件中完全定义。它可以依赖于一些其他文件的相对导入,只要所有文件都在同一个目录中(我们目前还不支持此功能的子模块)。对于我们的示例,我们将在当前工作目录中的一个名为resnet_model的文件夹中定义一个modeling_resnet.py文件和一个configuration_resnet.py文件。配置文件包含ResnetConfig的代码,建模文件包含ResnetModelResnetModelForImageClassification的代码。

代码语言:javascript
复制
.
└── resnet_model
    ├── __init__.py
    ├── configuration_resnet.py
    └── modeling_resnet.py

__init__.py可以为空,只是为了让 Python 检测resnet_model可以用作模块。

如果从库中复制建模文件,则需要将文件顶部的所有相对导入替换为从transformers包导入。

请注意,您可以重复使用(或子类化)现有的配置/模型。

要与社区共享您的模型,请按照以下步骤操作:首先从新创建的文件中导入 ResNet 模型和配置:

代码语言:javascript
复制
from resnet_model.configuration_resnet import ResnetConfig
from resnet_model.modeling_resnet import ResnetModel, ResnetModelForImageClassification

然后,当使用save_pretrained方法时,您必须告诉库您要复制这些对象的代码文件,并使用给定的 Auto 类正确注册它们(特别是对于模型),只需运行:

代码语言:javascript
复制
ResnetConfig.register_for_auto_class()
ResnetModel.register_for_auto_class("AutoModel")
ResnetModelForImageClassification.register_for_auto_class("AutoModelForImageClassification")

请注意,无需为配置指定自动类(它们只有一个自动类,AutoConfig),但对于模型来说情况不同。您的自定义模型可能适用于许多不同的任务,因此您必须指定哪个自动类是您模型的正确类。

如果要将代码文件复制,可以使用register_for_auto_class()。如果您更喜欢从另一个存储库中的 Hub 使用代码,则无需调用它。在存在多个自动类的情况下,可以直接修改config.json,使用以下结构:

代码语言:javascript
复制
"auto_map": {     
	"AutoConfig": "<your-repo-name>--<config-name>",     
	"AutoModel": "<your-repo-name>--<config-name>",
	"AutoModelFor<Task>": "<your-repo-name>--<config-name>",    
},

接下来,让我们像以前一样创建配置和模型:

代码语言:javascript
复制
resnet50d_config = ResnetConfig(block_type="bottleneck", stem_width=32, stem_type="deep", avg_down=True)
resnet50d = ResnetModelForImageClassification(resnet50d_config)

pretrained_model = timm.create_model("resnet50d", pretrained=True)
resnet50d.model.load_state_dict(pretrained_model.state_dict())

现在要将模型发送到 Hub,请确保您已登录。在终端中运行:

代码语言:javascript
复制
huggingface-cli login

或者从笔记本中:

代码语言:javascript
复制
from huggingface_hub import notebook_login

notebook_login()

然后,您可以像这样推送到您自己的命名空间(或您是其成员的组织):

代码语言:javascript
复制
resnet50d.push_to_hub("custom-resnet50d")

除了以 json 格式复制建模权重和配置外,还将建模和配置的.py文件复制到custom-resnet50d文件夹中,并将结果上传到 Hub。您可以在此model repo中查看结果。

有关将模型推送到 Hub 的方法的更多信息,请参阅共享教程。

使用具有自定义代码的模型

您可以在其存储库中使用任何配置、模型或分词器与自定义代码文件,使用自动类和from_pretrained方法。所有上传到 Hub 的文件和代码都会被扫描以检测恶意软件(有关更多信息,请参阅Hub 安全文档),但您仍应查看模型代码和作者,以避免在您的计算机上执行恶意代码。设置trust_remote_code=True以使用具有自定义代码的模型:

代码语言:javascript
复制
from transformers import AutoModelForImageClassification

model = AutoModelForImageClassification.from_pretrained("sgugger/custom-resnet50d", trust_remote_code=True)

强烈建议传递提交哈希作为revision,以确保模型的作者没有使用一些恶意的新代码更新代码(除非您完全信任模型的作者)。

代码语言:javascript
复制
commit_hash = "ed94a7c6247d8aedce4647f00f20de6875b5b292"
model = AutoModelForImageClassification.from_pretrained(
    "sgugger/custom-resnet50d", trust_remote_code=True, revision=commit_hash
)

请注意,在 Hub 上浏览模型存储库的提交历史时,有一个按钮可以轻松复制任何提交的提交哈希。

聊天模型的模板

原始文本:huggingface.co/docs/transformers/v4.37.2/en/chat_templating

介绍

越来越常见的 LLMs 的用例是聊天。在聊天环境中,模型不是继续单个文本字符串(这是标准语言模型的情况),而是继续由一个或多个消息组成的对话,每个消息包括一个角色,如“用户”或“助手”,以及消息文本。

与标记化类似,不同的模型对于聊天期望非常不同的输入格式。这就是我们将聊天模板作为一个特性添加的原因。聊天模板是分词器的一部分。它们指定如何将表示为消息列表的对话转换为模型期望的单个可标记化字符串的格式。

让我们通过使用 BlenderBot 模型的一个快速示例来具体化这一点。BlenderBot 有一个非常简单的默认模板,主要是在对话轮之间添加空格:

代码语言:javascript
复制
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/blenderbot-400M-distill")

>>> chat = [
...    {"role": "user", "content": "Hello, how are you?"},
...    {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
...    {"role": "user", "content": "I'd like to show off how chat templating works!"},
... ]

>>> tokenizer.apply_chat_template(chat, tokenize=False)
" Hello, how are you?  I'm doing great. How can I help you today?   I'd like to show off how chat templating works!</s>"

请注意整个聊天被压缩成一个字符串。如果我们使用 tokenize=True,这是默认设置,那么该字符串也将被标记化。然而,为了看到一个更复杂的模板在操作中的效果,让我们使用 mistralai/Mistral-7B-Instruct-v0.1 模型。

代码语言:javascript
复制
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")

>>> chat = [
...   {"role": "user", "content": "Hello, how are you?"},
...   {"role": "assistant", "content": "I'm doing great. How can I help you today?"},
...   {"role": "user", "content": "I'd like to show off how chat templating works!"},
... ]

>>> tokenizer.apply_chat_template(chat, tokenize=False)
"<s>[INST] Hello, how are you? [/INST]I'm doing great. How can I help you today?</s> [INST] I'd like to show off how chat templating works! [/INST]"

请注意,这次分词器已经添加了控制标记 [INST] 和 [/INST] 来指示用户消息的开始和结束(但不包括助手消息!)。Mistral-instruct 是使用这些标记进行训练的,但 BlenderBot 没有。

如何使用聊天模板?

正如您在上面的示例中所看到的,聊天模板很容易使用。只需构建一个带有 rolecontent 键的消息列表,然后将其传递给 apply_chat_template() 方法。一旦您这样做了,您将得到准备好的输出!当将聊天模板用作模型生成的输入时,使用 add_generation_prompt=True 添加一个 生成提示 也是一个好主意。

这是准备输入给 model.generate() 的示例,使用 Zephyr 助手模型:

代码语言:javascript
复制
from transformers import AutoModelForCausalLM, AutoTokenizer

checkpoint = "HuggingFaceH4/zephyr-7b-beta"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForCausalLM.from_pretrained(checkpoint)  # You may want to use bfloat16 and/or move to GPU here

messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a pirate",
    },
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
 ]
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt")
print(tokenizer.decode(tokenized_chat[0]))

这将产生一个符合 Zephyr 期望的输入格式的字符串。

代码语言:javascript
复制
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s> 
<|user|>
How many helicopters can a human eat in one sitting?</s> 
<|assistant|>

现在我们的输入已经正确格式化为 Zephyr,我们可以使用模型为用户的问题生成响应。

代码语言:javascript
复制
outputs = model.generate(tokenized_chat, max_new_tokens=128) 
print(tokenizer.decode(outputs[0]))

这将产生:

代码语言:javascript
复制
<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s> 
<|user|>
How many helicopters can a human eat in one sitting?</s> 
<|assistant|>
Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all.

啊,原来如此简单!

是否有用于聊天的自动化管道?

是的,有:ConversationalPipeline。这个管道旨在使使用聊天模型变得容易。让我们再次尝试 Zephyr 示例,但这次使用管道:

代码语言:javascript
复制
from transformers import pipeline

pipe = pipeline("conversational", "HuggingFaceH4/zephyr-7b-beta")
messages = [
    {
        "role": "system",
        "content": "You are a friendly chatbot who always responds in the style of a pirate",
    },
    {"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
]
print(pipe(messages))
代码语言:javascript
复制
Conversation id: 76d886a0-74bd-454e-9804-0467041a63dc
system: You are a friendly chatbot who always responds in the style of a pirate
user: How many helicopters can a human eat in one sitting?
assistant: Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all.

ConversationalPipeline 将负责所有的标记化细节,并为您调用 apply_chat_template - 一旦模型有了聊天模板,您所需要做的就是初始化管道并将消息列表传递给它!

“生成提示”是什么?

您可能已经注意到 apply_chat_template 方法有一个 add_generation_prompt 参数。这个参数告诉模板添加指示机器人响应开始的标记。例如,考虑以下聊天:

代码语言:javascript
复制
messages = [
    {"role": "user", "content": "Hi there!"},
    {"role": "assistant", "content": "Nice to meet you!"},
    {"role": "user", "content": "Can I ask a question?"}
]

这是没有生成提示的样子,使用我们在 Zephyr 示例中看到的 ChatML 模板:

代码语言:javascript
复制
tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)
"""<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>
"""

这是带有生成提示的样子:

代码语言:javascript
复制
tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
"""<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>
<|im_start|>assistant
"""

请注意,这一次,我们添加了指示机器人响应开始的标记。这确保了当模型生成文本时,它将写入一个机器人响应,而不是做一些意外的事情,比如继续用户的消息。请记住,聊天模型仍然只是语言模型 - 它们被训练来继续文本,而聊天只是对它们来说的一种特殊文本!您需要使用适当的控制标记来指导它们知道应该做什么。

并非所有模型都需要生成提示。一些模型,如 BlenderBot 和 LLaMA,在机器人响应之前没有任何特殊标记。在这些情况下,add_generation_prompt参数将不起作用。add_generation_prompt的确切效果将取决于所使用的模板。

我可以在训练中使用聊天模板吗?

是的!我们建议您将聊天模板应用为数据集的预处理步骤。之后,您可以像处理任何其他语言模型训练任务一样继续。在训练时,通常应设置add_generation_prompt=False,因为在训练过程中,添加的提示助手响应的标记将不会有帮助。让我们看一个例子:

代码语言:javascript
复制
from transformers import AutoTokenizer
from datasets import Dataset

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")

chat1 = [
    {"role": "user", "content": "Which is bigger, the moon or the sun?"},
    {"role": "assistant", "content": "The sun."}
]
chat2 = [
    {"role": "user", "content": "Which is bigger, a virus or a bacterium?"},
    {"role": "assistant", "content": "A bacterium."}
]

dataset = Dataset.from_dict({"chat": [chat1, chat2]})
dataset = dataset.map(lambda x: {"formatted_chat": tokenizer.apply_chat_template(x["chat"], tokenize=False, add_generation_prompt=False)})
print(dataset['formatted_chat'][0])

然后我们得到:

代码语言:javascript
复制
<|user|>
Which is bigger, the moon or the sun?</s>
<|assistant|>
The sun.</s>

从这里开始,就像处理标准语言建模任务一样继续训练,使用formatted_chat列。

高级:聊天模板如何工作?

模型的聊天模板存储在tokenizer.chat_template属性中。如果没有设置聊天模板,则将使用该模型类的默认模板。让我们看一下BlenderBot的模板:

代码语言:javascript
复制
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("facebook/blenderbot-400M-distill")

>>> tokenizer.default_chat_template
"{% for message in messages %}{% if message['role'] == 'user' %}{{ ' ' }}{% endif %}{{ message['content'] }}{% if not loop.last %}{{ '  ' }}{% endif %}{% endfor %}{{ eos_token }}"

这有点令人生畏。让我们添加一些换行和缩进,使其更易读。请注意,每个块后的第一个换行以及块之前的任何前导空格默认情况下会被忽略,使用 Jinja 的trim_blockslstrip_blocks标志。但是,请谨慎 - 尽管每行的前导空格被剥离,但同一行上块之间的空格不会被剥离。我们强烈建议检查您的模板是否在不应该的地方打印额外的空格!

代码语言:javascript
复制
{% for message in messages %}  {% if message['role'] == 'user' %}  {{ ' ' }}  {% endif %}  {{ message['content'] }}  {% if not loop.last %}  {{ '  ' }}  {% endif %}  {% endfor %}  {{ eos_token }}

如果您以前从未见过这种模板,这是一个Jinja 模板。Jinja 是一种模板语言,允许您编写生成文本的简单代码。在许多方面,代码和语法类似于 Python。在纯 Python 中,这个模板看起来会像这样:

代码语言:javascript
复制
for idx, message in enumerate(messages):
    if message['role'] == 'user':
        print(' ')
    print(message['content'])
    if not idx == len(messages) - 1:  # Check for the last message in the conversation
        print('  ')
print(eos_token)

实际上,模板执行三件事:

  1. 对于每条消息,如果消息是用户消息,则在其前添加一个空格,否则不打印任何内容。
  2. 添加消息内容
  3. 如果消息不是最后一条消息,请在其后添加两个空格。在最后一条消息之后,打印 EOS 标记。

这是一个非常简单的模板 - 它不添加任何控制标记,也不支持“系统”消息,这是一种常见的方式,用于向模型提供关于其在随后对话中应该如何行为的指令。但是 Jinja 为您提供了很大的灵活性来执行这些操作!让我们看一个 Jinja 模板,可以类似于 LLaMA 格式化输入(请注意,真正的 LLaMA 模板包括处理默认系统消息以及一般情况下稍有不同的系统消息处理 - 不要在实际代码中使用这个!)

代码语言:javascript
复制
{% for message in messages %}  {% if message['role'] == 'user' %}  {{ bos_token + '[INST] ' + message['content'] + ' [/INST]' }}  {% elif message['role'] == 'system' %}  {{ '<<SYS>>\\n' + message['content'] + '\\n<</SYS>>\\n\\n' }}  {% elif message['role'] == 'assistant' %}  {{ ' '  + message['content'] + ' ' + eos_token }}  {% endif %}  {% endfor %}

希望如果您仔细看一下,您就能看出这个模板在做什么 - 它根据每条消息的“角色”添加特定的标记,这些标记代表发送者是谁。用户、助手和系统消息因为它们被包裹在其中的标记而清晰可辨。

高级:添加和编辑聊天模板

如何创建聊天模板?

简单,只需编写一个 Jinja 模板并设置tokenizer.chat_template。您可能会发现,从另一个模型的现有模板开始,并为您的需求简单编辑它会更容易!例如,我们可以采用上面的 LLaMA 模板,并为助手消息添加"[ASST]“和”[/ASST]":

代码语言:javascript
复制
{% for message in messages %}  {% if message['role'] == 'user' %}  {{ bos_token + '[INST] ' + message['content'].strip() + ' [/INST]' }}  {% elif message['role'] == 'system' %}  {{ '<<SYS>>\\n' + message['content'].strip() + '\\n<</SYS>>\\n\\n' }}  {% elif message['role'] == 'assistant' %}  {{ '[ASST] '  + message['content'] + ' [/ASST]' + eos_token }}  {% endif %}  {% endfor %}

现在,只需设置tokenizer.chat_template属性。下次使用 apply_chat_template(),它将使用您的新模板!此属性将保存在tokenizer_config.json文件中,因此您可以使用 push_to_hub()将您的新模板上传到 Hub,并确保每个人都在使用正确的模板来使用您的模型!

代码语言:javascript
复制
template = tokenizer.chat_template
template = template.replace("SYS", "SYSTEM")  # Change the system token
tokenizer.chat_template = template  # Set the new template
tokenizer.push_to_hub("model_name")  # Upload your new template to the Hub!

使用您的聊天模板的方法 apply_chat_template()由 ConversationalPipeline 类调用,因此一旦您设置了正确的聊天模板,您的模型将自动与 ConversationalPipeline 兼容。

“默认”模板是什么?

在引入聊天模板之前,聊天处理是在模型类级别上硬编码的。为了向后兼容,我们保留了这种特定类处理作为默认模板,也在类级别上设置了。如果一个模型没有设置聊天模板,但是它的模型类有一个默认模板,ConversationalPipeline类和apply_chat_template等方法将使用类模板。您可以通过检查tokenizer.default_chat_template属性来查找您的分词器的默认模板。

这是我们纯粹为了向后兼容性的原因而做的事情,以避免破坏任何现有的工作流程。即使类模板适用于您的模型,我们强烈建议通过将chat_template属性显式设置来覆盖默认模板,以便向用户明确表明您的模型已正确配置为聊天,并为将来防范默认模板被修改或弃用的情况做好准备。

我应该使用哪个模板?

当为已经训练过的聊天模型设置模板时,您应该确保模板与模型在训练过程中看到的消息格式完全匹配,否则您可能会遇到性能下降。即使您继续训练模型,也是如此 - 如果保持聊天标记不变,您可能会获得最佳性能。这与标记化非常类似 - 在推理或微调时,当您精确匹配训练过程中使用的标记化时,通常会获得最佳性能。

如果您从头开始训练模型,或者在另一方面微调基础语言模型以用于聊天,您有很大的自由选择适当的模板!LLMs 足够聪明,可以学会处理许多不同的输入格式。我们为没有特定类别模板的模型提供的默认模板遵循 ChatML 格式,对于许多用例来说,这是一个很好的、灵活的选择。它看起来像这样:

代码语言:javascript
复制
{% for message in messages %}  {{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}  {% endfor %}

如果您喜欢这个,这里有一个一行代码形式的版本,可以直接复制到您的代码中。这个一行代码还包括对生成提示的方便支持,但请注意它不会添加 BOS 或 EOS 标记!如果您的模型需要这些标记,apply_chat_template不会自动添加它们 - 换句话说,文本将被使用add_special_tokens=False进行标记化。这是为了避免模板和add_special_tokens逻辑之间的潜在冲突。如果您的模型需要特殊标记,请确保将它们添加到模板中!

代码语言:javascript
复制
tokenizer.chat_template = "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"

此模板将每条消息封装在<|im_start|><|im_end|>令牌中,并简单地将角色写入字符串,这样可以灵活地使用训练的角色。输出如下所示:

代码语言:javascript
复制
<|im_start|>system
You are a helpful chatbot that will do its best not to say anything so stupid that people tweet about it.<|im_end|>
<|im_start|>user
How are you?<|im_end|>
<|im_start|>assistant
I'm doing great!<|im_end|>

“用户”、“系统”和“助手”角色是聊天的标准角色,我们建议在有意义的情况下使用它们,特别是如果您希望您的模型在 ConversationalPipeline 中运行良好。但是,您不限于这些角色 - 模板非常灵活,任何字符串都可以是一个角色。

我想添加一些聊天模板!我应该如何开始?

如果您有任何聊天模型,您应该设置它们的tokenizer.chat_template属性,并使用 apply_chat_template()进行测试,然后将更新后的 tokenizer 推送到 Hub。即使您不是模型所有者 - 如果您使用的模型具有空白聊天模板,或者仍在使用默认类模板,请打开一个拉取请求到模型存储库,以便正确设置此属性!

一旦设置了属性,就完成了!tokenizer.apply_chat_template现在将正确地为该模型工作,这意味着它也会自动支持像ConversationalPipeline这样的地方!

通过确保模型具有此属性,我们可以确保整个社区都能够使用开源模型的全部功能。格式不匹配已经困扰该领域并悄悄损害了性能太久了 - 是时候结束它们了!

高级:模板编写提示

如果您对 Jinja 不熟悉,我们通常发现编写聊天模板的最简单方法是首先编写一个格式化消息的 Python 脚本,然后将该脚本转换为模板。

记住模板处理程序将接收对话历史作为名为messages的变量。每条消息都是一个带有两个键rolecontent的字典。您可以在模板中像在 Python 中一样访问messages,这意味着您可以使用{% for message in messages %}循环遍历它,或者例如使用{{ messages[0] }}访问单个消息。

您还可以使用以下提示将您的代码转换为 Jinja:

对于循环

Jinja 中的 for 循环如下所示:

代码语言:javascript
复制
{% for message in messages %}  {{ message['content'] }}  {% endfor %}

请注意,无论{{表达式块}}中有什么都将打印到输出中。您可以在表达式块内使用+等运算符来组合字符串。

if 语句

Jinja 中的 if 语句如下所示:

代码语言:javascript
复制
{% if message['role'] == 'user' %}  {{ message['content'] }}  {% endif %}

请注意,Python 使用空格来标记forif块的开始和结束位置,而 Jinja 要求您使用{% endfor %}{% endif %}显式结束它们。

特殊变量

在您的模板中,您将可以访问messages列表,但也可以访问几个其他特殊变量。这些包括像bos_tokeneos_token这样的特殊标记,以及我们上面讨论过的add_generation_prompt变量。您还可以使用loop变量来访问有关当前循环迭代的信息,例如使用{% if loop.last %}来检查当前消息是否是对话中的最后一条消息。以下是一个将这些想法结合在一起,在对话结束时添加生成提示的示例,如果add_generation_promptTrue

代码语言:javascript
复制
{% if loop.last and add_generation_prompt %}  {{ bos_token + 'Assistant:\n' }}  {% endif %}
空格注意事项

尽可能地,我们已经尝试让 Jinja 忽略{{表达式}}之外的空格。但是,请注意,Jinja 是一个通用的模板引擎,它可能会将同一行上块之间的空格视为重要并将其打印到输出中。我们强烈建议在上传模板之前检查您的模板是否在不应该的地方打印额外的空格!

Trainer

原文链接:huggingface.co/docs/transformers/v4.37.2/en/trainer

Trainer 是在 Transformers 库中实现的 PyTorch 模型的完整训练和评估循环。您只需要传递训练所需的必要部分(模型、分词器、数据集、评估函数、训练超参数等),Trainer 类会处理其余部分。这使得更容易开始训练,而无需手动编写自己的训练循环。但同时,Trainer 非常可定制,并提供大量的训练选项,因此您可以根据自己的训练需求进行定制。

除了 Trainer 类外,Transformers 还提供了一个 Seq2SeqTrainer 类,用于序列到序列任务,如翻译或摘要。还有来自TRL库的SFTTrainer类,它包装了 Trainer 类,并针对使用自回归技术的 Llama-2 和 Mistral 等语言模型进行了优化。SFTTrainer还支持序列打包、LoRA、量化和 DeepSpeed 等功能,以有效地扩展到任何模型大小。

随时查看 API 参考以了解其他 Trainer 类型类的更多信息,以便了解何时使用哪种。一般来说,Trainer 是最通用的选择,适用于广泛的任务。Seq2SeqTrainer 专为序列到序列任务设计,而SFTTrainer专为训练语言模型设计。

在开始之前,请确保已安装Accelerate - 一个用于在分布式环境中启用和运行 PyTorch 训练的库。

代码语言:javascript
复制
pip install accelerate

# upgrade
pip install accelerate --upgrade

这个指南提供了 Trainer 类的概述。

基本用法

Trainer 包含在基本训练循环中找到的所有代码:

  1. 执行训练步骤来计算损失
  2. 使用backward方法计算梯度
  3. 根据梯度更新权重
  4. 重复这个过程,直到达到预定的 epoch 数量

Trainer 类将所有这些代码抽象化,因此您无需每次手动编写训练循环,或者如果您刚开始使用 PyTorch 和训练时担心。您只需要提供训练所需的基本组件,如模型和数据集,Trainer 类会处理其他一切。

如果要指定任何训练选项或超参数,您可以在 TrainingArguments 类中找到它们。例如,让我们定义在output_dir中保存模型的位置,并在训练后使用push_to_hub=True将模型推送到 Hub。

代码语言:javascript
复制
from transformers import TrainingArguments

training_args = TrainingArguments(
    output_dir="your-model",
    learning_rate=2e-5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=2,
    weight_decay=0.01,
    evaluation_strategy="epoch",
    save_strategy="epoch",
    load_best_model_at_end=True,
    push_to_hub=True,
)

training_args传递给 Trainer,以及一个模型、数据集、用于预处理数据集的内容(根据数据类型可能是令牌化器、特征提取器或图像处理器)、数据整理器和一个函数来计算您想要在训练过程中跟踪的指标。

最后,调用 train()开始训练!

代码语言:javascript
复制
from transformers import Trainer

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    tokenizer=tokenizer,
    data_collator=data_collator,
    compute_metrics=compute_metrics,
)

trainer.train()
检查点

Trainer 类将您的模型检查点保存到 TrainingArguments 中指定的目录中的output_dir参数。您将在checkpoint-000子文件夹中找到保存的检查点,其中末尾的数字对应训练步骤。保存检查点对于稍后恢复训练很有用。

代码语言:javascript
复制
# resume from latest checkpoint
trainer.train(resume_from_checkpoint=True)

# resume from specific checkpoint saved in output directory
trainer.train(resume_from_checkpoint="your-model/checkpoint-1000")

您可以通过在 TrainingArguments 中设置push_to_hub=True将检查点保存到 Hub 以提交和推送它们(默认情况下不保存优化器状态)。设置如何保存检查点的其他选项在hub_strategy参数中设置:

  • hub_strategy="checkpoint" 将最新的检查点推送到名为“last-checkpoint”的子文件夹,您可以从中恢复训练
  • hug_strategy="all_checkpoints" 将所有检查点推送到output_dir中定义的目录(您将在模型存储库中看到每个文件夹中的一个检查点)

当您从检查点恢复训练时,Trainer 会尝试保持 Python、NumPy 和 PyTorch RNG 状态与保存检查点时相同。但由于 PyTorch 具有各种非确定性的默认设置,RNG 状态不能保证相同。如果要启用完全确定性,请查看控制随机性源指南,了解您可以启用哪些内容以使您的训练完全确定性。请记住,通过使某些设置确定性,训练可能会变慢。

自定义 Trainer

虽然 Trainer 类旨在易于访问和使用,但也为更有冒险精神的用户提供了许多可定制性。许多 Trainer 的方法可以被子类化和重写,以支持您想要的功能,而无需重写整个训练循环以适应它。这些方法包括:

  • get_train_dataloader() 创建一个训练 DataLoader
  • get_eval_dataloader() 创建一个评估 DataLoader
  • get_test_dataloader() 创建一个测试 DataLoader
  • log() 记录监视训练的各种对象的信息
  • create_optimizer_and_scheduler() 在__init__中没有传入优化器和学习率调度器时创建它们;也可以使用 create_optimizer()和 create_scheduler()进行单独定制
  • compute_loss() 计算一批训练输入的损失
  • training_step() 执行训练步骤
  • prediction_step() 执行预测和测试步骤
  • evaluate() 评估模型并返回评估指标
  • predict() 在测试集上进行预测(如果有标签,则带有指标)

例如,如果您想要自定义 compute_loss()方法以使用加权损失。

代码语言:javascript
复制
from torch import nn
from transformers import Trainer

class CustomTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        labels = inputs.pop("labels")
        # forward pass
        outputs = model(**inputs)
        logits = outputs.get("logits")
        # compute custom loss for 3 labels with different weights
        loss_fct = nn.CrossEntropyLoss(weight=torch.tensor([1.0, 2.0, 3.0], device=model.device))
        loss = loss_fct(logits.view(-1, self.model.config.num_labels), labels.view(-1))
        return (loss, outputs) if return_outputs else loss
回调

自定义 Trainer 的另一个选项是使用 callbacks。回调不会改变训练循环中的任何内容。它们检查训练循环状态,然后根据状态执行某些操作(提前停止、记录结果等)。换句话说,回调不能用于实现类似自定义损失函数的内容,您需要子类化并重写 compute_loss()方法。

例如,如果您想在训练循环中的 10 步后添加一个提前停止回调。

代码语言:javascript
复制
from transformers import TrainerCallback

class EarlyStoppingCallback(TrainerCallback):
    def __init__(self, num_steps=10):
        self.num_steps = num_steps

    def on_step_end(self, args, state, control, **kwargs):
        if state.global_step >= self.num_steps:
            return {"should_training_stop": True}
        else:
            return {}

然后将其传递给 Trainer 的callback参数。

代码语言:javascript
复制
from transformers import Trainer

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    tokenizer=tokenizer,
    data_collator=data_collator,
    compute_metrics=compute_metrics,
    callback=[EarlyStoppingCallback()],
)

日志

查看 logging API 参考以获取有关不同日志级别的更多信息。

默认情况下,Trainer 设置为logging.INFO,报告错误、警告和其他基本信息。在分布式环境中,Trainer 的副本设置为logging.WARNING,仅报告错误和警告。您可以使用 TrainingArguments 中的log_levellog_level_replica参数更改日志级别。

要为每个节点配置日志级别设置,请使用log_on_each_node参数来确定是在每个节点上使用日志级别还是仅在主节点上使用。

Trainer 在Trainer.__init__()方法中为每个节点单独设置日志级别,因此如果您在创建 Trainer 对象之前使用其他 Transformers 功能,可能需要考虑更早设置这个。

例如,要根据每个节点设置主代码和模块使用相同的日志级别:

代码语言:javascript
复制
logger = logging.getLogger(__name__)

logging.basicConfig(
    format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
    datefmt="%m/%d/%Y %H:%M:%S",
    handlers=[logging.StreamHandler(sys.stdout)],
)

log_level = training_args.get_process_log_level()
logger.setLevel(log_level)
datasets.utils.logging.set_verbosity(log_level)
transformers.utils.logging.set_verbosity(log_level)

trainer = Trainer(...)

使用不同组合的log_levellog_level_replica来配置每个节点上记录什么。

单节点多节点

代码语言:javascript
复制
my_app.py ... --log_level warning --log_level_replica error

NEFTune

NEFTune是一种通过在训练过程中向嵌入向量添加噪音来提高性能的技术。要在 Trainer 中启用它,设置 TrainingArguments 中的neftune_noise_alpha参数来控制添加多少噪音。

代码语言:javascript
复制
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(..., neftune_noise_alpha=0.1)
trainer = Trainer(..., args=training_args)

训练后禁用 NEFTune,以恢复原始嵌入层,避免任何意外行为。

加速和 Trainer

Trainer 类由Accelerate支持,这是一个用于在分布式环境中轻松训练 PyTorch 模型的库,支持集成如FullyShardedDataParallel (FSDP)DeepSpeed

在 Trainer 的 Fully Sharded Data Parallel 指南中了解更多关于 FSDP 分片策略、CPU 卸载等内容。

使用 Trainer 与 Accelerate,运行accelerate.config命令来设置您的训练环境。这个命令会创建一个config_file.yaml,在您启动训练脚本时会用到。例如,您可以设置一些示例配置:

DistributedDataParallelFSDPDeepSpeedDeepSpeed 与 Accelerate 插件

代码语言:javascript
复制
compute_environment: LOCAL_MACHINE                                                                                             
distributed_type: MULTI_GPU                                                                                                    
downcast_bf16: 'no'
gpu_ids: all
machine_rank: 0 #change rank as per the node
main_process_ip: 192.168.20.1
main_process_port: 9898
main_training_function: main
mixed_precision: fp16
num_machines: 2
num_processes: 8
rdzv_backend: static
same_network: true
tpu_env: []
tpu_use_cluster: false
tpu_use_sudo: false
use_cpu: false

accelerate_launch命令是在分布式系统上启动您的训练脚本的推荐方式,使用 Accelerate 和 Trainer 中在config_file.yaml中指定的参数。这个文件保存在 Accelerate 缓存文件夹中,并在运行accelerate_launch时自动加载。

例如,使用 FSDP 配置运行run_glue.py训练脚本:

代码语言:javascript
复制
accelerate launch \
    ./examples/pytorch/text-classification/run_glue.py \
    --model_name_or_path bert-base-cased \
    --task_name $TASK_NAME \
    --do_train \
    --do_eval \
    --max_seq_length 128 \
    --per_device_train_batch_size 16 \
    --learning_rate 5e-5 \
    --num_train_epochs 3 \
    --output_dir /tmp/$TASK_NAME/ \
    --overwrite_output_dir

您也可以直接在命令行中指定来自config_file.yaml文件的参数:

代码语言:javascript
复制
accelerate launch --num_processes=2 \
    --use_fsdp \
    --mixed_precision=bf16 \
    --fsdp_auto_wrap_policy=TRANSFORMER_BASED_WRAP  \
    --fsdp_transformer_layer_cls_to_wrap="BertLayer" \
    --fsdp_sharding_strategy=1 \
    --fsdp_state_dict_type=FULL_STATE_DICT \
    ./examples/pytorch/text-classification/run_glue.py
    --model_name_or_path bert-base-cased \
    --task_name $TASK_NAME \
    --do_train \
    --do_eval \
    --max_seq_length 128 \
    --per_device_train_batch_size 16 \
    --learning_rate 5e-5 \
    --num_train_epochs 3 \
    --output_dir /tmp/$TASK_NAME/ \
    --overwrite_output_dir

查看启动您的 Accelerate 脚本教程,了解更多关于accelerate_launch和自定义配置的内容。

在 Amazon SageMaker 上运行训练

原始文本:huggingface.co/docs/transformers/v4.37.2/en/sagemaker

文档已移至 hf.co/docs/sagemaker。此页面将在 transformers 5.0 中被移除。

目录

导出为 ONNX

原始文本:huggingface.co/docs/transformers/v4.37.2/en/serialization

在生产环境中部署🤗 Transformers 模型通常需要将模型导出为可以在专用运行时和硬件上加载和执行的序列化格式。

🤗 Optimum 是 Transformers 的扩展,通过其exporters模块使得可以将模型从 PyTorch 或 TensorFlow 导出为 ONNX 和 TFLite 等序列化格式。🤗 Optimum 还提供了一套性能优化工具,以在目标硬件上以最大效率训练和运行模型。

本指南演示了如何使用🤗 Optimum 将🤗 Transformers 模型导出为 ONNX,有关将模型导出为 TFLite 的指南,请参考导出到 TFLite 页面。

导出为 ONNX

ONNX(Open Neural Network eXchange)是一个开放标准,定义了一组通用操作符和一种通用文件格式,用于在各种框架中表示深度学习模型,包括 PyTorch 和 TensorFlow。当模型导出为 ONNX 格式时,这些操作符用于构建计算图(通常称为中间表示),表示数据通过神经网络的流动。

通过公开具有标准化操作符和数据类型的图,ONNX 使得在不同框架之间轻松切换变得容易。例如,在 PyTorch 中训练的模型可以导出为 ONNX 格式,然后在 TensorFlow 中导入(反之亦然)。

将模型导出为 ONNX 格式后,可以:

  • 通过诸如图优化量化等技术进行推理优化。
  • 使用 ONNX Runtime 运行,通过ORTModelForXXX,其遵循与🤗 Transformers 中您习惯的AutoModel API 相同。
  • 使用优化推理流水线运行,其 API 与🤗 Transformers 中的 pipeline()函数相同。

🤗 Optimum 通过利用配置对象提供对 ONNX 导出的支持。这些配置对象已经为许多模型架构准备好,并且设计为易于扩展到其他架构。

有关现成配置列表,请参阅🤗 Optimum 文档

有两种将🤗 Transformers 模型导出为 ONNX 的方法,这里我们展示两种:

  • 通过 CLI 使用🤗 Optimum 导出。
  • 使用optimum.onnxruntime与🤗 Optimum 导出。
使用 CLI 将🤗 Transformers 模型导出为 ONNX

要将🤗 Transformers 模型导出为 ONNX,首先安装额外的依赖项:

代码语言:javascript
复制
pip install optimum[exporters]

要查看所有可用参数,请参考🤗 Optimum 文档,或在命令行中查看帮助:

代码语言:javascript
复制
optimum-cli export onnx --help

要从🤗 Hub 导出模型的检查点,例如distilbert-base-uncased-distilled-squad,请运行以下命令:

代码语言:javascript
复制
optimum-cli export onnx --model distilbert-base-uncased-distilled-squad distilbert_base_uncased_squad_onnx/

您应该看到指示进度并显示结果model.onnx保存位置的日志,如下所示:

代码语言:javascript
复制
Validating ONNX model distilbert_base_uncased_squad_onnx/model.onnx...
	-[✓] ONNX model output names match reference model (start_logits, end_logits)
	- Validating ONNX Model output "start_logits":
		-[✓] (2, 16) matches (2, 16)
		-[✓] all values close (atol: 0.0001)
	- Validating ONNX Model output "end_logits":
		-[✓] (2, 16) matches (2, 16)
		-[✓] all values close (atol: 0.0001)
The ONNX export succeeded and the exported model was saved at: distilbert_base_uncased_squad_onnx

上面的示例说明了从 🤗 Hub 导出检查点。在导出本地模型时,首先确保您将模型的权重和分词器文件保存在同一个目录中(local_path)。在使用 CLI 时,将 local_path 传递给 model 参数,而不是在 🤗 Hub 上提供检查点名称,并提供 --task 参数。您可以在 🤗 Optimum 文档 中查看支持的任务列表。如果未提供 task 参数,它将默认为没有任何特定任务头的模型架构。

代码语言:javascript
复制
optimum-cli export onnx --model local_path --task question-answering distilbert_base_uncased_squad_onnx/

导出的 model.onnx 文件可以在支持 ONNX 标准的 许多加速器 中运行。例如,我们可以使用 ONNX Runtime 加载和运行模型如下:

代码语言:javascript
复制
>>> from transformers import AutoTokenizer
>>> from optimum.onnxruntime import ORTModelForQuestionAnswering

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert_base_uncased_squad_onnx")
>>> model = ORTModelForQuestionAnswering.from_pretrained("distilbert_base_uncased_squad_onnx")
>>> inputs = tokenizer("What am I using?", "Using DistilBERT with ONNX Runtime!", return_tensors="pt")
>>> outputs = model(**inputs)

这个过程对于 Hub 上的 TensorFlow 检查点是相同的。例如,这里是如何从 Keras 组织 导出一个纯 TensorFlow 检查点的:

代码语言:javascript
复制
optimum-cli export onnx --model keras-io/transformers-qa distilbert_base_cased_squad_onnx/
使用 optimum.onnxruntime 将 🤗 Transformers 模型导出到 ONNX

与 CLI 的替代方法是,您可以像这样以编程方式将 🤗 Transformers 模型导出到 ONNX:

代码语言:javascript
复制
>>> from optimum.onnxruntime import ORTModelForSequenceClassification
>>> from transformers import AutoTokenizer

>>> model_checkpoint = "distilbert_base_uncased_squad"
>>> save_directory = "onnx/"

>>> # Load a model from transformers and export it to ONNX
>>> ort_model = ORTModelForSequenceClassification.from_pretrained(model_checkpoint, export=True)
>>> tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)

>>> # Save the onnx model and tokenizer
>>> ort_model.save_pretrained(save_directory)
>>> tokenizer.save_pretrained(save_directory)
将模型导出到不受支持的架构

如果您希望通过为当前无法导出的模型添加支持来做出贡献,您应该首先检查它是否在 optimum.exporters.onnx 中受支持,如果不是,可以直接 为 🤗 Optimum 做出贡献

使用 transformers.onnx 导出模型

tranformers.onnx 不再维护,请按照上述使用 🤗 Optimum 导出模型的方法。这一部分将在未来版本中被移除。

要使用 transformers.onnx 将 🤗 Transformers 模型导出到 ONNX,需要安装额外的依赖:

代码语言:javascript
复制
pip install transformers[onnx]

使用 transformers.onnx 包作为 Python 模块,使用现成的配置导出检查点:

代码语言:javascript
复制
python -m transformers.onnx --model=distilbert-base-uncased onnx/

这将导出由 --model 参数定义的检查点的 ONNX 图。传递任何在 🤗 Hub 上或本地存储的检查点。导出的 model.onnx 文件可以在支持 ONNX 标准的许多加速器中运行。例如,加载并使用 ONNX Runtime 运行模型如下:

代码语言:javascript
复制
>>> from transformers import AutoTokenizer
>>> from onnxruntime import InferenceSession

>>> tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
>>> session = InferenceSession("onnx/model.onnx")
>>> # ONNX Runtime expects NumPy arrays as input
>>> inputs = tokenizer("Using DistilBERT with ONNX Runtime!", return_tensors="np")
>>> outputs = session.run(output_names=["last_hidden_state"], input_feed=dict(inputs))

所需的输出名称(如 ["last_hidden_state"])可以通过查看每个模型的 ONNX 配置来获得。例如,对于 DistilBERT,我们有:

代码语言:javascript
复制
>>> from transformers.models.distilbert import DistilBertConfig, DistilBertOnnxConfig

>>> config = DistilBertConfig()
>>> onnx_config = DistilBertOnnxConfig(config)
>>> print(list(onnx_config.outputs.keys()))
["last_hidden_state"]

这个过程对于 Hub 上的 TensorFlow 检查点是相同的。例如,像这样导出一个纯 TensorFlow 检查点:

代码语言:javascript
复制
python -m transformers.onnx --model=keras-io/transformers-qa onnx/

要导出存储在本地的模型,请将模型的权重和分词器文件保存在同一个目录中(例如 local-pt-checkpoint),然后通过将 transformers.onnx 包的 --model 参数指向所需目录来将其导出到 ONNX:

代码语言:javascript
复制
python -m transformers.onnx --model=local-pt-checkpoint onnx/

导出到 TFLite

原始文本:huggingface.co/docs/transformers/v4.37.2/en/tflite

TensorFlow Lite 是一个轻量级框架,用于在资源受限的设备上部署机器学习模型,例如移动电话、嵌入式系统和物联网(IoT)设备。TFLite 旨在优化并在这些计算能力、内存和功耗有限的设备上高效运行模型。TensorFlow Lite 模型以一种特殊的高效可移植格式表示,通过 .tflite 文件扩展名进行识别。

🤗 Optimum 提供了通过 exporters.tflite 模块将 🤗 Transformers 模型导出到 TFLite 的功能。有关支持的模型架构列表,请参考 🤗 Optimum 文档

要将模型导出到 TFLite,请安装所需的依赖项:

代码语言:javascript
复制
pip install optimum[exporters-tf]

要查看所有可用参数,请参考 🤗 Optimum 文档,或在命令行中查看帮助:

代码语言:javascript
复制
optimum-cli export tflite --help

例如,要从 🤗 Hub 导出模型的检查点,比如 bert-base-uncased,请运行以下命令:

代码语言:javascript
复制
optimum-cli export tflite --model bert-base-uncased --sequence_length 128 bert_tflite/

您应该看到指示进度并显示结果 model.tflite 保存位置的日志。

代码语言:javascript
复制
Validating TFLite model...
	-[✓] TFLite model output names match reference model (logits)
	- Validating TFLite Model output "logits":
		-[✓] (1, 128, 30522) matches (1, 128, 30522)
		-[x] values not close enough, max diff: 5.817413330078125e-05 (atol: 1e-05)
The TensorFlow Lite export succeeded with the warning: The maximum absolute difference between the output of the reference model and the TFLite exported model is not within the set tolerance 1e-05:
- logits: max diff = 5.817413330078125e-05.
 The exported model was saved at: bert_tflite

上面的示例说明了从 🤗 Hub 导出检查点。在导出本地模型时,首先确保您将模型的权重和分词器文件保存在同一个目录(local_path)中。在使用 CLI 时,将 local_path 传递给 model 参数,而不是在 🤗 Hub 上的检查点名称。

导出到 TorchScript

原文:huggingface.co/docs/transformers/v4.37.2/en/torchscript

这是我们使用 TorchScript 的实验的开始,我们仍在探索其对于可变输入大小模型的能力。这是我们感兴趣的焦点,我们将在即将发布的版本中深入分析,提供更多代码示例,更灵活的实现以及将 Python 代码与编译后的 TorchScript 进行比较的基准测试。

根据TorchScript 文档

TorchScript 是一种从 PyTorch 代码创建可序列化和可优化模型的方法。

有两个 PyTorch 模块JIT 和 TRACE,允许开发人员将他们的模型导出以便在其他程序中重复使用,比如面向效率的 C++程序。

我们提供了一个接口,允许您将🤗 Transformers 模型导出到 TorchScript,以便在与基于 PyTorch 的 Python 程序不同的环境中重复使用。在这里,我们解释了如何使用 TorchScript 导出和使用我们的模型。

导出模型需要两件事:

  • 使用torchscript标志实例化模型
  • 使用虚拟输入进行前向传递

这些必需品意味着开发人员应该注意以下几点。

TorchScript 标志和绑定权重

torchscript标志是必需的,因为大多数🤗 Transformers 语言模型的Embedding层和Decoding层之间有绑定权重。TorchScript 不允许您导出具有绑定权重的模型,因此需要在此之前解开并克隆权重。

使用torchscript标志实例化的模型将它们的Embedding层和Decoding层分开,这意味着它们不应该在训练过程中进行训练。训练会使这两层不同步,导致意外结果。

对于没有语言模型头的模型,情况并非如此,因为这些模型没有绑定权重。这些模型可以安全地导出而不使用torchscript标志。

虚拟输入和标准长度

虚拟输入用于模型的前向传递。当输入的值通过层传播时,PyTorch 会跟踪每个张量上执行的不同操作。然后使用这些记录的操作来创建模型的trace

跟踪是相对于输入维度创建的。因此,它受虚拟输入维度的限制,并且对于任何其他序列长度或批量大小都不起作用。当尝试使用不同大小时,会引发以下错误:

代码语言:javascript
复制
`The expanded size of the tensor (3) must match the existing size (7) at non-singleton dimension 2`

我们建议您使用至少与推理过程中将馈送到模型的最大输入一样大的虚拟输入大小来跟踪模型。填充可以帮助填补缺失的值。然而,由于模型是使用较大的输入大小跟踪的,矩阵的维度也会很大,导致更多的计算。

要注意每个输入上执行的总操作数,并在导出不同序列长度模型时密切关注性能。

在 Python 中使用 TorchScript

本节演示了如何保存和加载模型以及如何使用跟踪进行推理。

保存模型

要导出带有 TorchScript 的BertModel,请从BertConfig类实例化BertModel,然后将其保存到磁盘上的文件名为traced_bert.pt

代码语言:javascript
复制
from transformers import BertModel, BertTokenizer, BertConfig
import torch

enc = BertTokenizer.from_pretrained("bert-base-uncased")

# Tokenizing input text
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = enc.tokenize(text)

# Masking one of the input tokens
masked_index = 8
tokenized_text[masked_index] = "[MASK]"
indexed_tokens = enc.convert_tokens_to_ids(tokenized_text)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]

# Creating a dummy input
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])
dummy_input = [tokens_tensor, segments_tensors]

# Initializing the model with the torchscript flag
# Flag set to True even though it is not necessary as this model does not have an LM Head.
config = BertConfig(
    vocab_size_or_config_json_file=32000,
    hidden_size=768,
    num_hidden_layers=12,
    num_attention_heads=12,
    intermediate_size=3072,
    torchscript=True,
)

# Instantiating the model
model = BertModel(config)

# The model needs to be in evaluation mode
model.eval()

# If you are instantiating the model with *from_pretrained* you can also easily set the TorchScript flag
model = BertModel.from_pretrained("bert-base-uncased", torchscript=True)

# Creating the trace
traced_model = torch.jit.trace(model, [tokens_tensor, segments_tensors])
torch.jit.save(traced_model, "traced_bert.pt")
加载模型

现在,您可以加载先前保存的BertModeltraced_bert.pt,从磁盘上并在先前初始化的dummy_input上使用它:

代码语言:javascript
复制
loaded_model = torch.jit.load("traced_bert.pt")
loaded_model.eval()

all_encoder_layers, pooled_output = loaded_model(*dummy_input)
使用跟踪模型进行推理

通过使用其__call__ dunder 方法对推理使用跟踪模型:

代码语言:javascript
复制
traced_model(tokens_tensor, segments_tensors)

使用 Neuron SDK 将 Hugging Face TorchScript 模型部署到 AWS

AWS 推出了Amazon EC2 Inf1实例系列,用于在云中进行低成本、高性能的机器学习推理。Inf1 实例由 AWS Inferentia 芯片提供动力,这是一种专门用于深度学习推理工作负载的定制硬件加速器。AWS Neuron是用于 Inferentia 的 SDK,支持跟踪和优化 transformers 模型,以便在 Inf1 上部署。Neuron SDK 提供:

  1. 易于使用的 API,只需更改一行代码即可跟踪和优化 TorchScript 模型,以便在云中进行推理。
  2. 针对改进的成本性能进行即插即用的性能优化。
  3. 支持使用PyTorchTensorFlow构建的 Hugging Face transformers 模型。
影响

基于BERT(来自 Transformers 的双向编码器表示)架构的 transformers 模型,或其变体,如distilBERTroBERTa在非生成任务(如提取式问答、序列分类和标记分类)上在 Inf1 上运行效果最佳。然而,文本生成任务仍可以根据此AWS Neuron MarianMT 教程进行适应以在 Inf1 上运行。有关可以直接在 Inferentia 上转换的模型的更多信息,请参阅 Neuron 文档的模型架构适配部分。

依赖

使用 AWS Neuron 转换模型需要一个Neuron SDK 环境,该环境预先配置在AWS 深度学习 AMI上。

将模型转换为 AWS Neuron

使用与在 Python 中使用 TorchScript 相同的代码来为 AWS NEURON 转换模型,以跟踪BertModel。导入torch.neuron框架扩展以通过 Python API 访问 Neuron SDK 的组件:

代码语言:javascript
复制
from transformers import BertModel, BertTokenizer, BertConfig
import torch
import torch.neuron

您只需要修改以下行:

代码语言:javascript
复制
- torch.jit.trace(model, [tokens_tensor, segments_tensors])
+ torch.neuron.trace(model, [token_tensor, segments_tensors])

这使得 Neuron SDK 能够跟踪模型并为 Inf1 实例进行优化。

要了解有关 AWS Neuron SDK 功能、工具、示例教程和最新更新的更多信息,请参阅AWS NeuronSDK 文档

基准测试

原始文本:huggingface.co/docs/transformers/v4.37.2/en/benchmarks

Hugging Face 的基准测试工具已被弃用,建议使用外部基准测试库来衡量 Transformer 模型的速度和内存复杂性。

让我们看看如何对🤗 Transformers 模型进行基准测试,最佳实践以及已有的基准测试。

可以在此处找到更详细解释如何对🤗 Transformers 模型进行基准测试的笔记本。

如何对🤗 Transformers 模型进行基准测试

PyTorchBenchmarkTensorFlowBenchmark类允许灵活地对🤗 Transformers 模型进行基准测试。基准类允许我们测量峰值内存使用量所需时间,用于推理训练

在此,推理由单个前向传递定义,训练由单个前向传递和反向传递定义。

基准类PyTorchBenchmarkTensorFlowBenchmark分别期望使用PyTorchBenchmarkArgumentsTensorFlowBenchmarkArguments类型的对象进行实例化。PyTorchBenchmarkArgumentsTensorFlowBenchmarkArguments是数据类,包含其对应基准类的所有相关配置。在以下示例中,展示了如何对类型为bert-base-cased的 BERT 模型进行基准测试。

Pytorch 隐藏了 Pytorch 内容

代码语言:javascript
复制
>>> from transformers import PyTorchBenchmark, PyTorchBenchmarkArguments

>>> args = PyTorchBenchmarkArguments(models=["bert-base-uncased"], batch_sizes=[8], sequence_lengths=[8, 32, 128, 512])
>>> benchmark = PyTorchBenchmark(args)

TensorFlow 隐藏了 TensorFlow 内容

代码语言:javascript
复制
>>> from transformers import TensorFlowBenchmark, TensorFlowBenchmarkArguments

>>> args = TensorFlowBenchmarkArguments(
...     models=["bert-base-uncased"], batch_sizes=[8], sequence_lengths=[8, 32, 128, 512]
... )
>>> benchmark = TensorFlowBenchmark(args)

在这里,基准参数数据类给出了三个参数,分别是modelsbatch_sizessequence_lengths。参数models是必需的,期望从model hub中的模型标识符列表。list参数batch_sizessequence_lengths定义了对模型进行基准测试的input_ids的大小。还有许多其他参数可以通过基准参数数据类进行配置。有关这些参数的更多详细信息,可以直接查阅文件src/transformers/benchmark/benchmark_args_utils.pysrc/transformers/benchmark/benchmark_args.py(用于 PyTorch)和src/transformers/benchmark/benchmark_args_tf.py(用于 Tensorflow)。或者,从根目录运行以下 shell 命令将分别打印出 PyTorch 和 Tensorflow 的所有可配置参数的描述性列表。

Pytorch 隐藏了 Pytorch 内容

代码语言:javascript
复制
python examples/pytorch/benchmarking/run_benchmark.py --help

然后,通过调用benchmark.run()来简单运行实例化的基准对象。

代码语言:javascript
复制
>>> results = benchmark.run()
>>> print(results)
====================       INFERENCE - SPEED - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length     Time in s                  
--------------------------------------------------------------------------------
bert-base-uncased          8               8             0.006     
bert-base-uncased          8               32            0.006     
bert-base-uncased          8              128            0.018     
bert-base-uncased          8              512            0.088     
--------------------------------------------------------------------------------

====================      INFERENCE - MEMORY - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length    Memory in MB 
--------------------------------------------------------------------------------
bert-base-uncased          8               8             1227
bert-base-uncased          8               32            1281
bert-base-uncased          8              128            1307
bert-base-uncased          8              512            1539
--------------------------------------------------------------------------------

====================        ENVIRONMENT INFORMATION         ====================

- transformers_version: 2.11.0
- framework: PyTorch
- use_torchscript: False
- framework_version: 1.4.0
- python_version: 3.6.10
- system: Linux
- cpu: x86_64
- architecture: 64bit
- date: 2020-06-29
- time: 08:58:43.371351
- fp16: False
- use_multiprocessing: True
- only_pretrain_model: False
- cpu_ram_mb: 32088
- use_gpu: True
- num_gpus: 1
- gpu: TITAN RTX
- gpu_ram_mb: 24217
- gpu_power_watts: 280.0
- gpu_performance_state: 2
- use_tpu: False

TensorFlow 隐藏了 TensorFlow 内容

代码语言:javascript
复制
python examples/tensorflow/benchmarking/run_benchmark_tf.py --help

然后,通过调用benchmark.run()来简单运行实例化的基准对象。

代码语言:javascript
复制
>>> results = benchmark.run()
>>> print(results)
>>> results = benchmark.run()
>>> print(results)
====================       INFERENCE - SPEED - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length     Time in s                  
--------------------------------------------------------------------------------
bert-base-uncased          8               8             0.005
bert-base-uncased          8               32            0.008
bert-base-uncased          8              128            0.022
bert-base-uncased          8              512            0.105
--------------------------------------------------------------------------------

====================      INFERENCE - MEMORY - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length    Memory in MB 
--------------------------------------------------------------------------------
bert-base-uncased          8               8             1330
bert-base-uncased          8               32            1330
bert-base-uncased          8              128            1330
bert-base-uncased          8              512            1770
--------------------------------------------------------------------------------

====================        ENVIRONMENT INFORMATION         ====================

- transformers_version: 2.11.0
- framework: Tensorflow
- use_xla: False
- framework_version: 2.2.0
- python_version: 3.6.10
- system: Linux
- cpu: x86_64
- architecture: 64bit
- date: 2020-06-29
- time: 09:26:35.617317
- fp16: False
- use_multiprocessing: True
- only_pretrain_model: False
- cpu_ram_mb: 32088
- use_gpu: True
- num_gpus: 1
- gpu: TITAN RTX
- gpu_ram_mb: 24217
- gpu_power_watts: 280.0
- gpu_performance_state: 2
- use_tpu: False

默认情况下,对推理时间所需内存进行基准测试。在上面的示例输出中,前两个部分显示了与推理时间推理内存对应的结果。此外,关于计算环境的所有相关信息,例如 GPU 类型、系统、库版本等,都会在第三部分的环境信息下打印出来。当向PyTorchBenchmarkArgumentsTensorFlowBenchmarkArguments分别添加参数save_to_csv=True时,此信息可以选择保存在*.csv文件中。在这种情况下,每个部分都保存在单独的.csv文件中。可以通过参数数据类可选地定义每个.csv*文件的路径。

用户可以选择通过其模型标识符,例如 bert-base-uncased,对预训练模型进行基准测试,也可以选择对任何可用模型类的任意配置进行基准测试。在这种情况下,必须在基准参数中插入一组配置列表。如下所示。

Pytorch 隐藏了 Pytorch 内容

代码语言:javascript
复制
>>> from transformers import PyTorchBenchmark, PyTorchBenchmarkArguments, BertConfig

>>> args = PyTorchBenchmarkArguments(
...     models=["bert-base", "bert-384-hid", "bert-6-lay"], batch_sizes=[8], sequence_lengths=[8, 32, 128, 512]
... )
>>> config_base = BertConfig()
>>> config_384_hid = BertConfig(hidden_size=384)
>>> config_6_lay = BertConfig(num_hidden_layers=6)

>>> benchmark = PyTorchBenchmark(args, configs=[config_base, config_384_hid, config_6_lay])
>>> benchmark.run()
====================       INFERENCE - SPEED - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length       Time in s                  
--------------------------------------------------------------------------------
bert-base                  8              128            0.006
bert-base                  8              512            0.006
bert-base                  8              128            0.018     
bert-base                  8              512            0.088     
bert-384-hid              8               8             0.006     
bert-384-hid              8               32            0.006     
bert-384-hid              8              128            0.011     
bert-384-hid              8              512            0.054     
bert-6-lay                 8               8             0.003     
bert-6-lay                 8               32            0.004     
bert-6-lay                 8              128            0.009     
bert-6-lay                 8              512            0.044
--------------------------------------------------------------------------------

====================      INFERENCE - MEMORY - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length      Memory in MB 
--------------------------------------------------------------------------------
bert-base                  8               8             1277
bert-base                  8               32            1281
bert-base                  8              128            1307     
bert-base                  8              512            1539     
bert-384-hid              8               8             1005     
bert-384-hid              8               32            1027     
bert-384-hid              8              128            1035     
bert-384-hid              8              512            1255     
bert-6-lay                 8               8             1097     
bert-6-lay                 8               32            1101     
bert-6-lay                 8              128            1127     
bert-6-lay                 8              512            1359
--------------------------------------------------------------------------------

====================        ENVIRONMENT INFORMATION         ====================

- transformers_version: 2.11.0
- framework: PyTorch
- use_torchscript: False
- framework_version: 1.4.0
- python_version: 3.6.10
- system: Linux
- cpu: x86_64
- architecture: 64bit
- date: 2020-06-29
- time: 09:35:25.143267
- fp16: False
- use_multiprocessing: True
- only_pretrain_model: False
- cpu_ram_mb: 32088
- use_gpu: True
- num_gpus: 1
- gpu: TITAN RTX
- gpu_ram_mb: 24217
- gpu_power_watts: 280.0
- gpu_performance_state: 2
- use_tpu: False

TensorFlow 隐藏了 TensorFlow 内容

代码语言:javascript
复制
>>> from transformers import TensorFlowBenchmark, TensorFlowBenchmarkArguments, BertConfig

>>> args = TensorFlowBenchmarkArguments(
...     models=["bert-base", "bert-384-hid", "bert-6-lay"], batch_sizes=[8], sequence_lengths=[8, 32, 128, 512]
... )
>>> config_base = BertConfig()
>>> config_384_hid = BertConfig(hidden_size=384)
>>> config_6_lay = BertConfig(num_hidden_layers=6)

>>> benchmark = TensorFlowBenchmark(args, configs=[config_base, config_384_hid, config_6_lay])
>>> benchmark.run()
====================       INFERENCE - SPEED - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length       Time in s                  
--------------------------------------------------------------------------------
bert-base                  8               8             0.005
bert-base                  8               32            0.008
bert-base                  8              128            0.022
bert-base                  8              512            0.106
bert-384-hid              8               8             0.005
bert-384-hid              8               32            0.007
bert-384-hid              8              128            0.018
bert-384-hid              8              512            0.064
bert-6-lay                 8               8             0.002
bert-6-lay                 8               32            0.003
bert-6-lay                 8              128            0.0011
bert-6-lay                 8              512            0.074
--------------------------------------------------------------------------------

====================      INFERENCE - MEMORY - RESULT       ====================
--------------------------------------------------------------------------------
Model Name             Batch Size     Seq Length      Memory in MB 
--------------------------------------------------------------------------------
bert-base                  8               8             1330
bert-base                  8               32            1330
bert-base                  8              128            1330
bert-base                  8              512            1770
bert-384-hid              8               8             1330
bert-384-hid              8               32            1330
bert-384-hid              8              128            1330
bert-384-hid              8              512            1540
bert-6-lay                 8               8             1330
bert-6-lay                 8               32            1330
bert-6-lay                 8              128            1330
bert-6-lay                 8              512            1540
--------------------------------------------------------------------------------

====================        ENVIRONMENT INFORMATION         ====================

- transformers_version: 2.11.0
- framework: Tensorflow
- use_xla: False
- framework_version: 2.2.0
- python_version: 3.6.10
- system: Linux
- cpu: x86_64
- architecture: 64bit
- date: 2020-06-29
- time: 09:38:15.487125
- fp16: False
- use_multiprocessing: True
- only_pretrain_model: False
- cpu_ram_mb: 32088
- use_gpu: True
- num_gpus: 1
- gpu: TITAN RTX
- gpu_ram_mb: 24217
- gpu_power_watts: 280.0
- gpu_performance_state: 2
- use_tpu: False

再次,推理时间所需内存用于推理的测量,但这次是针对BertModel类的自定义配置。在决定应该为哪种配置训练模型时,此功能尤其有帮助。

基准测试最佳实践

本节列出了在对模型进行基准测试时应注意的一些最佳实践。

  • 目前仅支持单设备基准测试。在 GPU 上进行基准测试时,建议用户通过在 shell 中设置CUDA_VISIBLE_DEVICES环境变量来指定代码应在哪个设备上运行,例如在运行代码之前设置export CUDA_VISIBLE_DEVICES=0
  • 选项no_multi_processing应仅在测试和调试时设置为True。为了确保准确的内存测量,建议通过确保将no_multi_processing设置为True来在单独的进程中运行每个内存基准测试。
  • 在分享模型基准测试结果时,应始终说明环境信息。由于不同的 GPU 设备、库版本等之间的结果可能会有很大差异,因此单独的基准测试结果对社区来说并不是非常有用。

分享您的基准测试

以前,所有可用的核心模型(当时为 10 个)都已针对推理时间进行了基准测试,涵盖了许多不同的设置:使用 PyTorch,使用 TorchScript 或不使用,使用 TensorFlow,使用 XLA 或不使用。所有这些测试都是在 CPU(除了 TensorFlow XLA)和 GPU 上进行的。

该方法在以下博文中有详细说明,结果可在此处查看。

有了新的基准工具,与社区分享基准测试结果比以往更容易

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用于推理的多语言模型
    • XLM
      • 带有语言嵌入的 XLM
      • 没有语言嵌入的 XLM
    • BERT
      • XLM-RoBERTa
        • M2M100
          • MBart
          • 创建自定义架构
            • 配置
              • 模型
                • 模型头
              • Tokenizer
                • 图像处理器
                  • 特征提取器
                    • 处理器
                    • 构建自定义模型
                      • 编写自定义配置
                        • 编写自定义模型
                          • 将带有自定义代码的模型注册到自动类
                            • 将代码发送到 Hub
                              • 使用具有自定义代码的模型
                              • 聊天模型的模板
                                • 介绍
                                  • 如何使用聊天模板?
                                    • 是否有用于聊天的自动化管道?
                                      • “生成提示”是什么?
                                        • 我可以在训练中使用聊天模板吗?
                                          • 高级:聊天模板如何工作?
                                            • 高级:添加和编辑聊天模板
                                              • 如何创建聊天模板?
                                              • “默认”模板是什么?
                                              • 我应该使用哪个模板?
                                              • 我想添加一些聊天模板!我应该如何开始?
                                            • 高级:模板编写提示
                                              • 对于循环
                                              • if 语句
                                              • 特殊变量
                                              • 空格注意事项
                                          • Trainer
                                            • 基本用法
                                              • 检查点
                                            • 自定义 Trainer
                                              • 回调
                                            • 日志
                                              • NEFTune
                                                • 加速和 Trainer
                                                  • 目录
                                              • 在 Amazon SageMaker 上运行训练
                                              • 导出为 ONNX
                                                • 导出为 ONNX
                                                  • 使用 CLI 将🤗 Transformers 模型导出为 ONNX
                                                  • 使用 optimum.onnxruntime 将 🤗 Transformers 模型导出到 ONNX
                                                  • 将模型导出到不受支持的架构
                                                  • 使用 transformers.onnx 导出模型
                                              • 导出到 TFLite
                                              • 导出到 TorchScript
                                                • TorchScript 标志和绑定权重
                                                  • 虚拟输入和标准长度
                                                    • 在 Python 中使用 TorchScript
                                                      • 保存模型
                                                      • 加载模型
                                                      • 使用跟踪模型进行推理
                                                    • 使用 Neuron SDK 将 Hugging Face TorchScript 模型部署到 AWS
                                                      • 影响
                                                      • 依赖
                                                      • 将模型转换为 AWS Neuron
                                                  • 基准测试
                                                    • 如何对🤗 Transformers 模型进行基准测试
                                                      • 基准测试最佳实践
                                                        • 分享您的基准测试
                                                        相关产品与服务
                                                        腾讯云服务器利旧
                                                        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                                                        领券
                                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档