量化我的第一个网络
Quantize my first neural network.
看看我们需要准备些什么?
PPQ 目前支持量化来自于 pytorch, onnx, caffe 的神经网络模型,如果您是 mxnet, tensorflow, keras 的用户,您可以通过导出 onnx 的方式来间接使用 PPQ 进行量化。
而在开始之前,您需要准备:
- 一个需要量化的神经网络模型
- 一个小型的校准数据集(calibration dataset),用于校准您的网络
- 一个完整的测试数据集(test dataset),用于测试量化模型的精度
- 一块 Nvidia GPU,必须插在您的主板上并且正常供电;是的,拿在手上的不行
在这里我必须要提醒你校准数据集的要求,PPQ 要求校准数据集必须具有 8~512 个样本数据,与此同时它们不需要带有 标签。然而我需要提醒你请不要使用 calib_dataset = train_dataset[:512] 这样的作法,为了使我们的校准数据尽可能分散,我们希望你使用随机采样的方法从网络训练集或者其他什么地方构建校准集合。
加载我的神经网络模型
这里我们以 pytorch 中的 resnet 18 模型为例,向你展示如何通过 ppq.api 完成网络的量化,事实上它非常简单,仅仅需要一个函数调用就可以完成:
import torchvision
from ppq.api import quantize_torch_model
from ppq.core import TargetPlatform
from Utilities.Imagenet.imagenet_util import load_imagenet_from_directory
model = torchvision.models.resnet18(pretrained=True)
dataloader = load_imagenet_from_directory(directory='YOUR IMAGENET PATH HERE.', batchsize=32)
# quantize your network with only following call.
quantized_model = quantize_torch_model(
model=model, calib_dataloader=dataloader, calib_steps=16,
input_shape=[32, 3, 224, 224], collate_fn=lambda x: x.to('cuda'),
platform=TargetPlatform.PPL_CUDA_INT8, device='cuda')
哦,我已经听到了你的惊呼,这个函数所需要的参数真是太多了!它们都是做什么的?让我来为你一一解答:
- 参数 Model: 一个 torch.Module,用来指定需要被量化的网络
- 参数 calib_dataloader: 一个 torch.utils.data.Dataloader 对象,用来读取校准数据集
- 参数 calib_steps: 一个整数,用来说明校准所需要的步数,PPQ 推荐在 8 ~ 512 步中完成校准
- 参数 input_shape: 一个 List of int,用来说明输入 Tensor 的形状,如果你的网络可以接受很多种不同形状的输入,只需要写入任意一个可以被接受的形状即可
- 参数 collate_fn: 一个可执行函数,用来预处理 dataloader 中的数据,它们将被送入网络执行,因此首先我们需要把它们送上 gpu
- 参数 platform: 一个 TargetPlatform 对象,这是一个枚举类,用来确定一个目标量化部署平台,所有的量化策略与算法都将根据这个量化部署平台发生变化
- 参数 device: 一个字符串,用来确定神经网路量化中所需要的计算发生在什么设备上,当然我们推荐你使用 gpu 完成量化。你需要注意量化过程中的计算只是为了优化你的神经网络而存在的,它与你的部署平台(TargetPlatform)无关。
我需要告诉你:PPQ 有着自己的执行器来执行你的网络,它是基于 Pytorch 实现的,因此大部分使用方式与 Pytorch 类似。于此同时 PPQ 会将你的网络解析成自己的内部格式,这一格式基本遵从 onnx 标准。
下面我再向你展示如何量化一个 onnx / caffe 的模型,与 pytorch 模型不同的是,你必须通过读文件的方式来加载它们:
from ppq.api import quantize_onnx_model
from ppq.core import TargetPlatform
from Utilities.Imagenet.imagenet_util import load_imagenet_from_directory
dataloader = load_imagenet_from_directory(directory='YOUR IMAGENET PATH HERE.', batchsize=32)
# quantize your network with only following call.
quantized_model = quantize_onnx_model(
onnx_import_file='YOUR ONNX FILE PATH HERE', calib_dataloader=dataloader, calib_steps=16,
input_shape=[32, 3, 224, 224], collate_fn=lambda x: x.to('cuda'),
platform=TargetPlatform.PPL_CUDA_INT8, device='cuda')
quantized_model = quantize_caffe_model(
caffe_import_file='YOUR CAFFE FILE PATH HERE',
caffe_weight_file='YOUR CAFFE FILE PATH HERE',
calib_dataloader=dataloader, calib_steps=16,
input_shape=[32, 3, 224, 224], collate_fn=lambda x: x.to('cuda'),
platform=TargetPlatform.PPL_CUDA_INT8, device='cuda')
是的,正如你所看到的那样,我们使用几乎相同的接口来量化 onnx, caffe, pytorch 的模型。
Quantized Model
你或许已经注意到,在完成量化之后我们获得了一个被称为是 quantized_model 的对象,它是 ppq.IR.BaseGraph 的一个实例。 quantized_model 包含了 PPQ 完整的计算图定义,其地位与 pytorch 中的 Model 是等价的。这个对象包含了网络量化所需的一切信息——它十分复杂,我们还不能够向你完全介绍它的内部结构,但我们会逐渐揭开它的神秘面纱,这对理解量化而言是至关重要的。
在进一步了解 Quantized Model 的内部构造之前,我们还需要完成量化的最后一个环节:生成硬件 Runtime 支持的量化配置文件和网络信息,PPQ 已经做好了许多量化平台的支持,你只需要通过 ppq.api.export_ppq_graph 来使用这些功能:
export_ppq_graph(graph=quantized_model, platform=TargetPlatform.PPL_CUDA_INT8,
graph_save_to='MODEL SAVE PATH HERE',
config_save_to='CONFIG SAVE PATH HERE')
- 参数 graph: 一个 ppq.IR.BaseGraph,用来指定被导出的网络
- 参数 platform: 一个 TargetPlatform 对象,用来指定目标部署平台
- 参数 graph_save_to: 一个字符串,网络模型将被保存到此处
- 参数 config_save_to: 一个字符串,量化参数信息将被保存到此处(如果目标平台需要)
PPQ 目前支持导出 PPL.CUDA, PPL.DSP, TensorRT, Onnx, Caffe, Native, Nxp 七种平台的模型文件与部署信息。这些导出文件将被用于在硬件端上完成部署。
至此,你已经完成了网络量化的全部过程。接下来我们将向你介绍系统更为复杂的使用案例。