【深度学习】模型量化-笔记/实验

目录

一、量化方法

1、非对称量化

2、对称量化

 3、随机量化

二、量化类型

1、动态量化(Dynamic quantization)

2、静态量化(Static quantization)

3、量化感知训练(Quantization-aware training)

三、量化实践

1、实验配置

2、实验结果

3、实验代码

四、参考


深度学习已经被证明在各类任务(如:图像分类、目标检测、语义分割,自然语言处理等)上效果很好。在工业部署时,常常对模型有非常苛刻的限制,为了更有效地将模型应用于移动设备或嵌入式设备,需要有效地压缩模型的大小,常用的方法有2种:

(1)设计更有效的模型架构,如mobilenet和squeezenet;

(2)通过压缩、编码等方式减少网络大小。

如果深度学习的模型参数类型为FP32,每个数值在存储时需要32bit存储空间,若是将其转换为int8或者uint8来保存,那么模型的大小将会降低为1/4。下表为不同精度的数值计算成本,可以看出8bit数值的计算成本远低于32bit计算成本。

一、量化方法

量化方法:非对称量化、对称量化、随机量化。

1、非对称量化

 假设输入的浮点数范围为(X_min, X_max),量化后的范围为(0, N_levels - 1),对8bits量化来说N_levels为256,scale和零点的计算公式如下:

\Delta =(X\_max-X\_min)/255

z=-X\_min/\Delta

得到了scale和零点后,对于任意的输入x,量化计算过程为:

x_{int}=round(\frac{x}{\Delta })+z

x_Q=clamp(0, N\_levels-1,x_{init})

 对应的反量化计算公式为:

 注意:对于单边分布如(2.5, 3.5),需要将其范围放宽至(0, 3.5)再量化,在极端的单边分布的情况下会损失精度。

2、对称量化

scale计算公式如下:

\Delta =\frac{max(abs(x))}{N\_levels-1}

对称量化比较简单,它限制零点值为0,量化公式如下:

 反量化公式:

 3、随机量化

随机量化与非对称量化类似,区别在于量化时引入了噪音,其参数计算与反量化过程与非对称量化相同,此处不再赘述。

二、量化类型

pytorch量化方法有3种:动态量化、静态量化、量化感知训练。

1、动态量化(Dynamic quantization)

当网络训练完成后,其权重值已经确定,故权重的量化因子已经确定,但是对于不同的输入值来说,其缩放因子是动态计算的(“动态”的由来)。动态量化是几种量化方法中性能最差的。

动态量化常用于非常大的模型。

2、静态量化(Static quantization)

静态量化(Static quantization)与动态量化的区别在于其输入的缩放因子计算方法不同,静态量化的模型在使用前有fine-tuning的过程(校准缩放因子):准备部分输入(对于图像分类模型就是准备一些图片,其他任务类似),使用静态量化后的模型进行预测,在此过程中量化模型的缩放因子会根据输入数据的分布进行调整。

fine-tuning完成后,权重和输入的缩放因子都固定(“静态”的由来)。静态量化的性能一般比动态量化好,常用于中等模型和大模型。

3、量化感知训练(Quantization-aware training)

量化感知训练(Quantization-aware training, QAT)是3种方法中最高的,它将静态量化直接插入到网络的训练过程中,消除了网络训练后的校准过程。这种方法会降低训练速度,但是能够获得更高的精度。

三、量化实践

pytorch支持per tensor 和per channel非对称线性量化,Per tensor指tensor内所有的值有统一的缩放因子(scale),per channel指的是tensor不同的channel有不同的缩放因子。

1、实验配置

实验环境如下:

torch==1.11.0

windows 10 cpu

fx graph

流程,使用torchvision.models.mobilenet_v2模型作为测试模型,未训练模型参数,仅使用cifar10数据来测试模型量化后的运行速度,模型fuse后测试。

2、实验结果

注意:动态量化不支持卷积量化,所以仅量化了全连接层,故其参数和耗时几乎不变。

参数(pt大小,kb) 耗时(s)
原模型 8971 68.94
动态量化 8671 68.38
静态量化 2293 45.94
量化感知 2293 46.68

3、实验代码

实验代码比较多,这里贴出一个量化感知训练的测试代码,其余的代码可参考文末的链接下载:

import torch
import torchvision
from torchvision.transforms import ToTensor, Normalize, Compose
from torch.quantization.quantize_fx import convert_fx, prepare_fx, prepare_qat_fx, fuse_fx
import time

transforms = Compose(
    [
        ToTensor(),
        Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ]
)

cifar10_dataset = torchvision.datasets.CIFAR10(root='data', transform=transforms, download=False)
data_loader = torch.utils.data.DataLoader(cifar10_dataset,
                                          batch_size=32,
                                          shuffle=True,
                                          num_workers=0)

model = torchvision.models.mobilenet_v2(num_classes=10)
qconfig_dict = {"": torch.quantization.get_default_qat_qconfig('qnnpack')}

model.train()
model_quant = prepare_qat_fx(model, qconfig_dict)

ce_loss = torch.nn.CrossEntropyLoss()
learning_rate = 0.01
optimizer = torch.optim.SGD(model_quant.parameters(), momentum=0.1, lr=learning_rate)
epochs = 1
for i in range(epochs):
    for idx, (image, label) in enumerate(data_loader):
        logits = model_quant(image)
        loss = ce_loss(logits, label)
        loss.backward()
        optimizer.step()
        optimizer.zero_grad()
        if idx % 100:
            print("epochs: {}, loss: ".format(i), loss.detach().numpy())
            break
model_quant = convert_fx(model_quant)

torch.save(model_quant.state_dict(), "model_qat.pt")

model_quant.eval()
model_quant = fuse_fx(model_quant)

beg = time.time()
with torch.no_grad():
    model_quant.eval()
    for idx, (image, label) in enumerate(data_loader):
        logits = model_quant(image)

end = time.time()
print('time consume: ', end - beg)

四、参考

1、A developer-friendly guide to model quantization with PyTorch

2、introduction-to-quantization-on-pytorch

3、pytorch量化测试代码,mobilenetv2在cifar10速度测试

4、NCNN模型量化实战-人像抠图MODNet模型

猜你喜欢

转载自blog.csdn.net/qq_40035462/article/details/123745290