機械学習では、学習時間の短縮が非常に大事になってきます。
今回は、KaggleのT4×2環境を利用し、XGBoost、LightGBM、CatBoostの各ライブラリでのCPU版とGPU版の学習時間を比較しました。
データセットの生成
まず、scikit-learnのmake_classification
を用いて、80,000サンプル×50特徴量のデータセットを生成し、学習用とテスト用に分割します。
Python
import time
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# データ生成(サンプル数: 80,000, 特徴量: 50)
X, y = make_classification(n_samples=80000, n_features=50, n_informative=30, n_redundant=10, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print("データ生成完了: X_train={}, X_test={}".format(X_train.shape, X_test.shape))
XGBoost の CPU vs GPU
XGBoostでは、最新バージョンのパラメータとして、device='cuda'
を指定することでGPUを利用できます。以下は、CPU版とGPU版での学習時間を計測するコード例です。
Python
import xgboost as xgb
# DMatrixに変換
dtrain = xgb.DMatrix(X_train, label=y_train)
dtest = xgb.DMatrix(X_test, label=y_test)
# XGBoostパラメータ設定
params_cpu = {
'objective': 'binary:logistic',
'eval_metric': 'logloss'
}
params_gpu = {
'objective': 'binary:logistic',
'eval_metric': 'logloss',
'device': 'cuda'
}
num_round = 100
# CPUでの学習時間計測
start = time.time()
bst_cpu = xgb.train(params_cpu, dtrain, num_boost_round=num_round, evals=[(dtest, 'test')], verbose_eval=False)
cpu_time = time.time() - start
print("XGBoost CPU training time: {:.4f} seconds".format(cpu_time))
# GPUでの学習時間計測
start = time.time()
bst_gpu = xgb.train(params_gpu, dtrain, num_boost_round=num_round, evals=[(dtest, 'test')], verbose_eval=False)
gpu_time = time.time() - start
print("XGBoost GPU training time: {:.4f} seconds".format(gpu_time))
実測結果
- XGBoost CPU training time: 1.9852秒
- XGBoost GPU training time: 0.9797秒
XGBoostでは、GPUを利用することで学習時間が約半分に短縮されることが確認できました。
LightGBM の CPU vs GPU
LightGBMでは、パラメータにdevice='gpu'
を設定するだけでGPUを利用できます。
最初に、80,000サンプルのデータセットで計測した場合のコード例です。
Python
import lightgbm as lgb
# LightGBM用データセットに変換
lgb_train = lgb.Dataset(X_train, label=y_train)
lgb_test = lgb.Dataset(X_test, label=y_test, reference=lgb_train)
params_cpu = {
'objective': 'binary',
'metric': 'binary_logloss',
'boosting_type': 'gbdt'
}
params_gpu = {
'objective': 'binary',
'metric': 'binary_logloss',
'boosting_type': 'gbdt',
'device': 'gpu'
}
num_round = 100
# CPUでの学習時間計測
start = time.time()
gbm_cpu = lgb.train(params_cpu, lgb_train, num_boost_round=num_round, valid_sets=[lgb_test])
cpu_time = time.time() - start
print("LightGBM CPU training time: {:.4f} seconds".format(cpu_time))
# GPUでの学習時間計測
start = time.time()
gbm_gpu = lgb.train(params_gpu, lgb_train, num_boost_round=num_round, valid_sets=[lgb_test])
gpu_time = time.time() - start
print("LightGBM GPU training time: {:.4f} seconds".format(gpu_time))
実測結果(80,000サンプルの場合)
- LightGBM CPU training time: 1.9863秒
- LightGBM GPU training time: 5.9221秒
この結果では、GPU版は小規模データセットにおいては初期オーバーヘッド(カーネルコンパイルやデータ転送)の影響でCPU版よりも遅くなってしまいました。
データを80000→800000へ
次に、サンプル数を10倍の800,000に増やしたデータセットで計測した例です。大規模なデータでは、GPUの並列処理の効果がより顕著に現れます。
Python
# サンプル数を800,000に増やしたデータセットの生成
X_large, y_large = make_classification(n_samples=800000, n_features=50, n_informative=30, n_redundant=10, random_state=42)
X_train_large, X_test_large, y_train_large, y_test_large = train_test_split(X_large, y_large, test_size=0.2, random_state=42)
print("大規模データ生成完了: X_train={}, X_test={}".format(X_train_large.shape, X_test_large.shape))
# LightGBM用の大規模データセットに変換
lgb_train_large = lgb.Dataset(X_train_large, label=y_train_large)
lgb_test_large = lgb.Dataset(X_test_large, label=y_test_large, reference=lgb_train_large)
# CPUでの学習時間計測
start = time.time()
gbm_cpu_large = lgb.train(params_cpu, lgb_train_large, num_boost_round=num_round, valid_sets=[lgb_test_large])
cpu_time_large = time.time() - start
print("LightGBM CPU training time (large data): {:.4f} seconds".format(cpu_time_large))
# GPUでの学習時間計測
start = time.time()
gbm_gpu_large = lgb.train(params_gpu, lgb_train_large, num_boost_round=num_round, valid_sets=[lgb_test_large])
gpu_time_large = time.time() - start
print("LightGBM GPU training time (large data): {:.4f} seconds".format(gpu_time_large))
実測結果(800,000サンプルの場合)
- LightGBM CPU training time: 10.6567秒
- LightGBM GPU training time: 8.5092秒
大規模データセットの場合、GPUの初期オーバーヘッドが相対的に小さくなり、GPU版の学習時間がCPU版よりも短縮される結果となりました。
CatBoost の CPU vs GPU
CatBoostは、パラメータtask_type
を'CPU'
または'GPU'
にするだけで簡単に切り替えられます。
Python
from catboost import CatBoostClassifier
params_cpu = {
'iterations': 100,
'loss_function': 'Logloss',
'verbose': False,
'task_type': 'CPU'
}
params_gpu = {
'iterations': 100,
'loss_function': 'Logloss',
'verbose': False,
'task_type': 'GPU'
}
# CPUでの学習時間計測
start = time.time()
model_cpu = CatBoostClassifier(**params_cpu)
model_cpu.fit(X_train, y_train, eval_set=(X_test, y_test))
cpu_time = time.time() - start
print("CatBoost CPU training time: {:.4f} seconds".format(cpu_time))
# GPUでの学習時間計測
start = time.time()
model_gpu = CatBoostClassifier(**params_gpu)
model_gpu.fit(X_train, y_train, eval_set=(X_test, y_test))
gpu_time = time.time() - start
print("CatBoost GPU training time: {:.4f} seconds".format(gpu_time))
実測結果
- CatBoost CPU training time: 3.9969秒
- CatBoost GPU training time: 3.1977秒
CatBoostでは、GPUを使用することでわずかながら学習時間の短縮が確認されました。
まとめ
今回の実測結果は以下の通りです。
- XGBoost:
- CPU: 1.9852秒
- GPU: 0.9797秒
→ GPUを使うことで学習時間が約半分に短縮されました。
- LightGBM (80,000サンプルの場合):
- CPU: 1.9863秒
- GPU: 5.9221秒
→ 小規模データでは、GPU版は初期オーバーヘッドの影響で遅くなる傾向が見られました。
LightGBM (800,000サンプルの場合): - CPU: 10.6567秒
- GPU: 8.5092秒
→ 大規模データでは、GPUの並列処理が効果を発揮し、学習時間が短縮されました。
- CatBoost:
- CPU: 3.9969秒
- GPU: 3.1977秒
→ GPU利用で若干の高速化が見られました。
コメント