Model Serialization Format(モデルシリアライゼーションフォーマット)

article technology medium #model-serialization#safetensors#gguf#onnx#pytorch-pickle#tflite#litert#coreml#mlpackage#executorch#tensorrt-engine#mlx#numpy-npy#orbax#keras#tf-savedmodel#flatbuffers#protobuf#mmap#weights-only#huggingface-hub#sharded-weights#tokenizer-embedding#gguf-kv#state-dict#security-rce#version-compat
Created: 2026-05-28 Updated:

SafeTensors/GGUF/ONNX/pickle/TFLite/CoreML/.mlpackage/.pte/TensorRT engine の内部構造、mmap・アライメント・トークナイザ埋め込み・シャーディング・セキュリティ・10 種アンチパターン俯瞰。

Model Serialization Format(モデルシリアライゼーションフォーマット)

学習済み重みをロスレス固定する永続化層。tech-67 が IR・ランタイム・量子化なら、本稿は バイトレイアウト・mmap・メタデータ・シャーディング・セキュリティ・バージョン互換。圧縮は tech-66、カーネル/メモリは tech-76

ファイルフォーマット内部構造

フォーマットエンコーディングmmap主用途
SafeTensors 0.4.xu64 ヘッダ + JSON + 生 tensor、8 B 整列完全HF 配布、RCE フリー
GGUF v3magic+version+KV+tensor_info+data、32 B 整列完全llama.cpp LLM
PyTorch .pt/.binpickle-in-ZIP部分 (2.1+ mmap=True)PyTorch 標準、RCE リスク
ONNXprotobuf ModelProto、2 GB 上限 + external dataクロス FW 交換
TF SavedModelsaved_model.pb + variables/部分TF 2.x
Keras .kerasZIP (config.json + .h5)Keras 3
TFLite/LiteRTFlatBuffers Model完全エッジ推論
CoreML .mlpackageManifest + MIL protobuf + weight.bin部分Apple ANE/GPU
ExecuTorch .pteFlatBuffer ExecutionPlan + デリゲート完全PyTorch エッジ
TensorRT .engineプロプライエタリ、GPU/TRT 固定mmap 可NVIDIA 推論
NumPy .npymagic+header+raw、64 B 整列mmap_mode='r'数値配列
Orbax (JAX)フラットキーツリー + msgpack対応JAX/Flax

.mlmodel.h5 は deprecated → .mlpackage、Keras 3 .keras。MLX は .npz と SafeTensors を直接ロード。

SafeTensors と GGUF のバイトレイアウト

SafeTensors: u64 LE ヘッダ JSON 長 → UTF-8 JSON {"name":{"dtype":"F16","shape":[...],"data_offsets":[s,e]},"__metadata__":{...}} → 8 B 0x00 パディング → 生 tensor。コード実行経路ゼロ、Rust 境界チェック、memmap2 ゼロコピー。

GGUF v3: magic 0x47475546 + u32 version + u64 tensor_count + u64 kv_count → KV (gguf_string + u32 value_type 0=u8〜12=f64・9=array + 値) → tensor_info (name + n_dims + dims + ggml_type + offset) → general.alignment (32) パディング → offset 順 tensor。全 LE、big-endian は変換要 [要確認]。ランタイムが mmap()(file_base + offset) ゼロコピー view を構築。

GGUF メタデータ KV と埋め込みトークナイザ

GGUF はトークナイザを重みファイルに完全埋め込み。階層名前空間:

  • general.*: architecture (llama/mistral/qwen/gemma/phi)、name/licensefile_type (量子化)、quantization_versionalignment
  • <arch>.*: context_lengthembedding_lengthblock_countattention.head_count/head_count_kv (GQA/MQA)、rope.freq_baserope.scaling.typevocab_size
  • tokenizer.ggml.*: model (llama/gpt2/bert)、tokens[]scores[] (SP)、merges[] (BPE)、bos_token_id/eos_token_idadd_bos_token/add_eos_token
  • tokenizer.chat_template: Jinja2 文字列。

HF SafeTensors は外部サイドカー (tokenizer.json/tokenizer.model/special_tokens_map.json/tokenizer_config.json) に持ち、整合性は配布側責任。

ONNX protobuf と external data

ModelProto: ir_version (v9/v10 [要確認])、opset_import[]metadata_props[] 自由 KV、graph (node[]/input[]/output[]/initializer[])。

protobuf 単一メッセージは 2 GB 上限。LLM 7B+ は TensorProto.data_location=EXTERNAL + external_data.onnx + .data ペア配布。.onnx のみコピーで .data 欠損はサイレントゼロ化 (AP-4)。

ロードセマンティクス — mmap・遅延ロード

mmap 完全対応は SafeTensors/GGUF/TFLite/ExecuTorch、対応 .npy、部分 PyTorch .pt (2.1+ storage のみ)、非対応 ONNX。利点は (1) ゼロコピー (2) 遅延ロード (3) プロセス間ページ共有 (COW)。落とし穴は NFS v3 / overlay2 で MAP_SHAREDMAP_PRIVATE フォールバック → OOM (AP-2)、コールドキャッシュで first-token 急増 (vmtouch/madvise(MADV_WILLNEED))、CIFS/SMB アライメント無保証

大規模モデル遅延ロードは accelerate.init_empty_weights() (meta) → load_checkpoint_and_dispatch(model, "index.json", device_map="auto") で tensor 単位振り分け。

セキュリティモデル

Pickle RCE: .pt/.bin、Keras .h5lambdatf.py_function__reduce__ 経由で os.system(...)torch.load() 時実行可能。緩和は torch.load(weights_only=True) (2.4+ 警告、2.6+ デフォルト [要確認])。完全回避は SafeTensors。

SafeTensors: コード実行経路ゼロ、Rust 境界チェック、JSON + raw のみ。__metadata__ はプロンプトインジェクションを排除しない。

ONNX カスタム op: .so/.dlldlopen 実行、ORT はサンドボックスなし、信頼できない .onnx は DLL リスク。

トークナイザ注入: 重みが安全でも tokenizer.json 改ざんで BOS/EOS 改変、ホモグリフ、chat_template 経由のシステムプロンプト埋め込み可能。

HF Hub: LFS SHA256 検証、revision="main" は branch 更新で別重み (AP-7)。revision="<commit-sha>" / タグ固定が安全。

シャーディングと巨大モデル

SafeTensors: model.safetensors.index.jsonweight_map + metadata.total_size、各シャードは独立有効ファイル、from_pretrained() が必要分のみロード。ONNX External Data: .onnx + .data ペア、--all-tensors-to-one-file で単一 .dataGGUF split (2024+): model-00001-of-00005.ggufgeneral.split.count/general.split.no KV [要確認]。PyTorch シャード (レガシー): pytorch_model.bin.index.json、新規未使用。

変換可逆性と精度損失

ロスレス: PyTorch ↔ SafeTensors (同一 tensor バイト、コンテナのみ差替え)、.pt.bin、シャード再結合/分割、量子化なし GGUF (F32/F16) — tokenizer KV 正確再現が前提。

損失あり:

  • PyTorch → ONNX: torch.onnx.export は動的制御フロー喪失、dynamo_export も全 op 保証なし、opset 互換性確認必須。
  • PyTorch → GGUF: 重みは lossless だがトークナイザ再エンコード要、特殊トークンミスで EOS 未生成 / BOS 二重付与。
  • ONNX → TFLite (onnx2tf): Einsum/ScatterND/GridSample op ギャップ。
  • TF → ONNX (tf2onnx): tf.functioninput_signature 明示なしで型推論失敗。
  • JAX → ONNX: 直接パスなし、jax2tftf2onnx の 2 段。
  • bf16 → fp16: bf16 (~3.4×10³⁸) → fp16 (65504) でオーバーフロー NaN/Inf、clamp か bf16 → fp32 → 量子化の 2 段 (AP-10)。

バージョニング — opset / GGUF v1→v3 / SafeTensors

ONNX opset 17→22、ORT 1.16=18 / 1.17=19 / 1.18=20 [要確認]、opset_import が ORT サポート外なら InvalidGraphonnx.version_converter でダウングレード可だが op 不在で失敗あり。ONNX IR v7→v10。GGUF: v1 u32 count → v2 u64 count・パディング正式化 → v3 (2024) general.file_type・split 対応 [要確認]。SafeTensors 0.3→0.5 はバージョンフィールドなし、additive。TFLite FlatBuffers は後方互換維持。CoreML coremltools 7+.mlpackage + ML Program デフォルト、8+ 変更 [要確認]。PyTorch state_dict バージョンなし、torch.compile() 後は _orig_mod. プレフィクス、strict=False か strip 要。

アンチパターン 10 種

  1. Pickle RCE.pt/.binweights_only=False でロード。対策: weights_only=True、SafeTensors 移行。Critical。
  2. NFS/overlay2 mmap OOMMAP_SHARED フォールバックで heap コピー。対策: ローカル SSD/tmpfs へコピー後 mmap、または use_mmap=False。High。
  3. GGUF tokenizer KV ドリフト — Fine-tune で重みのみ更新、KV は古いまま。対策: convert_hf_to_gguf.py で全体再変換、既存 GGUF パッチ禁止。High。
  4. ONNX external data 紛失.onnx のみコピーで .data 欠損→サイレントゼロ。対策: --all-tensors-to-one-file、ペア検証。High。
  5. 精度メタデータ不整合config.json torch_dtype と実 tensor 不一致で silent NaN。対策: ロード後 model.dtype 照合、変換時 perplexity 再評価。Medium-High。
  6. シャード index 不整合*.index.jsonweight_map 乖離で KeyError か silent ゼロ。対策: 変更時 index 再生成、save_pretrained() で自動化。High。
  7. HF revision="main" 非固定 — branch 更新で別重み、再現性破壊。対策: <commit-sha> / タグ pin。Medium。
  8. Keras .h5 lambda RCElambda/tf.py_function が任意コード実行。対策: compile=False、サブクラス置換、Keras 3 移行。Critical。
  9. TensorRT エンジン GPU 固定 — Ampere → Ada コピーで起動失敗 / 誤出力。対策: .engine 配布せず trtexec リビルド、ONNX を配布単位。High。
  10. bf16 → fp16 直接キャスト — bf16 値域が fp16 (65504) 超過で NaN/Inf。対策: 事前 clamp / bf16 → fp32 → 量子化。Medium-High。

関連記事

未確認事項 (確認時点 2026-05)

情報カットオフ ~2025-08 で confidence: medium。最新は各公式 spec 参照。

  1. SafeTensors 0.5+ フォーマット拡張
  2. GGUF v4 仕様策定と llama.cpp 実装
  3. PyTorch weights_only=True 2.6 デフォルト確定
  4. ONNX opset 22→23 / ORT 1.18.x/1.19.x サポート上限
  5. GGUF split KV general.split.* 名前
  6. HuggingFace Xet LFS 置き換え採用状況
  7. Orbax v1.0 JAX 公式推奨
  8. CoreML coremltools 8+ ML Program spec 変更
  9. ExecuTorch FlatBuffer 1.0 GA 後の後方互換
  10. Apple Foundation Models iOS/macOS 26 配布形式
  11. GGUF v3 big-endian サポート
  12. TensorRT .engine 内部構造 (非公開)

Local graph