使用Intel® 神经压缩器为PyTorch实现易用的量化¶
Created On: Jan 11, 2022 | Last Updated: Aug 27, 2024 | Last Verified: Not Verified
概述¶
大多数深度学习应用都使用32位浮点数精度进行推理。但低精度数据类型,尤其是int8,由于其显著的性能提升而越来越受到关注。在采用低精度时,一个重要的问题是如何轻松缓解可能的精度损失并满足预定义的精度要求。
英特尔®神经压缩器旨在通过扩展PyTorch的基于精度的自动调优策略来解决上述问题,帮助用户快速找到在英特尔硬件(包括英特尔深度学习加速(Intel DL Boost)和英特尔高级矩阵扩展(Intel AMX)上)的最佳量化模型。
英特尔®神经压缩器已作为一个开源项目在`Github <https://github.com/intel/neural-compressor>`_上发布。
功能¶
易用的Python API: 英特尔®神经压缩器提供了简单的前端Python API和实用工具,使用户可以通过少量代码更改完成神经网络压缩。通常情况下,仅需添加5到6段代码即可。
量化: 英特尔®神经压缩器支持基于精确度的自动调优过程,包括后训练静态量化、后训练动态量化以及基于PyTorch fx图模式和eager模型的量化感知训练。
本教程主要关注量化部分。至于如何使用英特尔®神经压缩器进行剪枝和蒸馏,请参考英特尔®神经压缩器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
使用方法¶
用户仅需少量代码更改即可开始使用英特尔®神经压缩器的量化API。支持PyTorch fx图模式和eager模式。
英特尔®神经压缩器将FP32模型和一个yaml配置文件作为输入。要构建量化过程,用户可以通过yaml配置文件或Python API指定以下设置:
校准数据加载器(用于静态量化)
评估数据加载器
评估指标
英特尔®神经压缩器支持一些流行的数据加载器和评估指标。有关如何在yaml配置文件中配置这些内容,用户可以参考`内建数据集 <https://github.com/intel/neural-compressor/blob/master/docs/dataset.md>`_。
如果用户想使用自定义的数据加载器或评估指标,英特尔®神经压缩器也通过Python代码注册的方式支持这些定制。
有关yaml配置文件格式,请参考`yaml模板 <https://github.com/intel/neural-compressor/blob/master/neural_compressor/template/ptq.yaml>`_。
所需的代码更改在代码行上方以注释的形式标注。
模型¶
在本教程中,LeNet模型被用来演示如何使用英特尔®神经压缩器。
# 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`来源于`这里 <https://drive.google.com/drive/folders/1fn83DF14tWmit0RTKWRhPq5uVXt73e0h?usp=sharing>`_。
基于精度的量化¶
英特尔®神经压缩器支持基于精度的自动调优以生成满足预定义精度目标的最佳int8模型。
以下是一个通过自动调优在PyTorch `FX图模式 <https://pytorch.org/docs/stable/fx.html>`_中量化简单网络的示例。
# 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`文件中,英特尔®神经压缩器内置的评估方法`top1`被指定为评估指标,并将`1%`相对精度损失设置为自动调优的精度目标。英特尔®神经压缩器将遍历每个操作级别上所有可能的量化配置组合,以找到满足预定义精度目标的最佳int8模型。
除了这些内置指标,英特尔®神经压缩器还通过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()`函数的`类`,以记录每个小批量的结果并在最后计算最终精度。
量化感知训练¶
除了后训练静态量化和后训练动态量化,英特尔®神经压缩器还支持具有基于精度的自动调优机制的量化感知训练。
以下是在PyTorch `FX图模式 <https://pytorch.org/docs/stable/fx.html>`_上对简单网络进行量化感知训练的示例。
# 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')
仅以性能为目的的量化¶
英特尔®神经压缩器支持直接使用虚拟数据集生成int8模型,以进行性能基准测试。
以下是使用虚拟数据集在PyTorch `FX图模式 <https://pytorch.org/docs/stable/fx.html>`_中量化简单网络的示例。
# 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')
量化输出¶
用户可以通过英特尔®神经压缩器打印的日志了解多少操作被量化,例如:
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)
教程¶
请访问`英特尔®神经压缩器Github库 <https://github.com/intel/neural-compressor>`_以获取更多教程。