重み圧縮#
重み圧縮は、特にメモリー要件が高いモデルの効率を高めるための手法です。この方法により、大規模言語モデル (LLM) にとって重要な要素であるモデルのメモリー・フットプリントが削減されます。
重み圧縮は、特にメモリー要件が高いモデルの効率を高めるための手法です。この方法により、大規模言語モデル (LLM) にとって重要な要素であるモデルのメモリー・フットプリントが削減されます。
重みと活性化が量子化される完全なモデル量子化とは異なり、ニューラル・ネットワーク圧縮フレームワーク (NNCF) の重み圧縮はモデルの重みのみを対象とします。このアプローチにより、活性化を浮動小数点数のままにしておくことができ、モデル精度の大部分を維持しながら、速度を向上させ、サイズを縮小することができます。
サイズの縮小は特に大規模なモデルで顕著です。例えば、70 億のパラメーターを持つ Llama 2 モデルは、4 ビットの重み圧縮を使用して約 25 GB から 4 GB に縮小できます。より小さいモデル (つまり、1B 未満のパラメーター) の場合、重みの圧縮によって、より大きなモデルよりも精度が低下する可能性があります。
LLM やその他のモデルは、推論中に重みを保存する大量のメモリーを必要とするため、重み圧縮により次の利点を得られます:
デバイスのメモリーに格納できない大規模なモデルの推論を可能にします。
ストレージとメモリーのオーバーヘッドが削減され、モデルがより軽量になり、デプロイ時のリソース消費が少なくなります。
線形レイヤーなどの重みを使用した演算を行う際のメモリー・アクセス・レイテンシーを短縮することで、推論パフォーマンスを向上させます。重みが小さくなるため、メモリーからの読み込みが速くなります。
量子化とは異なり、アクティベーションの値の範囲を較正するサンプルデータは必要ありません。
現在、NNCF は、主に LLM の最適化向けに設計された圧縮方法として、8 ビットおよび 4 ビット整数データタイプへの重み量子化を提供しています。
モデルの重みを圧縮#
8 ビット重み量子化方法は、モデルサイズの縮小と精度の維持のバランスを実現し、通常、トランスフォーマー・ベースのモデルのパフォーマンスを大幅に向上させます。8 ビット圧縮重みを持つモデルは、サポートされる CPU および GPU プラットフォームの大部分でパフォーマンスの利点が得られます。デフォルトでは、重みは “INT8_ASYM” モードに非対称に圧縮されます。
以下のコードは、NNCF を使用して OpenVINO IR モデルの重みを非対称 8 ビット量子化する方法を示しています:
from nncf import compress_weights
...
model = compress_weights(model) # モデルは openvino.Model オブジェクト
これで、モデルをコンパイルして推論する準備が整いました。圧縮形式で保存することもできるため、バイナリーファイルのサイズが小さくなります。
4 ビット重み量子化 - これは、INT4-INT8 混合精度重み量子化を表し、INT4 が主精度、非対称 INT8 がバックアップ精度とみなされます。通常、これによりモデルサイズがさらに小さくなり、推論レイテンシーは低くなりますが、モデルによっては精度の低下が大きくなります。
以下のコードは、NNCF を使用して OpenVINO IR モデルの重みを 4 ビット量子化する方法を示しています:
from nncf import compress_weights, CompressWeightsMode
...
model = compress_weights(model, mode=CompressWeightsMode.INT4_SYM,
group_size=128, ratio=0.8) # モデルは openvino.Model オブジェクト
以下の表は、メモリー削減、速度向上、精度低下の観点から、各圧縮タイプの利点とトレードオフをまとめたものです。
メモリー・リダクション |
レイテンシーの改善 |
精度の低下 |
|
---|---|---|---|
INT8 非対称 |
低 |
中 |
低 |
INT4 対称 |
高 |
高 |
高 |
INT4 非対称 |
高 |
中 |
中 |
INT4 メソッドには、最適化後にさまざまなパフォーマンスと精度のトレードオフを制御するパラメーターがあります:
mode
- 最適化モードには対称と非対称の 2 つがあります。対称圧縮 -
INT4_SYM
INT4 対称モードでは、重みをゼロポイントなしで対称的に符号付き 4 ビット整数に量子化します。このモードは INT8_ASYM よりも高速なので、速度とサイズの削減が精度よりも優先される状況に最適です。
from nncf import compress_weights from nncf import CompressWeightsMode compressed_model = compress_weights(model, mode=CompressWeightsMode.INT4_SYM)
非対称圧縮 -
INT4_ASYM
INT4 非対称モードも符号なし 4 ビット整数を使用しますが、固定されていないゼロポイントを使用して重みを非対称に量子化します。このモードでは、対称モードと比較して、精度を高めるために速度がわずかに低下します。このモードは、精度の低下を最小限に抑えることが重要で、INT8 よりも高速なパフォーマンスが求められる場合に役立ちます。
from nncf import compress_weights from nncf import CompressWeightsMode compressed_model = compress_weights(model, mode=CompressWeightsMode.INT4_ASYM)
group_size
- 同じ量子化パラメーターを共有する重みのグループのサイズを制御します。共有量子化パラメーターは、レイヤー間で量子化および逆量子化されるときに、活性化値の計算を高速化するのに役立ちます。ただし、精度が低下する可能性があります。次のグループサイズが推奨されます:128
、64
、32
(128
はデフォルト値)。小さなグループサイズ: より正確なモデルになりますが、モデルのフットプリントが増加し、推論速度が低下します。
大きなグループサイズ: 推論が高速化され、モデルが小さくなりますが、精度が低下する可能性があります。
ratio
- モデル内の INT4 圧縮レイヤーと INT8_ASYM 圧縮レイヤーの比率を制御します。比率は 0 から 1 までの小数です。例えば、0.8 は、レイヤーの 80% が INT4 に圧縮され、残りが INT8_ASYM 精度に圧縮されることを意味します。比率のデフォルト値は 1 です。高い比率 (INT4 以上): モデルのサイズが小さくなり、推論速度が向上しますが、精度の低下が大きくなる可能性があります。
低い比率 (INT8_ASYM 以上): 精度は向上しますが、モデルのサイズが大きくなり、推論が遅くなる可能性があります。
この例では、モデルのレイヤーの 90% がグループサイズ 64 で非対称に INT4 に量子化されます:
from nncf import compress_weights, CompressWeightsMode #例: INT4_ASYM モード、グループサイズ 64、INT4 比率 90% で重みを圧縮 compressed_model = compress_weights( model, mode=CompressWeightsMode.INT4_ASYM, group_size=64, ratio=0.9, )
dataset
- データを意識した重み圧縮のためのキャリブレーション・データセット。これにはいくつかの圧縮オプションがあります。例えば、一部のタイプのsensitivity_metric
では精度の選択にデータを使用できます。sensitivity_metric
- ビット幅選択アルゴリズムにおける圧縮レイヤーの感度を推定するためのメトリックを制御します。一部のメトリックでは、データセットの提供が必要です。次のタイプがサポートされます:nncf.SensitivityMetric.WEIGHT_QUANTIZATION_ERROR
- 反転 8 ビット量子化ノイズとして計算されるデータフリー・メトリック。このメトリックの最高値を持つ重みは、チャネルごとに 8 ビットに正確に量子化されます。これらの重みを 8 ビットのままにして、残りのレイヤーをグループごとに 4 ビットに量子化します。グループ単位のほうがチャネル単位よりも正確であるため、精度が低下することはありません。nncf.SensitivityMetric.HESSIAN_INPUT_ACTIVATION
- データセットを必要とします。8 ビット量子化ノイズの L2 ノルムを乗算したレイヤーごとの量子化誤差に対する重みの平均ヘシアントレース。nncf.SensitivityMetric.MEAN_ACTIVATION_VARIANCE
- データセットを必要とします。レイヤーの入力の平均分散に、反転 8 ビット量子化ノイズを乗算したもの。nncf.SensitivityMetric.MAX_ACTIVATION_VARIANCE
- データセットを必要とします。レイヤーの入力の最大分散に、反転 8 ビット量子化ノイズを乗算したもの。nncf.SensitivityMetric.MEAN_ACTIVATION_MAGNITUDE
- データセットを必要とします。レイヤーの入力の平均値に、反転 8 ビット量子化ノイズを乗算したもの。
all_layers
- モデル内の最初と最後のレイヤーを含む、すべての全結合レイヤーと埋め込みレイヤーの INT4 重み量子化を有効にするブール・パラメーター。awq
- AWQ メソッドで正確な INT4 重み量子化を可能にするブール・パラメーター。すべてのレイヤーの重みが 4 ビットに量子化されている場合に役立ちます。この方法を活性化の動的量子化と併用すると、精度が低下する場合があります。データセットを必要とします。
データを意識した重み圧縮については、次の例を参照してください。
以下の例は、OpenVINO IR に適用されたデータフリーの 4 ビット重み量子化を示しています。例を試す前に、次のコマンドを実行して、環境に Optimum Intel がインストールされていることを確認してください:
pip install optimum[openvino,nncf]
最初の例では、Optimum Intel API を使用して事前トレーニング済みの Hugging Face モデルを読み込み、NNCF を使用して INT4 に圧縮してから、テキストフレーズを使用して推論を実行します。
モデルが Hugging Face から提供され、Optimum でサポートされている場合は、Optimum Intel API を使用して重みの圧縮を実行するほうが簡単な場合があります。圧縮タイプは、load_in_8bit=True
または load_in_4bit=True
パラメーターを使用してモデルをロードするときに指定されます。2 番目の例では、NNCF の代わりに Optimum Intel の重み圧縮 API を使用して、モデルを INT8_ASYM に圧縮します。
from nncf import compress_weights, CompressWeightsMode
from optimum.intel.openvino import OVModelForCausalLM
from transformers import AutoTokenizer, pipeline
# Hugging Face からモデルをロード
model_id = "HuggingFaceH4/zephyr-7b-beta"
model = OVModelForCausalLM.from_pretrained(model_id, export=True)
# INT4 対称に圧縮
model.model = compress_weights(model.model, mode=CompressWeightsMode.INT4_SYM)
# 推論
tokenizer = AutoTokenizer.from_pretrained(model_id)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
phrase = "The weather is"
results = pipe(phrase)
print(results)
from optimum.intel.openvino import OVModelForCausalLM
from transformers import AutoTokenizer, pipeline
# Hugging Face からモデルを読み込み圧縮
model_id = "HuggingFaceH4/zephyr-7b-beta"
model = OVModelForCausalLM.from_pretrained(model_id, export=True,
load_in_8bit=True)
# 推論
tokenizer = AutoTokenizer.from_pretrained(model_id)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
phrase = "The weather is"
results = pipe(phrase)
print(results)
圧縮モデルのエクスポートと読み込み##
モデルを NNCF または Optimum Intel で圧縮したら、保存してエクスポートし、将来のセッションやデプロイ環境で使用することができます。圧縮プロセスには時間がかかるため、最初の推論までの時間を短縮するには、モデルを一度圧縮して保存し、後で圧縮したモデルをロードすることを推奨します。
# 後でより速く読み込むために圧縮モデルを保存
model.save_pretrained("zephyr-7b-beta-int4-sym-ov")
tokenizer.save_pretrained("zephyr-7b-beta-int4-sym-ov")
# 保存したモデルを読み込む
model = OVModelForCausalLM.from_pretrained("zephyr-7b-beta-int4-sym-ov")
tokenizer = AutoTokenizer.from_pretrained("zephyr-7b-beta-int4-sym-ov")
GPTQ モデル#
OpenVINO は、GPTQ で最適化された Hugging Face トランスフォーマー・ライブラリーの 4 ビット・モデルもサポートしています。この場合、モデル変換によって INT4 最適化の結果が自動的に保存されてモデル推論の利点が得られるため、追加のモデル最適化ステップは必要ありません。
GPTQ モデルを使用した圧縮例を以下に示します。次のコマンドを実行して、GPTQ の依存関係を必ずインストールしてください:
pip install optimum[openvino] auto-gptq
from optimum.intel.openvino import OVModelForCausalLM
from transformers import AutoTokenizer, pipeline
# GPTQ で最適化済みの Hugging Face からモデルをロード
model_id = "TheBloke/Llama-2-7B-Chat-GPTQ"
model = OVModelForCausalLM.from_pretrained(model_id, export=True)
# 推論
tokenizer = AutoTokenizer.from_pretrained(model_id)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
phrase = "The weather is" results = pipe(phrase)
print(results)
GPTQ を使用して最適化されたモデルの例。
圧縮メトリックの例#
以下の表は、最適化ステップでデータセットが使用されない、データフリー設定のさまざまな最適化設定を使用したテキスト生成言語モデルの例を示しています。複雑度メトリックは応答精度の測定値であり、複雑度スコアが高いほど精度が低くなります。これは、Lambada OpenAI データセットで測定されます。
モデル |
最適化 |
Perplexity* |
モデルサイズ (Gb) |
---|---|---|---|
databricks/dolly-v2-3b |
FP32 |
5.01 |
10.3 |
databricks/dolly-v2-3b |
INT8_ASYM |
5.07 |
2.6 |
databricks/dolly-v2-3b |
INT4_ASYM,group_size=32,ratio=0.5 |
5.28 |
2.2 |
facebook/opt-6.7b |
FP32 |
4.25 |
24.8 |
facebook/opt-6.7b |
INT8_ASYM |
4.27 |
6.2 |
facebook/opt-6.7b |
INT4_ASYM,group_size=64,ratio=0.8 |
4.32 |
4.1 |
meta-llama/Llama-2-7b-chat-hf |
FP32 |
3.28 |
25.1 |
meta-llama/Llama-2-7b-chat-hf |
INT8_ASYM |
3.29 |
6.3 |
meta-llama/Llama-2-7b-chat-hf |
INT4_ASYM,group_size=128,ratio=0.8 |
3.41 |
4.0 |
togethercomputer/RedPajama-INCITE-7B-Instruct |
FP32 |
4.15 |
25.6 |
togethercomputer/RedPajama-INCITE-7B-Instruct |
INT8_ASYM |
4.17 |
6.4 |
togethercomputer/RedPajama-INCITE-7B-Instruct |
INT4_ASYM,group_size=128,ratio=1.0 |
4.17 |
3.6 |
meta-llama/Llama-2-13b-chat-hf |
FP32 |
2.92 |
48.5 |
meta-llama/Llama-2-13b-chat-hf |
INT8_ASYM |
2.91 |
12.1 |
meta-llama/Llama-2-13b-chat-hf |
INT4_SYM,group_size=64,ratio=0.8 |
2.98 |
8.0 |
次の表は、Wikitext データセットで測定されたデータ対応の 4 ビット重み量子化セットアップの精度メトリックを示しています:
モデル |
最適化 |
Word perplexity* |
モデルサイズ (Gb) |
---|---|---|---|
meta-llama/llama-7b-chat-hf |
FP32 |
11.57 |
12.61 |
meta-llama/llama-7b-chat-hf |
INT4_SYM,group_size=128,ratio=1.0,awq=True |
12.34 |
2.6 |
stabilityai_stablelm-3b-4e1t |
FP32 |
10.17 |
10.41 |
stabilityai_stablelm-3b-4e1t |
INT4_SYM,group_size=64,ratio=1.0,awq=True |
10.89 |
2.6 |
HuggingFaceH4/zephyr-7b-beta |
FP32 |
9.82 |
13.99 |
HuggingFaceH4/zephyr-7b-beta |
INT4_SYM,group_size=128,ratio=1.0 |
10.32 |
2.6 |
*両方のテーブルのパープレキシティー・メトリックは、OpenVINO ランタイムで動的量子化を無効化して測定されました。
重み圧縮パラメーターの自動調整#
特定のモデルに最適な重み圧縮パラメーターを見つけるには、値のサブセットから重み圧縮パラメーターが検索される例を参照してください。検索を高速化するため、独自に設計された検証パイプライン WhoWhatBench が使用されます。パイプラインは、ベースラインと比較した最適化されたモデルの精度の変化を迅速に評価できます。
関連情報#
OpenVINO GenAI リポジトリー : 画像とテキストの生成タスクを実装するサンプル・パイプラインを含むリポジトリー。また、LLM をベンチマークするツールも提供します。