6
6
import pickle
7
7
import numpy as np
8
8
import lightgbm as lgb
9
+ from functools import partial
9
10
from sklearn .model_selection import RandomizedSearchCV
11
+ from sklearn .metrics import roc_auc_score
10
12
from sklearn .model_selection import cross_val_score , StratifiedKFold
13
+ from hyperopt import hp , fmin , tpe , Trials , space_eval
14
+ from hyperopt .pyll import scope
11
15
from utils import load_data
12
16
13
17
N_JOBS = 4 * 4 * 9
14
18
N_ITER = 25 # budget for hyperparam search
15
19
16
20
17
- def evaluate_pipeline_helper (X , y , pipeline , param_grid , random_state = 0 ):
18
- inner_cv = StratifiedKFold (n_splits = 4 , shuffle = True , random_state = random_state )
19
- outer_cv = StratifiedKFold (n_splits = 4 , shuffle = True , random_state = random_state )
20
- clf = RandomizedSearchCV (
21
- estimator = pipeline ,
22
- param_distributions = param_grid ,
23
- n_iter = N_ITER ,
24
- cv = inner_cv ,
25
- scoring = "roc_auc_ovr_weighted" ,
26
- n_jobs = N_JOBS ,
27
- random_state = random_state ,
28
- verbose = - 1 ,
29
- )
30
- nested_score = cross_val_score (clf , X = X , y = y , cv = outer_cv , scoring = "roc_auc_ovr_weighted" , n_jobs = N_JOBS )
31
- return nested_score
21
+ HYPEROPT_SPACE = {
22
+ "learning_rate" : hp .choice ("learning_rate" , [0.1 , 0.05 , 0.01 , 0.005 , 0.001 ]),
23
+ "num_leaves" : scope .int (2 ** hp .quniform ("num_leaves" , 2 , 7 , 1 )),
24
+ "colsample_bytree" : hp .quniform ("colsample_bytree" , 0.4 , 1 , 0.1 ),
25
+ "subsample" : hp .quniform ("subsample" , 0.4 , 1 , 0.1 ),
26
+ "min_child_samples" : scope .int (2 ** hp .quniform ("min_child_samples" , 0 , 7 , 1 )),
27
+ "min_child_weight" : 10 ** hp .quniform ("min_child_weight" , - 6 , 0 , 1 ),
28
+ "reg_alpha" : hp .choice ("reg_alpha" , [0 , 10 ** hp .quniform ("reg_alpha_pos" , - 6 , 1 , 1 )]),
29
+ "reg_lambda" : hp .choice ("reg_lambda" , [0 , 10 ** hp .quniform ("reg_lambda_pos" , - 6 , 1 , 1 )]),
30
+ "max_depth" : scope .int (hp .choice ("max_depth" , [- 1 , 2 ** hp .quniform ("max_depth_pos" , 1 , 4 , 1 )])),
31
+ }
32
32
33
33
34
34
def define_and_evaluate_lightgbm_pipeline (X , y , random_state = 0 ):
35
- if len (set (y )) == 2 :
36
- pipeline = lgb .LGBMClassifier (
35
+ binary = len (set (y )) == 2
36
+ if binary :
37
+ lgb_model = lgb .LGBMClassifier (
37
38
objective = "binary" ,
38
39
n_estimators = 500 ,
39
40
metric = "auc" ,
@@ -43,7 +44,7 @@ def define_and_evaluate_lightgbm_pipeline(X, y, random_state=0):
43
44
silent = True ,
44
45
)
45
46
else :
46
- pipeline = lgb .LGBMClassifier (
47
+ lgb_model = lgb .LGBMClassifier (
47
48
objective = "multiclass" ,
48
49
n_estimators = 500 ,
49
50
metric = "auc_mu" ,
@@ -52,18 +53,40 @@ def define_and_evaluate_lightgbm_pipeline(X, y, random_state=0):
52
53
random_state = random_state ,
53
54
silent = True ,
54
55
)
55
- param_grid = {
56
- "learning_rate" : [1e-7 , 1e-6 , 1e-5 , 1e-4 , 1e-3 , 1e-2 , 1e-1 , 1e0 ],
57
- "num_leaves" : [2 , 4 , 8 , 16 , 32 , 64 ],
58
- "colsample_bytree" : [0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 1.0 ],
59
- "subsample" : [0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 1.0 ],
60
- "min_child_samples" : [2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 ],
61
- "min_child_weight" : [1e-7 , 1e-6 , 1e-5 , 1e-4 , 1e-3 , 1e-2 , 1e-1 , 1e0 ],
62
- "reg_alpha" : [1e-7 , 1e-6 , 1e-5 , 1e-4 , 1e-3 , 1e-2 , 1e-1 , 1e0 ],
63
- "reg_lambda" : [1e-7 , 1e-6 , 1e-5 , 1e-4 , 1e-3 , 1e-2 , 1e-1 , 1e0 ],
64
- "max_depth" : [1 , 2 , 4 , 8 , 16 , 32 , - 1 ],
65
- }
66
- nested_scores = evaluate_pipeline_helper (X , y , pipeline , param_grid , random_state = random_state )
56
+ nested_scores = []
57
+ outer_cv = StratifiedKFold (n_splits = 4 , shuffle = True , random_state = random_state )
58
+ for train_inds , test_inds in outer_cv .split (X , y ):
59
+ X_train , y_train = X [train_inds , :], y [train_inds ]
60
+ X_test , y_test = X [test_inds , :], y [test_inds ]
61
+
62
+ def obj (params ):
63
+ lgb_model .set_params (** params )
64
+ inner_cv = StratifiedKFold (n_splits = 4 , shuffle = True , random_state = random_state )
65
+ scores = cross_val_score (
66
+ lgb_model , X = X_train , y = y_train , cv = inner_cv , scoring = "roc_auc_ovr_weighted" , n_jobs = N_JOBS
67
+ )
68
+ return - np .mean (scores )
69
+
70
+ trials = Trials ()
71
+ _ = fmin (
72
+ fn = obj ,
73
+ space = HYPEROPT_SPACE ,
74
+ algo = partial (tpe .suggest , n_startup_jobs = 5 ),
75
+ max_evals = N_ITER ,
76
+ trials = trials ,
77
+ rstate = np .random .RandomState (random_state ),
78
+ )
79
+ # hyperopt has some problems with hp.choice so we need to do this:
80
+ best_params = space_eval (HYPEROPT_SPACE , trials .argmin )
81
+ lgb_model .set_params (** best_params )
82
+ lgb_model .fit (X_train , y_train )
83
+ y_pred = lgb_model .predict_proba (X_test )
84
+ # same as roc_auc_ovr_weighted
85
+ if binary :
86
+ score = roc_auc_score (y_test , y_pred [:, 1 ], average = "weighted" , multi_class = "ovr" )
87
+ else :
88
+ score = roc_auc_score (y_test , y_pred , average = "weighted" , multi_class = "ovr" )
89
+ nested_scores .append (score )
67
90
return nested_scores
68
91
69
92
0 commit comments