合約量化(量化合約)開發(fā)詳細丨合約量化(量化合約)系統(tǒng)開發(fā)策略及分析
執(zhí)行quantize.py,進行量化
整個量化過程:
設置量化參數(shù)-->載入數(shù)據(jù)-->執(zhí)行量化(如果要看結果,則定制一個executor)-->導出所有層量化結果-->分析量化誤差(總誤差,每層誤差)-->導出量化權重文件
量化文件最后在working/quantized.onnx
注意:該代碼輸入輸出格式都是onnx,但是輸出platfor和calibration方法與B站教程不同,該輸出模型包含了量化-反量化節(jié)點,可以用onnxruntime測試AP
"""
這是一個PPQ量化的入口腳本,將你的模型和數(shù)據(jù)按要求進行打包:
This file will show you how to quantize your network with PPQ
You should prepare your model and calibration dataset as follow:
~/working/model.onnx<--your model
~/working/data/*.npy or~/working/data/*.bin<--your dataset
if you are using caffe model:關于區(qū)塊鏈項目技術開發(fā)威:yy625019
~/working/model.caffemdoel<--your model
~/working/model.prototext<--your model
###MAKE SURE YOUR INPUT LAYOUT IS[N,C,H,W]or[C,H,W]###
quantized model will be generated at:~/working/quantized.onnx
"""
from ppq import*
from ppq.api import*
import os
#modify configuration below:
WORKING_DIRECTORY='working'#choose your working directory
TARGET_PLATFORM=TargetPlatform.PPL_CUDA_INT8#choose your target platform
MODEL_TYPE=NetworkFramework.ONNX#or NetworkFramework.CAFFE
INPUT_LAYOUT='chw'#input data layout,chw or hwc
NETWORK_INPUTSHAPE=[1,3,224,224]#input shape of your network
CALIBRATION_BATCHSIZE=16#batchsize of calibration dataset
EXECUTING_DEVICE='cuda'#'cuda'or'cpu'.
REQUIRE_ANALYSE=False
DUMP_RESULT=False#是否需要Finetuning一下你的網(wǎng)絡
#SETTING對象用于控制PPQ的量化邏輯
#當你的網(wǎng)絡量化誤差過高時,你需要修改SETTING對象中的參數(shù)進行特定的優(yōu)化
platform=TARGET_PLATFORM,finetune_steps=2500,
finetune_lr=1e-3,calibration='kl',#【改】量化算法可選'kl','pecentile','mse'
equalization=True,non_quantable_op=None)
SETTING=SETTING.convert_to_daddy_setting()
print('正準備量化你的網(wǎng)絡,檢查下列設置:')
print(f'WORKING DIRECTORY:{WORKING_DIRECTORY}')
print(f'TARGET PLATFORM:{TARGET_PLATFORM.name}')
print(f'NETWORK INPUTSHAPE:{NETWORK_INPUTSHAPE}')
print(f'CALIBRATION BATCHSIZE:{CALIBRATION_BATCHSIZE}')
#------------------------------------------------------------------------------
#此腳本針對單輸入模型,輸入數(shù)據(jù)必須是圖像數(shù)據(jù)layout:[n,c,h,w]
#如果你的模型具有更復雜的輸入格式,你可以重寫下面的load_calibration_dataset函數(shù)
#請注意,任何可遍歷對象都可以作為PPQ的數(shù)據(jù)集作為輸入
#------------------------------------------------------------------------------
dataloader=load_calibration_dataset(
directory=WORKING_DIRECTORY,
input_shape=NETWORK_INPUTSHAPE,
batchsize=CALIBRATION_BATCHSIZE,
input_format=INPUT_LAYOUT)
print('網(wǎng)絡正量化中,根據(jù)你的量化配置,這將需要一段時間:')
quantized=quantize(
working_directory=WORKING_DIRECTORY,setting=SETTING,
model_type=MODEL_TYPE,executing_device=EXECUTING_DEVICE,
input_shape=NETWORK_INPUTSHAPE,target_platform=TARGET_PLATFORM,
dataloader=dataloader,calib_steps=32)
#------------------------------------------------------------------------------
#如果你需要執(zhí)行量化后的神經(jīng)網(wǎng)絡并得到結果,則需要創(chuàng)建一個executor
#這個executor的行為和torch.Module是類似的,你可以利用這個東西來獲取執(zhí)行結果
#請注意必須在executor之前執(zhí)行此操作
#------------------------------------------------------------------------------
executor=TorchExecutor(graph=quantized)
#output=executor.forword(input)
#------------------------------------------------------------------------------
#導出PPQ執(zhí)行網(wǎng)絡的所有中間結果,該功能是為了和硬件對比結果
#中間結果可能十分龐大,因此PPQ將使用線性同余發(fā)射器從執(zhí)行結果中采樣
#對了對比中間結果,硬件執(zhí)行結果也必須使用同樣的隨機數(shù)種子采樣
#查閱ppq.util.fetch中的相關代碼以進一步了解此內容
#查閱ppq.api.fsys中的dump_internal_results函數(shù)以確定采樣邏輯
#------------------------------------------------------------------------------
if DUMP_RESULT:
dump_internal_results(
graph=quantized,dataloader=dataloader,
dump_dir=WORKING_DIRECTORY,executing_device=EXECUTING_DEVICE)
#-------------------------------------------------------------------
#PPQ計算量化誤差時,使用信噪比的倒數(shù)作為指標,即噪聲能量/信號能量
#量化誤差0.1表示在整體信號中,量化噪聲的能量約為10%
#你應當注意,在graphwise_error_analyse分析中,我們衡量的是累計誤差
#網(wǎng)絡的最后一層往往都具有較大的累計誤差,這些誤差是其前面的所有層所共同造成的
#你需要使用layerwise_error_analyse逐層分析誤差的來源
#-------------------------------------------------------------------
print('正計算網(wǎng)絡量化誤差(SNR),最后一層的誤差應小于0.1以保證量化精度:')
reports=graphwise_error_analyse(
graph=quantized,running_device=EXECUTING_DEVICE,steps=32,
dataloader=dataloader,collate_fn=lambda x:x.to(EXECUTING_DEVICE))
for op,snr in reports.items():
if snr>0.1:ppq_warning(f'層{op}的累計量化誤差顯著,請考慮進行優(yōu)化')
if REQUIRE_ANALYSE:
print('正計算逐層量化誤差(SNR),每一層的獨立量化誤差應小于0.1以保證量化精度:')
layerwise_error_analyse(graph=quantized,running_device=EXECUTING_DEVICE,
interested_outputs=None,
dataloader=dataloader,collate_fn=lambda x:x.to(EXECUTING_DEVICE))
print('網(wǎng)絡量化結束,正在生成目標文件:')
export_ppq_graph(
graph=quantized,platform=TargetPlatform.ONNXRUNTIME,
graph_save_to=os.path.join(WORKING_DIRECTORY,'quantized.onnx'),
config_save_to=os.path.join(WORKING_DIRECTORY,'quant_cfg.json'),
quantized_param=True)#【改】platform:保證輸出onnxruntime格式帶量化和反量化節(jié)點;
#quantized_param:確保param儲存int8格式,規(guī)避onnxruntime無法量化