Scikit-Learnが遅いので、C++製の超高速機械学習ライブラリを作った話

# 【VeloxML】Scikit-Learnが遅いので、C++製の超高速機械学習ライブラリを作った話

こんにちは！

機械学習の高速化を目指し、C++製の機械学習ライブラリ「***VeloxML***」(アルファ版) を開発したので紹介したいと思います。

## 導入（イントロ）

機械学習を実際のプロジェクトで活用しようとすると、計算速度の壁に直面することがあります。特に、数百万件のデータをローカル環境で学習させるようなケースでは、既存のライブラリの限界を感じることがありました。

最初は scikit-learn を使っていましたが、大規模データでの学習が遅く、処理時間がボトルネックになっていました。かといって、ロジスティック回帰をするためだけにPyTorchやTensorFlowを用意するのは大袈裟すぎます。シンプルな機械学習タスクに、数GBものディープラーニングフレームワークをインストールするのは非効率的です。

唯一、LightGBMだけは満足できる速度で処理できました。しかし、LightGBMは主に決定木ベースのアルゴリズムに特化しており、線形回帰やSVM、クラスタリングなどの手法はサポートされていません。

さらに、scikit-learnは公式にGPU対応の予定がない様子だったため、
「それなら自分で作ってしまおう！」
という思いから、C++で高速な機械学習ライブラリ VeloxML を開発しました。

VeloxMLは、C++による高速実装、OpenMP/TBBを活用した並列処理、BLAS/LAPACKを用いた最適化を組み合わせ、scikit-learnの使いやすさを維持しながら、高速な機械学習を実現することを目指しています。
また、Python APIも提供しており、scikit-learnのように簡単に使える設計になっています。

この記事では、VeloxMLの特徴や使い方、今後の展望について紹介します！

## VeloxMLとは？

VeloxML は、C++で実装された機械学習ライブラリで、Pythonから手軽に使えます。

BLAS/LAPACKを活用し、高速な計算を実現！

* 並列処理：OpenMP/TBBで高速化
* Python API対応：pybind11でラップ
* 主要アルゴリズム実装済み
  * 線形回帰 / ロジスティック回帰 / 決定木 / ランダムフォレスト  / SVM など
* 将来的にAutoML・GPU対応を視野に開発中！

## インストール

~~ 執筆時点では、MacOS(Apple Siliconのみ)に対応しています。今後拡張予定です。~~

2025/02/05時点で、Linux(x86_64, aarch64), MacOS(Apple Sillicon, Intel)に対応しています。

（Windowsは謎のエラーによりGCCでビルドできないため、作業中断中）


```sh
pip install veloxml
```

## 使い方（例: 線形回帰）

```python
import veloxml as vx

model = vx.LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
```

## 実行速度を計測してみた。

以下のようなコードで、Pythonから実行速度を計測してみました。計測環境は以下のような実験設定で行いました。

* MacBookPro 2023 (Apple M2 Pro, 16GB)
* 100万件のレコード
* 1レコードあたり100個の特徴量
* ツリーの数が10個
* ツリーの最大深さを５に制限
* 5つのツリーを並列処理する


```python
import time
import numpy as np
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
import warnings
warnings.simplefilter("ignore")

from veloxml.tree import RandomForestClassification
# from sklearn.ensemble import RandomForestClassifier

fit_time_list = []
pred_time_list = []

for i in range(100):
  # ランダムシード
  rng = np.random.default_rng()

  # データ数と特徴量数
  num_samples = 1000000
  num_features = 100

  # 数値特徴量の生成 (ガウス分布)
  X_numeric = rng.normal(0, 1, (num_samples, num_features - 5))
  
  W = rng.normal(0, 1, (num_features - 5))

  # カテゴリカルな特徴量を追加 (0, 1, 2の3カテゴリ)
  X_categorical = rng.integers(0, 3, (num_samples, 5))

  # 全特徴を結合
  X = np.hstack([X_numeric, X_categorical])

  # ターゲット変数の作成（非線形な条件付きで決定）
  Y = ((X_numeric.dot(W) > 1.5) & ((X[:, -1] == 1) | (X[:, -2] == 2))).astype(np.int32)

  X_train, X_test, y_train, y_test = train_test_split(X, Y)

  print()

  # モデルの作成
  model = RandomForestClassification(
    n_trees=10,
    criterion="Gini",
    split_algorithm="Histogram",
    max_depth=5,
    max_leaf_nodes=100,
    random_seed=42,
    n_jobs=5
  )
  
  # # sklearnの場合
  # model = RandomForestClassifier(
  #   n_estimators=10,
  #   criterion="gini",
  #   max_depth=5,
  #   max_leaf_nodes=100,
  #   random_state=42,
  #   n_jobs=5
  # )

  # 学習時間の計測
  start_time = time.time()
  model.fit(X_train, y_train)
  train_time = time.time() - start_time
  
  fit_time_list.append(train_time)
  
  # 推論時間の計測
  start_time = time.time()
  y_pred = model.predict(X_test[[0], :])
  inference_time = (time.time() - start_time)
  
  pred_time_list.append(inference_time)

  # 精度の計測
  accuracy = accuracy_score(y_test[[0]], y_pred[[0]])

  print(f"学習時間: {train_time:.4f} 秒")
  print(f"推論時間: {inference_time:.4e} 秒 / サンプル")
  print(f"精度: {accuracy:.4f}")

print(f"平均学習時間: {np.mean(fit_time_list):.4f} 秒")
print(f"平均推論時間: {np.mean(pred_time_list):.4e} 秒 / サンプル")

```

最終的に、計測時間は以下のような平均値になりました。

```
平均学習時間: 1.5178 秒
平均推論時間: 8.5713e-04 秒 / サンプル
```

また参考までに、同様の実験をScikit-Learnの`RandomForestClassifier`で行ったところ、以下の結果が出ました。

```
平均学習時間: 7.1197 秒
平均推論時間: 1.4954e-02 秒 / サンプル
```

学習時間は4倍、推論時間は17倍程度早くなりました。👏

## 今後の展望と現状の課題

### 今後の展望
VeloxMLは、より高速で汎用的な機械学習ライブラリを目指して、今後も開発を続けていきます。具体的には、以下のような方向性を考えています。

1. 主要なアルゴリズムの実装を継続
  * 現在実装されている線形回帰、ロジスティック回帰、決定木、ランダムフォレスト、SVM、k-means、PCAなどに加えて、さらなるアルゴリズムの追加を予定しています。

2. CUDA, Metal, VulkanでのGPGPU対応

  * 現在はCPU上での並列処理（OpenMP/TBB）を活用していますが、今後は ***CUDA（NVIDIA）、Metal（Apple）、Vulkan（クロスプラットフォーム）*** を利用したGPGPU対応を進めていきます。
  * 特に、大規模なデータセットを処理する際にはGPUの恩恵が大きいため、学習時間の短縮を目指します。

3. AutoMLの実装

  * 単にアルゴリズムを提供するだけでなく、ハイパーパラメータチューニングや特徴量選択を自動化するAutoML機能を追加する予定です。
  * これにより、エンドユーザーがより簡単に高精度なモデルを作成できるようになります。

4. さらなる高速化

  * すでにBLAS/LAPACKを活用していますが、さらなる最適化を行い、計算負荷の高い処理を効率化していきます。
  * SIMD（AVX2, AVX-512）を活用した最適化や、メモリアクセスの効率改善にも取り組む予定です。

### 現状の課題
現時点では、以下のような課題もあります。

1. SVM分類器が遅い
  * SVM（サポートベクターマシン）の学習に時間がかかるのが大きな問題点です。
  * 特に、大規模データセットでは計算コストが高くなるため、カーネルの計算をより効率化する方法を検討中です。
  * 現在の解決策として、線形SVMの場合はBLASを活用、カーネルSVMは適切な近似アルゴリズムを導入することを考えています。

VeloxMLは、 ***「手軽に使えるが、高速でスケーラブル」*** な機械学習フレームワークを目指して、引き続き開発を進めていきます。
今後のアップデートにもご期待ください！ 

## GitHub

以下のリポジトリにて、MIT License で公開しています。

https://github.com/veloxml/VeloxML

ぜひスターをお願いします！