0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで学習したCNNモデルをONNX Runtime (C#) で推論してみた

0
Posted at

はじめに

前回の記事では、
ONNX Runtime (C++) で推論し、0.04msという圧倒的な速度を得た。
ただしC++は環境構築が手間で、コードも冗長になりがちだ。

今回は同じmodel.onnxを使い、C#のONNX Runtime APIで推論してみる。
NuGetで簡単にセットアップできる点も見どころだ。


全体の流れ

[PyTorch環境]              [ONNX Runtime C#環境]
学習 → model.onnx保存 →   読み込み → 推論
                           ※PyTorchもPythonも不要!

前回と同じmodel.onnxをそのまま使い回せる。


環境構築

C++と大きく違うのがここだ。
libtrochやONNX RuntimeのC++版は手動でダウンロード・配置が必要だったが、
C#ではNuGetパッケージを.csprojに1行書くだけで済む。

.devcontainer/devcontainer.json:

{
  "name": "ONNX Runtime C#",
  "image": "mcr.microsoft.com/devcontainers/dotnet:8.0",
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-dotnettools.csharp"
      ]
    }
  }
}

inference.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <!-- NuGetで一発インストール:C++のような手動セットアップ不要 -->
    <PackageReference Include="Microsoft.ML.OnnxRuntime" Version="1.18.0" />
  </ItemGroup>

</Project>

setup.shCMakeLists.txtも不要。これだけで環境が整う。


推論コード

Program.cs:

using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using System.Diagnostics;

// モデルの読み込み
using var session = new InferenceSession("model.onnx");
Console.WriteLine("モデルを読み込みました: model.onnx");

// ダミー入力を準備(MNISTと同じサイズ: 1x1x28x28)
var inputShape = new int[] { 1, 1, 28, 28 };
int inputSize = 1 * 1 * 28 * 28;

var random = new Random(42);
var inputData = new float[inputSize];
for (int i = 0; i < inputSize; i++)
{
    // 正規分布の近似(Box-Muller法)
    double u1 = 1.0 - random.NextDouble();
    double u2 = 1.0 - random.NextDouble();
    inputData[i] = (float)(Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2));
}

var tensor = new DenseTensor<float>(inputData, inputShape);
var inputName = session.InputMetadata.Keys.First();

var inputs = new List<NamedOnnxValue>
{
    NamedOnnxValue.CreateFromTensor(inputName, tensor)
};

// ウォームアップ(前回と条件を揃える)
session.Run(inputs);
Console.WriteLine("ウォームアップ完了");

// 推論時間を計測(100回平均)
const int N = 100;
var sw = Stopwatch.StartNew();

IDisposableReadOnlyCollection<DisposableNamedOnnxValue>? output = null;
for (int i = 0; i < N; i++)
{
    output?.Dispose();
    output = session.Run(inputs);
}

sw.Stop();
double elapsedMs = sw.Elapsed.TotalMilliseconds / N;

// 結果の表示
var outputTensor = output!.First().AsTensor<float>();
int predicted = Enumerable.Range(0, 10)
    .OrderByDescending(i => outputTensor[0, i])
    .First();

Console.WriteLine($"予測クラス: {predicted}");
Console.WriteLine($"推論時間({N}回平均): {elapsedMs:F4} ms");

output?.Dispose();

実行:

# ビルドと実行を一括でやってくれる
dotnet run

cmakemakeも不要なのがC#の楽なところだ。


実行結果・5者比較

実行環境:Ryzen 5 7530U(CPUのみ)、ウォームアップあり、100回平均

実装 推論時間(100回平均) Pythonとの比較
Python (PyTorch) 0.20 ms 基準
C++ (libtorch) 0.23 ms 1.15倍遅い
ONNX Runtime (Python) 0.13 ms 1.54倍速い
ONNX Runtime (C#) 0.08 ms 2.5倍速い
ONNX Runtime (C++) 0.04 ms 5倍速い

C#はPythonとC++のちょうど中間に収まった。


C#の立ち位置

速度だけで見るとC++には及ばないが、
C#には別の強みがある。

環境構築が圧倒的に楽
C++版はONNX Runtimeを手動でダウンロード・配置し、
CMakeLists.txtでパスを指定する必要があった。
C#はNuGetの1行だけで完結する。

コードが読みやすい
C++版と比べてコード量が少なく、意図が伝わりやすい。
dotnet run一発で動くのも開発効率が高い。

既存C#システムへの組み込みが容易
業務システムや.NETアプリにCNN推論を組み込む場合、
C#は最も自然な選択肢になる。


まとめ

5回の比較を振り返ると:

実装 速度 環境構築 主なユースケース
Python (PyTorch) 0.20 ms 簡単 学習・開発・検証
C++ (libtorch) 0.23 ms やや手間 Pythonが使えない環境
ONNX Runtime (Python) 0.13 ms 簡単 軽量デプロイ
ONNX Runtime (C#) 0.08 ms 簡単 .NETシステムへの組み込み
ONNX Runtime (C++) 0.04 ms 手間 速度重視の本番環境

速度・環境構築のしやすさ・ユースケース、
三つのバランスで選ぶのが正解だと思う。


おわりに・次回予告

次回は最終回として、5つの実装を改めて整理し、
「どのユースケースに何を使うべきか」をまとめていく予定。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?