英特尔与Hugging Face合作,推广机器学习硬件加速技术
Intel collaborates with Hugging Face to promote hardware acceleration technology for machine learning.
Hugging Face 的使命是使良好的机器学习民主化,并在各个行业和社会中实现最大的积极影响。我们不仅努力推进 Transformer 模型的发展,还致力于简化它们的采用。
今天,我们很高兴地宣布 Intel 正式加入我们的硬件合作伙伴计划。借助 Optimum 开源库,Intel 和 Hugging Face 将合作构建最先进的硬件加速器,用于 Transformer 的训练、微调和预测。
Transformer 模型越来越大、越来越复杂,这可能对搜索或聊天机器人等对延迟敏感的应用程序造成生产挑战。遗憾的是,延迟优化一直是机器学习(ML)从业者面临的难题。即使了解底层框架和硬件平台的深度知识,也需要大量的试错来确定要利用哪些旋钮和功能。
Intel 提供了用于加速人工智能的完整基础,包括 Intel Xeon 可扩展 CPU 平台和广泛的硬件优化人工智能软件工具、框架和库。因此,Hugging Face 和 Intel 联手合作,在 Intel 平台上构建强大的模型优化工具,使用户能够实现最佳性能、规模和工作效率。
“我们很高兴与 Hugging Face 合作,通过开源集成和集成开发体验,将英特尔 Xeon 硬件和英特尔 AI 软件的最新创新带给 Transformer 社区。”英特尔副总裁兼人工智能与分析总经理魏力(Wei Li)表示。
近几个月来,英特尔和 Hugging Face 在扩展 Transformer 工作负载方面展开了合作。我们在推理(第一部分,第二部分)方面发布了详细的调优指南和基准测试,并在最新的英特尔 Xeon Ice Lake CPU 上实现了 DistilBERT 的单位时间毫秒级延迟。在训练方面,我们增加了对 Habana Gaudi 加速器的支持,其性能与 GPU 相比提高了 40%。
下一个逻辑步骤是在这项工作的基础上进行扩展,并与机器学习社区共享。这就是 Optimum Intel 开源库的出现!让我们深入了解一下。
通过 Optimum Intel 获得最佳 Transformer 性能
Optimum 是由 Hugging Face 创建的开源库,旨在简化不断增长的训练和推理设备上的 Transformer 加速。借助内置的优化技术,您可以在几分钟内开始加速工作负载,使用现成的脚本或对现有代码进行最小更改。初学者可以直接使用 Optimum 并取得出色的结果。专家可以进行微调以获得最佳性能。
Optimum Intel 是 Optimum 的一部分,建立在英特尔神经压缩器(INC)之上。INC 是一个开源库,为流行的网络压缩技术(如量化、剪枝和知识蒸馏)在多个深度学习框架上提供统一接口。该工具支持自动准确性驱动的调优策略,帮助用户快速构建最佳的量化模型。
使用 Optimum Intel,您可以以最小的努力应用最先进的优化技术到您的 Transformer 模型上。让我们看一个完整的示例。
案例研究:使用 Optimum Intel 进行 DistilBERT 量化
在本示例中,我们将对经过微调的 DistilBERT 模型进行后训练量化,以进行分类。量化是通过减少模型参数的位宽来缩小内存和计算要求的过程。例如,您通常可以通过将 32 位浮点参数替换为 8 位整数来降低预测准确性的代价。
我们已经对原始模型进行了微调,以根据鞋子的星级评价(从 1 到 5 星)对产品评论进行分类。您可以在 Hugging Face Hub 上查看此模型及其量化版本。您还可以在此空间中测试原始模型。
让我们开始吧!所有代码都可以在此笔记本中找到。
通常情况下,第一步是安装所有所需的库。值得一提的是,我们必须使用仅支持 CPU 的 PyTorch 版本才能正确进行量化过程。
pip -q uninstall torch -y
pip -q install torch==1.11.0+cpu --extra-index-url https://download.pytorch.org/whl/cpu
pip -q install transformers datasets optimum[neural-compressor] evaluate --upgrade
然后,我们准备了一个评估数据集,以在量化过程中评估模型性能。从用于微调原始模型的数据集开始,我们只保留了几千个评论及其标签,并将它们保存到本地存储器中。
接下来,我们从Hugging Face hub加载原始模型、其分词器和评估数据集。
from datasets import load_dataset
from transformers import AutoModelForSequenceClassification, AutoTokenizer
model_name = "juliensimon/distilbert-amazon-shoe-reviews"
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=5)
tokenizer = AutoTokenizer.from_pretrained(model_name)
eval_dataset = load_dataset("prashantgrao/amazon-shoe-reviews", split="test").select(range(300))
接下来,我们定义一个评估函数,用于在评估数据集上计算模型指标。这样,Optimum Intel库就可以在量化之前和之后比较这些指标。为此,Hugging Face评估库非常方便!
import evaluate
def eval_func(model):
task_evaluator = evaluate.evaluator("text-classification")
results = task_evaluator.compute(
model_or_pipeline=model,
tokenizer=tokenizer,
data=eval_dataset,
metric=evaluate.load("accuracy"),
label_column="labels",
label_mapping=model.config.label2id,
)
return results["accuracy"]
然后,我们使用[configuration]设置量化作业。您可以在Neural Compressor文档中找到有关此配置的详细信息。在这里,我们选择后训练动态量化,允许精度下降5%。如果精度下降超过允许的5%,则会量化模型的不同部分,直到达到可接受的精度下降,或者达到最大尝试次数(此处设置为10次)。
from neural_compressor.config import AccuracyCriterion, PostTrainingQuantConfig, TuningCriterion
tuning_criterion = TuningCriterion(max_trials=10)
accuracy_criterion = AccuracyCriterion(tolerable_loss=0.05)
# 加载详细说明我们希望应用的量化配置
quantization_config = PostTrainingQuantConfig(
approach="dynamic",
accuracy_criterion=accuracy_criterion,
tuning_criterion=tuning_criterion,
)
现在,我们可以启动量化作业,并将结果模型及其配置文件保存到本地存储。
from neural_compressor.config import PostTrainingQuantConfig
from optimum.intel.neural_compressor import INCQuantizer
# 量化模型将保存的目录
save_dir = "./model_inc"
quantizer = INCQuantizer.from_pretrained(model=model, eval_fn=eval_func)
quantizer.quantize(quantization_config=quantization_config, save_directory=save_dir)
日志告诉我们Optimum Intel已经量化了38个Linear
和2个Embedding
运算符。
[INFO] |******混合精度统计*****|
[INFO] +----------------+----------+---------+
[INFO] | 运算符类型 | 总数 | INT8 |
[INFO] +----------------+----------+---------+
[INFO] | Embedding | 2 | 2 |
[INFO] | Linear | 38 | 38 |
[INFO] +----------------+----------+---------+
比较原始模型的第一层(model.distilbert.transformer.layer[0]
)和其量化版本(inc_model.distilbert.transformer.layer[0]
),我们可以看到Linear
已经被其量化等价物DynamicQuantizedLinear
所取代。
# 原始模型
TransformerBlock(
(attention): MultiHeadSelfAttention(
(dropout): Dropout(p=0.1, inplace=False)
(q_lin): Linear(in_features=768, out_features=768, bias=True)
(k_lin): Linear(in_features=768, out_features=768, bias=True)
(v_lin): Linear(in_features=768, out_features=768, bias=True)
(out_lin): Linear(in_features=768, out_features=768, bias=True)
)
(sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
(ffn): FFN(
(dropout): Dropout(p=0.1, inplace=False)
(lin1): Linear(in_features=768, out_features=3072, bias=True)
(lin2): Linear(in_features=3072, out_features=768, bias=True)
)
(output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
)
# 量化模型
TransformerBlock(
(attention): MultiHeadSelfAttention(
(dropout): Dropout(p=0.1, inplace=False)
(q_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
(k_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
(v_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
(out_lin): DynamicQuantizedLinear(in_features=768, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
)
(sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
(ffn): FFN(
(dropout): Dropout(p=0.1, inplace=False)
(lin1): DynamicQuantizedLinear(in_features=768, out_features=3072, dtype=torch.qint8, qscheme=torch.per_channel_affine)
(lin2): DynamicQuantizedLinear(in_features=3072, out_features=768, dtype=torch.qint8, qscheme=torch.per_channel_affine)
)
(output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)
)
很好,但这对准确性和预测时间有什么影响?
在每个量化步骤之前和之后,Optimum Intel在当前模型上运行评估函数。量化模型的准确性现在比原始模型稍低(0.546
),而原始模型的准确性为(0.574
)。我们还发现量化模型的评估步骤比原始模型快了1.34倍。这对于几行代码来说还不错!
[INFO] |**********************调整结果统计**********************|
[INFO] +--------------------+----------+---------------+------------------+
[INFO] | 信息类型 | 基准 | 调整1结果 | 最佳调整结果 |
[INFO] +--------------------+----------+---------------+------------------+
[INFO] | 准确性 | 0.5740 | 0.5460 | 0.5460 |
[INFO] | 持续时间(秒) | 13.1534 | 9.7695 | 9.7695 |
[INFO] +--------------------+----------+---------------+------------------+
您可以在Hugging Face hub上找到生成的模型。要加载在本地或在🤗 hub上托管的量化模型,可以按照以下步骤进行:
from optimum.intel.neural_compressor import INCModelForSequenceClassification
inc_model = INCModelForSequenceClassification.from_pretrained(save_dir)
我们只是刚刚开始
在这个例子中,我们向您展示了如何使用Optimum Intel轻松进行训练后的模型量化,而这只是个开始。该库还支持其他类型的量化以及修剪,一种将对预测结果没有或很小影响的模型参数置零或删除的技术。
我们很高兴与Intel合作,为Hugging Face用户在最新的Intel Xeon CPU和Intel AI库上提供最佳效率。请给Optimum Intel点个赞以获取更新,并期待即将推出的许多新功能!
非常感谢Ella Charlaix在本文中的帮助。