ハイライト
iOS 18 の per-grouped-channel palettization により、Stable Diffusion の 4-bit 圧縮はノイズ出力からほぼロスレスに近い品質へ回復。サイズ増加はわずか 0.8%。
主要内容
5GB の Stable Diffusion モデルを iPhone に入れるのは非現実的に聞こえる。しかし Core ML Tools の圧縮パイプラインはその距離を縮め続けている。iOS 17 の palettization はモデルを半分以下に圧縮でき、6-bit では正常に画像生成、4-bit では完全に崩壊——16 個のクラスタ中心で重み行列全体をマッピングする精度では耐えられない。
iOS 18 は圧縮粒度を per-tensor から per-grouped-channel へ進化。16 channel ごとに 1 つのルックアップテーブルを共有。4-bit 圧縮下で Stable Diffusion のサイズは 1.29GB から 1.3GB へ微増するが、生成品質は「判別不能」から「6-bit に近い」へ回復。同じ “Cat in a tuxedo, oil on canvas” プロンプトでも、2 つの粒度では天と地ほどの差。
Apple はさらに 2 つの重要な改善を実施。第一に、プルーニングと量子化/palettization の組み合わせが可能に——sparse palettization と sparse quantization で両技術の圧縮効果を両立。第二に、data-free と fine-tuning の中間にある calibration data 支援の post-training 圧縮ワークフローを追加。128 サンプルで 40% スパース化された Stable Diffusion を「ノイズ出力」から「正常生成」へ戻せる。大規模モデルでは fine-tuning は高コスト、data-free は粗すぎる——calibration がそのギャップを埋める。
詳細
Per-grouped-channel palettization
iOS 17 は per-tensor palettization のみサポート:重み行列全体が 1 つのルックアップテーブルを共有。4-bit では 16 個のクラスタ中心のみで、大行列には誤差が大きすぎる。iOS 18 では group_size channel ごとに 1 つのルックアップテーブルを共有でき、粒度が大幅に向上(07:02)。
import coremltools as ct
from coremltools.optimize import palettize_weights
config = ct.optimize.coreml.OpPalettizerConfig(
mode="kmeans",
nbits=4,
granularity="per_grouped_channel",
group_size=16,
)
opt_config = ct.optimize.coreml.OptimizationConfig(global_config=config)
compressed_model = palettize_weights(model, opt_config)
キーポイント:
nbits=4:4-bit 圧縮。ルックアップテーブルは 2^4 = 16 個のクラスタ中心granularity="per_grouped_channel":group_sizechannel ごとに 1 テーブル。tensor 全体ではないgroup_size=16:16 channel ごとに 1 グループ。グループ数が多いほどテーブル増、精度向上、サイズ微増- 4-bit per-grouped-channel 圧縮後、Stable Diffusion は 1.29GB から 1.3GB へ増加するが、生成品質は 6-bit に近づく(08:56)
Calibration data 支援の post-training 圧縮
Data-free 圧縮は高圧縮比で精度低下が速い。Fine-tuning 圧縮は精度良好だが時間がかかり大量データが必要。calibration ワークフローは少量サンプルでキャリブレーションし、両者の中間に位置(10:41)。
from coremltools.optimize.torch.layerwise_compressor import LayerwiseCompressor
prune_config = ct.optimize.torch.LayerwiseCompressorConfig(
target_sparsity=0.4,
n_samples=128,
)
pruner = LayerwiseCompressor(model, prune_config)
sparse_model = pruner.compress(calibration_data_loader)
キーポイント:
target_sparsity=0.4:40% の重みをプルーニングしてゼロ化n_samples=128:calibration は 128 サンプルのみ。fine-tuning よりはるかに少ないcalibration_data_loader:モデル入力形式のサンプルを提供するユーザー定義データローダー- 40% スパース化後、Stable Diffusion は 1.3GB から 1.1GB へ。data-free ではノイズ、calibration 後は正常画像(12:52)
スパース化後、palettization を重ねてさらに圧縮可能:
from coremltools.optimize.torch.post_training_quantization import PostTrainingPalettizer
palett_config = ct.optimize.torch.PostTrainingPalettizerConfig(
nbits=4,
granularity="per_grouped_channel",
group_size=16,
)
palettizer = PostTrainingPalettizer(sparse_model, palett_config)
sparse_palettized_model = palettizer.compress(calibration_data_loader)
キーポイント:
- すでにスパース化されたモデルに 4-bit palettization を適用——sparse palettization
- 同じ
calibration_data_loaderを再利用可能 - 最終 PyTorch モデルは Core ML 形式へシームレス変換
Stateful model と KV-cache
Core ML は stateful model をサポート。状態テンソルは推論間で永続化され、自動的にインプレース更新——出力を入力へ手動コピーする必要がなくなった(15:55)。
Transformer の KV-cache に自然に適合。KV-cache は各 token 生成時に Key/Value ベクトルを保存し、再計算を回避。stateful model 実装後、KV-cache はインプレース更新——大テンソルの I/O 間コピーが不要(18:24)。
stateful モデル変換時、ct.StateType で状態を宣言:
import coremltools as ct
states = [
ct.StateType(
name="keyCache",
dtype=np.float16,
shape=(1, num_layers, max_seq_len, head_dim),
),
ct.StateType(
name="valueCache",
dtype=np.float16,
shape=(1, num_layers, max_seq_len, head_dim),
),
]
model = ct.convert(
traced_model,
inputs=[...],
outputs=[...],
states=states,
minimum_deployment_target=ct.target.iOS18,
)
キーポイント:
ct.StateType:状態テンソルの名前、型、形状を宣言する新 APIname="keyCache"/"valueCache":PyTorch モデルのregister_buffer名と一致必須statesをct.convertに渡すと、変換後 Core ML モデルは自動的に stateful 化minimum_deployment_target=ct.target.iOS18:stateful model は iOS 18 が必要
SDPA オペレータ融合
iOS 18 の Core ML Tools は PyTorch の Scaled Dot Product Attention(SDPA)オペレータを複数の小オペレータに分解せず、全体として保持。SDPA は Apple Silicon GPU 上でより効率的(19:21)。
Multi-function model
複数の Core ML モデルを 1 つの multi-function model に統合可能。共有重みは自動的に重複排除。典型的なシナリオは 1 つの base model に異なる adapter(LoRA など)を接続——各 adapter が 1 function、base model 重みは 1 回のみ保存(27:20)。
重要ポイント
-
何をするか:大規模モデルの端末デプロイ向けに per-grouped-channel 圧縮実験マトリクスを構築。bit 数(8/6/4)、
group_size(8/16/32)、圧縮技術の組み合わせ(palettization / quantization / pruning)を試し、精度とサイズの最適バランスを探索。なぜ価値があるか:4-bit では per-tensor 比でサイズほぼ不変で精度が大幅向上——大規模モデル圧縮のデフォルト選択。始め方:OpPalettizerConfig(nbits=4, granularity="per_grouped_channel", group_size=16)から始め、自分のモデルで比較実行。 -
何をするか:既存 KV-cache 実装を stateful Core ML model へ移行。なぜ価値があるか:KV-cache テンソルは通常大きい。stateful model のインプレース更新で I/O コピー削減、LLM 推論速度が明確に向上。始め方:PyTorch モデルで
register_bufferにより KV-cache を宣言、変換時にct.StateTypeをct.convertへ渡し、minimum_deployment_target=ct.target.iOS18を設定。 -
何をするか:data-free 圧縮を calibration data ワークフローで置き換え。なぜ価値があるか:高圧縮比で data-free は精度崩壊。calibration は 128 サンプルで使用可能精度を回復、fine-tuning よりはるかに低コスト。始め方:128 個の典型入力サンプルを準備、
LayerwiseCompressorのn_samples=128で calibration 実行、data-free と calibration 後の出力品質を比較。 -
何をするか:複数 adapter を multi-function Core ML model に統合。なぜ価値があるか:adapter 間で base model 重みを共有——ストレージは N コピーから 1 base + N 小 adapter へ。ロードと切り替えも高速化。始め方:各 adapter モデルを Core ML に個別変換、
MultiFunctionDescriptorで統合ルール指定、save_multifunctionで統合モデル生成。
関連セッション
- Train your machine learning and AI models on Apple GPUs — Metal で Apple Silicon 上で PyTorch/JAX/TensorFlow モデルを訓練
- Deploy machine learning and AI models on-device with Core ML — 端末上 Core ML の性能最適化、実行、model stitching
- What’s new in Create ML — Create ML フレームワーク更新。インタラクティブデータソースプレビューと物体追跡テンプレート
- Discover Swift enhancements in the Vision framework — Vision フレームワーク Swift API 再設計。画像美学と全身ポーズ検出を追加
コメント
GitHub Issues · utterances