エッジAI

ONNX

機械学習モデルの共通フォーマット。

概要

ONNX(Open Neural Network Exchange:オープン・ニューラル・ネットワーク・エクスチェンジ)は、機械学習・ディープラーニングモデルを異なるフレームワーク間で交換・共有するための共通フォーマット(標準規格)です。2017年にMicrosoftとFacebookが共同で提案し、現在はLinux Foundation傘下のAI標準化プロジェクトとして多くの企業が参加しています。

ONNX登場の背景:

機械学習フレームワークはTensorFlow・PyTorch・MXNet・Caffe2など多数が存在し、それぞれ独自のモデル形式を持っていました。これにより以下の問題が生じていました。

  • PyTorchで学習したモデルをモバイル向けTFLiteに変換するのが困難
  • フレームワークごとに異なるデプロイツールが必要
  • 推論エンジンの最適化がフレームワーク依存で断片化

ONNXはこれらの問題を「共通の中間表現フォーマット」として解決します。

[学習フェーズ]                    [推論フェーズ]
PyTorch ──┐                    ┌── ONNX Runtime
TensorFlow─┤→ ONNX形式 → 変換 →┤── TensorRT
MXNet ────┘   (.onnx)         ├── OpenVINO
JAX ──────┘                   ├── CoreML
                               ├── TFLite
                               └── 独自NPUランタイム

歴史・背景

出来事
2017年9月MicrosoftとFacebookがONNX v1.0を共同発表
2018年IBMなど多数の企業がコミュニティに参加
2019年ONNX Runtime(ORT)v1.0リリース
2020年Linux Foundation AI配下に移管
2021年ONNX Runtime MobileがiOS/Android対応
2022年ONNXオペレータセット v17、量子化演算子強化
2023年ONNX Runtime v1.16、LLM向け大規模推論対応
2024年ONNX v22、スパース演算・動的形状の改善

参加企業・プロジェクト(主要なもの):

Microsoft、Meta(Facebook)、IBM、Intel、NVIDIA、Qualcomm、ARM、AMD、Baidu、Apple(非公式ながらCore ML変換サポート)、など100社超が参加。

技術仕様

ファイルフォーマット

ONNXはProtocol Buffers(protobuf)を使って定義されています。.onnxファイルはバイナリprotobuf形式です。

// onnx.proto3の主要定義(簡略版)
message ModelProto {
  int64 ir_version = 1;          // IR(中間表現)バージョン
  repeated OperatorSetIdProto opset_import = 8;
  string domain = 2;
  int64 model_version = 5;
  string doc_string = 6;
  GraphProto graph = 7;          // 計算グラフ
  repeated TensorProto initializer = 11; // 重みデータ
}

message GraphProto {
  repeated NodeProto node = 1;   // 演算ノードのリスト
  string name = 2;
  repeated TensorProto initializer = 5;  // 定数テンソル
  repeated ValueInfoProto input = 11;
  repeated ValueInfoProto output = 12;
}

message NodeProto {
  repeated string input = 1;     // 入力テンソル名
  repeated string output = 2;    // 出力テンソル名
  string name = 3;
  string op_type = 4;            // 演算子種別(Conv, ReLU, etc)
  string domain = 7;
  repeated AttributeProto attribute = 5;
}

オペレータセット(opset)

ONNXは演算子の集合を「オペレータセット」としてバージョン管理します。モデルはどのopsetバージョンを使っているかを明示します。

import onnx

model = onnx.load('model.onnx')
print(f"IR Version: {model.ir_version}")
for opset in model.opset_import:
    print(f"Opset: domain={opset.domain!r}, "
          f"version={opset.version}")
# 出力例:
# IR Version: 8
# Opset: domain='', version=17

主要演算子カテゴリ

カテゴリ演算子例
たたみ込みConv, ConvTranspose, DepthwiseConv
プーリングMaxPool, AveragePool, GlobalAveragePool
活性化Relu, Sigmoid, Tanh, Softmax, Gelu
正規化BatchNormalization, LayerNormalization
変形Reshape, Transpose, Concat, Split, Slice
演算Add, Mul, Gemm, MatMul, Pad
リカレントLSTM, GRU, RNN
量子化QuantizeLinear, DequantizeLinear

テンソルデータ型

型名説明バイト数
FLOAT32bit浮動小数点4
DOUBLE64bit浮動小数点8
FLOAT1616bit浮動小数点2
BFLOAT16Brain Float 162
INT88bit符号付き整数1
UINT88bit符号なし整数1
INT16/INT32/INT64整数型2/4/8
BOOL論理値1

動作原理

モデル変換の流れ

# PyTorch → ONNX 変換例
import torch
import torch.onnx

# 学習済みモデル
model = MyModel()
model.load_state_dict(torch.load('weights.pth'))
model.eval()

# ダミー入力(形状の確認用)
dummy_input = torch.randn(1, 3, 224, 224)

# ONNX形式でエクスポート
torch.onnx.export(
    model,
    dummy_input,
    'model.onnx',
    export_params=True,      # 重みを含める
    opset_version=17,        # opsetバージョン
    do_constant_folding=True, # 定数畳み込み最適化
    input_names=['input'],
    output_names=['output'],
    dynamic_axes={           # 動的バッチサイズ対応
        'input': {0: 'batch_size'},
        'output': {0: 'batch_size'}
    }
)
print("ONNX変換完了")
# TensorFlow / Keras → ONNX 変換例
import tf2onnx
import tensorflow as tf

model = tf.keras.models.load_model('model.h5')

# 変換
onnx_model, _ = tf2onnx.convert.from_keras(
    model,
    opset=17
)

import onnx
onnx.save(onnx_model, 'model.onnx')

ONNXモデルの検証と最適化

import onnx
from onnxruntime.tools import optimizer

# モデルの妥当性チェック
model = onnx.load('model.onnx')
onnx.checker.check_model(model)
print("モデル検証OK")

# グラフの最適化(Fusion、定数折り畳みなど)
optimized_model = optimizer.optimize_model(
    'model.onnx',
    model_type='bert',  # bert, gpt2, vit など
    optimization_level=99
)
optimized_model.save_model_to_file('model_opt.onnx')

ONNX Runtime での推論

import onnxruntime as ort
import numpy as np

# セッション作成(EPを指定可能)
session_options = ort.SessionOptions()
session_options.graph_optimization_level = (
    ort.GraphOptimizationLevel.ORT_ENABLE_ALL
)

# Execution Provider(実行バックエンド)の選択
providers = [
    ('CUDAExecutionProvider', {'device_id': 0}),  # GPU
    'CPUExecutionProvider'  # フォールバック
]

session = ort.InferenceSession(
    'model.onnx',
    session_options,
    providers=providers
)

# 入力情報確認
input_name = session.get_inputs()[0].name
input_shape = session.get_inputs()[0].shape
print(f"入力: {input_name}, shape={input_shape}")

# 推論実行
input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)
outputs = session.run(None, {input_name: input_data})
print(f"出力shape: {outputs[0].shape}")

ONNX量子化(INT8への変換)

from onnxruntime.quantization import quantize_dynamic, QuantType

# ダイナミック量子化(キャリブレーション不要)
quantize_dynamic(
    model_input='model.onnx',
    model_output='model_int8.onnx',
    weight_type=QuantType.QInt8
)

# 静的量子化(高精度、キャリブレーション必要)
from onnxruntime.quantization import quantize_static, CalibrationDataReader

class MyCalibrationReader(CalibrationDataReader):
    def get_next(self):
        # キャリブレーション用データを返す
        return {'input': calibration_data}

quantize_static(
    model_input='model.onnx',
    model_output='model_static_int8.onnx',
    calibration_data_reader=MyCalibrationReader()
)

用途・ユースケース

フレームワーク間の移植

研究目的でPyTorchを使って学習したモデルを、本番環境のTensorRT(NVIDIA GPU)やOpenVINO(Intel)に展開する際に、ONNXが橋渡しとなります。

研究環境           → ONNX → 本番環境
PyTorch (研究)           TensorRT (NVIDIA GPU)
TensorFlow (研究)        OpenVINO (Intel)
JAX (Google)             CoreML (Apple)
MXNet (AWS)              ORT Mobile (スマートフォン)

エッジデバイスへのデプロイ

ONNX RuntimeはAndroid/iOSのモバイルアプリにも組み込め、ONNXモデルを直接実行できます。

// Android での ORT Mobile 使用例 (Java)
OrtEnvironment env = OrtEnvironment.getEnvironment();
OrtSession session = env.createSession(
    "model.onnx",
    new OrtSession.SessionOptions()
);
Map<String, OnnxTensor> inputs = Map.of(
    "input",
    OnnxTensor.createTensor(env, inputData)
);
OrtSession.Result results = session.run(inputs);

AIモデル開発エコシステム

ONNX Model Zooには事前学習済みの標準モデルが公開されており、すぐに推論に使えます。

モデルタスクサイズ
ResNet-50画像分類約100MB
MobileNetV2画像分類約14MB
YOLOv8n物体検出約6MB
BERT-base自然言語処理約400MB
Whisper-tiny音声認識約39MB

実装・開発のポイント

ONNXモデルの可視化

Netronを使ってONNXモデルの計算グラフをブラウザで視覚化できます。

# Netronをインストールして使用
pip install netron
netron model.onnx
# → ブラウザでインタラクティブなグラフが開く

デバッグ:中間テンソルの確認

import onnxruntime as ort
import onnx

# 全ノードの出力を可視化用に追加
model = onnx.load('model.onnx')
for node in model.graph.node:
    for output in node.output:
        if output not in [o.name for o in model.graph.output]:
            model.graph.output.extend([
                onnx.helper.make_tensor_value_info(
                    output, onnx.TensorProto.FLOAT, None)
            ])

session = ort.InferenceSession(
    model.SerializeToString()
)
results = session.run(None, {'input': input_data})
# 全中間テンソルの値を確認可能

各フレームワークからの変換ツール

元フレームワーク変換ツールコマンド例
PyTorchtorch.onnxtorch.onnx.export(model, ...)
TensorFlow/Kerastf2onnxpython -m tf2onnx.convert --saved-model ...
scikit-learnsklearn-onnxto_onnx(clf, X_train)
LightGBMonnxmltoolsconvert_lightgbm(model, ...)
PaddlePaddlepaddle2onnxpaddle2onnx --model_dir ...

他技術との比較

比較軸ONNXTFLiteCoreMLTensorRT
汎用性最高Apple専用NVIDIA専用
エコシステム最大Apple向けGPU向け
MCU対応△(ORT Mobile)○(TFLite Micro)××
変換の容易さ中(TF限定が多い)難(独自形式)
推論性能高(Apple)最高(NVIDIA)
量子化INT8対応INT8対応INT8対応INT8/FP16対応

ONNXはエッジAIエコシステムの中で「共通語」として機能します。TensorFlow Lite推論アクセラレータと組み合わせることで、フレームワークを問わず最適なハードウェアへのデプロイが可能になります。量子化もONNX上で直接実施でき、学習済みモデルの配布形式としても広く採用されています。

関連用語

参考リンク