11import io
2+ import itertools
23import lzma
34import pickle
45import textwrap
1112
1213from examples .utils import generate_dataset
1314from slim_trees .lgbm_booster import dump_lgbm
15+ from slim_trees .pickling import get_pickled_size
1416from slim_trees .sklearn_tree import dump_sklearn
1517
1618MODELS_PATH = "examples/benchmark_models"
@@ -20,51 +22,93 @@ def load_model(model_name: str, generate: Callable) -> Any:
2022 model_path = Path (f"{ MODELS_PATH } /{ model_name } .pkl" )
2123
2224 if model_path .exists ():
25+ print (f"Loading model `{ model_name } .pkl` from disk..." )
2326 with open (model_path , "rb" ) as f :
2427 return pickle .load (f )
2528
29+ print (f"Training model `{ model_name } `..." )
2630 regressor = generate ()
27- regressor .fit (* generate_dataset (n_samples = 10000 ))
31+ regressor .fit (
32+ * generate_dataset (n_samples = 10000 ),
33+ )
34+ size = get_pickled_size (regressor , "no" , pickle .dump )
35+ print (f"Trained model { model_name } . Size { size / 2 ** 20 :.2f} MB" )
36+
2837 model_path .parent .mkdir (parents = True , exist_ok = True )
38+
2939 with open (model_path , "wb" ) as f :
3040 pickle .dump (regressor , f )
3141 return regressor
3242
3343
34- def train_gb_sklearn () -> GradientBoostingRegressor :
44+ def train_sklearn_rf_20m () -> RandomForestRegressor :
45+ return load_model (
46+ "sklearn_rf_20m" ,
47+ lambda : RandomForestRegressor (
48+ n_estimators = 100 , max_leaf_nodes = 1700 , random_state = 42 , n_jobs = - 1
49+ ),
50+ )
51+
52+
53+ def train_sklearn_rf_200m () -> RandomForestRegressor :
54+ return load_model (
55+ "sklearn_rf_200m" ,
56+ lambda : RandomForestRegressor (n_estimators = 275 , random_state = 42 , n_jobs = - 1 ),
57+ )
58+
59+
60+ def train_sklearn_rf_1g () -> RandomForestRegressor :
3561 return load_model (
36- "gb_sklearn" ,
37- lambda : GradientBoostingRegressor (n_estimators = 2000 , random_state = 42 ),
62+ "sklearn_rf_1g" ,
63+ lambda : RandomForestRegressor (
64+ n_estimators = 1500 , max_leaf_nodes = 10000 , random_state = 42 , n_jobs = - 1
65+ ),
66+ )
67+
68+
69+ def train_sklearn_gb_2m () -> GradientBoostingRegressor :
70+ return load_model (
71+ "sklearn_gb_2m" ,
72+ lambda : GradientBoostingRegressor (
73+ n_estimators = 2000 , random_state = 42 , verbose = True
74+ ),
3875 )
3976
4077
41- def train_model_sklearn () -> RandomForestRegressor :
78+ def train_lgbm_gbdt_2m () -> lgb . LGBMRegressor :
4279 return load_model (
43- "rf_sklearn" ,
44- lambda : RandomForestRegressor (n_estimators = 100 , random_state = 42 , n_jobs = - 1 ),
80+ "lgbm_gbdt_2m" , lambda : lgb .LGBMRegressor (n_estimators = 1000 , random_state = 42 )
4581 )
4682
4783
48- def train_gbdt_lgbm () -> lgb .LGBMRegressor :
84+ def train_lgbm_gbdt_5m () -> lgb .LGBMRegressor :
4985 return load_model (
50- "gbdt_lgbm" , lambda : lgb .LGBMRegressor (n_estimators = 2000 , random_state = 42 )
86+ "lgbm_gbdt_5m" ,
87+ lambda : lgb .LGBMRegressor (n_estimators = 2000 , random_state = 42 ),
5188 )
5289
5390
54- def train_gbdt_large_lgbm () -> lgb .LGBMRegressor :
91+ def train_lgbm_gbdt_20m () -> lgb .LGBMRegressor :
5592 return load_model (
56- "gbdt_large_lgbm " ,
57- lambda : lgb .LGBMRegressor (n_estimators = 20000 , random_state = 42 ),
93+ "lgbm_gbdt_20m " ,
94+ lambda : lgb .LGBMRegressor (n_estimators = 8000 , random_state = 42 ),
5895 )
5996
6097
61- def train_rf_lgbm () -> lgb .LGBMRegressor :
98+ def train_lgbm_gbdt_100m () -> lgb .LGBMRegressor :
6299 return load_model (
63- "rg_lgbm" ,
100+ "lgbm_gbdt_100m" ,
101+ lambda : lgb .LGBMRegressor (n_estimators = 35000 , random_state = 42 ),
102+ )
103+
104+
105+ def train_lgbm_rf_10m () -> lgb .LGBMRegressor :
106+ return load_model (
107+ "lgbm_rf_10m" ,
64108 lambda : lgb .LGBMRegressor (
65109 boosting_type = "rf" ,
66- n_estimators = 100 ,
67- num_leaves = 1000 ,
110+ n_estimators = 700 ,
111+ num_leaves = 8000 ,
68112 random_state = 42 ,
69113 bagging_freq = 5 ,
70114 bagging_fraction = 0.5 ,
@@ -74,12 +118,9 @@ def train_rf_lgbm() -> lgb.LGBMRegressor:
74118
75119
76120def benchmark (func : Callable , * args , ** kwargs ) -> float :
77- times = []
78- for _ in range (5 ):
79- start = time .perf_counter ()
80- func (* args , ** kwargs )
81- times .append (time .perf_counter () - start )
82- return min (times )
121+ start = time .perf_counter ()
122+ func (* args , ** kwargs )
123+ return time .perf_counter () - start
83124
84125
85126def benchmark_model ( # noqa: PLR0913
@@ -99,11 +140,13 @@ def benchmark_model( # noqa: PLR0913
99140
100141 model = train_func ()
101142
143+ print (f"Benchmarking naive implementation of `{ name } `..." )
102144 naive_dump_time = benchmark (base_dumps_func , model )
103145 naive_pickled = base_dumps_func (model )
104146 naive_pickled_size = len (naive_pickled )
105147 naive_load_time = benchmark (base_loads_func , naive_pickled )
106148
149+ print (f"Benchmarking our implementation of `{ name } `..." )
107150 our_dump_time = benchmark (dumps_func , model )
108151 our_pickled = dumps_func (model )
109152 our_pickled_size = len (our_pickled )
@@ -210,18 +253,39 @@ def loads_lzma(data):
210253 dumps_lzma ,
211254 loads_lzma ,
212255 )
213- models_to_benchmark = [
214- ("sklearn rf" , train_model_sklearn ) + dumps_sklearn_args ,
215- ("sklearn rf LZMA" , train_model_sklearn ) + dumps_sklearn_lzma_args ,
216- ("sklearn gb" , train_gb_sklearn ) + dumps_sklearn_args ,
217- ("sklearn gb LZMA" , train_gb_sklearn ) + dumps_sklearn_lzma_args ,
218- ("LGBM gbdt" , train_gbdt_lgbm ) + dumps_lgbm_args ,
219- ("LGBM gbdt LZMA" , train_gbdt_lgbm ) + dumps_lgbm_lzma_args ,
220- ("LGBM gbdt large" , train_gbdt_large_lgbm ) + dumps_lgbm_args ,
221- ("LGBM gbdt large LZMA" , train_gbdt_large_lgbm ) + dumps_lgbm_lzma_args ,
222- ("LGBM rf" , train_rf_lgbm ) + dumps_lgbm_args ,
223- ("LGBM rf LZMA" , train_rf_lgbm ) + dumps_lgbm_lzma_args ,
256+ models = [
257+ ("sklearn rf 20M" , train_sklearn_rf_20m ),
258+ ("sklearn rf 200M" , train_sklearn_rf_200m ),
259+ ("sklearn rf 1G" , train_sklearn_rf_1g ),
260+ ("sklearn gb 2M" , train_sklearn_gb_2m ),
261+ ("lgbm gbdt 2M" , train_lgbm_gbdt_2m ),
262+ ("lgbm gbdt 5M" , train_lgbm_gbdt_5m ),
263+ ("lgbm gbdt 20M" , train_lgbm_gbdt_20m ),
264+ ("lgbm gbdt 100M" , train_lgbm_gbdt_100m ),
265+ ("lgbm rf 10M" , train_lgbm_rf_10m ),
224266 ]
267+
268+ def get_dumps_args (model_name , train_func ):
269+ if "sklearn" in model_name :
270+ return (model_name , train_func ) + dumps_sklearn_args
271+ elif "lgbm" in model_name :
272+ return (model_name , train_func ) + dumps_lgbm_args
273+ else :
274+ raise ValueError (f"Unknown model name: { model_name } " )
275+
276+ def get_dumps_args_lzma (model_name , train_func ):
277+ if "sklearn" in model_name :
278+ return (model_name + " lzma" , train_func ) + dumps_sklearn_lzma_args
279+ elif "lgbm" in model_name :
280+ return (model_name + " lzma" , train_func ) + dumps_lgbm_lzma_args
281+ else :
282+ raise ValueError (f"Unknown model name: { model_name } " )
283+
284+ models_to_benchmark = itertools .chain .from_iterable (
285+ [[get_dumps_args (* model ), get_dumps_args_lzma (* model )] for model in models ]
286+ )
225287 benchmark_results = [benchmark_model (* args ) for args in models_to_benchmark ]
226- print ("Base results / Our results / Change" )
227- print (format_benchmarks_results_table (benchmark_results ))
288+ results_str = format_benchmarks_results_table (benchmark_results )
289+ with open ("benchmark.md" , "w" ) as f :
290+ f .write ("Base results / Our results / Change\n " )
291+ f .write (results_str )
0 commit comments