更新时间:2024-11-21 GMT+08:00
分享

推理精度测试

本章节介绍两个精度测评工具。如何使用opencompass工具开展语言模型的推理精度测试,数据集是ceval_gen、mmlu_gen、math_gen、gsm8k_gen、humaneval_gen;以及使用lm-eval工具开展语言模型的推理精度测试,数据集包含mmlu、ARC_Challenge、GSM_8k、Hellaswag、Winogrande、TruthfulQA等,该工具为离线测评,不需要启动推理服务,目前支持大语言模型。

约束限制

  • 确保容器可以访问公网。
  • 使用opencompass工具需用vllm接口启动在线服务。
  • 当前的精度测试仅适用于语言模型精度验证,不适用于多模态模型的精度验证。多模态模型的精度验证,建议使用开源MME数据集和工具(GitHub - BradyFU/Awesome-Multimodal-Large-Language-Models at Evaluation)。
  • 配置需要使用的NPU卡,例如:实际使用的是第1张和第2张卡,此处填写为“0,1”,以此类推。
    export ASCEND_RT_VISIBLE_DEVICES=0,1

使用Opencompass精度测评工具

  1. 获取精度测试代码。精度测试代码存放在代码包AscendCloud-LLM的llm_tools/llm_evaluation目录中,代码目录结构如下。目前使用的opencompass版本是0.2.6
    benchmark_eval
    ├──opencompass.sh       #运行opencompass脚本
    ├──install.sh           #安装opencompass脚本
    ├──vllm_api.py          #启动vllm api服务器
    ├──vllm.py              #构造vllm评测配置脚本名字
    ├──vllm_ppl.py          #ppl精度测试脚本
  2. 精度评测切换conda环境,确保之前启动服务为vllm接口,进入到benchmark_eval目录下,执行如下命令。
    conda activate python-3.9.10 
    bash install.sh
  3. 在/home/ma-user/AscendCloud/AscendCloud-LLM/llm_tools/llm_evaluation/benchmark_eval目录下安装依赖。
    cd opencompass #在benchmark_eval目录下
    pip install -e . #下载对应依赖
    cd ../human-eval #在benchmark_eval目录下 (可选,如果选择使用humaneval数据集)
    pip install -e .  # 可选,如果选择使用humaneval数据集
    pip install huggingface-hub==0.25.1 
  4. (可选)如果需要在humaneval数据集上评估模型代码能力,请执行此步骤,否则忽略这一步。原因是通过opencompass使用humaneval数据集时,需要执行模型生成的代码。请仔细阅读human_eval/execution.py文件第48-57行的注释,内容参考如下。了解执行模型生成代码可能存在的风险,如果接受这些风险,请取消第58行的注释,执行下面步骤5进行评测。
    # WARNING
    # This program exists to execute untrusted model-generated code. Although
    # it is highly unlikely that model-generated code will do something overtly
    # malicious in response to this test suite, model-generated code may act
    # destructively due to a lack of model capability or alignment.
    # Users are strongly encouraged to sandbox this evaluation suite so that it 
    # does not perform destructive actions on their host or network. For more 
    # information on how OpenAI sandboxes its code, see the accompanying paper.
    # Once you have read this disclaimer and taken appropriate precautions, 
    # uncomment the following line and proceed at your own risk:
    #                       exec(check_program, exec_globals)     #第58行
  5. 执行精度测试启动脚本opencompass.sh,具体操作命令如下,可以根据参数说明修改参数。请确保${work_dir} 已经通过export设置。
    vllm_path=${vllm_path} \
    host=$host \
    service_port=${service_port} \
    max_out_len=${max_out_len} \
    batch_size=${batch_size} \
    eval_datasets=${eval_datasets}  \
    model_name=${model_name} \
    benchmark_type=${benchmark_type} \
    bash -x opencompass.sh

    参数说明:

    • vllm_path:构造vllm评测配置脚本名字,默认为vllm。
    • host:与起服务的host保持一致,比如起服务为0.0.0.0,host设置也为0.0.0.0。
    • service_port:服务端口,与启动服务时的端口保持,比如8080。
    • max_out_len:在运行类似mmlu、ceval等判别式回答时,max_out_len建议设置小一些,比如16。在运行human_eval等生成式回答(生成式回答是对整体进行评测,少一个字符就可能会导致判断错误)时,max_out_len设置建议长一些,比如512,至少包含第一个回答的全部字段。
    • batch_size:输入的batch_size大小,不影响精度,只影响得到结果速度。
    • eval_datasets:评测数据集和评测方法,比如ceval_gen、mmlu_gen,不同数据集可以详见opencompass下面data目录。
    • model_name:评测模型名称,不需要与启动服务时的模型参数保持一致。
    • benchmark_type:作为一个保存log结果中的一个变量名,默认选eval。
    参考命令:
    vllm_path=vllm host=0.0.0.0 service_port=8080 max_out_len=16 batch_size=2 eval_datasets=mmlu_gen   model_name=llama_7b  benchmark_type=eval bash -x opencompass.sh
  6. (可选)如果同时运行多个数据集,需要将不同数据集通过空格分开,加入到eval_datasets中,比如eval_datasets=ceval_gen mmlu_gen。运行命令如下所示。
    cd opencompass
    python run.py --models vllm --datasets mmlu_gen ceval_gen --debug -w ${output_path}

    output_path: 要保存的结果路径。

  7. (可选)创建新conda环境,安装vllm和opencompass。执行完之后,在 opencompass/configs/models/vllm/vllm_ppl.py 里是ppl的配置项。由于离线执行推理,消耗的显存相当庞大。其中以下参数需要根据实际来调整。
    • batch_size,推理时传入的prompts数量,可配合后面的参数适当减少
    • offline,是否启动离线模型,使用ppl时必须为True
    • tp_size,使用推理的卡数
    • max_seq_len,推理的上下文长度,和消耗的显存直接相关,建议稍微高于prompts。其中,mmlu和ceval 建议 3200

    另外,在 opencompass/opencompass/models/vllm_api.py 中,可以适当调整 gpu_memory_utilization。如果还是 oom,建议适当往下调整。

    最后,如果执行报错提示oom,建议修改数据集的shot配置。例如mmlu,可以修改文件 opencompass/configs/datasets/mmlu/mmlu_ppl_ac766d.py 中的

    fix_id_list, 将最大值适当调低。

    ppl困惑度评测一般用于base权重测评,会将n个选项上拼接上下文,形成n个序列,再计算着n个序列的困惑度(perplexity)。其中,perplexity最小的序列所对应的选项即为这道题的推理结果。运行时间比较长,例如llama3_8b 跑完mmlu要2~3小时。

    在npu卡上,使用多卡进行推理时,需要预置变量

    export PYTORCH_NPU_ALLOC_CONF=expandable_segments:False

    执行脚本如下:

    python run.py --models vllm_ppl --datasets mmlu_ppl -w ${output_path}

    output_path 指定保存结果的路径。

    参考模型llama3系列模型,数据集mmlu为例,配置如下:

    表1 参数配置

    模型

    max_seq_len

    batch_size

    shot数

    llama3_8b

    3200

    8

    采用默认值

    llama3_70b

    3200

    4

    [0, 1, 2]

  8. (可选) opencompass也支持通过本地权重来进行ppl精度测试。本质上使用transformers进行推理,因为没有框架的优化,执行时间最长。另一方面,由于是使用transformers推理,结果也是最稳定的。对单卡运行的模型比较友好,算力利用率比较高。对多卡运行的推理,缺少负载均衡,利用率低。

    在昇腾卡上执行时,需要在 opencompass/opencompass/runners/local.py 中添加如下代码

    import torch
    import torch_npu
    from torch_npu.contrib import transfer_to_npu
    执行脚本如下
    # for llama3_8b
    python run.py --datasets mmlu_ppl \  
    --hf-type base --hf-path {hf-path} \  
    --max-seq-len 3200 --max-out-len 16 --hf-num-gpus 1 --batch-size 4 \  
    -w {output_path} --debug 

    参数说明如下:

    • --datasets:评测的数据集及评测方法,其中 mmlu 是数据集,ppl 是评测方法。
    • --hf-type:HuggingFace模型权重类型(base,chat),默认为chat,依据实际的模型选择。
    • --hf-path:本地 HuggingFace 权重的路径,比如/home/ma-user/nfs/model/Meta-Llama-3-8B。
    • --max-seq-len:模型的最大序列长度。
    • --max-out-len:模型的最大输出长度。
    • --hf-num-gpus:需要使用的卡数。
    • --batch-size:推理每次处理的输入数目。
    • -w:存放输出结果的目录。
  9. 查看精度测试结果。

    默认情况下,评测结果会按照result/{model_name}/的目录结果保存到对应的测试工程。执行多少次,则会在{model_name}下生成多少次结果。benchmark_eval下生成的log中记录了客户端产生结果。数据集的打分结果在result/{model_name}/...目录下,查找到summmary目录,有txt和csv两种保存格式。

    总体打分结果参考txt和csv文件的最后一行,举例如下:

    npu:

    mmlu:46.6

    gpu:

    mmlu:47

    NPU打分结果(mmlu取值46.6)和GPU打分结果(mmlu取值47)进行对比,误差在1以内(计算公式:(47-46.6) < 1)认为NPU精度和GPU对齐。NPU和GPU的评分结果和社区的评分不能差太远(小于10)认为分数有效。

使用Lm-eval精度测评工具

使用lm-eval工具暂不支持qwen-7b、qwen-14b、qwen-72b、chatglm2-6b、chatglm3-6b模型。

  1. 精度评测可以在原先conda环境,进入到一个固定目录下,执行如下命令。
    rm -rf lm-evaluation-harness/  
    git clone https://github.com/EleutherAI/lm-evaluation-harness.git
    cd lm-evaluation-harness
    git checkout 383bbd54bc621086e05aa1b030d8d4d5635b25e6
    pip install -e .
  2. 执行如下精度测试命令,可以根据参数说明修改参数。
    lm_eval --model vllm   --model_args pretrained=${vllm_path},dtype=auto,tensor_parallel_size=${tensor_parallel_size},gpu_memory_utilization=${gpu_memory_utilization},add_bos_token=True,max_model_len=${max_model_len},quantization=${quantization},distributed_executor_backend='ray' \
    --tasks ${task}  --batch_size ${batch_size}   --log_samples  --cache_requests true  --trust_remote_code --output_path ${output_path}
    参数说明:
    • model_args:标志向模型构造函数提供额外参数,比如指定运行模型的数据类型;
      • vllm_path是模型权重路径;
      • max_model_len 是最大模型长度,默认设置为4096;
      • gpu_memory_utilization是gpu利用率,如果模型出现oom报错,调小参数;
      • tensor_parallel_size是使用的卡数;
      • quantization是量化参数,使用非量化权重,去掉quantization参数;如果使用awq、smoothquant或者gptq加载的量化权重,根据量化方式选择对应参数,可选awq,smoothquant,gptq。
      • distributed_executor_backend是开启多进程服务方式,选择ray开启。
    • model:模型启动模式,可选vllm,openai或hf,hf代表huggingface。
    • tasks:评测数据集任务,比如openllm。
    • batch_size:输入的batch_size大小,不影响精度,只影响得到结果速度,默认使用auto,代表自动选择batch大小。
    • output_path:结果保存路径。
    使用lm-eval,比如加载非量化或者awq量化,llama3.2-1b模型的权重,参考命令:
    lm_eval --model vllm   --model_args pretrained="/data/nfs/benchmark/tokenizer/Llama-3.2-1B-Instruct/",dtype=auto,tensor_parallel_size=1,gpu_memory_utilization=0.7,add_bos_token=True,max_model_len=4096,distributed_executor_backend='ray' \
    --tasks openllm   --batch_size auto   --log_samples  --cache_requests true  --trust_remote_code --output_path ./
    使用lm-eval,比如smoothquant量化,llama3.1-70b模型的权重,参考命令:
    lm_eval --model vllm   --model_args pretrained="/data/nfs/benchmark/tokenizer_w8a8/llama3.1-70b/",dtype=auto,tensor_parallel_size=4,gpu_memory_utilization=0.7,add_bos_token=True,max_model_len=4096,quantization="smoothquant",distributed_executor_backend='ray' \
    --tasks openllm   --batch_size auto   --log_samples  --cache_requests true  --trust_remote_code --output_path ./

相关文档