将模型导出为 ONNX 格式¶
在生产环境中部署 🤗 Transformers 模型时,通常需要将模型导出为一种序列化格式,以便在专用运行时和硬件上加载和执行。
🤗 Optimum 是 Transformers 的一个扩展,通过其 exporters 模块,可以将模型从 PyTorch 或 TensorFlow 导出为序列化格式,如 ONNX 和 TFLite。🤗 Optimum 还提供了一组性能优化工具,以在目标硬件上以最大效率训练和运行模型。
本指南演示了如何使用 🤗 Optimum 将 🤗 Transformers 模型导出为 ONNX 格式。有关将模型导出为 TFLite 的指南,请参阅 导出到 TFLite 页面。
导出到 ONNX¶
ONNX(开放神经网络交换) 是一个开放标准,定义了一组通用的操作符和一个通用的文件格式,用于在各种框架(包括 PyTorch 和 TensorFlow)中表示深度学习模型。当模型导出为 ONNX 格式时,这些操作符用于构建一个计算图(通常称为中间表示),该图表示数据在神经网络中的流动。
通过公开具有标准化操作符和数据类型的图,ONNX 使得在框架之间切换变得容易。例如,在 PyTorch 中训练的模型可以导出为 ONNX 格式,然后在 TensorFlow 中导入(反之亦然)。
一旦导出为 ONNX 格式,模型可以:
- 通过图优化和量化等技术进行推理优化。
- 通过
ORTModelForXXX类 使用 ONNX Runtime 运行,这些类遵循与 🤗 Transformers 中相同的AutoModelAPI。 - 通过优化推理管道运行,其 API 与 🤗 Transformers 中的 pipeline() 函数相同。
🤗 Optimum 通过利用配置对象来支持 ONNX 导出。这些配置对象为多种模型架构提供了现成的支持,并且设计为易于扩展到其他架构。
有关现成配置的列表,请参阅 🤗 Optimum 文档。
有两种方法可以将 🤗 Transformers 模型导出为 ONNX,这里我们展示两种方法:
- 通过 CLI 使用 🤗 Optimum 导出。
- 通过
optimum.onnxruntime使用 🤗 Optimum 导出。
通过 CLI 导出 🤗 Transformers 模型到 ONNX¶
要将 🤗 Transformers 模型导出为 ONNX,首先安装一个额外的依赖项:
pip install optimum[exporters]
要查看所有可用参数,请参阅 🤗 Optimum 文档,或在命令行中查看帮助:
optimum-cli export onnx --help
要从 🤗 Hub 导出模型的检查点,例如 distilbert/distilbert-base-uncased-distilled-squad,运行以下命令:
optimum-cli export onnx --model distilbert/distilbert-base-uncased-distilled-squad distilbert_base_uncased_squad_onnx/
你应该会看到日志指示进度,并显示保存的 model.onnx 文件的位置,如下所示:
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 参数,它将默认为模型架构,而不带任何任务特定的头部。
optimum-cli export onnx --model local_path --task question-answering distilbert_base_uncased_squad_onnx/
生成的 model.onnx 文件可以在支持 ONNX 标准的许多加速器上运行。例如,我们可以使用 ONNX Runtime 加载和运行模型,如下所示:
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 检查点:
optimum-cli export onnx --model keras-io/transformers-qa distilbert_base_cased_squad_onnx/
通过 optimum.onnxruntime 导出 🤗 Transformers 模型到 ONNX¶
除了 CLI,你还可以通过编程方式将 🤗 Transformers 模型导出为 ONNX,如下所示:
from optimum.onnxruntime import ORTModelForSequenceClassification
from transformers import AutoTokenizer
model_checkpoint = "distilbert_base_uncased_squad"
save_directory = "onnx/"
# 从 transformers 加载模型并导出为 ONNX
ort_model = ORTModelForSequenceClassification.from_pretrained(model_checkpoint, export=True)
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
# 保存 ONNX 模型和分词器
ort_model.save_pretrained(save_directory)
tokenizer.save_pretrained(save_directory)
导出不支持架构的模型¶
如果你想通过添加对当前无法导出的模型的支持来贡献,你应该首先检查它是否在 optimum.exporters.onnx 中受支持,如果未受支持,请直接贡献到 🤗 Optimum。
通过 transformers.onnx 导出模型¶
transformers.onnx 不再维护,请按照上述方法使用 🤗 Optimum 导出模型。此部分将在未来版本中删除。
要将 🤗 Transformers 模型通过 transformers.onnx 导出为 ONNX,请安装额外的依赖项:
pip install transformers[onnx]
使用 transformers.onnx 包作为 Python 模块,使用现成的配置导出检查点:
python -m transformers.onnx --model=distilbert/distilbert-base-uncased onnx/
这将导出由 --model 参数定义的检查点的 ONNX 图。传递 🤗 Hub 上的任何检查点或本地存储的检查点。生成的 model.onnx 文件可以在支持 ONNX 标准的许多加速器上运行。例如,使用 ONNX Runtime 加载和运行模型,如下所示:
from transformers import AutoTokenizer
from onnxruntime import InferenceSession
tokenizer = AutoTokenizer.from_pretrained("distilbert/distilbert-base-uncased")
session = InferenceSession("onnx/model.onnx")
# ONNX Runtime 期望输入为 NumPy 数组
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,我们有:
from transformers.models.distilbert import DistilBertConfig, DistilBertOnnxConfig
config = DistilBertConfig()
onnx_config = DistilBertOnnxConfig(config)
print(list(onnx_config.outputs.keys()))
对于 Hub 上的 TensorFlow 检查点,过程是相同的。例如,导出纯 TensorFlow 检查点,如下所示:
python -m transformers.onnx --model=keras-io/transformers-qa onnx/
要导出本地存储的模型,请将模型的权重和分词器文件保存在同一目录(例如 local-pt-checkpoint)中,然后通过将 transformers.onnx 包的 --model 参数指向所需目录来将其导出为 ONNX:
python -m transformers.onnx --model=local-pt-checkpoint onnx/