@@ -110,7 +110,7 @@ def getNFeaturesMarkovBlanket(
110110 svc_kernel (str): The kernel to be used by the SVC model.
111111 Defaults to "rbf".
112112 suppress_print (bool): If True, suppresses stdout from the fit method.
113- Defaults to "rbf" .
113+ Defaults to True .
114114
115115 Raises:
116116 TypeError: If X_train is not a pandas DataFrame.
@@ -119,6 +119,9 @@ def getNFeaturesMarkovBlanket(
119119 List[str]: A list containing the names of the top n features from
120120 the Markov Blanket.
121121 """
122+ import os
123+ import sys
124+
122125 # Ensure input is a pandas DataFrame to access column names
123126 if not isinstance (X_train , pd .DataFrame ):
124127 raise TypeError (
@@ -131,53 +134,86 @@ def getNFeaturesMarkovBlanket(
131134 stratified_kfold = StratifiedKFold (n_splits = cv , shuffle = True , random_state = 27 )
132135
133136 # Use the provided classifier, or default to SVC if none is given.
134- model_to_use = classifier if classifier is not None else SVC (random_state = 27 , class_weight = "balanced" , kernel = svc_kernel )
135-
136- # Initialize the PyImpetus object with desired parameters
137- model = PPIMBC (model = model_to_use ,
138- p_val_thresh = 0.05 ,
139- num_simul = num_simul ,
140- simul_size = 0.2 ,
141- simul_type = 0 ,
142- sig_test_type = "non-parametric" ,
143- cv = stratified_kfold ,
144- random_state = 27 ,
145- n_jobs = - 1 ,
146- # Set verbose to 0 to prevent calls to the problematic
147- # progress printing function in joblib, which causes the
148- # 'AttributeError: ... _pre_dispatch_amount'.
149- verbose = 0 )
137+ # CRITICAL: Set verbose=False for SVC to prevent LibSVM output
138+ model_to_use = classifier if classifier is not None else SVC (
139+ random_state = 27 ,
140+ class_weight = "balanced" ,
141+ kernel = svc_kernel ,
142+ verbose = False # This is the key parameter for LibSVM
143+ )
150144
151- import os
152- import sys
145+ # Ensure verbose is set to False at multiple levels
146+ if hasattr (model_to_use , 'set_params' ):
147+ try :
148+ model_to_use .set_params (verbose = False )
149+ except :
150+ pass
151+ if hasattr (model_to_use , 'verbose' ):
152+ model_to_use .verbose = False
153+
154+ # Suppress output at the OS level BEFORE creating any model objects
155+ devnull_fd = None
156+ old_stdout_fd = None
157+ old_stderr_fd = None
158+
159+ if suppress_print :
160+ try :
161+ # Save original file descriptors
162+ old_stdout_fd = os .dup (1 )
163+ old_stderr_fd = os .dup (2 )
164+
165+ # Open devnull and redirect stdout/stderr to it
166+ devnull_fd = os .open (os .devnull , os .O_RDWR )
167+ os .dup2 (devnull_fd , 1 )
168+ os .dup2 (devnull_fd , 2 )
169+ except Exception as e :
170+ # If suppression fails, just continue without it
171+ logging .getLogger ('ml_grid' ).warning (f"Could not suppress output: { e } " )
172+ suppress_print = False
153173
154- # Fit and transform the training data
155- # PyImpetus works with numpy arrays and returns feature indices in model.MB
156174 try :
157- if suppress_print :
158- # Use OS-level redirection to silence C-level libraries like LibSVM
159- devnull = os .open (os .devnull , os .O_WRONLY )
160- old_stdout = os .dup (1 )
161- old_stderr = os .dup (2 )
162- os .dup2 (devnull , 1 )
163- os .dup2 (devnull , 2 )
164- try :
165- model .fit (X_train .values , y_train )
166- finally :
167- # Restore original stdout and stderr
168- os .dup2 (old_stdout , 1 )
169- os .dup2 (old_stderr , 2 )
170- os .close (devnull )
171- os .close (old_stdout )
172- os .close (old_stderr )
173- else :
174- model .fit (X_train .values , y_train )
175+ # Initialize the PyImpetus object with desired parameters
176+ model = PPIMBC (model = model_to_use ,
177+ p_val_thresh = 0.05 ,
178+ num_simul = num_simul ,
179+ simul_size = 0.2 ,
180+ simul_type = 0 ,
181+ sig_test_type = "non-parametric" ,
182+ cv = stratified_kfold ,
183+ random_state = 27 ,
184+ n_jobs = - 1 ,
185+ verbose = 0 )
186+
187+ # Fit the model (this is where LibSVM prints)
188+ model .fit (X_train .values , y_train )
189+
175190 except ValueError as e :
191+ # Restore output before logging
192+ if suppress_print and old_stdout_fd is not None :
193+ os .dup2 (old_stdout_fd , 1 )
194+ os .dup2 (old_stderr_fd , 2 )
195+ if devnull_fd is not None :
196+ os .close (devnull_fd )
197+ os .close (old_stdout_fd )
198+ os .close (old_stderr_fd )
199+
176200 # This handles cases where PyImpetus fails due to numerical precision
177201 # issues (e.g., y_prob > 1). We'll log the error and fall back to
178202 # using all original features for this trial.
179203 logging .getLogger ('ml_grid' ).error (f"PyImpetus failed during fit: { e } . Using all features as a fallback." )
180204 return list (original_columns )
205+ finally :
206+ # Always restore stdout/stderr
207+ if suppress_print and old_stdout_fd is not None :
208+ try :
209+ os .dup2 (old_stdout_fd , 1 )
210+ os .dup2 (old_stderr_fd , 2 )
211+ if devnull_fd is not None :
212+ os .close (devnull_fd )
213+ os .close (old_stdout_fd )
214+ os .close (old_stderr_fd )
215+ except :
216+ pass # Silently fail if restoration doesn't work
181217
182218 # Get the feature indices from the Markov blanket (MB)
183219 selected_features = model .MB
0 commit comments