/
githubmirror
/
scikit-learn
Обзор
Документация
Войти
/
githubmirror
/
scikit-learn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
benchmarks/bench_hist_gradient_boosting_threading.py
347 строк
11 KB
Adrin Jalali
MNT add isort to ruff's rules (#26649)
21 июн 2023, 18:50
Не верифицирован
21 июн 2023, 18:50
42173fd
Код
Авторство
О чём код?
import argparse import os from pprint import pprint from time import time import numpy as np from threadpoolctl import threadpool_limits import sklearn from sklearn.datasets import make_classification, make_regression from sklearn.ensemble import ( HistGradientBoostingClassifier, HistGradientBoostingRegressor, ) from sklearn.ensemble._hist_gradient_boosting.utils import get_equivalent_estimator from sklearn.model_selection import train_test_split parser = argparse.ArgumentParser() parser.add_argument("--n-leaf-nodes", type=int, default=31) parser.add_argument("--n-trees", type=int, default=10) parser.add_argument( "--lightgbm", action="store_true", default=False, help="also benchmark lightgbm" ) parser.add_argument( "--xgboost", action="store_true", default=False, help="also benchmark xgboost" ) parser.add_argument( "--catboost", action="store_true", default=False, help="also benchmark catboost" ) parser.add_argument("--learning-rate", type=float, default=0.1) parser.add_argument( "--problem", type=str, default="classification", choices=["classification", "regression"], ) parser.add_argument("--loss", type=str, default="default") parser.add_argument("--missing-fraction", type=float, default=0) parser.add_argument("--n-classes", type=int, default=2) parser.add_argument("--n-samples", type=int, default=int(1e6)) parser.add_argument("--n-features", type=int, default=100) parser.add_argument("--max-bins", type=int, default=255) parser.add_argument("--print-params", action="store_true", default=False) parser.add_argument( "--random-sample-weights", action="store_true", default=False, help="generate and use random sample weights", ) parser.add_argument( "--plot", action="store_true", default=False, help="show a plot results" ) parser.add_argument( "--plot-filename", default=None, help="filename to save the figure to disk" ) args = parser.parse_args() n_samples = args.n_samples n_leaf_nodes = args.n_leaf_nodes n_trees = args.n_trees lr = args.learning_rate max_bins = args.max_bins print("Data size: %d samples train, %d samples test." % (n_samples, n_samples)) print(f"n_features: {args.n_features}") def get_estimator_and_data(): if args.problem == "classification": X, y = make_classification( args.n_samples * 2, n_features=args.n_features, n_classes=args.n_classes, n_clusters_per_class=1, n_informative=args.n_features // 2, random_state=0, ) return X, y, HistGradientBoostingClassifier elif args.problem == "regression": X, y = make_regression( args.n_samples_max * 2, n_features=args.n_features, random_state=0 ) return X, y, HistGradientBoostingRegressor X, y, Estimator = get_estimator_and_data() if args.missing_fraction: mask = np.random.binomial(1, args.missing_fraction, size=X.shape).astype(bool) X[mask] = np.nan if args.random_sample_weights: sample_weight = np.random.rand(len(X)) * 10 else: sample_weight = None if sample_weight is not None: (X_train_, X_test_, y_train_, y_test_, sample_weight_train_, _) = train_test_split( X, y, sample_weight, test_size=0.5, random_state=0 ) else: X_train_, X_test_, y_train_, y_test_ = train_test_split( X, y, test_size=0.5, random_state=0 ) sample_weight_train_ = None sklearn_est = Estimator( learning_rate=lr, max_iter=n_trees, max_bins=max_bins, max_leaf_nodes=n_leaf_nodes, early_stopping=False, random_state=0, verbose=0, ) loss = args.loss if args.problem == "classification": if loss == "default": # loss='auto' does not work with get_equivalent_estimator() loss = "log_loss" else: # regression if loss == "default": loss = "squared_error" sklearn_est.set_params(loss=loss) if args.print_params: print("scikit-learn") pprint(sklearn_est.get_params()) for libname in ["lightgbm", "xgboost", "catboost"]: if getattr(args, libname): print(libname) est = get_equivalent_estimator( sklearn_est, lib=libname, n_classes=args.n_classes ) pprint(est.get_params()) def one_run(n_threads, n_samples): X_train = X_train_[:n_samples] X_test = X_test_[:n_samples] y_train = y_train_[:n_samples] y_test = y_test_[:n_samples] if sample_weight is not None: sample_weight_train = sample_weight_train_[:n_samples] else: sample_weight_train = None assert X_train.shape[0] == n_samples assert X_test.shape[0] == n_samples print("Fitting a sklearn model...") tic = time() est = sklearn.base.clone(sklearn_est) with threadpool_limits(n_threads, user_api="openmp"): est.fit(X_train, y_train, sample_weight=sample_weight_train) sklearn_fit_duration = time() - tic tic = time() sklearn_score = est.score(X_test, y_test) sklearn_score_duration = time() - tic print("score: {:.4f}".format(sklearn_score)) print("fit duration: {:.3f}s,".format(sklearn_fit_duration)) print("score duration: {:.3f}s,".format(sklearn_score_duration)) lightgbm_score = None lightgbm_fit_duration = None lightgbm_score_duration = None if args.lightgbm: print("Fitting a LightGBM model...") lightgbm_est = get_equivalent_estimator( est, lib="lightgbm", n_classes=args.n_classes ) lightgbm_est.set_params(num_threads=n_threads) tic = time() lightgbm_est.fit(X_train, y_train, sample_weight=sample_weight_train) lightgbm_fit_duration = time() - tic tic = time() lightgbm_score = lightgbm_est.score(X_test, y_test) lightgbm_score_duration = time() - tic print("score: {:.4f}".format(lightgbm_score)) print("fit duration: {:.3f}s,".format(lightgbm_fit_duration)) print("score duration: {:.3f}s,".format(lightgbm_score_duration)) xgb_score = None xgb_fit_duration = None xgb_score_duration = None if args.xgboost: print("Fitting an XGBoost model...") xgb_est = get_equivalent_estimator(est, lib="xgboost", n_classes=args.n_classes) xgb_est.set_params(nthread=n_threads) tic = time() xgb_est.fit(X_train, y_train, sample_weight=sample_weight_train) xgb_fit_duration = time() - tic tic = time() xgb_score = xgb_est.score(X_test, y_test) xgb_score_duration = time() - tic print("score: {:.4f}".format(xgb_score)) print("fit duration: {:.3f}s,".format(xgb_fit_duration)) print("score duration: {:.3f}s,".format(xgb_score_duration)) cat_score = None cat_fit_duration = None cat_score_duration = None if args.catboost: print("Fitting a CatBoost model...") cat_est = get_equivalent_estimator( est, lib="catboost", n_classes=args.n_classes ) cat_est.set_params(thread_count=n_threads) tic = time() cat_est.fit(X_train, y_train, sample_weight=sample_weight_train) cat_fit_duration = time() - tic tic = time() cat_score = cat_est.score(X_test, y_test) cat_score_duration = time() - tic print("score: {:.4f}".format(cat_score)) print("fit duration: {:.3f}s,".format(cat_fit_duration)) print("score duration: {:.3f}s,".format(cat_score_duration)) return ( sklearn_score, sklearn_fit_duration, sklearn_score_duration, lightgbm_score, lightgbm_fit_duration, lightgbm_score_duration, xgb_score, xgb_fit_duration, xgb_score_duration, cat_score, cat_fit_duration, cat_score_duration, ) max_threads = os.cpu_count() n_threads_list = [2**i for i in range(8) if (2**i) < max_threads] n_threads_list.append(max_threads) sklearn_scores = [] sklearn_fit_durations = [] sklearn_score_durations = [] lightgbm_scores = [] lightgbm_fit_durations = [] lightgbm_score_durations = [] xgb_scores = [] xgb_fit_durations = [] xgb_score_durations = [] cat_scores = [] cat_fit_durations = [] cat_score_durations = [] for n_threads in n_threads_list: print(f"n_threads: {n_threads}") ( sklearn_score, sklearn_fit_duration, sklearn_score_duration, lightgbm_score, lightgbm_fit_duration, lightgbm_score_duration, xgb_score, xgb_fit_duration, xgb_score_duration, cat_score, cat_fit_duration, cat_score_duration, ) = one_run(n_threads, n_samples) for scores, score in ( (sklearn_scores, sklearn_score), (sklearn_fit_durations, sklearn_fit_duration), (sklearn_score_durations, sklearn_score_duration), (lightgbm_scores, lightgbm_score), (lightgbm_fit_durations, lightgbm_fit_duration), (lightgbm_score_durations, lightgbm_score_duration), (xgb_scores, xgb_score), (xgb_fit_durations, xgb_fit_duration), (xgb_score_durations, xgb_score_duration), (cat_scores, cat_score), (cat_fit_durations, cat_fit_duration), (cat_score_durations, cat_score_duration), ): scores.append(score) if args.plot or args.plot_filename: import matplotlib import matplotlib.pyplot as plt fig, axs = plt.subplots(2, figsize=(12, 12)) label = f"sklearn {sklearn.__version__}" axs[0].plot(n_threads_list, sklearn_fit_durations, label=label) axs[1].plot(n_threads_list, sklearn_score_durations, label=label) if args.lightgbm: import lightgbm label = f"LightGBM {lightgbm.__version__}" axs[0].plot(n_threads_list, lightgbm_fit_durations, label=label) axs[1].plot(n_threads_list, lightgbm_score_durations, label=label) if args.xgboost: import xgboost label = f"XGBoost {xgboost.__version__}" axs[0].plot(n_threads_list, xgb_fit_durations, label=label) axs[1].plot(n_threads_list, xgb_score_durations, label=label) if args.catboost: import catboost label = f"CatBoost {catboost.__version__}" axs[0].plot(n_threads_list, cat_fit_durations, label=label) axs[1].plot(n_threads_list, cat_score_durations, label=label) for ax in axs: ax.set_xscale("log") ax.set_xlabel("n_threads") ax.set_ylabel("duration (s)") ax.set_ylim(0, None) ax.set_xticks(n_threads_list) ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) ax.legend(loc="best") axs[0].set_title("fit duration (s)") axs[1].set_title("score duration (s)") title = args.problem if args.problem == "classification": title += " n_classes = {}".format(args.n_classes) fig.suptitle(title) plt.tight_layout() if args.plot_filename: plt.savefig(args.plot_filename) if args.plot: plt.show()