大模型量化

大模型量化工具将高位浮点数转为低位的定点数,例如16bit降低到8bit,直接减少模型权重的体积,生成量化参数和权重文件。在无需训练成本的前提下,完成大模型的训练后压缩并最大程度保障其精度。

前提条件

功能实现流程

图1 量化接口调用流程

关键步骤说明如下:

  1. 用户准备原始模型和校准数据。
  2. 可选:使用离群值抑制功能对LLM模型进行离群值抑制,可参考精度保持策略选择是否启用。
    1. 使用AntiOutlierConfig生成离群值抑制配置。
    2. 调用AntiOutlier接口,将模型、校准数据等传入,生成抑制器。
    3. 调用抑制器的process()方法对原始模型进行离群值抑制。
  3. 使用QuantConfig生成量化配置。
  4. 根据原始模型、量化配置和校准数据,调用Calibrator接口构建量化校准对象。
  5. 调用生成的量化校准对象的run()方法对原始模型进行量化。
  6. 调用生成的量化校准对象的save()接口保存量化后的模型,包括模型量化权重和模型相关参数,用于后续量化模型的部署任务,具体请参见MindIE的“加速库支持模型列表”章节中已适配量化的模型。

量化步骤(以ChatGLM2-6B为例)

  1. 用户自行准备模型、权重文件和校准数据,本样例以ChatGLM2-6B为例,点击获取链接自行下载权重文件,并上传至服务器文件夹内,如上传至“chatglm2”文件夹,目录示例如下:

    ├── config.json
    ├── configuration chatglm.py
    ├── modeling_chatglm.py
    ├── pytorch_model-00001-of-00007.bin
    ├── pytorch_model-00002-of-00007.bin
    ├── pytorch_model-00003-of-00007.bin
    ├── pytorch_model-00004-of-00007.bin
    ├── pytorch_model-00005-of-00007.bin
    ├── pytorch_model-00006-of-00007.bin
    ├── pytorch_model-00007-of-00007.bin
    ├── pytorch_model.bin.index.json
    ├── quantization.py
    ├── README.md
    ├── tokenization_chatglm.py
    ├── tokenizer.model
    ├── tokenizer_config.json

    大模型量化工具建议在大模型下游任务评估流程打通的前提下使用,请自行调试源码后进行如下量化配置。

  2. ChatGLM2-6B模型进行量化前请执行如下命令安装所需依赖,若运行量化工具过程中提示缺失某个依赖,请根据提示安装。

    pip3 install protobuf==4.24.1
    pip3 install sentencepiece==0.1.99
    pip3 install sympy==1.11.1

  3. 新建模型的量化脚本quant.py,编辑quant.py文件,根据实际的量化场景导入样例代码,参考加粗字体信息提示,并根据实际情况进行修改。

    推荐大模型量化时在npu上执行。

    • W8A8 per_channel量化场景导入的样例代码如下,kvcache、lowbit算法以及per_token算法量化场景导入的代码样例请参考w8a8量化场景
      # 导入相关依赖
      import torch 
      import torch_npu   # 若需要cpu上进行量化,可忽略此步骤
      from transformers import AutoTokenizer, AutoModel
      
      # for local path
      tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path='./chatglm2', trust_remote_code=True)
      model = AutoModel.from_pretrained(
          pretrained_model_name_or_path='./chatglm2',
          trust_remote_code=True,
        ).npu()    # 若在npu上进行多卡量化时,需要先参考前提条件进行配置,并配置device_map='auto',创建model时需去掉.npu();若在cpu上进行量化时,需要配置torch_dtype=torch.float32,创建model时需去掉.npu()
      # 准备校准数据,请根据实际情况修改
      calib_list = ["中国的首都在哪里?",
                    "请做一首诗歌:",
                    "我想要学习python,该怎么学习?",
                    "请帮我写一篇关于大模型推理优化的任职报告:",
                    "中国最值得去的几个景点"]
      #获取校准数据函数定义
      def get_calib_dataset(tokenizer, calib_list):
          calib_dataset = []
          for calib_data in calib_list:
              inputs = tokenizer([calib_data], return_tensors='pt').to(model.device)   
              print(inputs)
              calib_dataset.append([inputs.data['input_ids'], inputs.data['attention_mask']])     
          return calib_dataset
      
      dataset_calib = get_calib_dataset(tokenizer, calib_list)  #校准数据获取
      
      # 量化配置,请根据实际情况修改
      from msmodelslim.pytorch.llm_ptq.llm_ptq_tools import Calibrator, QuantConfig    # 导入量化配置接口
      # 使用QuantConfig接口,配置量化参数,并返回量化配置实例
      quant_config = QuantConfig(
          a_bit=8, 
          w_bit=8,       
          disable_names=['transformer.encoder.layers.0.self_attention.query_key_value','transformer.encoder.layers.0.self_attention.dense', 'transformer.encoder.layers.0.mlp.dense_h_to_4h'], 
          dev_id=model.device.index, 
          dev_type='npu',   # 在cpu进行量化时,需配置参数dev_type='cpu',并取消dev_id=model.device.index参数的配置
          act_method=3,
          pr=0.5, 
          mm_tensor=False
        )  
      #使用Calibrator接口,输入加载的原模型、量化配置和校准数据,定义校准
      calibrator = Calibrator(model, quant_config, calib_data=dataset_calib, disable_level='L0')  
      calibrator.run()     #使用run()执行量化
      calibrator.save('./quant_weight', save_type=['numpy', 'safe_tensor'])      #使用save()保存模型量化参数,请根据实际情况修改路径
      print('Save quant weight success!')
    • W8A16 per-channel per_channel场景导入的样例代码如下,MinMax算法、HQQ算法、GPTQ算法、AWQ算法以及w8a16 per-group量化场景导入的代码样例请参考w8a16 per-channel量化场景
      # 导入相关依赖
      import torch
      import torch_npu   # 若需要cpu上进行量化,可忽略此步骤
      from transformers import AutoTokenizer, AutoModel
      
      # for local path
      tokenizer = AutoTokenizer.from_pretrained(pretrained_model_name_or_path='./chatglm2', trust_remote_code=True) 
      model = AutoModel.from_pretrained(
          pretrained_model_name_or_path='./chatglm2',
          trust_remote_code=True,
          ).npu()    # 若在npu上进行多卡量化时,需要先参考前提条件进行配置,并配置device_map='auto',创建model时需去掉.npu();若在cpu上进行量化时,需要配置torch_dtype=torch.float32,创建model时需去掉.npu()
      # 准备校准数据,请根据实际情况修改W8A16 Data-Free模式下请忽略此步骤
      calib_list = ["中国的首都在哪里?",
                    "请做一首诗歌:",
                    "我想要学习python,该怎么学习?",
                    "请帮我写一篇关于大模型推理优化的任职报告:",
                    "中国最值得去的几个景点"]
      #获取校准数据函数定义
      def get_calib_dataset(tokenizer, calib_list):
          calib_dataset = []
          for calib_data in calib_list:
              inputs = tokenizer([calib_data], return_tensors='pt').to(model.device)
              print(inputs)
              calib_dataset.append([inputs.data['input_ids'], inputs.data['attention_mask']])
          return calib_dataset
      
      dataset_calib = get_calib_dataset(tokenizer, calib_list)  #校准数据获取
      
      # 量化配置,请根据实际情况修改
      from msmodelslim.pytorch.llm_ptq.llm_ptq_tools import Calibrator, QuantConfig    # 导入量化配置接口
      # 使用QuantConfig接口,配置量化参数,并返回量化配置实例
      quant_config = QuantConfig(
          w_bit=8,    
          a_bit=16,         
          disable_names=[], 
          dev_id=model.device.index, 
          dev_type='npu',   # 在cpu进行量化时,需配置参数dev_type='cpu',并取消参数dev_id=model.device.index的配置
          w_sym=False, 
          mm_tensor=False
        )  
      #使用Calibrator接口,输入加载的原模型、量化配置和校准数据,定义校准
      calibrator = Calibrator(model, quant_config, calib_data=dataset_calib, disable_level='L0')  calibrator.run()     #使用run()执行量化
      calibrator.save('./quant_weight', save_type=['numpy', 'safe_tensor'])      #使用save()保存模型量化参数,请根据实际情况修改路径
      print('Save quant weight success!')

    因为在存储量化参数过程中存在反序列化风险,所以已通过在存储过程中,将保存的量化结果文件夹权限设置为750,量化权重文件权限设置为400,量化权重描述文件设为600来消减风险。

  4. 启动模型量化任务,并在指定的输出目录获取模型量化参数,量化后权重文件的介绍请参见量化后权重文件,若使用MindIE进行后续的推理部署任务,请保存为safetensors格式,具体请参见MindIE的“加速库支持模型列表”章节中已适配量化的模型。

    python3 quant.py

    量化任务完成后,可能会存在模型精度下降的情况,可以参考精度保持策略进行配置优化减少精度损耗。

量化后权重文件

精度保持策略

在量化权重生成后,可以使用伪量化模型进行推理,检验伪量化精度是否正常。伪量化是指通过torch,通过浮点运算完成量化模型运算逻辑,运算过程中的数据和真实量化的数据差异只在算子精度上。

若伪量化精度不满足预期,可先使用精度定位方法进行定位,再参考量化精度提升方法提升精度。