お仕事でリアルタイムのMLエンドポイントを立てる事がなく、知見があまりない。
単純に、各フレームワークでの実行速度が気になったから雑に比較してみた。

実装したコードはこちらのGitHubリポジトリ

雑なまとめ

Pythonを使う環境ならFastAPIを使えば問題ない。欲を言えば、onnxにモデルを変換しておくのが理想。
モデルをonnxに変換できる かつ Rustを利用できる環境 なら、Rustでエンドポイントを立てるとより高速な推論が期待できる。

比較する条件

フレームワーク

※ RustのコードはClaudeCodeに書いてもらいました

モデル

  • PyTorch(2層のNN)
  • LightGBM
  • PyTorch ONNX(2層のNN)
  • LightGBM ONNX

タスク

Titanicの生存予測(2値分類)

学習コードは notebooks/ にある。

特徴量

  • Pclass(Int)
  • Sex(String)
  • Age(Int)
  • SibSp(Int)
  • Parch(Int)
  • Fare(Float)

前処理

  • Sex → Label Encoding
  • Age → Fill Null(median)
  • Age → Standard Scaler
  • Fare → Standard Scaler

結果

各フレームワークで実装したエンドポイントに1000回のリクエストを送信して、計測した結果を集計した。
すべて、同じマシン上で実行・リクエストを行っている。

Framework平均推論時間 (ms)
FastAPI1.75 ms
Flask2.0 ms
ort (Rust)0.47 ms
tract (Rust)0.46 ms

各フレームワークごとの結果

FrameworkモデルAvgMinMaxTotalVariance
FastAPIPyTorch1.7611.5917.4401760.6290.043
LightGBM1.7581.5483.1421758.4140.017
PyTorch (onnx)1.5421.4002.5341541.6260.009
LightGBM (onnx)1.7571.5622.7161757.1610.010
FlaskPyTorch2.0131.8366.4412013.0750.037
LightGBM2.1702.0053.0722169.7530.009
PyTorch (onnx)1.7741.6122.3481773.5350.008
LightGBM (onnx)1.9901.7983.9431989.9030.023
ort (Rust)PyTorch (onnx)0.4260.4020.804425.5800.001
LightGBM (onnx)0.5990.5330.917598.6310.000
tract (Rust)PyTorch (onnx)0.4280.4030.693427.6090.000
LightGBM (onnx)0.5100.4880.764510.1880.000

モデルごとの結果

モデルFrameworkAvgMinMaxTotalVariance
PyTorchFastAPI1.7611.5917.4401760.6290.043
Flask2.0131.8366.4412013.0750.037
LightGBMFastAPI1.7581.5483.1421758.4140.017
Flask2.1702.0053.0722169.7530.009
PyTorch (onnx)FastAPI1.5421.4002.5341541.6260.009
Flask1.7741.6122.3481773.5350.008
ort (Rust)0.4260.4020.804425.5800.001
tract (Rust)0.4280.4030.693427.6090.000
LightGBM (onnx)FastAPI1.7571.5622.7161757.1610.010
Flask1.9901.7983.9431989.9030.023
ort (Rust)0.5990.5330.917598.6310.000
tract (Rust)0.5100.4880.764510.1880.000

まとめ

Pythonでエンドポイントを立てるならFastAPIを選べば間違いない、特に学習したモデルをonnxに変換できるとベスト。

モデルをonnxに変換できる かつ Rustを利用できる環境 なら、Rustでエンドポイントを立てるのを検討しても良いと思う。