Giter VIP home page Giter VIP logo

666dzy666 / micronet Goto Github PK

View Code? Open in Web Editor NEW
2.2K 40.0 479.0 7.01 MB

micronet, a model compression and deploy lib. compression: 1、quantization: quantization-aware-training(QAT), High-Bit(>2b)(DoReFa/Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference)、Low-Bit(≤2b)/Ternary and Binary(TWN/BNN/XNOR-Net); post-training-quantization(PTQ), 8-bit(tensorrt); 2、 pruning: normal、regular and group convolutional channel pruning; 3、 group convolution structure; 4、batch-normalization fuse for quantization. deploy: tensorrt, fp32/fp16/int8(ptq-calibration)、op-adapt(upsample)、dynamic_shape

License: MIT License

Python 100.00%
quantization pruning dorefa twn bnn xnor-net pytorch model-compression group-convolution network-slimming

micronet's Introduction

micronet

"目前在深度学习领域分类两个派别,一派为学院派,研究强大、复杂的模型网络和实验方法,为了追求更高的性能;另一派为工程派,旨在将算法更稳定、高效的落地在硬件平台上,效率是其追求的目标。复杂的模型固然具有更好的性能,但是高额的存储空间、计算资源消耗是使其难以有效的应用在各硬件平台上的重要原因。所以,深度神经网络日益增长的规模为深度学习在移动端的部署带来了巨大的挑战,深度学习模型压缩与部署成为了学术界和工业界都重点关注的研究领域之一"

项目简介

PyPI PyPI - Python Version

micronet, a model compression and deploy lib.

压缩

  • 量化:High-Bit(>2b): QAT, PTQ, QAFT; Low-Bit(≤2b)/Ternary and Binary: QAT
  • 剪枝:正常、规整和分组卷积结构剪枝
  • 针对特征(A)二值量化的BN融合(训练量化后,BN参数 —> conv的偏置b)
  • High-Bit量化的BN融合(训练量化中,先融合再量化,融合:BN参数 —> conv的权重w和偏置b)

部署

  • TensorRT(fp32/fp16/int8(ptq-calibration)、op-adapt(upsample)、dynamic_shape等)

代码结构

code_structure

micronet
├── __init__.py
├── base_module
│   ├── __init__.py
│   └── op.py
├── compression
│   ├── README.md
│   ├── __init__.py
│   ├── pruning
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── gc_prune.py
│   │   ├── main.py
│   │   ├── models_save
│   │   │   └── models_save.txt
│   │   └── normal_regular_prune.py
│   └── quantization
│       ├── README.md
│       ├── __init__.py
│       ├── wbwtab
│       │   ├── __init__.py
│       │   ├── bn_fuse
│       │   │   ├── bn_fuse.py
│       │   │   ├── bn_fused_model_test.py
│       │   │   └── models_save
│       │   │       └── models_save.txt
│       │   ├── main.py
│       │   ├── models_save
│       │   │   └── models_save.txt
│       │   └── quantize.py
│       └── wqaq
│           ├── __init__.py
│           ├── dorefa
│           │   ├── __init__.py
│           │   ├── main.py
│           │   ├── models_save
│           │   │   └── models_save.txt
│           │   ├── quant_model_test
│           │   │   ├── models_save
│           │   │   │   └── models_save.txt
│           │   │   ├── quant_model_para.py
│           │   │   └── quant_model_test.py
│           │   └── quantize.py
│           └── iao
│               ├── __init__.py
│               ├── bn_fuse
│               │   ├── bn_fuse.py
│               │   ├── bn_fused_model_test.py
│               │   └── models_save
│               │       └── models_save.txt
│               ├── main.py
│               ├── models_save
│               │   └── models_save.txt
│               └── quantize.py
├── data
│   └── data.txt
├── deploy
│   ├── README.md
│   ├── __init__.py
│   └── tensorrt
│       ├── README.md
│       ├── __init__.py
│       ├── calibrator.py
│       ├── eval_trt.py
│       ├── models
│       │   ├── __init__.py
│       │   └── models_trt.py
│       ├── models_save
│       │   └── calibration_seg.cache
│       ├── test_trt.py
│       └── util_trt.py
├── models
│   ├── __init__.py
│   ├── nin.py
│   ├── nin_gc.py
│   └── resnet.py
└── readme_imgs
    ├── code_structure.jpg
    └── micronet.xmind

项目进展

  • 2019.12.4, 初次提交
  • 12.8, DoReFa特征(A)量化前先进行缩放(* 0.1),然后再截断,以减小截断误差
  • 12.11, 增加项目代码结构图
  • 12.12, 完善使用示例
  • 12.14, 增加:1、BN融合量化情况(W三值/二值)可选,即训练量化时选择W三/二值,这里则对应选择; 2、BN融合时对卷积核(conv)不带偏置(bias)的处理
  • 12.17, 增加模型压缩前后数据对比(示例)
  • 12.20, 增加设备可选(cpu、gpu(单卡、多卡))
  • 12.27, 补充相关论文
  • 12.29, 取消High-Bit量化8-bit以内的限制,即现在可以量化至10-bit、16-bit等
  • 2020.2.17, 1、精简W三值/二值量化代码; 2、加速W三值量化训练
  • 2.18, 优化针对特征(A)二值的BN融合:去除对BN层gamma参数的限制,即现在此情况下融合时BN可正常训练
  • 2.24, 再次优化三/二值量化代码组织结构,增强可移植性,旧版确实不太好移植。目前移植方法:将想要量化的Conv用compression/quantization/wbwtab/models/util_wbwtab.py中的QuantConv2d替换即可,可参照该路径下nin_gc.py中的使用方法
  • 3.1, 新增:1、google的High-Bit量化方法; 2、训练中High-Bit量化的BN融合
  • 3.2、3.3, 规整量化代码整体结构,目前所有量化方法都可采取类似的移植方式:将想要量化的Conv(或FC,目前dorefa支持,其他方法类似可写)用models/util_wxax.py中的QuantConv2d(或QuantLinear)替换即可,可分别参照该路径下nin_gc.py中的使用方法进行移植(分类、检测、分割等均适用,但需要据实际情况具体调试)
  • 3.4, 规整优化wbwtab/bn_fuse中“针对特征(A)二值的BN融合”的相关实现代码,可进行BN融合及融合前后模型对比测试(精度/速度/(大小))
  • 3.11, 调整compression/wqaq/iao中的BN层momentum参数(0.1 —> 0.01),削弱batch统计参数占比,一定程度抑制量化带来的抖动。经实验,量化训练更稳定,acc提升1%左右
  • 3.13, 更新代码结构图
  • 4.6, 修正二值量化训练中W_clip的相关问题(之前由于这个,导致二值量化训练精度上不去,现在已可正常使用)(同时修正无法找到一些模块如models/util_wxax.py的问题)
  • 12.14, 1、improve code structure; 2、add deploy-tensorrt(main module, but not running yet)
  • 12.18, 1、improve code structure/module reference/module_name; 2、add transfer-use demo
  • 12.21, improve pruning-quantization pipeline and code
  • 2021.1.4, add other quant_op
  • 1.5, add quant_weight's per-channel and per-layer selection
  • 1.7, fix iao's loss-nan bug. The bug is due to per-channel min/max error
  • 1.8, 1、improve quant_para save. Now, only save scale and zero_point; 2、add optional weight_observer(MinMaxObserver or MovingAverageMinMaxObserver)
  • 1.11, fix bug in binary_a(1/0) and binary_w preprocessing
  • 1.12, add "pip install"
  • 1.22, add auto_insert_quant_op(this still needs to be improved)
  • 1.27, improve auto_insert_quant_op(now you can easily use quantization, as quant_test_auto)
  • 1.28, 1、fix prune-quantization pipeline and code; 2、improve code structure
  • 2.1, improve wbwtab_bn_fuse
  • 2.4, 1、add wqaq_bn_fuse; 2、add quant_model_inference_simulation; 3、improve code format
  • 4.30, 1、update code_structure img; 2、fix iao's quant_weight_range, quant_contrans and quant_bn_fuse_conv pretrained_model bn_para load bug
  • 5.4, add qaft, it's beneficial to improve the quantization accuracy
  • 5.6, add ptq, its quantization accuracy is also good
  • 5.11, add bn_fuse_calib flag
  • 5.14, 1、change ste to clip_ste, it's beneficial to improve the quant_train;2、remove quant_relu and add quant_leaky_relu
  • 5.15, fix bug in quant_model_para post-processing
  • 6.7, add quant_add(need use base_module's op) and quant_resnet demo
  • 6.9, iao_quant supports multi gpus
  • 6.16, fix quant_round() and quant_binary()
  • 10.6, format

环境要求

  • python >= 3.5
  • torch >= 1.1.0
  • torchvison >= 0.3.0
  • numpy
  • onnx == 1.6.0
  • tensorrt == 7.0.0.11

安装

PyPI

pip install micronet -i https://pypi.org/simple

GitHub

git clone https://github.com/666DZY666/micronet.git
cd micronet
python setup.py install

验证

python -c "import micronet; print(micronet.__version__)"

测试

Install from github

压缩

量化

--refine,可加载预训练浮点模型参数,在其基础上做量化

wbwtab

--W --A, 权重W和特征A量化取值

cd micronet/compression/quantization/wbwtab
  • WbAb
python main.py --W 2 --A 2
  • WbA32
python main.py --W 2 --A 32
  • WtAb
python main.py --W 3 --A 2
  • WtA32
python main.py --W 3 --A 32
wqaq

--w_bits --a_bits, 权重W和特征A量化位数

dorefa
cd micronet/compression/quantization/wqaq/dorefa
  • W16A16
python main.py --w_bits 16 --a_bits 16
  • W8A8
python main.py --w_bits 8 --a_bits 8
  • W4A4
python main.py --w_bits 4 --a_bits 4
  • 其他bits情况类比
iao
cd micronet/compression/quantization/wqaq/iao

量化位数选择同dorefa

单卡

QAT/PTQ —> QAFT

! 注意,需要在QAT/PTQ之后再做QAFT !

--q_type, 量化类型(0-对称, 1-非对称)

--q_level, 权重量化级别(0-通道级, 1-层级)

--weight_observer, weight_observer选择(0-MinMaxObserver, 1-MovingAverageMinMaxObserver)

--bn_fuse, 量化中bn融合标志

--bn_fuse_calib, 量化中bn融合校准标志

--pretrained_model, 预训练浮点模型

--qaft, qaft标志

--ptq, ptq_observer

--ptq_control, ptq_control

--ptq_batch, ptq的batch数量

--percentile, ptq校准的比例

QAT

  • 默认: 对称、(权重)通道级量化, bn不融合, weight_observer-MinMaxObserver, 不加载预训练浮点模型, 进行qat
python main.py --q_type 0 --q_level 0 --weight_observer 0
  • 对称、(权重)通道级量化, bn不融合, weight_observer-MovingAverageMinMaxObserver
python main.py --q_type 0 --q_level 0 --weight_observer 1
  • 对称、(权重)层级量化, bn不融合
python main.py --q_type 0 --q_level 1
  • 非对称、(权重)通道级量化, bn不融合
python main.py --q_type 1 --q_level 0
  • 非对称、(权重)层级量化, bn不融合
python main.py --q_type 1 --q_level 1
  • 对称、(权重)通道级量化, bn融合
python main.py --q_type 0 --q_level 0 --bn_fuse
  • 对称、(权重)层级量化, bn融合
python main.py --q_type 0 --q_level 1 --bn_fuse
  • 非对称、(权重)通道级量化, bn融合
python main.py --q_type 1 --q_level 0 --bn_fuse
  • 非对称、(权重)层级量化, bn融合
python main.py --q_type 1 --q_level 1 --bn_fuse
  • 对称、(权重)通道级量化, bn融合校准
python main.py --q_type 0 --q_level 0 --bn_fuse --bn_fuse_calib

PTQ

需要加载预训练浮点模型,本项目中其可由剪枝中采用正常训练获取

  • 对称、(权重)通道级量化, bn融合
python main.py --refine ../../../pruning/models_save/nin_gc.pth --q_level 0 --bn_fuse --pretrained_model --ptq_control --ptq --batch_size 32 --ptq_batch 200 --percentile 0.999999
  • 其他情况类比

QAFT

! 注意,需要在QAT/PTQ之后再做QAFT !

QAT —> QAFT

  • 对称、(权重)通道级量化, bn融合
python main.py --resume models_save/nin_gc_bn_fused.pth --q_type 0 --q_level 0 --bn_fuse --qaft --lr 0.00001
  • 其他情况类比

PTQ —> QAFT

  • 对称、(权重)通道级量化, bn融合
python main.py --resume models_save/nin_gc_bn_fused.pth --q_level 0 --bn_fuse --qaft --lr 0.00001 --ptq
  • 其他情况类比

剪枝

稀疏训练 —> 剪枝 —> 微调

cd micronet/compression/pruning
稀疏训练

-sr 稀疏标志

--s 稀疏率(需根据dataset、model情况具体调整)

--model_type 模型类型(0-nin, 1-nin_gc)

  • nin(正常卷积结构)
python main.py -sr --s 0.0001 --model_type 0
  • nin_gc(含分组卷积结构)
python main.py -sr --s 0.001 --model_type 1
剪枝

--percent 剪枝率

--normal_regular 正常、规整剪枝标志及规整剪枝基数(如设置为N,则剪枝后模型每层filter个数即为N的倍数)

--model 稀疏训练后的model路径

--save 剪枝后保存的model路径(路径默认已给出, 可据实际情况更改)

  • 正常剪枝(nin)
python normal_regular_prune.py --percent 0.5 --model models_save/nin_sparse.pth --save models_save/nin_prune.pth
  • 规整剪枝(nin)
python normal_regular_prune.py --percent 0.5 --normal_regular 8 --model models_save/nin_sparse.pth --save models_save/nin_prune.pth

python normal_regular_prune.py --percent 0.5 --normal_regular 16 --model models_save/nin_sparse.pth --save models_save/nin_prune.pth
  • 分组卷积结构剪枝(nin_gc)
python gc_prune.py --percent 0.4 --model models_save/nin_gc_sparse.pth
微调

--prune_refine 剪枝后的model路径(在其基础上做微调)

  • nin
python main.py --model_type 0 --prune_refine models_save/nin_prune.pth
  • nin_gc

需要传入剪枝后得到的新模型的cfg

python main.py --model_type 1 --gc_prune_refine 154 162 144 304 320 320 608 584

剪枝 —> 量化(注意剪枝率和量化率平衡)

加载剪枝后的浮点模型再做量化

剪枝 —> 量化(高位)(剪枝率偏大、量化率偏小)
w8a8(dorefa)
cd micronet/compression/quantization/wqaq/dorefa
  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_quant ../../../pruning/models_save/nin_finetune.pth
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_quant ../../../pruning/models_save/nin_gc_retrain.pth
w8a8(iao)
cd micronet/compression/quantization/wqaq/iao

QAT/PTQ —> QAFT

! 注意,需要在QAT/PTQ之后再做QAFT !

QAT

bn不融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_quant ../../../pruning/models_save/nin_finetune.pth --lr 0.001
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_quant ../../../pruning/models_save/nin_gc_retrain.pth --lr 0.001

bn融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_quant ../../../pruning/models_save/nin_finetune.pth --bn_fuse --pretrained_model --lr 0.001
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_quant ../../../pruning/models_save/nin_gc_retrain.pth --bn_fuse --pretrained_model --lr 0.001

PTQ

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_quant ../../../pruning/models_save/nin_finetune.pth --bn_fuse --pretrained_model --ptq_control --ptq --batch_size 32 --ptq_batch 200 --percentile 0.999999
  • 其他情况类比

QAFT

! 注意,需要在QAT/PTQ之后再做QAFT !

QAT —> QAFT

bn不融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_qaft models_save/nin.pth --qaft --lr 0.00001
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_qaft models_save/nin_gc.pth --qaft --lr 0.00001

bn融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_qaft models_save/nin_bn_fused.pth --bn_fuse --qaft --lr 0.00001
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_qaft models_save/nin_gc_bn_fused.pth --bn_fuse --qaft --lr 0.00001

PTQ —> QAFT

bn不融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_qaft models_save/nin.pth --qaft --lr 0.00001 --ptq
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_qaft models_save/nin_gc.pth --qaft --lr 0.00001 --ptq

bn融合

  • nin(正常卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 0 --prune_qaft models_save/nin_bn_fused.pth --bn_fuse --qaft --lr 0.00001 --ptq
  • nin_gc(含分组卷积结构)
python main.py --w_bits 8 --a_bits 8 --model_type 1 --prune_qaft models_save/nin_gc_bn_fused.pth --bn_fuse --qaft --lr 0.00001 --ptq
其他可选量化配置类比
剪枝 —> 量化(低位)(剪枝率偏小、量化率偏大)
cd micronet/compression/quantization/wbwtab
wbab
  • nin(正常卷积结构)
python main.py --W 2 --A 2 --model_type 0 --prune_quant ../../pruning/models_save/nin_finetune.pth
  • nin_gc(含分组卷积结构)
python main.py --W 2 --A 2 --model_type 1 --prune_quant ../../pruning/models_save/nin_gc_retrain.pth
其他取值情况类比

BN融合与量化推理仿真测试

wbwtab
cd micronet/compression/quantization/wbwtab/bn_fuse
bn_fuse(得到quant_model_train和quant_bn_fused_model_inference的结构和参数)

--model_type, 1 - nin_gc(含分组卷积结构); 0 - nin(正常卷积结构)

--prune_quant, 剪枝_量化模型标志

--W, weight量化取值

均需要与量化训练保持一致,可直接用默认

  • nin_gc, quant_model, wb
python bn_fuse.py --model_type 1 --W 2
  • nin_gc, prune_quant_model, wb
python bn_fuse.py --model_type 1 --prune_quant --W 2
  • nin_gc, quant_model, wt
python bn_fuse.py --model_type 1 --W 3
  • nin, quant_model, wb
python bn_fuse.py --model_type 0 --W 2
bn_fused_model_test(对quant_model_train和quant_bn_fused_model_inference进行测试)
python bn_fused_model_test.py
dorefa
cd micronet/compression/quantization/wqaq/dorefa/quant_model_test
quant_model_para(得到quant_model_train和quant_model_inference的结构和参数)

--model_type, 1 - nin_gc(含分组卷积结构); 0 - nin(正常卷积结构)

--prune_quant, 剪枝_量化模型标志

--w_bits, weight量化位数; --a_bits, activation量化位数

均需要与量化训练保持一致,可直接用默认

  • nin_gc, quant_model, w8a8
python quant_model_para.py --model_type 1 --w_bits 8 --a_bits 8
  • nin_gc, prune_quant_model, w8a8
python quant_model_para.py --model_type 1 --prune_quant --w_bits 8 --a_bits 8
  • nin, quant_model, w8a8
python quant_model_para.py --model_type 0 --w_bits 8 --a_bits 8
quant_model_test(对quant_model_train和quant_model_inference进行测试)
python quant_model_test.py
iao

注意,量化训练时 --bn_fuse 需要设置为 True

cd micronet/compression/quantization/wqaq/iao/bn_fuse
bn_fuse(得到quant_bn_fused_model_train和quant_bn_fused_model_inference的结构和参数)

--model_type, 1 - nin_gc(含分组卷积结构); 0 - nin(正常卷积结构)

--prune_quant, 剪枝_量化模型标志

--w_bits, weight量化位数; --a_bits, activation量化位数

--q_type, 0 - 对称; 1 - 非对称

--q_level, 0 - 通道级; 1 - 层级

均需要与量化训练保持一致,可直接用默认

  • nin_gc, quant_model, w8a8
python bn_fuse.py --model_type 1 --w_bits 8 --a_bits 8
  • nin_gc, prune_quant_model, w8a8
python bn_fuse.py --model_type 1 --prune_quant --w_bits 8 --a_bits 8
  • nin, quant_model, w8a8
python bn_fuse.py --model_type 0 --w_bits 8 --a_bits 8
  • nin_gc, quant_model, w8a8, 非对称, 层级
python bn_fuse.py --model_type 0 --w_bits 8 --a_bits 8 --q_type 1 --q_level 1
bn_fused_model_test(对quant_bn_fused_model_train和quant_bn_fused_model_inference进行测试)
python bn_fused_model_test.py

设备选取

现支持cpu、gpu(单卡、多卡)

--cpu 使用cpu,--gpu_id 使用并选择gpu

  • cpu
python main.py --cpu
  • gpu单卡
python main.py --gpu_id 0

python main.py --gpu_id 1
  • gpu多卡
python main.py --gpu_id 0,1

python main.py --gpu_id 0,1,2

默认,使用服务器全卡

部署

TensorRT

目前仅提供相关核心模块代码,后续再加入完整可运行demo

相关解读

迁移

量化训练

LeNet example

quant_test_manual.py

A model can be quantized(High-Bit(>2b)、Low-Bit(≤2b)/Ternary and Binary) by simply replacing op with quant_op.

import torch.nn as nn
import torch.nn.functional as F

# some base_op, such as ``Add``、``Concat``
from micronet.base_module.op import *

# ``quantize`` is quant_module, ``QuantConv2d``, ``QuantLinear``, ``QuantMaxPool2d``, ``QuantReLU`` are quant_op
from micronet.compression.quantization.wbwtab.quantize import (
    QuantConv2d as quant_conv_wbwtab,
)
from micronet.compression.quantization.wbwtab.quantize import (
    ActivationQuantizer as quant_relu_wbwtab,
)
from micronet.compression.quantization.wqaq.dorefa.quantize import (
    QuantConv2d as quant_conv_dorefa,
)
from micronet.compression.quantization.wqaq.dorefa.quantize import (
    QuantLinear as quant_linear_dorefa,
)
from micronet.compression.quantization.wqaq.iao.quantize import (
    QuantConv2d as quant_conv_iao,
)
from micronet.compression.quantization.wqaq.iao.quantize import (
    QuantLinear as quant_linear_iao,
)
from micronet.compression.quantization.wqaq.iao.quantize import (
    QuantMaxPool2d as quant_max_pool_iao,
)
from micronet.compression.quantization.wqaq.iao.quantize import (
    QuantReLU as quant_relu_iao,
)


class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)
        self.max_pool = nn.MaxPool2d(kernel_size=2)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.relu(self.max_pool(self.conv1(x)))
        x = self.relu(self.max_pool(self.conv2(x)))
        x = x.view(-1, 320)
        x = self.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


class QuantLeNetWbWtAb(nn.Module):
    def __init__(self):
        super(QuantLeNetWbWtAb, self).__init__()
        self.conv1 = quant_conv_wbwtab(1, 10, kernel_size=5)
        self.conv2 = quant_conv_wbwtab(10, 20, kernel_size=5)
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)
        self.max_pool = nn.MaxPool2d(kernel_size=2)
        self.relu = quant_relu_wbwtab()

    def forward(self, x):
        x = self.relu(self.max_pool(self.conv1(x)))
        x = self.relu(self.max_pool(self.conv2(x)))
        x = x.view(-1, 320)
        x = self.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


class QuantLeNetDoReFa(nn.Module):
    def __init__(self):
        super(QuantLeNetDoReFa, self).__init__()
        self.conv1 = quant_conv_dorefa(1, 10, kernel_size=5)
        self.conv2 = quant_conv_dorefa(10, 20, kernel_size=5)
        self.fc1 = quant_linear_dorefa(320, 50)
        self.fc2 = quant_linear_dorefa(50, 10)
        self.max_pool = nn.MaxPool2d(kernel_size=2)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.relu(self.max_pool(self.conv1(x)))
        x = self.relu(self.max_pool(self.conv2(x)))
        x = x.view(-1, 320)
        x = self.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


class QuantLeNetIAO(nn.Module):
    def __init__(self):
        super(QuantLeNetIAO, self).__init__()
        self.conv1 = quant_conv_iao(1, 10, kernel_size=5)
        self.conv2 = quant_conv_iao(10, 20, kernel_size=5)
        self.fc1 = quant_linear_iao(320, 50)
        self.fc2 = quant_linear_iao(50, 10)
        self.max_pool = quant_max_pool_iao(kernel_size=2)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.relu(self.max_pool(self.conv1(x)))
        x = self.relu(self.max_pool(self.conv2(x)))
        x = x.view(-1, 320)
        x = self.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


lenet = LeNet()
quant_lenet_wbwtab = QuantLeNetWbWtAb()
quant_lenet_dorefa = QuantLeNetDoReFa()
quant_lenet_iao = QuantLeNetIAO()

print("***ori_model***\n", lenet)
print("\n***quant_model_wbwtab***\n", quant_lenet_wbwtab)
print("\n***quant_model_dorefa***\n", quant_lenet_dorefa)
print("\n***quant_model_iao***\n", quant_lenet_iao)

print("\nquant_model is ready")
print("micronet is ready")
quant_test_auto.py

A model can be quantized(High-Bit(>2b)、Low-Bit(≤2b)/Ternary and Binary) by simply using micronet.compression.quantization.quantize.prepare(model).

import torch.nn as nn
import torch.nn.functional as F

# some base_op, such as ``Add``、``Concat``
from micronet.base_module.op import *

import micronet.compression.quantization.wqaq.dorefa.quantize as quant_dorefa
import micronet.compression.quantization.wqaq.iao.quantize as quant_iao


class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)
        self.max_pool = nn.MaxPool2d(kernel_size=2)
        self.relu = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.relu(self.max_pool(self.conv1(x)))
        x = self.relu(self.max_pool(self.conv2(x)))
        x = x.view(-1, 320)
        x = self.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


"""
--w_bits --a_bits, 权重W和特征A量化位数
--q_type, 量化类型(0-对称, 1-非对称)
--q_level, 权重量化级别(0-通道级, 1-层级)
--weight_observer, weight_observer选择(0-MinMaxObserver, 1-MovingAverageMinMaxObserver)
--bn_fuse, 量化中bn融合标志
--bn_fuse_calib, 量化中bn融合校准标志
--pretrained_model, 预训练浮点模型
--qaft, qaft标志
--ptq, ptq标志
--percentile, ptq校准的比例
"""
lenet = LeNet()
quant_lenet_dorefa = quant_dorefa.prepare(lenet, inplace=False, a_bits=8, w_bits=8)
quant_lenet_iao = quant_iao.prepare(
    lenet,
    inplace=False,
    a_bits=8,
    w_bits=8,
    q_type=0,
    q_level=0,
    weight_observer=0,
    bn_fuse=False,
    bn_fuse_calib=False,
    pretrained_model=False,
    qaft=False,
    ptq=False,
    percentile=0.9999,
)

# if ptq == False, do qat/qaft, need train
# if ptq == True, do ptq, don't need train
# you can refer to micronet/compression/quantization/wqaq/iao/main.py

print("***ori_model***\n", lenet)
print("\n***quant_model_dorefa***\n", quant_lenet_dorefa)
print("\n***quant_model_iao***\n", quant_lenet_iao)

print("\nquant_model is ready")
print("micronet is ready")

test

quant_test_manual
python -c "import micronet; micronet.quant_test_manual()"
quant_test_auto
python -c "import micronet; micronet.quant_test_auto()"

when outputting "quant_model is ready", micronet is ready.

量化推理

参考BN融合与量化推理仿真测试

模型压缩数据对比(仅供参考)

以下为cifar10示例,可在更冗余模型、更大数据集上尝试其他组合压缩方式

类型 W(Bits) A(Bits) Acc GFLOPs Para(M) Size(MB) 压缩率 损失
原模型(nin) FP32 FP32 91.01% 0.15 0.67 2.68 *** ***
采用分组卷积结构(nin_gc) FP32 FP32 91.04% 0.15 0.58 2.32 13.43% -0.03%
剪枝 FP32 FP32 90.26% 0.09 0.32 1.28 52.24% 0.75%
量化 1 FP32 90.93% *** 0.58 0.204 92.39% 0.08%
量化 1.5 FP32 91% *** 0.58 0.272 89.85% 0.01%
量化 1 1 86.23% *** 0.58 0.204 92.39% 4.78%
量化 1.5 1 86.48% *** 0.58 0.272 89.85% 4.53%
量化(DoReFa) 8 8 91.03% *** 0.58 0.596 77.76% -0.02%
量化(IAO,全量化,symmetric/per-channel/bn_fuse) 8 8 90.99% *** 0.58 0.596 77.76% 0.02%
分组+剪枝+量化 1.5 1 86.13% *** 0.32 0.19 92.91% 4.88%

--train_batch_size 256, 单卡

相关资料

压缩

量化

QAT
二值
三值
High-Bit
PTQ
High-Bit

剪枝

适配专用芯片的模型压缩

部署

TensorRT

后续

  • tensorrt完整demo
  • 其他压缩算法(量化/剪枝/蒸馏/NAS等)
  • 其他部署框架(mnn/tnn/tengine等)
  • 压缩 —> 部署

micronet's People

Contributors

666dzy666 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

micronet's Issues

BnFoldConv question

你好:
in quantization/WqAq/IAO/models/util_wqaq.py
if self.bias is not None:
bias = reshape_to_bias(self.beta + (self.bias - batch_mean) * (self.gamma / torch.sqrt(batch_var + self.eps)))
else:
bias = reshape_to_bias(self.beta - batch_mean * (self.gamma / torch.sqrt(batch_var + self.eps)))
weight = self.weight * reshape_to_weight(self.gamma / torch.sqrt(self.running_var + self.eps))
为什么torch.sqrt()里面batch_var不使用平方,类似于这种:
bias = reshape_to_bias(self.beta + (self.bias - batch_mean) * (self.gamma / torch.sqrt(batch_varbatch_var + self.eps)))
weight = self.weight * reshape_to_weight(self.gamma / torch.sqrt(self.running_var
self.runing_var + self.eps))
期待您的回复。

关于注释和论文

您好, 非常感谢您的分享。不过比较遗憾的是你的代码中注释很少,也没有相关的论文。能否把代码相关的论文附上, 以便大家学习。谢谢

缩放操作的位置

你好,在二值量化时我遇到一个问题:STE算法流程结束再调用权重量化器保存权重时,由于alpha缩放位于量化器的forward()中,导致保存下来的权重可行域并非{-1,1}而是{-alpha,alpha}(浮点数)。根据相关论文,是不是应该在量化卷积(Conv2d_Q)forward()时再计算alpha并让它和W*input的结果相乘作为卷积的输出?

想请教一下剪枝方面的问题

你好,看到你的readme介绍,你实现了规整剪枝、正常剪枝和分组卷积结构剪枝,我理解规整和正常剪枝是实现了slimming论文里的剪枝方法是吗,那分组卷积剪枝具体实现的是Rethinking the Value of Network Pruning论文里提到的哪个方法呢?

稀疏训练(对BN层γ进行约束)的程式碼看不懂

def updateBN():
    for m in model.modules():
        if isinstance(m, nn.BatchNorm2d):
            if hasattr(m.weight, 'data'):
                m.weight.grad.data.add_(args.s*torch.sign(m.weight.data))

想問為什麼 這段是出自那兩篇paper哪一段
目前看L1正則都是取絕對值 而不是直接加梯度

特征值量化的一点疑问

class activation_quantize_fn(nn.Module):
def init(self, a_bit):
super(activation_quantize_fn, self).init()
assert a_bit <= 8 or a_bit == 32
self.a_bit = a_bit
self.uniform_q = uniform_quantize(k=a_bit)

def forward(self, x):
if self.a_bit == 32:
activation_q = x
else:
activation_q = self.uniform_q(torch.clamp(x, 0, 1))
# print(np.unique(activation_q.detach().numpy()))
return activation_q

特征值量化前强行归一到(0,1),这一点不是很理解,有些特征值是比较大

大佬可以多在知乎上发表模型压缩优化的文章

我是做嵌入式端模型部署的工作,对模型压缩比较感兴趣。像了解在模型压缩过程中一些需要注意的事项,比如混合通道、组卷积。为什么训练组卷积的weight_decay设置0?还有models/util_w_t_b_conv.py中实现了哪些算法?还有util_w_t_gap.py这个代码是做什么的?

关于WbWtAb中二值化实现的问题

很棒的代码!
有几个关于二值化实现的问题想请教:
1.根据paper,STE是用在weight的BP上,为什么WbWtAb的实现中STE是在Binary_a而不是Binary_w上?
2.二值化deterministic方法直接使用torch.sign(),0依然是0,是否成为了三值化?
3.util_wt_bab.py中activation_bin的forward函数,A!=2时,为何要加relu函数?
4.根据其他issue,readme 中二/三值化后model size和压缩率是手动计算的。那bit量化后的结果也是计算的吗?
感谢!

可以Post-training quantization 训练后量化压缩吗?

您好,我目前所做的项目训练好的.pth格式的目标检测模型有460兆左右,希望对其进行压缩处理。请问对于训练后的模型,如.pth模型文件,可以应用您的方法对其进行压缩吗?
如果是边训练边量化,我能否在一个基于MaskRcnn的而且是斜框检测的目标检测网络中应用您的方法去实现模型的压缩呢?非常希望您能回复我的问题,万分感谢!

如何获取压缩后的模型?以及压缩率的计算公式?

请教大佬,请问如何获取压缩后的模型?目前网上能搜到开源的代码只有filter pruning(整个通道的剪枝)如何获取剪枝后的模型,针对weight pruning方式(我理解为是3*3卷积核有很多为0),如何获取压缩后的模型,实在是找不到了。另外压缩率的公式如何计算?实际计算过程,需要考虑BN层的参数吗?因为没办法获取压缩后的模型,只能是计算整个网络有多少为0的卷积核数量除以总的卷积核数量,请问这样可以吗?

ModuleNotFoundError: No module named 'util_wt_bab'

你好!首先感谢分享,但在二值量化模型的使用中,出现找不到util_wt_bab的情况,这好像并不是第三方包,文件结构里也没有找到该文件,请问应该如何解决呢?谢谢!

单独对bn层进行量化,不进行bn_fold的量化实施方案

大佬,您好,我想请问一下,如果我不对bn层进行和conv层的融合,而只针对bn层做单独的量化,这一块应该如何实施,是对bn层当中的gama参数等效为conv层中的w,并对输入进bn层的特征图进行量化,这样的思路是对的吗?

向大佬请教量化模型保存的问题

想问一下大佬,就是模型压缩数据对比那张表中的Size(MB)是怎么出来的,得到的模型pth文件大小确实不变,我看您之前的回复说可以通过脚本提取量化模型参数以txt文件形式保存吗?但是那个模型Size是怎么衡量的呢,谢谢!

入门小白求问XNORnet

你好,请问下大大,关于代码,我在代码结构中看到quantization,WbWtAb下看到有bnn与xnornet分类,但由于刚入门,分不太清楚,哪个是bnn代码哪个是xnor代码,xnort论文提及是引入特征因子a进行二值量化,而代码中的A特征值是否就是尼?如果是,,我可否取消A的二值,先只做W的二值呢,因为我试过只输入--w 2,--A还是自动为2了

显存不够

CUDA out of memory. 我将batch size 从原来50调到5 , nvidia-smi显示显存远未用完,但是第一个epoch快完时报这个错(6G显存),batch size无论调为多少都有错

pruning方案存在问题

1.prunin文件下的main函数超参数输入如下
Options: Namespace(cpu=False, data='../data', epochs=300, eval_batch_size=256, evaluate=False, gpu_id='', lr=0.01, num_workers=2, refine='', resume='', s=0.001, sr=True, train_batch_size=512, wd=1e-07)
稀疏训练后,模型准确率为89.21%
2.根据该稀疏模型,做正常剪枝/规整剪枝,超参数如下
Namespace(cpu=False, data='../data', layers=9, model='models_save/nin_preprune.pth', normal_regular=1, percent=0.5, save='models_save/nin_prune.pth')
问题:
!please turn down the prune_ratio!

layer_index: 3 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792

!please turn down the prune_ratio!

layer_index: 6 total_channel: 160 remaining_channel: 1 pruned_ratio: 0.993750

!please turn down the prune_ratio!

layer_index: 10 total_channel: 96 remaining_channel: 1 pruned_ratio: 0.989583

!please turn down the prune_ratio!

layer_index: 15 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792

!please turn down the prune_ratio!

layer_index: 19 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792

!please turn down the prune_ratio!

layer_index: 23 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792

!please turn down the prune_ratio!

layer_index: 28 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792

!please turn down the prune_ratio!

layer_index: 32 total_channel: 192 remaining_channel: 1 pruned_ratio: 0.994792
剪完后的通道数异常,全部仅为1,调整percent=0.9仍出现相同错误;规整剪枝同样存在以下问题。
是否因为稀疏训练时设置的s只能为0.0001

IAO BN融合量化测试

我在使用 您所说的bn_folding.py中的程序对IAO进行量化融合测试时,出现如下问题:
RuntimeError: Error(s) in loading state_dict for Net:
Unexpected key(s) in state_dict: "conv1.q_conv.weight_quantizer.scale", "conv1.q_conv.weight_quantizer.zero_point", "conv2.q_conv.activation_quantizer.scale", "conv2.q_conv.activation_quantizer.zero_point", "conv2.q_conv.weight_quantizer.scale", "conv2.q_conv.weight_quantizer.zero_point".
这个问题是如何解决呢?
我猜想这个问题的出现是由于IAO和二三值量化的方法不同所造成的。

GFLOPs如何计算

您好,我刚接触模型压缩。请问在README.md的模型压缩数据对比表格中有个参数GFLOPs,这个GFLOPs是如何计算得到的?

二值量化中心化并截断部分发现一处不知是bug还是我没有理解

你好,
image
quantization/WbWtAb/models/util_wt_bab.py这个文件中的meancenter_clampConvParams(w)函数貌似并没有对输入w进行修改就直接返回w了,不知道是不是bug。
另外,你这里中心化和截断操作都用.data截断梯度流是为何呢,我有点不能理解,是为了反向传播时这部分不进行求导吗?

量化流程细节的疑问?

Hi,
感谢自己的分享。在代码中有一处疑问向你请假一下,
image
对权重和输入执行量化后进行卷积操作,但在代码对权重进行量化时,为什么还进行了反量化的操作,数据也是如此,且这反量化都在卷积之前,有点疑惑?

二,有考虑过量化后部署的问题吗?目前似乎三方工具都不直接支持。

关于BN_fold的问题

在使用IAO中的BN_fold进行BN层模拟训练量化后,使用bn_folding.py和bn_folding_test.py中的代码完成后,发现网络会自动把所有的样本判别为一类,不能得到和模拟训练量化同样的结果。请问这一块您是怎么做的呢?

移植到目标检测模型效果不佳

大佬好,我将dorefanet移植到基于resnet的backbone的检测网络,在voc数据集上测试,原始fp32精度大概在0.80左右,移植后进行量化训练,我量化了整个backbone,但是保留了head与fpn结构的fp卷积,精度大概在0.13左右,不甚理想,请问有什么tricks吗

关于量化后模型的问题

1.我的模型在量化后,权重文件会多出来一些key值,head4.0.q_conv.weight_quantizer.range_tracker.first_w,这些在加载时会报错,这些值有什么影响吗?
2.量化后的模型可以转换为onnx吗?

希望作者的回复

量化部分的两个文件夹的代码,如果用单张显卡,每次在一个epoch之后保存模型,显存会暴涨,导致显存不够(单张12g或者6g都不够用),多张显卡才能正常训练。有办法解决这个问题吗

关于量化后权值的精度

大佬你好,请问8bit量化后的网络卷积层权值为什么不是整数呢?大佬的定点化是8位小数的定点化么。如果按大佬的教程量化部分跑一遍,8bit量化后网络的权值应该长啥样吖
刚入门量化,恳请大佬教小白做人,感激不尽

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.