使用英特尔®神经压缩器为PyTorch提供的易用量化¶
创建日期:2022年1月11日 | 最后更新:2024年8月27日 | 最后验证:未验证
概述¶
大多数深度学习应用在推理时使用32位浮点精度。但由于显著的性能提升,低精度数据类型,尤其是int8,正受到越来越多的关注。采用低精度时的一个关键问题是如何轻松缓解可能的精度损失并达到预定义的精度要求。
Intel® Neural Compressor 旨在通过扩展 PyTorch 的精度驱动自动调优策略来解决上述问题,帮助用户快速找到在 Intel 硬件上的最佳量化模型,包括 Intel 深度学习加速 (Intel DL Boost) 和 Intel 高级矩阵扩展 (Intel AMX)。
英特尔® 神经压缩器已在 Github 上作为开源项目发布。
功能¶
易于使用的Python API: Intel® Neural Compressor 提供了简单的前端Python API和实用工具,使用户只需进行少量代码更改即可进行神经网络压缩。通常,只需在原始代码中添加5到6条子句。
量化: Intel® Neural Compressor 支持在训练后静态量化、训练后动态量化以及量化感知训练上进行精度驱动的自动调优过程,适用于 PyTorch fx 图模式和 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图模式和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,用于记录每个小批次的结果并在最后计算最终准确率。
量化感知训练¶
除了训练后静态量化和训练后动态量化,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 repo获取更多教程。