2626from ostap .utils .basic import numcpu , num_jobs , NoContext
2727from ostap .logger .utils import map2table_ex
2828from ostap .logger .pretty import nice_print
29- from ostap .logger .symbols import arrow_right
3029from ostap .utils .progress_bar import progress_bar , ProgressBar
3130from ostap .tools .reweighter import Reweighter
3231from ostap .stats .counters import SE , table_counters
3938 check_all ,
4039 nEff )
4140from ostap .stats .tools import hasSkLearn
41+ from ostap .utils .memory import memory
4242import ostap .logger .symbols as S
4343import numpy , abc , math , gc
4444# =============================================================================
@@ -248,14 +248,12 @@ def __init__( self , * ,
248248 n_features = num_features ( target )
249249 n_rows = num_samples ( target ) + num_samples ( original )
250250 data_size = n_rows * n_features
251- K = 200000
251+ K = 100_000
252252
253253 n_jobs = num_jobs ( params )
254254 n_jobs = min ( n_jobs , max ( 1 , math .floor ( data_size / K ) ) )
255- ##
256255 params [ 'n_jobs' ] = n_jobs
257-
258-
256+
259257 reg_case = self .needs_regularization ( original = original ,
260258 target = target ,
261259 original_weight = original_weight ,
@@ -330,7 +328,7 @@ def __init__( self , * ,
330328 if neff_after < 0.10 * neff_before :
331329 n1 = nice_print ( neff_before )
332330 n2 = nice_print ( neff_after )
333- logger .warning ( "%s: Large degradation of nEff %s %s %s" % ( self .method , n1 , arrow_right , n2 ) )
331+ logger .warning ( "%s: Large degradation of nEff %s %s %s" % ( self .method , n1 , S . arrow_right , n2 ) )
334332
335333 clipped_count = numpy .sum ( original_ratios >= ( self .__clip_threshold * 0.99 ) )
336334 if 0 < clipped_count :
@@ -652,35 +650,25 @@ def __fit_eval_stream ( self ,
652650 n_folds = 1
653651
654652 stream_models = []
655- print ( 'PROGRESS-BAR' , typename ( self ) )
656653 for train_idx , val_idx in progress_bar ( splits ,
657654 max_value = n_folds ,
658655 description = 'Folds:' ,
659656 silent = not self .progress or self .silent or 1 >= self .n_splits ) :
660657
661- print ( 'START-LOOP' , typename ( self ) )
662-
663658 X_tr , y_tr = X_comb [ train_idx ] , y_comb [ train_idx ]
664659 X_va , y_va = X_comb [ val_idx ] , y_comb [ val_idx ]
665660
666661 w_tr = w_comb [ train_idx ] if w_comb is not None else None
667662 w_va = w_comb [ val_idx ] if w_comb is not None else None
668-
669-
670- print ( 'BEFORE-TRAIN' , typename ( self ) )
671663
672664 model , _ = self ._train_single_model ( X_tr , y_tr , w_tr , X_va , y_va , w_va )
673665 stream_models .append ( model )
674666
675- print ( 'BEFORE-PREDICT' , typename ( self ) )
676-
677667 raw_val_p = self ._predict_single_model ( model , X_va )
678668 if 1 < raw_val_p .ndim : raw_val_p = raw_val_p [:, 1 ]
679669
680670 oof_raw [ val_idx ] = raw_val_p .astype ( numpy .float32 , copy = False )
681671
682- print ( 'END-LOOP' , typename ( self ) )
683-
684672 self .__fitted_models [ stream_key ] = stream_models
685673 self .__scale_factors [ stream_key ] = scale_factor
686674 self .__priors [ stream_key ] = numpy .float32 ( 1.0 )
@@ -982,23 +970,17 @@ def _train_single_model ( self ,
982970 if early_stopping_rounds is not None :
983971 callbacks .append ( LightGBM .early_stopping ( stopping_rounds = early_stopping_rounds , verbose = False ) )
984972
985- print ( 'BEFORE-LIGHTGBM-TRAIN' , typename ( self ) )
986973 model = LightGBM .train ( params = params ,
987974 train_set = trn_data ,
988975 num_boost_round = num_boost_round ,
989976 valid_sets = [ val_data ] ,
990977 callbacks = callbacks )
991978
992- print ( 'AFTER-LIGHTGBM-PREDICT' , typename ( self ) )
993-
994- data_size = num_features ( X_train ) * num_samples ( X_train ) * 4 / ( 1024 * 1024 )
995-
996- from ostap .utils .memory import memory
997-
998- print ( 'data_size [MB]' , data_size )
999-
1000- with memory ( "MEMORY LIGHTGBM" , logger = logger ) :
1001-
979+ # =====================================================================
980+ ## PHOENIX
981+ # =====================================================================
982+ if True : # ===========================================================
983+ # =================================================================
1002984 model_bytes = model .model_to_string ()
1003985
1004986 model .free_dataset ()
@@ -1011,25 +993,9 @@ def _train_single_model ( self ,
1011993 del model_bytes
1012994
1013995 gc .collect ()
1014-
1015996
1016- print ( 'BEFORE-LIGHTGBM-PREDICT' , typename ( self ) )
1017-
1018- """
1019- print ('--- ТЕСТ ИЗОЛЯЦИИ: СТАРТ ТРЕНИРОВКИ БЕЗ VALIDATION ---', flush=True)
1020-
1021- model = LightGBM.train (
1022- params = params ,
1023- train_set = trn_data ,
1024- num_boost_round = num_boost_round,
1025- valid_sets = None , # Никакой валидации
1026- callbacks = None # Никаких колбэков ранней остановки
1027- )
1028- print ('--- ТЕСТ ИЗОЛЯЦИИ: УСПЕХ! ---', flush=True)
1029- """
1030-
997+
1031998 val_preds = self ._predict_single_model ( model , X_val )
1032- print ( 'AFTER-LIGHTGBM-PREDICT' , typename ( self ) )
1033999
10341000 return model , val_preds
10351001
@@ -1205,9 +1171,11 @@ def _train_single_model ( self,
12051171 verbose_eval = False
12061172 )
12071173
1208- from ostap .utils .memory import memory
1209-
1210- with memory ( "MEMORY XGBOOST" , logger = logger ) :
1174+ # =====================================================================
1175+ ## PHOENIX
1176+ # =====================================================================
1177+ if True : # ===========================================================
1178+ # =================================================================
12111179
12121180 # Export tree structure into a lightweight binary/JSON byte array
12131181 model_bytes = model .save_raw ( raw_format = "json" )
@@ -1222,7 +1190,7 @@ def _train_single_model ( self,
12221190 del model_bytes
12231191
12241192 gc .collect ()
1225-
1193+
12261194 # Compute validation predictions safely using pre-allocated contiguous array
12271195 val_preds = self ._predict_single_model ( model , X_val )
12281196
@@ -1400,10 +1368,12 @@ def _train_single_model ( self ,
14001368 verbose_level = params .get ('verbose' , False )
14011369 model .fit ( trn_pool , verbose = verbose_level , ** fit_kwargs )
14021370
1403- import pickle
1404- from ostap .utils .memory import memory
1405-
1406- with memory ( 'MEMORY CATBOOST' , logger = logger ) :
1371+ # =====================================================================
1372+ ## PHOENIX
1373+ # =====================================================================
1374+ if True : # ===========================================================
1375+ # =================================================================
1376+ import pickle
14071377
14081378 # Extract tree geometry into a lightweight binary blob
14091379 model_bytes = pickle .dumps ( model )
@@ -1586,7 +1556,7 @@ def forward ( self , x ) :
15861556
15871557 device = self .params .get ( 'device' , 'cuda' if torch .cuda .is_available () else 'cpu' )
15881558 if not torch .cuda .is_available () : device = 'cpu'
1589- device = torch .device ( device_str )
1559+ device = torch .device ( device )
15901560
15911561 patience = self .params .get ( 'patience' , 250 )
15921562 nepochs = self .params .get ( 'epochs' , 2000 )
@@ -1699,11 +1669,12 @@ def forward ( self , x ) :
16991669 if best_state is None :
17001670 best_state = { k : v .detach ().cpu ().clone () for k , v in model .state_dict ().items () }
17011671
1702- import gc
1703- from ostap .utils .memory import memory
1672+ # =====================================================================
1673+ ## PHOENIX
1674+ # =====================================================================
1675+ if True : # ===========================================================
1676+ # =================================================================
17041677
1705- with memory ( 'MEMORY PYTORCH' , logger = logger ) :
1706-
17071678 # Destroy heavy training objects, optimizer states, and CUDA/CPU tensors
17081679 del model , optimizer , scheduler , criterion_base
17091680 del X_tr_t , y_tr_t , w_tr_t , X_va_t , y_va_t , w_va_t
@@ -1713,9 +1684,6 @@ def forward ( self , x ) :
17131684 ##
17141685 if torch .cuda .is_available () : torch .cuda .empty_cache ()
17151686
1716- # -------------------------------------------------------------------------
1717- # RESTORATION OF CLEAN INFERENCE MODEL
1718- # -------------------------------------------------------------------------
17191687 # Instantiate a clean, stateless model dedicated strictly to inference
17201688 model = TabularMLP ( in_features = X_train .shape [1 ] ,
17211689 hidden_dims = hidden_dims ,
@@ -1771,7 +1739,8 @@ def _predict_single_model ( self , model , X ) :
17711739 'multi_class' ,
17721740 'verbose' ,
17731741 'warm_start' ,
1774- 'l1_ratio'
1742+ 'l1_ratio' ,
1743+ 'n_jobs'
17751744)
17761745# =============================================================================
17771746## @class LogRegressionDensityReweighter
@@ -1798,9 +1767,16 @@ def __init__( self , * ,
17981767 config = { 'C' : 1.0 ,
17991768 'solver' : 'lbfgs' ,
18001769 'max_iter' : 2000 ,
1801- 'polynomials' : 2 }
1770+ 'polynomials' : 2 }
1771+
18021772 config .update ( params )
18031773
1774+ poly = config .get ( 'polynomials' , 2 )
1775+ n_features = num_features ( original )
1776+
1777+ if 20 <= n_features and 1 < poly :
1778+ config [ 'polynomials' ] = 1
1779+
18041780 super ().__init__ ( original = original ,
18051781 target = target ,
18061782 original_weight = original_weight ,
@@ -1817,8 +1793,10 @@ def method ( self ) :
18171793 def regularization ( self , params , n_features , n_samples ) :
18181794 """ Dynamic regularization rules for Logistic Regression.
18191795 """
1820- current_c = params .get ( 'C' , 1.0 )
1821- params [ 'C' ] = max ( 0.1 , min ( current_c , 0.5 ) )
1796+ penalty = params .get ( 'penalty' , 'l2' )
1797+ if penalty not in ( None , 'none' ) :
1798+ current_c = params .get ( 'C' , 1.0 )
1799+ params [ 'C' ] = max ( 0.1 , min ( current_c , 0.5 ) )
18221800 return params
18231801
18241802 # =========================================================================
@@ -1837,13 +1815,15 @@ def _train_single_model ( self ,
18371815 params .pop ( 'n_jobs' , None )
18381816
18391817 poly = params .pop ( 'polynomials' , 2 )
1840-
1818+ n_features = num_features ( X_train )
1819+ if 20 <= n_features and 1 < poly : poly = 1
1820+
18411821 lr_kwargs = { k : v for k , v in params .items () if k in valid_LR_params }
18421822
18431823 # Build the pipeline
18441824 steps = [ ( 'scaler1' , StandardScaler () ) ]
18451825
1846- if poly and isinstance ( poly , int ) and 0 < poly <= 5 :
1826+ if poly and isinstance ( poly , int ) and 1 < poly <= 5 :
18471827 steps += [ ( 'poly' , PolynomialFeatures ( degree = poly , include_bias = False ) ) ]
18481828 steps += [ ( 'scaler2' , StandardScaler () ) ]
18491829
@@ -1857,6 +1837,22 @@ def _train_single_model ( self ,
18571837 if w_tr is not None : model .fit ( X_train , y_train , logistic__sample_weight = w_tr )
18581838 else : model .fit ( X_train , y_train )
18591839
1840+ # =====================================================================
1841+ ## PHOENIX
1842+ # =====================================================================
1843+ if True : # ===========================================================
1844+ # =================================================================
1845+ import pickle
1846+
1847+ model_bytes = pickle .dumps ( model )
1848+ del model
1849+ del w_tr
1850+
1851+ model = pickle .loads ( model_bytes )
1852+ del model_bytes
1853+
1854+ gc .collect ()
1855+
18601856 val_preds = self ._predict_single_model ( model , X_val )
18611857 return model , val_preds .astype ( numpy .float32 , copy = False )
18621858
@@ -1865,8 +1861,8 @@ def _train_single_model ( self ,
18651861 def _predict_single_model ( self , model , X ) :
18661862 """ Predict probabilities using a Logistic Regression model.
18671863 """
1868- X_clean = numpy .ascontiguousarray ( X , dtype = numpy .float64 )
1869- p = model .predict_proba ( X_clean ) [ : , 1 ]
1864+ X_clean = numpy .ascontiguousarray ( X , dtype = numpy .float32 )
1865+ p = model .predict_proba ( X_clean ) [ : , 1 ]
18701866 return p .astype ( numpy .float32 , copy = False )
18711867
18721868# ==============================================================================
@@ -1979,6 +1975,20 @@ def __init__ ( self , * ,
19791975 original_weight = original_weight ,
19801976 target_weight = target_weight )
19811977
1978+ # =====================================================================
1979+ ## PHOENIX
1980+ # =====================================================================
1981+ if True : # ===========================================================
1982+ # =================================================================
1983+ import pickle
1984+
1985+ model_bytes = pickle .dumps ( self .__reweighter )
1986+ del self .__reweighter
1987+ self .__reweighter = pickle .loads ( model_bytes )
1988+ del model_bytes
1989+
1990+ gc .collect ()
1991+
19821992 self .__original_ratios = None
19831993 self .__original_reweighted_weights = None
19841994 if store_original_weights :
0 commit comments