【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のみ)に対応しています。今後拡張予定です。
pip install veloxml
使い方(例: 線形回帰)
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に制限
- 5つのツリーを並列処理する
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は、より高速で汎用的な機械学習ライブラリを目指して、今後も開発を続けていきます。具体的には、以下のような方向性を考えています。
- 主要なアルゴリズムの実装を継続
- 現在実装されている線形回帰、ロジスティック回帰、決定木、ランダムフォレスト、SVM、k-means、PCAなどに加えて、さらなるアルゴリズムの追加を予定しています。
- CUDA, Metal, VulkanでのGPGPU対応
- 現在はCPU上での並列処理(OpenMP/TBB)を活用していますが、今後は CUDA(NVIDIA)、Metal(Apple)、Vulkan(クロスプラットフォーム) を利用したGPGPU対応を進めていきます。
- 特に、大規模なデータセットを処理する際にはGPUの恩恵が大きいため、学習時間の短縮を目指します。
- AutoMLの実装
- 単にアルゴリズムを提供するだけでなく、ハイパーパラメータチューニングや特徴量選択を自動化するAutoML機能を追加する予定です。
- これにより、エンドユーザーがより簡単に高精度なモデルを作成できるようになります。
- さらなる高速化
- すでにBLAS/LAPACKを活用していますが、さらなる最適化を行い、計算負荷の高い処理を効率化していきます。
- SIMD(AVX2, AVX-512)を活用した最適化や、メモリアクセスの効率改善にも取り組む予定です。
現状の課題
現時点では、以下のような課題もあります。
- SVM分類器が遅い
- SVM(サポートベクターマシン)の学習に時間がかかるのが大きな問題点です。
- 特に、大規模データセットでは計算コストが高くなるため、カーネルの計算をより効率化する方法を検討中です。
- 現在の解決策として、線形SVMの場合はBLASを活用、カーネルSVMは適切な近似アルゴリズムを導入することを考えています。
VeloxMLは、 「手軽に使えるが、高速でスケーラブル」 な機械学習フレームワークを目指して、引き続き開発を進めていきます。
今後のアップデートにもご期待ください!
GitHub
以下のリポジトリにて、MIT License で公開しています。
ぜひスターをお願いします!