- 人工智能
- 大模型
- 模型优化
- 模型量化
- 模型压缩
【免费下载链接】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.
导读
本文围绕 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)的主要应用场景包括:
- 模型优化验证:验证经过量化、剪枝等优化后的模型是否保持了输出质量;
- 框架对比:比较 Hugging Face 模型与 ONNX Runtime GenAI 模型的输出差异;
- 精度分析:评估 FP16、INT4、INT8 等不同精度模型的输出差异;
- 执行提供者测试:测试 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,保证所有模型在完全相同的评估语料上比较;
- 数据集通过 HuggingFace
datasets库自动加载与预处理。源码中get_wikitext2()(compute_kl_divergence.py)执行load_dataset("wikitext", "wikitext-2-raw-v1", split="test"),并将所有样本以双换行符拼接为一段连续文本用于后续分块推理。
安装与环境准备
1. 安装基础依赖
pip install -r requirements.txtrequirements.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/cu1292. 安装 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 |
可选参数
| 参数 | 说明 | 默认值 |
|---|---|---|
--device | HF 模型推理设备 | 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
- Hub 标识符:
- 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.
相关推荐
llama.cpp Perplexity 工具实战:困惑度与 KL 散度驱动的量化模型质量评估
llama.cpp Perplexity 工具实战:困惑度与 KL 散度驱动的量化模型质量评估 llama.cpp 仓库内置的 llama perplexity
人工智能大模型模型推理服务推理引擎本地部署后端从困惑度到KL散度:llama.cpp量化模型输出质量全面测评指南
从困惑度到KL散度:llama.cpp量化模型输出质量全面测评指南 你是否曾为选择合适的llama.cpp量化模型而烦恼?明明Q4_0体积更小,Q5_K_M却号
人工智能大模型模型推理服务推理引擎本地部署后端PowerInfer llama-perplexity 模型评测指南:Perplexity、KL 散度与量化质量评估
PowerInfer llama perplexity 模型评测指南:Perplexity、KL 散度与量化质量评估 本文是一份围绕 PowerInfer 仓库
人工智能大模型推理引擎本地部署
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考