Transformersの4-bit・8-bit量子化入門

CHATGPT / AIChatGPTなどの生成AIを活用して運営・記事制作・更新を行っています。制作方針

Transformersとbitsandbytesを初めて使う人向けに、対応環境を確認して小型modelを8-bitまたは4-bitで読み込み、生成、配置、memory footprintを確かめる最短手順と戻し方を説明します。

対応環境を確認し、4-bitまたは8-bitで読み込み、生成とMemoryを確かめる最短手順

先に結論

TransformersではBitsAndBytesConfigload_in_8bit=Trueまたはload_in_4bit=Trueを指定すると、対応するlinear layerをbitsandbytesの量子化layerへ置き換えてmodelを読み込めます。最初は対応GPU、CUDA、Python、PyTorchを確認し、小型modelを一つだけ読み込みます。短い生成が完了した後にhf_device_mapget_memory_footprint()を記録すれば、「読めた」と「想定したmemoryへ収まった」を分けて確認できます。

確認日時: 2026年8月11日(Asia/Tokyo)
対象: Transformers v5.15.0(commit 5eddc12、2026年8月10日公開)と、同日確認したTransformers main/bitsandbytes現行文書。
検証区分: 公式資料に基づく机上調査・Python構文確認対象の手順です。この制作環境ではpackage install、model download、CUDA推論を実行していません。
更新範囲: 例はNVIDIA CUDAでの推論を主対象にします。Apple Silicon、AMD ROCm preview、Intel XPU、Gaudi、CPU backendの速度とfeature差は未検証です。

始める前に確認すること

量子化は、model weightを表すbit数を減らし、主にmemory使用量を抑える方法です。ここで分けて考えるものは3つあります。

  • weightのbit幅: 8-bitまたは4-bitで保持する範囲
  • 計算dtype: 4-bit weightを使う計算途中のfloat32、float16、bfloat16など
  • 配置: layerをGPU、CPU、複数deviceのどこへ置くか

「4-bitにしたから全計算が4-bitになる」わけではありません。LayerNormなど量子化対象外のmoduleは別dtypeを使い、8-bitのCPU offloadではCPUへ置いたweightがfloat32で保持されます。読み込み後の実測を確認する理由はここにあります。

公式Transformers文書が示すNVIDIA CUDAの主な条件は、CUDA 11.8〜13.0、LLM.int8()がTuring世代以降、NF4/FP4がPascal世代以降です。現行bitsandbytes installation guideは共通最小条件としてPython 3.10以上、PyTorch 2.3以上を示しています。実際にはOS、driver、PyTorchが利用するCUDA、bitsandbytes wheelの組み合わせも一致させます。

既存環境を直接更新せず、新しいvirtual environmentを用意します。次は読者側で実行する例で、この制作環境では実行していません。

python -m venv .venv-bnb
source .venv-bnb/bin/activate
python -m pip install --upgrade transformers accelerate bitsandbytes
python -m pip freeze > requirements-bnb.txt

install後は、versionとCUDA認識を先に記録します。

python - <<'PY'
import torch, transformers, bitsandbytes
print({
    "torch": torch.__version__,
    "transformers": transformers.__version__,
    "bitsandbytes": bitsandbytes.__version__,
    "cuda_available": torch.cuda.is_available(),
    "torch_cuda": torch.version.cuda,
})
PY

cuda_availableFalseなら、GPU向け手順を続ける前にdriver、PyTorch build、containerのGPU割当を直します。package名を推測で追加し続けず、作ったvirtual environmentを削除して元へ戻せる状態を保ちます。

最短手順:8-bitで読み込んで生成する

最初は公式文書でも例に使われるfacebook/opt-350mを8-bitで読み込みます。実運用modelより小さいものから始めると、download、認証、device配置、生成の問題を分けやすくなります。

from time import perf_counter

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

model_id = "facebook/opt-350m"
quantization_config = BitsAndBytesConfig(load_in_8bit=True)

tokenizer = AutoTokenizer.from_pretrained(model_id)
started = perf_counter()
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    dtype="auto",
    quantization_config=quantization_config,
)
load_seconds = perf_counter() - started

inputs = tokenizer("Quantization helps local inference because", return_tensors="pt")
input_device = next(model.parameters()).device
inputs = {name: value.to(input_device) for name, value in inputs.items()}

with torch.inference_mode():
    output_ids = model.generate(
        **inputs,
        max_new_tokens=24,
        do_sample=False,
    )

print(tokenizer.decode(output_ids[0], skip_special_tokens=True))
print({
    "load_seconds": load_seconds,
    "memory_footprint_bytes": model.get_memory_footprint(),
    "device_map": model.hf_device_map,
})

成功は架空の文章や固定秒数では判定しません。次の4点を確認します。

  1. exceptionなしでmodelが読み込まれ、24 token以内の生成が完了する
  2. model.hf_device_mapに想定したGPU配置がある
  3. memory_footprint_bytesが正の値として取得できる
  4. 出力が空、文字化け、同じtokenの無限反復になっていない

get_memory_footprint()はmodelのfootprintを確認する入口で、process全体のhost RAM、CUDA context、allocator reservation、同居processまですべて表す値ではありません。system monitorやnvidia-smiも同じ時点で見て、別の指標として記録します。

4-bitへ切り替える

8-bitの成功を保存した後、設定だけを4-bitへ変えます。NF4は正規分布で初期化されたweight向けに設計され、公式文書は4-bit base modelのtrainingで使うよう案内しています。推論ではNF4とFP4の差を普遍的な速度差とみなさず、modelの配布条件と固定taskで確認します。

quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

このblockだけを8-bit設定と置き換え、model ID、prompt、max_new_tokensdo_sample=Falseは変えません。まず既定のcompute dtypeで生成を成立させます。GPUがbfloat16を正しく支えることを確認した後に限り、次のように計算dtypeを別experimentとして変更します。

quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
)

bit幅とcompute dtypeを同時に変えて結果が崩れると、どちらが原因か分かりません。8-bit、4-bit既定compute、4-bit bfloat16を別々に保存します。

つまずきやすい点と戻し方

CUDAを認識しない

まずtorch.cuda.is_available()torch.version.cudaへ戻ります。systemへ入ったCUDA toolkitの表示だけでは、現在のPyTorch wheelが使うruntimeを確認したことになりません。新しいvirtual environmentを作り直し、公式installation matrixにある組み合わせを一つ選びます。

out of memoryになる

大きなmodelへ進む前にOPT-350mへ戻ります。GPU上の別processを確認し、modelを解放してから再試行します。8-bitでは公式にCPU offloadがありますが、CPUへ移したweightはfloat32なのでhost RAMも測ります。device_map=“auto”は推論向けであり、このままtraining手順へ流用しません。

dtype errorやNaNが出る

bfloat16指定を外し、既定compute dtypeへ戻します。次にGPUのbfloat16対応、modelが期待するdtype、量子化対象外moduleのdtypeを確認します。4-bit/8-bitの読み込み成功だけで、出力品質がfull precisionと同じだとは判断しません。

出力が期待と違う

sampling差をなくすためdo_sample=Falseを維持し、同じmodel revisionとpromptを使います。量子化前のmodelが収まる環境なら同じ条件のreference出力も保存します。収まらない場合は8-bitを運用baselineにできますが、それを品質の正解と呼ばないようにします。

local LLM全体のmemory見積もりはVRAM計算の考え方、複数requestの処理方法はTransformers連続バッチング入門で役割を分けて確認できます。

さらに深く理解する

4-bit・8-bit量子化のメモリ品質検証設計では、weight bit、compute dtype、double quant、device配置を一変数ずつ比較し、VRAM、host RAM、load時間、TTFT、decode速度、固定task品質を混ぜずに評価します。

参考資料