エラー内容

ONNXモデルを読み込む際に、以下のようなエラーが出ることがあります。

Microsoft.ML.OnnxRuntime.OnnxRuntimeException:
[ErrorCode:Fail] Load model failed:
Type Error: Type parameter (T) of Optype (MatMul)
bound to different types (tensor(float) and tensor(float16))

エラーの意味(簡単に)

このエラーは一言でいうと:

👉 MatMul(行列積)の入力の型が一致していない

という意味です。

具体的には

  • 一方の入力 → float32(tensor(float))
  • もう一方 → float16(tensor(float16))

ONNXの仕様では、MatMulは:

👉 同じデータ型同士でしか計算できない

そのため、モデルのロード時点でエラーになります。


なぜこの問題が起きるのか

よくある原因は以下です。

① FP16とFP32が混在している

  • モデルの一部だけFP16化した
  • 一部の重みやサブモデルがFP32のまま

② モデルを後から合成した

特に以下の構成でよく起きます:

  • Stable Diffusion本体(FP16)
  • FaceID / LoRA / LCM(FP32)

👉 精度がバラバラのままONNX化される


③ ONNX変換時の不備

  • 正しくFP16変換されていない
  • Constantノードだけfloat32のまま残っている

解決方法(結論)

👉 モデル全体のデータ型を統一する(FP16 or FP32)


FP16に変換する方法(Python)

必要ライブラリ

pip install onnx onnxruntime-tools

実装コード

import onnx
from onnxruntime.tools import float16_converter

# モデル読み込み
model = onnx.load("model.onnx")

# FP16に変換
model_fp16 = float16_converter.convert_float_to_float16(
    model,
    keep_io_types=True  # 入出力はfloat32のまま(重要)
)

# 保存(外部データ形式)
onnx.save_model(
    model_fp16,
    "model.onnx",
    location="model_weights.bin",
    save_as_external_data=True,
    all_tensors_to_one_file=True,
)

重要ポイント

❌ save_modelでは型は変わらない

onnx.save_model(model, ...)

これは「保存」だけです。

👉 float32 → float16 の変換は行われません


✅ 必ず「変換 → 保存」の順番にする

onnx.load
↓
FP16変換(ここが重要)
↓
onnx.save_model

✅ keep_io_types=True の理由

これを付けないと:

  • 入力・出力もFP16になる
  • 推論時に別のエラーが発生しやすい

👉 内部だけFP16、入出力はFP32が安全


変換できたか確認する方法

for tensor in model_fp16.graph.initializer:
    print(tensor.data_type)

結果

  • FLOAT16 → OK
  • FLOAT → まだFP32が残っている

それでもエラーが出る場合

以下の可能性があります:

・ConstantノードがFP32のまま

→ 完全に変換されていない


・CastノードでFP32に戻されている

→ モデル構造の問題


・サブモデルがFP32固定

例:

  • FaceID
  • ControlNet

👉 この場合は:

  • 全部FP32に統一する
    または
  • FP16版モデルを使う

まとめ

  • MatMulは同じ型同士でしか計算できない
  • float32とfloat16が混ざるとエラーになる
  • 解決策はシンプル:

👉 モデル全体の精度を統一すること


おすすめの対応順

  1. まずFP16に統一してみる
  2. ダメならFP32に戻す
  3. サブモデル(FaceIDなど)も確認する

これでONNX Runtimeの「型不一致エラー」はほぼ解決できます。