PyTorch 使用 Intel® Neural Compressor 的易用量化¶
创建于:2022 年 1 月 11 日 | 最后更新于:2024 年 8 月 27 日 | 最后验证:未验证
概述¶
大多数深度学习应用使用 32 位浮点精度进行推理。但是,低精度数据类型,尤其是 int8,因其显著的性能提升而受到越来越多的关注。采用低精度的一个主要担忧是如何轻松地减轻可能的精度损失并达到预定义的精度要求。
Intel® Neural Compressor 旨在通过扩展 PyTorch,提供精度驱动的自动调优策略来解决上述担忧,帮助用户快速在 Intel 硬件(包括 Intel 深度学习加速 (Intel DL Boost) 和 Intel 高级矩阵扩展 (Intel AMX))上找到最佳量化模型。
Intel® Neural Compressor 已在 Github 上发布为开源项目。
特性¶
易用的 Python API: Intel® Neural Compressor 提供了简单的前端 Python API 和实用程序,用户只需修改少量代码即可进行神经网络压缩。通常,只需在原始代码中添加 5 到 6 行语句即可。
量化: Intel® Neural Compressor 支持在 PyTorch 的 FX 图模式和 Eager 模式上进行训练后静态量化、训练后动态量化和量化感知训练的精度驱动自动调优过程。
本教程主要关注量化部分。关于如何使用 Intel® Neural Compressor 进行模型剪枝 (pruning) 和知识蒸馏 (distillation),请参考 Intel® Neural Compressor GitHub 仓库中的相关文档。
入门¶
安装¶
# install stable version from pip
pip install neural-compressor
# install nightly version from pip
pip install -i https://test.pypi.org/simple/ neural-compressor
# install stable version from from conda
conda install neural-compressor -c conda-forge -c intel
支持的 Python 版本为 3.6、3.7、3.8 或 3.9
使用方法¶
用户只需少量代码更改即可开始使用 Intel® Neural Compressor 量化 API。支持 PyTorch FX 图模式和 Eager 模式。
Intel® Neural Compressor 接受 FP32 模型和 yaml 配置文件作为输入。用户可以通过 yaml 配置文件或 Python API 指定以下设置来构建量化过程:
校准数据加载器(静态量化必需)
评估数据加载器
评估指标
Intel® Neural Compressor 支持一些常用的数据加载器和评估指标。关于如何在 yaml 配置文件中配置它们,用户可以参考内置数据集。
如果用户想使用自定义的数据加载器或评估指标,Intel® Neural Compressor 支持通过 Python 代码注册自定义数据加载器/指标。
关于 yaml 配置文件的格式,请参考 yaml 模板。
Intel® Neural Compressor 所需的代码更改已在上一行用注释高亮显示。
模型¶
在本教程中,使用 LeNet 模型演示如何处理 Intel® Neural Compressor。
# main.py
import torch
import torch.nn as nn
import torch.nn.functional as F
# LeNet Model definition
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.conv2_drop = nn.Dropout2d()
self.fc1 = nn.Linear(320, 50)
self.fc1_drop = nn.Dropout()
self.fc2 = nn.Linear(50, 10)
def forward(self, x):
x = F.relu(F.max_pool2d(self.conv1(x), 2))
x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
x = x.reshape(-1, 320)
x = F.relu(self.fc1(x))
x = self.fc1_drop(x)
x = self.fc2(x)
return F.log_softmax(x, dim=1)
model = Net()
model.load_state_dict(torch.load('./lenet_mnist_model.pth', weights_only=True))
预训练模型权重 lenet_mnist_model.pth 来自此处。
精度驱动量化¶
Intel® Neural Compressor 支持精度驱动的自动调优,以生成满足预定义精度目标的最佳 int8 模型。
下面是一个示例,展示了如何在 PyTorch FX 图模式下通过自动调优量化一个简单网络。
# conf.yaml
model:
name: LeNet
framework: pytorch_fx
evaluation:
accuracy:
metric:
topk: 1
tuning:
accuracy_criterion:
relative: 0.01
# main.py
model.eval()
from torchvision import datasets, transforms
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('./data', train=False, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
])),
batch_size=1)
# launch code for Intel® Neural Compressor
from neural_compressor.experimental import Quantization
quantizer = Quantization("./conf.yaml")
quantizer.model = model
quantizer.calib_dataloader = test_loader
quantizer.eval_dataloader = test_loader
q_model = quantizer()
q_model.save('./output')
在 conf.yaml 文件中,Intel® Neural Compressor 的内置指标 top1 被指定为评估方法,并将 1% 的相对精度损失设置为自动调优的精度目标。Intel® Neural Compressor 将遍历每个操作层面所有可能的量化配置组合,以找到达到预定义精度目标的最佳 int8 模型。
除了这些内置指标外,Intel® Neural Compressor 还支持通过 Python 代码自定义指标。
# conf.yaml
model:
name: LeNet
framework: pytorch_fx
tuning:
accuracy_criterion:
relative: 0.01
# main.py
model.eval()
from torchvision import datasets, transforms
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('./data', train=False, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
])),
batch_size=1)
# define a customized metric
class Top1Metric(object):
def __init__(self):
self.correct = 0
def update(self, output, label):
pred = output.argmax(dim=1, keepdim=True)
self.correct += pred.eq(label.view_as(pred)).sum().item()
def reset(self):
self.correct = 0
def result(self):
return 100. * self.correct / len(test_loader.dataset)
# launch code for Intel® Neural Compressor
from neural_compressor.experimental import Quantization
quantizer = Quantization("./conf.yaml")
quantizer.model = model
quantizer.calib_dataloader = test_loader
quantizer.eval_dataloader = test_loader
quantizer.metric = Top1Metric()
q_model = quantizer()
q_model.save('./output')
在上面的示例中,实现了一个包含 update() 和 result() 函数的 class,用于记录每个 mini-batch 的结果,并在最后计算最终精度。
量化感知训练¶
除了训练后静态量化和训练后动态量化之外,Intel® Neural Compressor 还支持带精度驱动自动调优机制的量化感知训练。
下面是一个示例,展示了如何在 PyTorch FX 图模式下对一个简单网络进行量化感知训练。
# conf.yaml
model:
name: LeNet
framework: pytorch_fx
quantization:
approach: quant_aware_training
evaluation:
accuracy:
metric:
topk: 1
tuning:
accuracy_criterion:
relative: 0.01
# main.py
model.eval()
from torchvision import datasets, transforms
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('./data', train=True, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=64, shuffle=True)
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('./data', train=False, download=True,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=1)
import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=0.0001, momentum=0.1)
def training_func(model):
model.train()
for epoch in range(1, 3):
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = model(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
# launch code for Intel® Neural Compressor
from neural_compressor.experimental import Quantization
quantizer = Quantization("./conf.yaml")
quantizer.model = model
quantizer.q_func = training_func
quantizer.eval_dataloader = test_loader
q_model = quantizer()
q_model.save('./output')
仅用于性能的量化¶
Intel® Neural Compressor 支持直接使用虚拟数据集生成 int8 模型,用于性能基准测试。
下面是一个示例,展示了如何在 PyTorch FX 图模式下使用虚拟数据集量化一个简单网络。
# conf.yaml
model:
name: lenet
framework: pytorch_fx
# main.py
model.eval()
# launch code for Intel® Neural Compressor
from neural_compressor.experimental import Quantization, common
from neural_compressor.experimental.data.datasets.dummy_dataset import DummyDataset
quantizer = Quantization("./conf.yaml")
quantizer.model = model
quantizer.calib_dataloader = common.DataLoader(DummyDataset([(1, 1, 28, 28)]))
q_model = quantizer()
q_model.save('./output')
量化输出¶
用户可以从 Intel® Neural Compressor 打印的日志中得知有多少操作被量化,如下所示:
2021-12-08 14:58:35 [INFO] |********Mixed Precision Statistics*******|
2021-12-08 14:58:35 [INFO] +------------------------+--------+-------+
2021-12-08 14:58:35 [INFO] | Op Type | Total | INT8 |
2021-12-08 14:58:35 [INFO] +------------------------+--------+-------+
2021-12-08 14:58:35 [INFO] | quantize_per_tensor | 2 | 2 |
2021-12-08 14:58:35 [INFO] | Conv2d | 2 | 2 |
2021-12-08 14:58:35 [INFO] | max_pool2d | 1 | 1 |
2021-12-08 14:58:35 [INFO] | relu | 1 | 1 |
2021-12-08 14:58:35 [INFO] | dequantize | 2 | 2 |
2021-12-08 14:58:35 [INFO] | LinearReLU | 1 | 1 |
2021-12-08 14:58:35 [INFO] | Linear | 1 | 1 |
2021-12-08 14:58:35 [INFO] +------------------------+--------+-------+
量化后的模型将生成在 ./output 目录下,其中包含两个文件:1. best_configure.yaml 2. best_model_weights.pt
第一个文件包含每个操作的量化配置,第二个文件包含 int8 权重以及激活的零点和缩放信息。
部署¶
用户可以使用以下代码加载量化后的模型,然后进行推理或性能基准测试。
from neural_compressor.utils.pytorch import load
int8_model = load('./output', model)
教程¶
请访问 Intel® Neural Compressor Github 仓库查看更多教程。