OpenSource-Hub

Model-Optimizer

ライブラリ

NVIDIA/Model-Optimizer

NVIDIA モデル最適化ライブラリ:量子化、プルーニング、蒸留により推論を加速。

概要

NVIDIAが提供する統合モデル最適化ライブラリ。量子化、プルーニング、蒸留、ニューラルアーキテクチャサーチ、投機的デコーディングなどの技術を統合。Hugging Face、PyTorch、ONNXのモデル入力をサポートし、圧縮後のチェックポイントをエクスポートでき、TensorRT-LLM、TensorRT、vLLM、SGLangなどの推論フレームワークにシームレスにデプロイ可能。

README プレビュー

\n\n\n\n# NVIDIA Model Optimizer\n\n[](https://nvidia.github.io/Model-Optimizer)\n[](https://pypi.org/project/nvidia-modelopt/)\n[](./LICENSE)\n\n[Documentation](https://nvidia.github.io/Model-Optimizer) |\n[Roadmap](https://github.com/NVIDIA/Model-Optimizer/issues/1699) |\n[Announcement Blogs](https://nvidia.github.io/Model-Optimizer/#announcements)\n\n\n\n______________________________________________________________________\n\n**NVIDIA Model Optimizer** (referred to as **Model Optimizer**, or **ModelOpt**) is a library comprising state-of-the-art model optimization [techniques](#techniques) including quantization, pruning, Neural Architecture Search (NAS), distillation, speculative decoding and sparsity to accelerate models.\n\n**[Input]** Model Optimizer currently supports inputs of a [Hugging Face](https://huggingface.co/), [PyTorch](https://github.com/pytorch/pytorch) or [ONNX](https://github.com/onnx/onnx) model.\n\n**[Optimize]** Model Optimizer provides Python APIs for users to easily compose the above model optimization techniques and export an optimized quantized checkpoint.\nModel Optimizer is also integrated with [NVIDIA Megatron-Bridge](https://github.com/NVIDIA-NeMo/Megatron-Bridge), [Megatron-LM](https://github.com/NVIDIA/Megatron-LM) and [Hugging Face Accelerate](https://github.com/huggingface/accelerate) for training required inference optimization techniques.\n\n**[Export for deployment]** Seamlessly integrated within the NVIDIA AI software ecosystem, the quantized checkpoint generated from Model Optimizer is ready for deployment in downstream inference frameworks like [SGLang](https://github.com/sgl-project/sglang), [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM/tree/main/examples/quantization), [TensorRT](https://github.com/NVIDIA/TensorRT), or [vLLM](https://github.com/vllm-project/vllm). The unified Hugging Face export API now supports both transformers and diffusers models.\n\n## Latest News\n\n- [2026/09/16] [**End-to-end W4A4 NVFP4 +

FAQ (5)

トラブル対応
なぜenable_kv_cache=Falseの場合、megatron_generateはVLMモデルに対して視覚的にグラウンディングされていない出力を生成するのですか?また、それを修正するにはどうすればよいですか?

根本原因: ModelOpt の modelopt.torch.utils.plugins.megatron_generate.megatron_generate において(0.46.0rc1 および main に影響)、視覚入力 pixel_values、image_grid_thw、image_sizes は step == 0 の条件のみでゲートされている。enable_kv_cache=False の場合、各デコードステップで増大していくトークンプレフィックス全体が再計算されるが、ステップ1以降は視覚埋め込みなしで実行されるため、画像プレースホルダートークンが一切置き換えられず、生成はエラーを出すことなく静かに視覚的根拠を失ったものになる(エラーは発生しない)。この問題は model.config.sequence_parallel=True の場合にも発生する。megatron_generate がその場合に自動的にキャッシュなしデコードへフォールバックするためである。

修正方法: 3つの視覚テンソルすべてについて、ゲート条件を step == 0 から以下に変更する:

replay_vision_inputs = inference_context is None or step == 0

この条件を pixel_values、image_grid_thw、image_sizes に適用し、推論コンテキスト(KVキャッシュ)が存在しない場合はプレフィックス全体の再計算のたびに視覚入力が渡され、KVキャッシュが有効な場合はプリフィル時のみ渡されるようにする。

検証結果: パッチ適用後、プレフィックスの logits はステップ間で不変となり(max|diff| = 0.0、argmax 一致率は未修正版の 0.529 に対して 1.000)、Qwen3-VL-8B-Instruct は無関係な内容をハルシネーションする代わりに、画像を正しく説明するようになった。

パッチを適用できない場合の回避策: (1) KVキャッシュを有効化し(enable_kv_cache=True)、視覚テンソルがプリフィル時にのみ必要となるようにする — sequence_parallel では不可能。または (2) 呼び出し前に、修正済みのゲート条件を適用したジェネレーター関数をメモリ上でモンキーパッチする。

参照 Issue #2189
トラブル対応
tied embeddingsを持つMegatronモデルでmtq.fold_weightを呼び出した際に発生する「AttributeError: 'NoneType' object has no attribute 'data'」を修正する方法

このクラッシュは、share_embeddings_and_output_weights=True を指定した Megatron-Core モデル(例:Qwen3-0.6B GPTModel)で発生します。これは、output_layer が weight = None を保持し(順伝播時に埋め込み層の重みを借用する)、一方で mtq.fold_weight が None ガードなしで保持されている重みを参照するためです。**修正:** PR #2140 を含むバージョンに TensorRT-Model-Optimizer をアップグレードしてください。この PR により、fold_weight は重みがテンソルでないペアをスキップするようになります。借用されたテンソルは埋め込みモジュールに属し、そこで畳み込まれるため、スキップは正しい動作です。**回避策(修正適用前):** mtq.fold_weight を呼び出す代わりに、ペアごとの重みの畳み込みを None ガード付きで手動で再実装してください。つまり、getattr(module, weight_name) が torch.Tensor でない場合はスキップします。これは NeMo-RL PR #3441 で採用されているアプローチです。なお、通常の QAT 順伝播パスではこのバグは発生しません。Megatron プラグインは、保持されている module.weight ではなく、線形関数に渡される重み引数を量子化するためです。保持されている属性を読み取るのは fold_weight のみです。

参照 Issue #2131
トラブル対応
なぜ NVIDIA ModelOpt Puzzletron は Mistral-Small-24B、gpt-oss-20b、Gemma-3 モデルの KV-cache メモリを誤って見積もるのですか?

Puzzletron の modelopt/torch/puzzletron/utils/misc.py にある calculate_kv_dim は、モデル config から head_dim を読み取るのではなく、head_size = n_embd // n_head を計算しています。head_dim != hidden_size / num_attention_heads となるモデルでは、すべての attention レイヤーの KV キャッシュコストが誤っています。Mistral-Small-24B(head_dim 128 に対し計算値 160)は 25% 過大評価され、gpt-oss-20b(head_dim 64 に対し計算値 45)は 30% 過小評価され、Gemma-3-12B(256 対 240)も影響を受けます。target_memory 制約下では、これによりソルバーは attention ブロックを誤ってプルーニングする方向に偏ります。修正(PR #2484):head 次元を優先順位 qk_head_dim(設定されている場合)→ モデル config の head_dim → フォールバック n_embd // n_head で解決します。例えば head_dim = getattr(config, 'head_dim', n_embd // n_head) とし、その後 kv_dim = 2 * num_kv_heads * head_dim とします。解決した同じ head 次元を calculate_additive_metrics の attention FLOP 推定にも適用します(以前は qk_head_dim or (n_embd // n_head) を使用していました)。Llama-3.x、Qwen2.5-7B、Qwen3-8B は、head_dim が hidden_size/num_attention_heads と等しいため影響を受けません。

参照 Issue #2482
トラブル対応
NVIDIA Model Optimizer で QAD(Quantization-Aware Distillation)トレーニングが精度を回復しないのはなぜか、また arXiv:2601.20088 の結果を再現するトレーニング設定は何か?

QADの精度回復が不十分な最も一般的な原因は、グローバルバッチサイズが小さすぎ、シーケンス長が短すぎることです(例:gbs=16、seq_len=8192では改善はほとんど見られません)。NVIDIAのメンテナーによると、論文の設定(例:AceReason Nemotron 1.1 7B)では以下が使用されています:

- seq_len = 32768、シーケンスパッキングを有効化
- global_batch_size = 100(パッキングされたサンプル約1024個に相当)
- warmup_steps = 10
- 200〜600ステップのみ学習(合計約1Bトークン)。十分なデータがある場合はサンプルを再利用しないこと
- 総トークン数:約1B
- 損失:forward KL、温度T=1

重要なポイント:
1. 蒸留データとしてモデルの元のSFTデータセットを使用すること — これは必須であると強調されています。
2. 検証損失だけでなく、実際の下流ベンチマークを実行して最適なチェックポイントを選択すること。
3. 論文ではNeMo/Megatron-LMパス(examples/llm_qad)が使用されており、これはHugging Face/FSDP2パス(examples/llm_qat)よりも活発にメンテナンスされています。再現にはMegatron-LMを使用してください。
4. 標準的なオプティマイザ設定(AdamW、lr ~1e-5、コサインスケジュール、grad clip 1.0、BF16)で問題ありません — 重要なのはデータとバッチ/シーケンスのスケールです。

参照 Issue #2002
トラブル対応
TensorRT Model Optimizer(INT8からFP8へのスケール変換)において、FP8量子化テンソルが±448ではなく±36の範囲しか取らないのはなぜですか?

modelopt/onnx/quantization/fp8.py では、INT8 スケールは np_fp8_scale = (np_scale * 448.0) / 127.0 によって変換されます。int8_scale = amax / 127 かつ fp8_scale = amax / 448 であるため、数学的に一貫した変換は fp8_scale = int8_scale * (127.0 / 448.0) です。現在の乗数はスケールを約3.5倍に膨張させるため、量子化されたテンソルは FP8 の ±448 範囲のうち約 ±36 しか占有せず、アクティベーションの爆発、飽和/クリッピング、レイヤー間の不均衡を引き起こす可能性があります。NVIDIA が推奨する回避策: INT8 スケールを変換せず、代わりに FP8 に対して直接 amax キャリブレーションを実行してください。これにより、膨張した値(現在のコード)とゼロへのアンダーフロー(安易な逆比率)の両方を回避できます。注: ソースには依然として scale * 448 / 127 が含まれているため、公式の修正が適用されるまではネイティブな FP8 amax キャリブレーションを優先してください。

参照 Issue #215