面向易用性的 PyTorch 量化,使用 Intel® Neural Compressor¶
创建于:2022 年 1 月 11 日 | 最后更新:2024 年 8 月 27 日 | 最后验证:未验证
概述¶
大多数深度学习应用程序都使用 32 位浮点精度进行推理。但低精度数据类型,尤其是 int8,由于显著的性能提升而越来越受到关注。采用低精度的主要顾虑之一是如何轻松缓解可能的精度损失并达到预定义的精度要求。
Intel® Neural Compressor 旨在通过扩展 PyTorch 并采用精度驱动的自动调优策略来解决上述问题,帮助用户在 Intel 硬件上快速找出最佳量化模型,包括 Intel Deep Learning Boost (Intel DL Boost) 和 Intel Advanced Matrix Extensions (Intel AMX)。
Intel® Neural Compressor 已作为开源项目在 Github 上发布。
特性¶
易于使用的 Python API: Intel® Neural Compressor 为用户提供了简单的前端 Python API 和实用程序,只需少量代码更改即可进行神经网络压缩。通常,只需在原始代码中添加 5 到 6 行代码即可。
量化: Intel® Neural Compressor 支持在 PyTorch fx graph 模式和 eager 模型上进行后训练静态量化、后训练动态量化和量化感知训练的精度驱动自动调优过程。
本教程主要关注量化部分。关于如何使用 Intel® Neural Compressor 进行剪枝和蒸馏,请参考 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 graph 模式和 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 graph 模式 上通过自动调优量化一个简单网络。
# 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,用于记录每个小批量结果并在最后计算最终精度。
量化感知训练¶
除了后训练静态量化和后训练动态量化外,Intel® Neural Compressor 还支持具有精度驱动自动调优机制的量化感知训练。
以下示例展示了如何在 PyTorch FX graph 模式 上对一个简单网络进行量化感知训练。
# 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 graph 模式 上使用虚拟数据集量化一个简单网络。
# 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 仓库 获取更多教程。