PyTorch模型训练完毕后静态量化、保存、加载int8量化模型

本文详细介绍了如何使用PyTorch进行模型静态量化,包括量化准备、模型转换、推理代码修改等步骤,以实现模型大小从200M到50M的压缩,并将运行时间从5.7s减少到3.4s,同时提供了完整的代码示例和量化后的性能对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. PyTorch模型量化方法

Pytorch模型量化方法介绍有很多可以参考的,这里推荐两篇文章写的很详细可以给大家一个大致的参考Pytorch的量化官方量化文档

Pytorch的量化大致分为三种:模型训练完毕后动态量化、模型训练完毕后静态量化、模型训练中开启量化,本文从一个工程项目(Pose Estimation)给大家介绍模型训练后静态量化的过程。

具体量化知识可以从推荐的两篇文章中学习。

2. 量化过程准备工作。

代码运行环境:PyTorch1.9.0, Python3.6.4.

1.数据集下载(在做静态量化时需要对数据集进行推理获取数据的分布特点、定标),用MSCOCO的验证集,选100张左右MSCOCO_val2017

2.Pytorch模型文件可以从这里下载Pose_Model提取密码:s7qh.

3.量化代码下载Pytorch_Model_Quantization

 代码下载后如上图,把下载的MSCOC数据集选100张放在data目录,把下载的模型文件coco_pose_iter_440000.pth.tar放在models目录。

pth_to_int.py是对Pytorch的float32模型转成int8模型。

evaluate_model.py里加载int8模型进行推理。

3. 模型静态量化

模型静态量化主要代码如下,读取float32模型,然后转成int8模型保存为openpose_vgg_quant.pth。完整代码可以从pth_to_int.py文件中看到。具体每一步做什么工作在注释中详细说明了。

# loading model
state_dict = torch.load('./models/coco_pose_iter_440000.pth.tar')['state_dict']

# create a model instance
model_fp32 = get_pose_model()
model_fp32.load_state_dict(state_dict)
model_fp32.float()

# model must be set to eval mode for static quantization logic to work
model_fp32.eval()

# attach a global qconfig, which contains information about what kind
# of observers to attach. Use 'fbgemm' for server inference and
# 'qnnpack' for mobile inference. Other quantization configurations such
# as selecting symmetric or assymetric quantization and MinMax or L2Norm
# calibration techniques can be specified here.
model_fp32.qconfig = torch.quantization.get_default_qconfig('fbgemm')

# Prepare the model for static quantization. This inserts observers in
# the model that will observe activation tensors during calibration.
model_fp32_prepared = torch.quantization.prepare(model_fp32)

# calibrate the prepared model to determine quantization parameters for activations
# in a real world setting, the calibration would be done with a representative dataset
evaluate(model_fp32_prepared)

# Convert the observed model to a quantized model. This does several things:
# quantizes the weights, computes and stores the scale and bias value to be
# used with each activation tensor, and replaces key operators with quantized
# implementations.
model_int8 = torch.quantization.convert(model_fp32_prepared)
print("model int8", model_int8)
# save model
torch.save(model_int8.state_dict(),"./openpose_vgg_quant.pth")

4. 量化模型加载进行推理

注意:量化后模型的forward代码稍有改动,需要在模型输入前后安插量化和解量化。如下示例:

 class Net(nn.Module):
 
    def __init__(self):
        # 对输入数据量化 
        self.quant = torch.quantization.QuantStub()
        # model structure.
        layer = self.layer()
        # 对输出数据解量化
        self.dequant = torch.quantization.DeQuantStub()
    def forward(self,input):
        x = self.quant(input)
        x = self.layer(x)
        x = self.dequant(x)

量化和解量化在pose_estimation.py文件34-86行可以看到.

加载int8模型不能和之前加载float32模型一样,需要将模型通过prepare() , convert()操作转成量化模型,然后load_state_dict加载进模型。

# Load int8 model
state_dict = torch.load('./openpose_vgg_quant.pth')
model_fp32 = get_pose_model()
model_fp32.qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_fp32_prepared = torch.quantization.prepare(model_fp32)
model_int8 = torch.quantization.convert(model_fp32_prepared)
model_int8.load_state_dict(state_dict)
model = model_int8
model.eval()

5. 性能

下图为量化后结果,整体来说损失不大。其中模型大小200M->50M,模型运行时间5.7s->3.4s。整体来说,模型大小压缩为原来的1/4, 模型运行时间减少20%左右

GitHub上有完整代码,可自行复现。欢迎一起讨论!!

我的Github, 我的个人博客

### PyTorch MNIST 模型 INT8 量化的实现 对于希望减少计算资源消耗并提高推理速度的应用场景而言,INT8量化是一种有效的方法。通过降低权重和激活值的精度到8位整数表示,可以在保持较高准确性的同时显著提升性能。 在PyTorch中执行INT8量化涉及几个重要步骤: #### 准备环境与加载训练模型 为了确保后续操作顺利进行,先安装必要的库,并导入所需的模块[^1]。 ```python import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader from tqdm import tqdm ``` 接着定义转换函数以及数据集加载器来获取MNIST测试集用于校准过程: ```python transform = transforms.Compose([ transforms.ToTensor(), ]) test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) calibration_loader = DataLoader(test_dataset, batch_size=32, shuffle=False) ``` #### 定义辅助类来进行统计收集 创建一个简单的观察者类以记录每一层的最大最小值范围,这对于后续确定合适的缩放因子至关重要: ```python class MinMaxObserver(torch.nn.Module): def __init__(self): super(MinMaxObserver, self).__init__() self.min_val = float('inf') self.max_val = -float('inf') def forward(self, x): min_x = torch.min(x).item() max_x = torch.max(x).item() if min_x < self.min_val: self.min_val = min_x if max_x > self.max_val: self.max_val = max_x return x ``` #### 应用量化感知训练 (QAT) 或静态量化方法 这里展示的是基于静态仿真的方式,在此之前需确保已有一个经过充分训练好的浮点版本模型实例 `model` 可供使用。应用量化配置前记得设置为评估模式: ```python model.eval() # Switch the model into evaluation mode. quantized_model = torch.quantization.convert(model.to('cpu'), inplace=False) ``` 如果采用动态量化,则只需指定哪些类型的层需要被处理;而对于静态量化来说,除了上述之外还需要额外提供代表性的输入样本以便于调整比例尺参数: ```python # Static Quantization Preparation fused_model = torch.quantization.fuse_modules( copy.deepcopy(model), [['conv1', 'relu1'], ['conv2', 'relu2']]) qconfig_dict = {"": torch.quantization.get_default_qat_qconfig('fbgemm')} prepared_quantized_model = torch.quantization.prepare_qat(fused_model, qconfig_spec=qconfig_dict) for images, _ in calibration_loader: prepared_quantized_model(images) final_quantized_model = torch.quantization.convert(prepared_quantized_model.cpu().eval(), inplace=False) ``` 完成以上流程之后便得到了适用于部署阶段使用的低比特宽度网络结构——即完成了从FP32至INT8的数据类型转变工作[^2]。
评论 65
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值