☰
Model-Optimizer 的 KL 散度模型验证工具包:量化/剪枝模型输出相似度评估实战指南
2026/9/26 23:33:50 网站建设 项目流程
  • 人工智能
  • 大模型
  • 模型优化
  • 模型量化
  • 模型压缩

【免费下载链接】Model-Optimizer

A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning models for downstream deployment frameworks like TensorRT-LLM, TensorRT, vLLM, etc. to optimize inference speed.

项目地址:https://gitcode.com/GitHub_Trending/te/Model-Optimizer
点击查看免费下载

导读

本文围绕 Model-Optimizer 仓库中 examples/windows/accuracy_benchmark/kl_divergence_metrics/README.md 所介绍的 KL Divergence Model Validation Toolkit 展开,它是 Windows 端 LLM 精度验证工具链中的核心组件,用于通过 KL(Kullback-Leibler)散度定量比较两个模型的输出概率分布。读完本文你将掌握:如何使用compute_kl_divergence.py在 Hugging Face(HF)模型与 ONNX Runtime GenAI 模型之间、或同一执行提供者(EP)下的两个 GenAI 模型之间做顺序式逐块比较,理解其内存友好的两阶段设计、参数含义、结果输出格式,以及常见问题的排查思路。

工具包定位:为什么要用 KL 散度验证模型

在模型优化流程中,量化、剪枝、蒸馏等操作会改变模型权重与计算精度,最核心的问题是"优化后模型是否还保持了原模型的输出质量"。KL 散度从信息论角度量化一个概率分布相对另一个概率分布的差异,恰好可以用于衡量优化前后模型在每个 token 位置输出分布的变化程度——KL 值越小,说明两个模型的输出越相似。

该工具包(compute_kl_divergence.py)的主要应用场景包括:

  1. 模型优化验证:验证经过量化、剪枝等优化后的模型是否保持了输出质量;
  2. 框架对比:比较 Hugging Face 模型与 ONNX Runtime GenAI 模型的输出差异;
  3. 精度分析:评估 FP16、INT4、INT8 等不同精度模型的输出差异;
  4. 执行提供者测试:测试 CUDA、DirectML、CPU、TensorRT 等不同 EP 实现的一致性。

从仓库整体结构看,该工具包与 perplexity_metrics(困惑度)、fvd_metrics(视频 FVD)共同构成 accuracy_benchmark 目录下的"附加指标"体系,弥补了 MMLU 等端到端任务评估之外的分布级相似度检查能力,属于量化模型上线前的常规回归验证手段。

核心组件与工作模式

主脚本与比较模式

脚本用途比较模式
compute_kl_divergence.py双模型顺序式比较HF vs GenAI、GenAI vs GenAI(同一 EP)、GenAI vs HF、HF vs HF

从脚本的 argparse 定义(compute_kl_divergence.py)可以看出,--model1_type与--model2_type均在["hf", "genai"]中取值,因此四种组合全部被支持,顺序可互换。

数据集

  • 统一使用WikiText-2 的 test split,保证所有模型在完全相同的评估语料上比较;
  • 数据集通过 HuggingFacedatasets库自动加载与预处理。源码中get_wikitext2()(compute_kl_divergence.py)执行load_dataset("wikitext", "wikitext-2-raw-v1", split="test"),并将所有样本以双换行符拼接为一段连续文本用于后续分块推理。

安装与环境准备

1. 安装基础依赖

pip install -r requirements.txt

requirements.txt 中包含accelerate、datasets、numpy、safetensors>=0.4.0、torch>=2.6.0、transformers<5.0,并配置了--extra-index-url https://download.pytorch.org/whl/cu129的 CUDA 12.9 轮子索引。

如需更快的推理速度,建议显式安装带 CUDA 的 PyTorch:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu129

2. 安装 ONNX Runtime GenAI 包

根据硬件选择其中一个安装:

# 面向 CUDA pip install onnxruntime-genai-cuda # 面向 DirectML pip install onnxruntime-genai-directml # 面向 CPU pip install onnxruntime-genai

安装哪个包会直接决定 GenAI 模型在脚本中自动使用的执行提供者:源码注释明确说明"GenAI 模型会根据所安装的 onnxruntime-genai 包自动使用合适的执行提供者(cuda、directml、cpu、tensorrt)"。这是 GenAI vs GenAI 比较必须"同一 EP"的根因——不同 EP 对应不同安装包,而每次进程只能加载一个包。

使用示例

快速上手

对比 HF 与 GenAI 模型
python compute_kl_divergence.py \ --model1 "meta-llama/Llama-3.1-8B-Instruct" --model1_type hf \ --model2 "G:\models\genai_model" --model2_type genai \ --device cuda \ --output results.json
对比两个 GenAI 模型(同一 EP)
python compute_kl_divergence.py \ --model1 "G:\models\genai_fp16" --model1_type genai \ --model2 "G:\models\genai_int4" --model2_type genai \ --output fp16_vs_int4.json

上述第二个示例即典型的精度分析用例:FP16 基线与 INT4 量化版对比,直接用 KL 值反映量化带来的输出分布漂移。

开启调试输出

python compute_kl_divergence.py \ --model1 "meta-llama/Llama-3.1-8B-Instruct" --model1_type hf \ --model2 "G:\models\genai_model" --model2_type genai \ --device cuda \ --output results.json \ --debug # 开启详细日志

--debug对应脚本内的全局DEBUG标志,会驱动debug_print()打印每个 chunk 的形状、每步的 GPU 显存分配/保留量、模型清理状态等中间信息,便于定位显存或形状不匹配问题。

配置参数详解

必需参数

参数说明取值
--model1第一个模型本地路径或 HF Hub 标识符
--model1_type第一个模型类型hf、genai
--model2第二个模型本地路径或 HF Hub 标识符
--model2_type第二个模型类型hf、genai

可选参数

参数说明默认值
--deviceHF 模型推理设备cuda(可选cpu)
--output结果 JSON 输出路径无(打印到控制台)
--debug开启详细调试输出False

注意:--device只影响HF 模型的推理设备(源码 epilog 中明确说明),GenAI 模型始终由所装包决定 EP。

模型路径格式

  • HF 模型:
    • Hub 标识符:meta-llama/Llama-3.1-8B-Instruct(首次使用会自动下载)
    • 本地路径:F:\shared\Llama-3.1-8B-Instruct
  • GenAI 模型:
    • 仅支持本地目录路径:G:\models\genai_model(须包含genai_config.json与 tokenizer 等 ORT-GenAI 可加载的组件)

脚本在main()中做了路径校验(compute_kl_divergence.py):genai类型强制要求本地路径存在;hf类型仅在路径含路径分隔符(看起来像本地路径)时才检查存在性,避免把 Hub 标识符误判为缺失。

关键解读口径

  • 越小越好:更小的 KL 散度 = 输出更相似;
  • 相对比较:应以基线(如 HF FP32 或 FP16 原始模型)为参照解读数值,绝对数值本身没有独立阈值意义。

源码实现原理:内存友好的两阶段顺序式比较

这是本工具包最有价值的工程细节。README 之外,脚本源码揭示了两阶段设计,使其可以在单进程、最小显存条件下完成双模型比较。

阶段一:加载模型 1 并提取 logits 存入 CPU 内存

  • HF 模型走extract_hf_logits()(compute_kl_divergence.py):CUDA 下以float16加载,CPU 下回退float32;刻意不使用device_map="auto",以保证后续能够彻底清理显存。
  • GenAI 模型走extract_genai_logits()(compute_kl_divergence.py):通过onnxruntime_genai的GeneratorParams.set_search_options(max_length=..., do_sample=False, early_stopping=False)配置确定性解码,append_tokens后调用generate_next_token()获取"logits"输出——这正是 README 在 accuracy_benchmark 总览 中提到的 GenAI v0.6 新 API(append_tokens取代了旧的compute_logits)。
  • 每个 chunk 的 logits 都立即.cpu().numpy()转移到系统内存保存,chunk 结束后立刻del释放 GPU 张量。

阶段二:加载模型 2 并逐块计算 KL

compute_kl_with_model2()(compute_kl_divergence.py)随后只加载第二个模型,复用阶段一保存的 logits:

  • 两套 logits 在序列维和词表维上分别取min裁剪对齐(min_seq、min_vocab),兼容不同 tokenizer 或不同输出长度;
  • 每个 chunk 通过torch.nn.functional.log_softmax(..., dim=2)计算 log 概率,再调用compute_kl_divergence()(compute_kl_divergence.py)按位置累加prob_ref * |log_probs_ref - log_probs_tar|并除以序列长度得到平均 KL;
  • 输出结果按 chunk 汇总,最终average_kl_divergence = total_kl / chunk_count。

内存与显存策略

  • 一次只加载一个模型,仅需容纳单个模型的显存(源码注释:8B 模型约 8GB);
  • logits 存于系统内存(约 2–4GB);
  • 每个阶段结束都调用cleanup_vram()(compute_kl_divergence.py):gc.collect()+torch.cuda.empty_cache()+torch.cuda.synchronize(),HF 模型还会先.to("cpu")再删除引用,确保"同一时刻只有一个模型在显存中"。

分块推理

默认max_context_length=4096,超长文本按 4096 token 切块(range(0, seq_len, max_context_length))。这既控制了单次前向的显存峰值,也天然适配长上下文模型;chunk 数量会记入结果 JSON 的total_chunks字段。

输出 JSON 结构

指定--output后,脚本会写入包含以下信息的 JSON(见 compute_kl_divergence.py):

{ "models": { "model1": {"path": "...", "type": "hf"}, "model2": {"path": "...", "type": "genai"} }, "device": "cuda", "total_chunks": 4, "max_context_length": 4096, "kl_divergence": { "total": 0.123456, "average": 0.030864 }, "chunk_results": [ {"chunk_id": 1, "begin_loc": 0, "end_loc": 4096, "kl_divergence": 0.0289} ], "timing": { "model1_extraction_seconds": 42.5, "model2_computation_seconds": 39.1, "total_seconds": 81.6 }, "computation_timestamp": "2026-09-26T00:00:00" }

包含模型元信息、分块明细、总体/平均 KL 与耗时统计,方便做量化前后、多后端的批量对比与存档。

与量化工作流的衔接

该工具在 Model-Optimizer 的 Windows 量化落地流程中处于"验证"环节:先用 genai_llm/quantize.py 对 ONNX GenAI 模型执行 INT4 AWQ(--algo awq_lite/rtn/rtn_dq等)等量化得到model.onnx,再用本工具比较 FP16 基线与量化模型的输出分布。其姊妹工具 perplexity_metrics 提供困惑度视角,而 KL 散度则关注逐 token 分布的漂移,两者互补。GenAI 模型由python -m onnxruntime_genai.models.builder从 HF 导出(参考 genai_llm README 的模型准备命令),导出的目录结构(含genai_config.json)正是本工具--model2_type genai期望的输入。

故障排查

1. CUDA 显存不足

报错示例:

RuntimeError: CUDA out of memory

解决方案:

  • HF 模型改用 CPU:--device cpu;
  • 关闭其他占用 GPU 的应用;
  • 需要时缩小批大小(修改代码中的分块逻辑);
  • 确认脚本同一时刻只加载一个模型(脚本已内置该机制,两阶段设计可保证)。

2. 执行提供者不匹配

提示信息:

[INFO] Comparing two GenAI models (same execution provider)

说明:该日志属于信息提示。GenAI vs GenAI 比较要求两个模型由同一执行提供者导出/运行(例如都基于 CUDA 包,或都基于 DirectML 包)。

解决办法:确保两个模型都通过相同的执行提供者创建(即用匹配的onnxruntime-genai-*包导出与加载)。

3. 其他补充建议

  • 若遇到 onnxruntime-genai 或 tokenizer 相关的模型特定问题,可尝试回退到旧版 GenAI(如onnxruntime-genai-directml0.4 配合transformers4.44),具体见 accuracy_benchmark 总览 的 Troubleshoot 章节;
  • 如需更多端到端任务指标(MMLU 等),参见同一目录下的 mmlu_benchmark.py 及其使用文档。

小结

KL Divergence Model Validation Toolkit 以"两阶段顺序式 + logits 驻留 CPU 内存 + 分块对齐裁剪"的设计,在最小显存占用下完成了 HF 与 GenAI(及同 EP 双 GenAI)之间的输出分布相似度定量评估。它适用于量化/剪枝验证、精度对比、框架与 EP 一致性测试四类典型场景,是 Model-Optimizer Windows 量化流程中连接"量化产出"与"精度回归"的关键校验工具。直接运行 compute_kl_divergence.py 即可复现文中的全部示例。

  • 人工智能
  • 大模型
  • 模型优化
  • 模型量化
  • 模型压缩

【免费下载链接】Model-Optimizer

A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning models for downstream deployment frameworks like TensorRT-LLM, TensorRT, vLLM, etc. to optimize inference speed.

项目地址:https://gitcode.com/GitHub_Trending/te/Model-Optimizer
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询