NVIDIA モデルオプティマイザーを用いたポストトレーニング量子化:モデル量子化の手法
NVIDIA は、GeForce RTX などのコンシューマー向け GPU で AI モデルの推論効率を向上させるため、FP8 フォーマットでの後処理量子化(PTQ)を実行する NVIDIA Model Optimizer の具体的な手順と機能を解説した技術記事を発表しました。
キーポイント
NVIDIA Model Optimizer の機能概要
ModelOpt ライブラリは、量子化、蒸留、プルーニングなど多様な最適化手法を統合し、Hugging Face や PyTorch 形式のモデルを入力として受け付けて効率的なチェックポイントを作成します。
FP8 フォーマットによる CLIP モデルの量子化
本記事では、OpenAI の CLIP モデルを FP8 フォーマットで後処理量子化(PTQ)する具体的なワークフローを紹介し、VRAM 使用量の削減と推論性能の向上を実証しています。
高度な量子化アルゴリズムとフォーマットのサポート
FP4, FP8, INT8, INT4 の高性能フォーマットに加え、SmoothQuant や AWQ などの先進アルゴリズムをサポートし、PTQ と QAT(量子化意識トレーニング)の両方に対応しています。
リソース制約環境での効率化
計算量とメモリ要件を下げつつモデル品質を維持することで、コンシューマー向けデバイスやリソースが限られた環境でも AI モデルを効率的に稼働させることが可能になります。
CLIP の多様な活用と進化
CLIP は画像とテキストの共有埋め込み空間を学習する基盤モデルであり、テキスト生成やマルチモーダル LLM のバックボーンとして広く再利用されています。
ModelOpt による PTQ 評価タスク
FP8 量子化の実行には、CLIP_benchmark から CIFAR-100、ImageNet-1k、MS-COCO キャプションの 3 つのゼロショットタスクを精度評価に使用します。
量子化レシピの準備要件
モデル最適化には、Laion2B でトレーニングされた CLIP-ViT-L-14 モデルと、MS-COCO から抽出した 10K サンプルのキャリブレーションデータセットが必要です。
影響分析・編集コメントを表示
影響分析
この記事は、大規模モデルをコンシューマー向けハードウェアで動作させるための具体的な技術的アプローチを示しており、開発者がリソース制約のある環境でも高性能な AI アプリケーションを構築する際の指針となります。特に FP8 量子化の普及と Model Optimizer の活用により、エッジデバイスにおける AI の実用性がさらに高まることが期待されます。
編集コメント
コンシューマー向け GPU で大規模モデルを動かしたい開発者にとって、FP8 量子化の実装手順が明確に示された非常に実用的なガイドです。NVIDIA のツールチェーンを活用すれば、リソース制約下でも高精度な推論が可能になるため、エッジ AI 開発のハードルを下げる内容と言えます。
モデル量子化は、NVIDIA GeForce RTX GPU などの消費者向けデバイス上で VRAM の使用量を削減し、推論パフォーマンスを向上させる効果的な手法です。計算量とメモリ要件を下げつつモデルの品質を維持することで、量子化はリソース制約のある環境において AI モデルがより効率的に動作するのを助けます。
この投稿では、post-training quantization (PTQ) 手法を用いて NVIDIA Model Optimizer を使用し、CLIP モデルを FP8 フォーマットで量子化する方法について解説します。モデル量子化に関する一般的な紹介については、Model Quantization: Concepts, Methods, and Why It Matters をご覧ください。
NVIDIA Model Optimizer とは何か?
NVIDIA Model Optimizer(ModelOpt)ライブラリは、AI モデルを圧縮・高速化するための最先端のモデル最適化技術を組み込んでいます。これらの技術には、量子化、蒸留、プルーニング、推測的デコーディング、スパース性が含まれます。ModelOpt は Hugging Face、PyTorch、または ONNX フォーマットのモデルを入力として受け付け、ユーザーが異なる最適化技術を容易に組み合わせて最適化されたチェックポイントを生成できるよう Python API を提供します。
ModelOpt は、FP4、FP8、INT8、INT4 といった高性能な量子化フォーマットや、SmoothQuant、AWQ、SVDQuant、Double Quantization などの高度なアルゴリズムをサポートしています。また、PTQ と 量子化意識トレーニング (QAT) の両方に対応しています。
CLIP とは何か?
OpenAI が 2021 年に発表した CLIP(Contrastive Language-Image Pretraining)は、大規模な画像テキストペアに対する対照学習を通じて、画像とテキストの共通埋め込み空間を学習する基盤となるビジョン言語モデル (VLM) です。意味的に整合した表現を生成できる能力により、現代のマルチモーダルシステムにおける中核的な構成要素となっています。
CLIP のテキストエンコーダは、テキストから画像への合成(例:Stable Diffusion)やテキストから動画への合成(例:AnimateDiff)のための条件付けモジュールとして広く再利用されています。一方、ビジョンエンコーダは、LLaVA などのマルチモーダル LLM や、OWL-ViT のようなオープンボキャブラリ知覚モデルにおける視覚的なバックボーンとして機能しています。後継となる OpenCLIP や SigLIP はデータ規模の拡大と目的関数の洗練を行っていますが、デュアルエンコーダによる対照学習のパラダイムは維持されています。
量子化レシピ
本記事では、ModelOpt を用いて CLIP モデルの量子化を実行し、そのプロセスを理解するためのステップバイステップガイドとして、以下の量子化レシピを使用します。
まず、以下に示すように対応するモデルとデータセットを準備してください:
- ベース CLIP モデル: CLIP-ViT-L-14-laion2B-s32B-b82K
- 量子化用のキャリブレーションデータセット:MS-COCO から抽出した 10K サブセット
- モデル精度評価タスクは、CLIP_benchmark の以下の 3 つに焦点を当てます:
cifar100 (ゼロショット分類)
- imagenet1k (ゼロショット分類)
- mscoco_captions (ゼロショット検索)
ModelOpt を用いた PTQ の実行方法
以下のコードサンプルは、ModelOpt を使用して CLIP モデルを FP8 で PTQ(Post-Training Quantization:ポストトレーニング量子化)を実行する方法を示しています:
import torch
from torch.utils.data import DataLoader, Subset
from transformers import CLIPModel, CLIPTokenizer, CLIPImageProcessor
from transformers.models.clip.modeling_clip import CLIPAttention
import modelopt.torch.opt as mto
import modelopt.torch.quantization as mtq
from modelopt.torch.quantization.plugins.diffusion.diffusers import _QuantAttention
FP8_CFG = {
"quant_cfg": {
"*weight_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*input_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*[qkv]_bmm_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*bmm2_output_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"default": {"enable": False},
},
"algorithm": "max",
}
mto.enable_huggingface_checkpointing()
mtq.QuantModuleRegistry.register({CLIPAttention: "CLIPAttention"})(_QuantAttention)
model = CLIPModel.from_pretrained(args.model_ckpt, attn_implementation="sdpa").half().eval().cuda()
tokenizer = CLIPTokenizer.from_pretrained(args.model_ckpt)
processor = CLIPImageProcessor.from_pretrained(args.model_ckpt)
calib_set = Subset(CLIP_COCO_dataset(ANN, IMG_DIR, tokenizer, processor), range(8192))
loader = DataLoader(calib_set, batch_size=512, num_workers=4)
def calibrate(m):
for img, txt in loader:
m.get_text_features(input_ids=txt.cuda())
m.get_image_features(pixel_values=img.cuda())
q_model = mtq.quantize(model, FP8_CFG, forward_loop=calibrate)
q_model.save_pretrained(ckpt_path)
mtq.print_quant_summary(q_model)
FP8_CFG は単なるレシピの一つに過ぎません。これは重みと活性化の両方に FP8 を使用する W8A8、テンソルごとの量子化、静的量子化であり、単純な AbsMax アルゴリズムで較正されています。ModelOpt では、チャネルごと/ブロックごとの粒度、動的活性化量子化、AWQ や GPTQ などの高度な較正アルゴリズムなど、さらに多くの選択の次元をサポートしています。
詳細な設定スキーマについては、ModelOpt 量子化ガイドを参照してください。量子化設定内のハイパーパラメータは必要に応じて常に微調整可能であり、最適な値を見つけるには通常、いくつかの反復処理が必要です。
mtq.quantize が返された後、CLIP の Linear レイヤーにはすべて重みと活性化の量子化器が割り当てられていますが、アテンションブロックはまだ変更されていません。これは、マルチヘッドアテンションが torch.nn.functional.scaled_dot_product_attention(関数型 API)に委譲しており、ModelOpt モジュールウォーカーではこれを単独でインターセプトできないためです。
アテンションを量子化の対象範囲に含めるために、CLIPAttention に対して量子化された代替実装を登録します:
mtq.QuantModuleRegistry.register({CLIPAttention: "CLIPAttention"}) (_QuantAttention)
各 CLIPAttention インスタンスは、ModelOpt diffusers プラグインから _QuantAttention にアップグレードされます。その forward パス内では、_QuantAttention が SDPA(Scaled Dot Product Attention)呼び出しを透過的にインターセプトし、融合されたカーネルの周囲に 4 つの量子化器を挿入します:
- q_bmm_quantizer、k_bmm_quantizer、v_bmm_quantizer は、Q / K / V テンソルがカーネルに入る前に投影されたテンソルをラップします。
- bmm2_output_quantizer は、カーネル出力(softmax @ V)が out_proj に流れる前にそれをラップします。
これにより、アテンション機構全体で適切な量子化が保証されます。
精度をある程度回復させるためには、mtq.disable_quantizer を使用して一部の量子化器を無効化することがよく推奨されます。この関数は、モジュール名を入力として受け取る関数を引数として取ります。正規表現や文字列マッチングを使用することで、無効化するレイヤーを選択できます。以下の例では、CLIP モデルの patch_embedding レイヤー内の量子化器が無効化されています。
import re
def filter_func(name):
pattern = re.compile(
r".*(patch_embedding).*"
)
return pattern.match(name) is not None
mtq.disable_quantizer(q_model, filter)
CLIP ベンチマーク評価
保存された ModelOpt チェックポイントは、任意のダウンストリーム評価スクリプトに復元できます。詳細は ModelOpt モデルの復元 を参照してください。量子化された CLIP チェックポイントは、3 つのベンチマークで評価されました:ゼロショット分類(CIFAR-100, ImageNet-1k)およびゼロショット検索(MS-COCO Captions)。FP16 の CLIP モデルがベースラインとして使用されます。
image*図 1. FP16 ベースラインと FP8-PTQ 量子化モデルの CLIP モデル品質比較*
評価結果に基づくと、CLIP-FP8 量子化モデルは CLIP-FP16 モデルと比較して同等の品質を示します。特筆すべきは、パッチ埋め込みレイヤーで量子化器を無効化した場合、モデル品質に対する量子化の影響がほぼ無視できるほど小さくなることです。
ModelOpt PTQ フローの内部
この段階では、モデルの実データ型は変更されていないため、「疑似量子化」を扱うことになると理解することが重要です。代わりに、挿入された量子化器は観測者として機能し、モデルを元の浮動小数点形式のままに保ちつつ、量子化の影響をシミュレートします。
この疑似量子化プロセスは、主に 2 つの重要な方法で動作します:
- 統計情報の収集:量子化器は、データが通過する際にテンソルの統計情報(最小値や最大値など)を収集します。これらの統計情報は、スケーリング係数などの最適な量子化パラメータを計算するために使用されます。
- 量子化シミュレーション:量子化器は、ネットワークを流れるテンソルに対して量子化後再量子化(QDQ: quantize-then-dequantize)演算を実行します。これは低精度計算のシミュレーションに過ぎず、実際の高速化やメモリ削減効果は、モデルを NVIDIA TensorRT などのデプロイメントフレームワークへエクスポートすることで初めて達成されます。
このシミュレーションが重要な理由は、実際の量子化を行う前にモデルの精度を評価できるからです。量子化器は、下流の推論フレームワークで展開された量子化モデルで発生するのと同じ丸め処理や精度制限を適用するため、以下が可能になります:
- デプロイ前の精度への影響を測定
- 異なる量子化構成を実験
- 特別な処理が必要な問題のあるレイヤーを特定
一般的に、ModelOpt PTQ フローは以下の 6 つの段階に従います:
- 準備:モデルの重みおよび/または活性化値の周囲に量子化モジュールを挿入するための量子化設定を設定します。
- キャリブレーション:代表データの小バッチをモデルに対して順方向伝播させ、各量子化器が統計情報(例えば、活性化値の最大値)を収集し、スケーリング係数を導出できるようにします。
- 疑似量子化:量子化器は現在、浮動小数点演算内で Q → DQ の往復処理を適用し、モデルが FP16/BF16 で実行されている間も、ターゲット形式の精度低下を忠実にシミュレートします。
- 評価:保持された評価セット上で精度を測定し、量子化されていないベースラインと比較します。
- 反復:許容できない誤差がある場合は、量子化設定(粒度、アルゴリズム、量子化層)を調整するか、敏感な層に対する量子化を無効にして再キャリブレーションを行います。
- エクスポートとデプロイ:精度が許容範囲内になったら、疑似量子化された重みを真の低精度形式に圧縮し、ダウンストリームエンジン用のチェックポイントとしてエクスポートします。今回のケースでは、PyTorch チェックポイントを ONNX 形式でエクスポートし、TensorRT で推論を実行します。速度向上とメモリ削減効果はここで得られます。
image*Figure 2. ModelOpt PTQ workflow*
QAT は、量子化状態を固定したままモデルの重みを微調整することで、量子化によって引き起こされる品質の低下を回復します。これは PTQ よりも計算コストがかかりますが、量子化されたモデルの品質をより効果的に向上させることができます。詳細については、ModelOpt の例をご覧ください。
NVIDIA Model Optimizer によるスタートガイド
本記事では NVIDIA Model Optimizer を紹介し、CLIP モデルを FP8 に量子化する実践的なコード例を通じて、典型的なポストトレーニング量子化ワークフローを実演しました。3 つの評価データセットにわたる結果は、FP8 量子化がモデルの品質を維持しつつ、より効率的な展開パスを実現できることを示しています。
ご自身のモデルで ModelOpt の使用を開始する準備はできましたか?以下のワークフローに従ってください:モデルとキャリブレーションデータの準備、量子化設定の設定、キャリブレーションの実行、タスク固有の品質指標を用いた量子化モデルの検証、ModelOpt チェックポイントの保存および復元。
追加のワークフローを探求したり、ご自身のユースケースに合わせて ModelOpt を適応させたりしたい場合は、ModelOpt のドキュメントをご覧ください。
原文を表示
Model quantization is an effective method to reduce VRAM usage and improve inference performance on consumer devices such as NVIDIA GeForce RTX GPUs. By lowering computational and memory requirements while preserving model quality, quantization helps AI models run more efficiently in resource-constrained environments.
This post walks through how to use NVIDIA Model Optimizer to quantize a CLIP model in FP8 format with the post-training quantization (PTQ) method. For a general introduction to model quantization, see Model Quantization: Concepts, Methods, and Why It Matters.
What is NVIDIA Model Optimizer?
The NVIDIA Model Optimizer (ModelOpt) library incorporates state-of-the-art model optimization techniques to compress and accelerate AI models. These techniques include quantization, distillation, pruning, speculative decoding, and sparsity. ModelOpt accepts Hugging Face, PyTorch, or ONNX format models as input and provides Python APIs for users to easily combine different optimization techniques to produce optimized checkpoints.
ModelOpt supports highly performant quantization formats such as FP4, FP8, INT8, and INT4, and advanced algorithms including SmoothQuant, AWQ, SVDQuant, and Double Quantization. It supports both PTQ and quantization-aware training (QAT).
What is CLIP?
CLIP (Contrastive Language-Image Pretraining), introduced by OpenAI in 2021, is a foundation vision language model (VLM) that learns a shared embedding space for images and text through contrastive learning on large image-text pairs. Its ability to produce semantically aligned representations has made it a core building block across modern multimodal systems.
The CLIP text encoder is widely reused as a conditioning module for text-to-image (Stable Diffusion, for example) and text-to-video (AnimateDiff, for example) synthesis. Its vision encoder serves as the visual backbone in multimodal LLMs, such as LLaVA, and open-vocabulary perception models, such as OWL-ViT. Successors such as OpenCLIP and SigLIP scale the data and refine the objective but preserve the dual-encoder contrastive paradigm.
Quantization recipe
The following quantization recipe is used in this post as a step-by-step guide for running CLIP model quantization with ModelOpt to understand how the process works.
First, prepare the corresponding models and datasets as shown below:
- Base CLIP model: CLIP-ViT-L-14-laion2B-s32B-b82K
- Calibration dataset for quantization: 10K subset from MS-COCO
- Model accuracy evaluation tasks focus on three from the CLIP_benchmark
cifar100 (zero-shot classification)
- imagenet1k (zero-shot classification)
- mscoco_captions (zero-shot retrieval)
How to run PTQ with ModelOpt
The following code sample shows how to run PTQ for the CLIP model in FP8 using ModelOpt:
import torch
from torch.utils.data import DataLoader, Subset
from transformers import CLIPModel, CLIPTokenizer, CLIPImageProcessor
from transformers.models.clip.modeling_clip import CLIPAttention
import modelopt.torch.opt as mto
import modelopt.torch.quantization as mtq
from modelopt.torch.quantization.plugins.diffusion.diffusers import _QuantAttention
FP8_CFG = {
"quant_cfg": {
"*weight_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*input_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*[qkv]_bmm_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"*bmm2_output_quantizer": {"num_bits": (4, 3), "axis": None, "trt_high_precision_dtype": "Half"},
"default": {"enable": False},
},
"algorithm": "max",
}
mto.enable_huggingface_checkpointing()
mtq.QuantModuleRegistry.register({CLIPAttention: "CLIPAttention"})(_QuantAttention)
model = CLIPModel.from_pretrained(args.model_ckpt, attn_implementation="sdpa").half().eval().cuda()
tokenizer = CLIPTokenizer.from_pretrained(args.model_ckpt)
processor = CLIPImageProcessor.from_pretrained(args.model_ckpt)
calib_set = Subset(CLIP_COCO_dataset(ANN, IMG_DIR, tokenizer, processor), range(8192))
loader = DataLoader(calib_set, batch_size=512, num_workers=4)
def calibrate(m):
for img, txt in loader:
m.get_text_features(input_ids=txt.cuda())
m.get_image_features(pixel_values=img.cuda())
q_model = mtq.quantize(model, FP8_CFG, forward_loop=calibrate)
q_model.save_pretrained(ckpt_path)
mtq.print_quant_summary(q_model)
FP8_CFG is just one recipe: W8A8 (FP8 on both weights and activations), per-tensor, static quantization, calibrated with the simple AbsMax algorithm. ModelOpt supports many more dimensions of choice (per-channel / block-wise granularity, dynamic activations quantization, advanced calibration algorithms such as AWQ / GPTQ, and many more).
For the detailed configuration schema, see the ModelOpt quantization guide. The hyperparameters in the quantization configuration can always be fine-tuned as needed, and finding the optimal values usually requires some iteration.
After mtq.quantize returns, CLIP’s Linear layers all carry weight and activation quantizers—but the attention blocks are still untouched. This is because multi-head attention dispatches to torch.nn.functional.scaled_dot_product_attention, a functional API that the ModelOpt module walker cannot intercept on its own.
To bring attention into the quantization scope, register a quantized replacement for CLIPAttention:
mtq.QuantModuleRegistry.register({CLIPAttention:
"CLIPAttention"})(_QuantAttention)
Each CLIPAttention instance is now upgraded to _QuantAttention from the ModelOpt diffusers plugin. Inside its forward pass, _QuantAttention transparently intercepts the SDPA call and inserts four quantizers around the fused kernel:
- q_bmm_quantizer, k_bmm_quantizer, v_bmm_quantizer wrap the projected Q / K / V tensors before they enter the kernel
- bmm2_output_quantizer wraps the kernel output (softmax @ V) before it flows into out_proj
This ensures proper quantization throughout the attention mechanism.
To restore some accuracy, it is often advised to disable some of the quantizers using mtq.disable_quantizer. This takes a function as input, where the function itself takes a module name as input. By using regex or string matching, you can select the layers to disable. In the following example, the quantizers are disabled in the patch_embedding layer of the CLIP model.
import re
def filter_func(name):
pattern = re.compile(
r".*(patch_embedding).*"
)
return pattern.match(name) is not None
mtq.disable_quantizer(q_model, filter)
CLIP benchmark evaluation
The saved ModelOpt checkpoint can be restored into any downstream evaluation script. For details, reference Restoring ModelOpt Models. The quantized CLIP checkpoint was evaluated on three benchmarks: zero-shot classification (CIFAR-100, ImageNet-1k) and zero-shot retrieval (MS-COCO Captions). The FP16 CLIP model serves as the baseline.

Based on the evaluation results, the CLIP-FP8 quantized model demonstrates comparable quality to the CLIP-FP16 model. Notably, when quantizers are disabled in the patch embedding layer, the impact of quantization for model quality becomes negligible.
Inside the ModelOpt PTQ flow
It’s important to understand that this stage involves working with “fake quantization” because the actual data type of the model hasn’t changed. Instead, these inserted quantizers act as observers that simulate the effects of quantization while keeping the model in original floating-point format.
The fake quantization process works in two key ways:
- Statistics collection: The quantizers collect tensor statistics (minimum and maximum values, for example) as data passes through them. These statistics are used to calculate optimal quantization parameters such as scaling factors.
- Quantization simulation: The quantizers perform a quantize-then-dequantize (QDQ) operation on tensors flowing through the network. It only simulates the low-precision computation and real speedup and memory saving should be achieved by exporting the model to deployment frameworks such as NVIDIA TensorRT.
This simulation is crucial because it enables you to evaluate the model’s accuracy before committing to actual quantization. The quantizers apply the same rounding and precision limitations that would occur in the deployed quantized model with downstream inference frameworks, so you can:
- Measure accuracy impacts before deployment
- Experiment with different quantization configurations
- Identify problematic layers that might need special handling
In general, the ModelOpt PTQ flow follows six stages:
- Prepare: Set quantization config to insert quantizer modules around the model’s weights and/or activations.
- Calibrate: Forward a small batch of representative data through the model so each quantizer can collect statistics (for example, activation amax) and derive its scaling factor.
- Fake quantization: Quantizers now apply a Q → DQ round-trip in floating point, faithfully simulating the precision loss of the target format while the model still runs in FP16/BF16.
- Evaluate: Measure accuracy on a held-out evaluation set and compare against the unquantized baseline.
- Iterate: If the gap is unacceptable, adjust the quantization configuration (granularity, algorithm, quantized layers), disable quantization for sensitive layers, and recalibrate.
- Export and deploy: Once the accuracy is acceptable, the fake quantized weights are compressed into their true low-precision form and exported as a checkpoint for downstream engines. In our case, we export the PyTorch checkpoint to ONNX and run inference with TensorRT. The speedups and memory savings will happen there.

QAT recovers quantization-induced quality loss by fine-tuning the model weights with frozen quantizer states. It is more compute-intensive than PTQ but can better improve quantized model quality. For more details, see the ModelOpt examples.
Get started with NVIDIA Model Optimizer
This post introduced NVIDIA Model Optimizer and demonstrated a typical post-training quantization workflow by quantizing the CLIP model to FP8 with a practical code example. The results across three evaluation datasets show that FP8 quantization can preserve model quality while enabling a more efficient deployment path.
Ready to start using ModelOpt with your own models? Follow this workflow: prepare the model and calibration data, set quantization configuration, calibrate, validate the quantized model against task-specific quality metrics, save and restore ModelOpt checkpoints.
To explore additional workflows and adapt ModelOpt for your own use cases, see the ModelOpt documentation.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み