本文将会介绍如何使用HuggingFace的Optimum,来对微调后的BERT模型进行量化(Quantization)。
在文章NLP(六十七)BERT模型训练后动态量化(PTDQ) 中,我们使用PyTorch自带的PTDQ(Post
Training Dynamic
Quantization)量化策略对微调后的BERT模型进行量化,取得了模型推理性能的提升(大约1.5倍)。本文将尝试使用Optimum量化工具。
Optimum介绍 
Optimum 是 Transformers
的扩展,它提供了一组性能优化工具,可以在目标硬件上以最高效率训练和运行模型。
Optimum针对不同的硬件,提供了不同的优化方案,如下表:
 
ONNX runtime 
python -m pip install optimum[onnxruntime] 
 
Intel Neural Compressor (INC) 
python -m pip install optimum[neural-compressor] 
 
Intel OpenVINO 
python -m pip install optimum[openvino,nncf] 
 
Graphcore IPU 
python -m pip install optimum[graphcore] 
 
Habana Gaudi Processor (HPU) 
python -m pip install optimum[habana] 
 
GPU 
python -m pip install optimum[onnxruntime-gpu] 
 
 
本文将会介绍基于ONNX的模型量化技术。ONNX(英语:Open Neural Network
Exchange)是一种针对机器学习所设计的开放式的文件格式,用于存储训练好的模型。它使得不同的人工智能框架(如Pytorch、MXNet)可以采用相同格式存储模型数据并交互。
模型量化 
我们使用的微调后的BERT模型采用文章https://percent4.github.io/NLP%EF%BC%88%E5%85%AD%E5%8D%81%E5%85%AD%EF%BC%89%E4%BD%BF%E7%94%A8HuggingFace%E4%B8%AD%E7%9A%84Trainer%E8%BF%9B%E8%A1%8CBERT%E6%A8%A1%E5%9E%8B%E5%BE%AE%E8%B0%83/ 中给出的文本分类模型。
首先,我们先加载PyTorch中的设备(CPU)。
1 2 3 4 import  torch"cpu" )
接着,我们使用optimum.onnxruntime模块加载模型和tokenizer,并将模型保存为onnx格式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from  optimum.onnxruntime import  ORTModelForSequenceClassificationfrom  transformers import  AutoTokenizerimport  torch"./sougou_test_trainer_256/checkpoint-96" "./sougou_test_trainer_256/onnx_256" True )
此时,会多出onnx_256文件夹,保存模型为model.onnx。
保存为onnx模型 
 
输出结果为:
1 2 3 4 5 ('./sougou_test_trainer_256/onnx_256 \\tokenizer_config.json','./sougou_test_trainer_256/onnx_256 \\special_tokens_map.json','./sougou_test_trainer_256/onnx_256 \\vocab.txt','./sougou_test_trainer_256/onnx_256 \\added_tokens.json','./sougou_test_trainer_256/onnx_256 \\tokenizer.json')
使用transfomers中的pipeline对模型进行快速推理。
1 2 3 4 from  transformers import  pipeline"text-classification" , model=model, tokenizer=tokenizer)"这期节目继续关注中国篮球的话题。众所周知,我们已经结束了男篮世界杯的所有赛程,一胜四负的一个成绩,甚至比上一届的世界杯成绩还要差。因为这一次我们连奥运会落选赛也都没有资格参加,所以,连续两次错过了巴黎奥运会的话,对于中国篮协,还有对于姚明来说,确实成为了他任职的一个最大的败笔。对于球迷非常关注的一个话题,乔尔杰维奇是否下课,可能对于这个悬念来说也都是暂时有答案了。" )
输出结果如下:
1 [{'label ':  'LABEL_0 ', 'score ':  0.9963239431381226 }]
对ONNX模型进行优化。
1 2 3 4 5 6 7 8 9 10 11 12 from  optimum.onnxruntime import  ORTOptimizerfrom  optimum.onnxruntime.configuration import  OptimizationConfig99 ) 
此时,优化后的模型为model_optimized.onnx。
对优化后的模型进行推理。
1 2 3 4 5 6 7 8 from  transformers import  pipeline"model_optimized.onnx" )"text-classification" , model=optimized_model, tokenizer=tokenizer)"今年7月,教育部等四部门联合印发了《关于在深化非学科类校外培训治理中加强艺考培训规范管理的通知》(以下简称《通知》)。《通知》针对近年来校外艺术培训的状况而发布,并从源头就校外艺术培训机构的“培训主体、从业人员、招生行为、安全底线”等方面进行严格规范。校外艺术培训之所以火热,主要在于高中阶段艺术教育发展迟滞于学生需求。分析教育部数据,2021年艺术学科在校生占比为9.84%,高于2020年的9.73%;2020至2021年艺术学科在校生的年增长率为5.04%,远高于4.28%的总在校生年增长率。增长的数据,是近年来艺考招生连年火热的缩影,在未来一段时间内,艺考或将在全国范围内继续保持高热度。" )
输出结果为:
1 [{'label ':  'LABEL_3 ', 'score ':  0.9926980137825012 }]
对优化后的ONNX模型再进行量化,代码为:
1 2 3 4 5 6 7 8 9 10 11 12 from  optimum.onnxruntime import  ORTQuantizerfrom  optimum.onnxruntime.configuration import  AutoQuantizationConfigFalse , per_channel=False )
此时量化后的模型为model_optimized_quantized.onnx。比较量化前后的模型大小,代码为:
1 2 3 4 5 6 7 8 import  os"model_optimized.onnx" ))/(1024 *1024 )"model_optimized_quantized.onnx" ))/(1024 *1024 )print (f"Model file size: {size:.2 f}  MB" )print (f"Quantized Model file size: {quantized_model:.2 f}  MB" )
输出结果为:
1 2 Model  file size: 390 .17  MBQuantized  Model file size: 97 .98  MB
最后,加载量化后的模型,代码为:
1 2 3 4 5 6 from  optimum.onnxruntime import  ORTModelForSequenceClassificationfrom  transformers import  pipeline, AutoTokenizer"model_optimized_quantized.onnx" ).to(device)
推理实验 
在进行模型推理实验前,先加载测试数据集。
1 2 3 import  pandas as  pd"./data/sougou/test.csv" )
使用量化前的模型进行推理,记录推理时间,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  numpy as  npimport  timefor  i, row in  test_df.iterrows():"label" ])'text' ], max_length=256 , truncation=True , padding=True , return_tensors='pt' )0 ].detach().numpy(), axis=1 )[0 ]1000 )if  i % 100 :print (i, (time.time() - row_s_time) * 1000 , label_id)print ("avg time:" , (time.time() - s_time) * 1000  / test_df.shape[0 ])print ("P50 time:" , np.percentile(np.array(cost_time_list), 50 ))print ("P95 time:" , np.percentile(np.array(cost_time_list), 95 ))
输出结果为:
1 2 3 4 5 6 7 8 9 10 0  710 .2577686309814  0 100  477 .72765159606934  1 200  616 .3530349731445  2 300  509 .63783264160156  3 400  531 .57639503479  4 avg  time: 501 .0757282526806 P50  time: 504 .6522617340088 P95  time: 623 .9353895187337 
对输出结果进行指标评级,代码为:
1 2 3 from  sklearn.metrics import  classification_reportprint (classification_report(true_labels, pred_labels, digits=4 ))
重复上述代码,将模型替换为量化前ONNX模型(model.onnx),优化后ONNX模型(model_oprimized.onnx),量化后ONNX模型(model_optimized_quantized.onnx),进行推理时间(单位:ms)统计和推理指标评估,结果见下表:
 
量化前ONNX模型 
501.1 
623.9 
0.9717 
 
优化后ONNX模型 
484.6 
629.6 
0.9717 
 
量化后ONNX模型 
361.5 
426.9 
0.9738 
 
 
对比文章NLP(六十七)BERT模型训练后动态量化(PTDQ) 中的推理结果,原始模型的平均推理时间为666.6ms,weighted
F1值为0.9717,我们有如下结论:
个人微信公众号 
 
参考文献 
NLP(六十六)使用HuggingFace中的Trainer进行BERT模型微调:https://percent4.github.io/2023/09/02/NLP%EF%BC%88%E5%85%AD%E5%8D%81%E5%85%AD%EF%BC%89%E4%BD%BF%E7%94%A8HuggingFace%E4%B8%AD%E7%9A%84Trainer%E8%BF%9B%E8%A1%8CBERT%E6%A8%A1%E5%9E%8B%E5%BE%AE%E8%B0%83/  
NLP(六十七)BERT模型训练后动态量化(PTDQ):https://percent4.github.io/2023/09/03/NLP%EF%BC%88%E5%85%AD%E5%8D%81%E4%B8%83%EF%BC%89BERT%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83%E5%90%8E%E5%8A%A8%E6%80%81%E9%87%8F%E5%8C%96%EF%BC%88PTDQ%EF%BC%89/  
Optimum: https://huggingface.co/docs/optimum/index  
Optimizing Transformers with Hugging Face Optimum: https://www.philschmid.de/optimizing-transformers-with-optimum  
 
欢迎关注我的公众号
NLP奇幻之旅 ,原创技术文章第一时间推送。
 
欢迎关注我的知识星球“自然语言处理奇幻之旅 ”,笔者正在努力构建自己的技术社区。