使用 🤗 Optimum Intel 和 OpenVINO 加速您的模型

发布于 2022 年 11 月 2 日
在 GitHub 上更新

image

去年七月,我们宣布英特尔和 Hugging Face 将合作构建用于 Transformer 模型的先进而简单的硬件加速工具。今天,我们很高兴地宣布,我们已将英特尔 OpenVINO 添加到 Optimum Intel 中。现在,您可以使用 OpenVINO Runtime 轻松在各种英特尔处理器上执行推理(查看支持设备的完整列表),使用可在 Hugging Face Hub 或本地托管的 Transformer 模型。您还可以使用 OpenVINO 神经网络压缩框架(NNCF)量化您的模型,并在几分钟内减少其大小和预测延迟。

此第一个版本基于 OpenVINO 2022.2,并使用我们的 OVModels 为大量 PyTorch 模型提供推理功能。训练后静态量化和量化感知训练可以应用于许多编码器模型(BERT、DistilBERT 等)。更多编码器模型将在即将发布的 OpenVINO 版本中得到支持。目前,编码器-解码器模型的量化尚未启用,但此限制应在我们的下一个 OpenVINO 版本集成后解除。

让我们向您展示如何在几分钟内开始!

使用 Optimum Intel 和 OpenVINO 量化 Vision Transformer

在本例中,我们将对在 food101 数据集上进行图像分类微调的 Vision Transformer (ViT) 模型执行训练后静态量化。

量化是一种通过减少模型参数的位宽来降低内存和计算需求的过程。减少位数意味着生成的模型在推理时需要更少的内存,并且由于整数运算,矩阵乘法等操作可以更快地执行。

首先,让我们创建一个虚拟环境并安装所有依赖项。

virtualenv openvino
source openvino/bin/activate
pip install pip --upgrade
pip install optimum[openvino,nncf] torchvision evaluate

接下来,进入 Python 环境,我们导入适当的模块并下载原始模型及其处理器。

from transformers import AutoImageProcessor, AutoModelForImageClassification
​
model_id = "juliensimon/autotrain-food101-1471154050"
model = AutoModelForImageClassification.from_pretrained(model_id)
processor = AutoImageProcessor.from_pretrained(model_id)

训练后静态量化需要一个校准步骤,其中数据通过网络进行馈送以计算量化的激活参数。在这里,我们从原始数据集中取出 300 个样本来构建校准数据集。

from optimum.intel.openvino import OVQuantizer
​
quantizer = OVQuantizer.from_pretrained(model)
calibration_dataset = quantizer.get_calibration_dataset(
    "food101",
    num_samples=300,
    dataset_split="train",
)

与图像数据集一样,我们需要应用与训练时相同的图像转换。我们使用处理器中定义的预处理。我们还定义了一个数据整理函数,以将正确格式化的张量批次馈送到模型。

import torch
from torchvision.transforms import (
    CenterCrop,
    Compose,
    Normalize,
    Resize,
    ToTensor,
)
​
normalize = Normalize(mean=processor.image_mean, std=processor.image_std)
size = processor.size["height"]
_val_transforms = Compose(
    [
        Resize(size),
        CenterCrop(size),
        ToTensor(),
        normalize,
    ]
)
def val_transforms(example_batch):
    example_batch["pixel_values"] = [_val_transforms(pil_img.convert("RGB")) for pil_img in example_batch["image"]]
    return example_batch
​
calibration_dataset.set_transform(val_transforms)
​
def collate_fn(examples):
    pixel_values = torch.stack([example["pixel_values"] for example in examples])
    labels = torch.tensor([example["label"] for example in examples])
    return {"pixel_values": pixel_values, "labels": labels}

对于我们的第一次尝试,我们使用默认的量化配置。您还可以指定在校准步骤中使用的样本数量,默认为 300。

from optimum.intel.openvino import OVConfig
​
quantization_config = OVConfig()
quantization_config.compression["initializer"]["range"]["num_init_samples"] = 300

我们现在可以量化模型了。`OVQuantizer.quantize()` 方法将模型量化并将其导出为 OpenVINO 格式。生成的图表由两个文件表示:一个描述网络拓扑的 XML 文件和一个描述权重的二进制文件。生成的模型可以在任何 Intel® 目标设备上运行。

save_dir = "quantized_model"

# Apply static quantization and export the resulting quantized model to OpenVINO IR format
quantizer.quantize(
    quantization_config=quantization_config,
    calibration_dataset=calibration_dataset,
    data_collator=collate_fn,
    remove_unused_columns=False,
    save_directory=save_dir,
)
processor.save_pretrained(save_dir)

一两分钟后,模型已经量化完成。然后,我们可以使用我们的 OVModelForXxx 类轻松加载它,这些类等同于 `transformers` 库中的 Transformers AutoModelForXxx 类。同样,我们可以创建 管道 并使用 OpenVINO Runtime 运行推理。

from transformers import pipeline
from optimum.intel.openvino import OVModelForImageClassification
​
ov_model = OVModelForImageClassification.from_pretrained(save_dir)
ov_pipe = pipeline("image-classification", model=ov_model, image_processor=processor)
outputs = ov_pipe("http://farm2.staticflickr.com/1375/1394861946_171ea43524_z.jpg")
print(outputs)

为了验证量化是否对准确性没有负面影响,我们应用了评估步骤来比较原始模型与其量化模型的准确性。我们评估了数据集子集(仅取评估数据集的 20%)上的两个模型。我们观察到准确性损失很小或没有损失,两个模型的准确性均为 **87.6**。

from datasets import load_dataset
from evaluate import evaluator

# We run the evaluation step on 20% of the evaluation dataset
eval_dataset = load_dataset("food101", split="validation").select(range(5050))
task_evaluator = evaluator("image-classification")

ov_eval_results = task_evaluator.compute(
    model_or_pipeline=ov_pipe,
    data=eval_dataset,
    metric="accuracy",
    label_mapping=ov_pipe.model.config.label2id,
)

trfs_pipe = pipeline("image-classification", model=model, image_processor=processor)
trfs_eval_results = task_evaluator.compute(
    model_or_pipeline=trfs_pipe,
    data=eval_dataset,
    metric="accuracy",
    label_mapping=trfs_pipe.model.config.label2id,
)
print(trfs_eval_results, ov_eval_results)

查看量化模型,我们发现其内存大小从 344MB 减少到 90MB,缩小了 **3.8 倍**。对 5050 张图像预测进行快速基准测试,我们还注意到延迟加快了 **2.4 倍**,从每样本 98 毫秒降至 41 毫秒。这对于几行代码来说还不错!

⚠️ 需要提及的重要一点是,模型在第一次推理之前才会编译,这会增加第一次推理的延迟。因此,在进行您自己的基准测试之前,请务必先通过至少一次预测来预热模型。

您可以在 Hugging Face Hub 上找到生成的模型。要加载它,您可以轻松地执行以下操作:

from optimum.intel.openvino import OVModelForImageClassification
​
ov_model = OVModelForImageClassification.from_pretrained("echarlaix/vit-food101-int8")

现在轮到你了

如您所见,使用 🤗 Optimum Intel 和 OpenVINO 加速您的模型非常容易。如果您想开始,请访问 Optimum Intel 仓库,并且不要忘记给它一个星⭐。您还可以在此处找到其他示例。如果您想深入了解 OpenVINO,Intel 文档会为您提供帮助。

试一试,让我们知道您的想法。我们很乐意在 Hugging Face 论坛上听到您的反馈,并且请随时在 Github 上提出功能请求或提交问题。

祝您使用 🤗 Optimum Intel 愉快,感谢您的阅读。

社区

注册登录以发表评论