Coverage for uqmodels/custom_UQModel.py: 15%
314 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 14:29 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-05 14:29 +0000
1###################################################################################
2# UQModel : "Model than apply an modeling pipeline composed of an predictor(optional), UQestimator and KPI
3# To write a custom UQModel, inherite from UQModel class an use supoer().__init__()
5# Class UQmodels : from an UQestimators : perform dadada
7import numpy as np
9import uqmodels.postprocessing.custom_UQKPI_Processor as custom_UQProc
10import uqmodels.postprocessing.UQKPI_Processor as UQProc
11import uqmodels.preprocessing.preprocessing as pre_pre
12import uqmodels.preprocessing.structure as pre_struc
13from uqmodels.modelization.DL_estimator import lstm_ed, transformer_ed
14from uqmodels.modelization.DL_estimator.metalayers import mlp
15from uqmodels.modelization.DL_estimator.neural_network_UQ import (
16 NN_UQ,
17 get_params_dict,
18 get_training_parameters,
19)
20from uqmodels.modelization.ML_estimator.random_forest_UQ import (
21 RandomForestRegressor,
22 RF_UQEstimator,
23)
24from uqmodels.preprocessing.Custom_Preprocessor import Generic_Features_processor
25from uqmodels.preprocessing.features_processing import (
26 compute_pca,
27 fit_compute_lag_values,
28 fit_pca,
29)
30from uqmodels.processing import Cache_manager
31from uqmodels.UQModel import UQModel
32from uqmodels.utils import apply_mask, coefficients_spreaded, cut
34# We can also create a more complexe UQmodel that handle several UQKPI_Processor to build at inference (UQMesure, Predictive interval and model unreliability score) and after observation (Anomaly score)
36# Specification of the UQestimator & Instanciation in a UQmodels wrapper that include post-processing
39type_output = "MC_Dropout"
41factory_params = {"factory_lag_st": 0, "factory_lag_lt": 0}
44class TADKIT_UQModel(UQModel):
45 def __init__(
46 self,
47 y_shape,
48 n_window=20,
49 model="RF_UQ",
50 model_params=None,
51 epochs=30,
52 reduc_coef=True,
53 beta=0.001,
54 random_state=None,
55 cache_manager=Cache_manager(),
56 ):
58 lag_values_params = {
59 "lag": coefficients_spreaded(n_window),
60 "deriv": [0, 1],
61 "windows": [1, int(n_window / 4), n_window],
62 }
64 list_params_features = [lag_values_params]
65 list_fit_features = [fit_pca, None]
66 list_compute_features = [fit_compute_lag_values]
68 targets_params = {"lag": [0]}
69 list_params_targets = [targets_params]
70 list_fit_targets = [None]
71 list_compute_targets = [fit_compute_lag_values]
73 Formalizer = Generic_Features_processor(
74 name="Generic_Features_processor",
75 cache=None,
76 list_params_features=list_params_features,
77 list_fit_features=list_fit_features,
78 list_compute_features=list_compute_features,
79 list_params_targets=list_params_targets,
80 list_fit_targets=list_fit_targets,
81 list_compute_targets=list_compute_targets,
82 concat_features=True,
83 )
84 # Specification of the UQestimator
85 X_, y_ = Formalizer.fit_transform(np.zeros((2 * n_window, y_shape)))
86 X_shape = X_.shape[-1]
88 Anom_param = {
89 "type_norm": "Nsigma_global",
90 "em" "beta": beta,
91 "filt": [0.05, 0.15, 0.8, 0, 0],
92 "min_cut": 0.05,
93 "max_cut": 0.95,
94 "var_min": 0.0001,
95 "q_var": 0.7,
96 "q_var_e": 0.7,
97 "k_var_e": 1,
98 "q_Eratio": 1,
99 "d": 2,
100 "global_median_normalization": False,
101 "reduc_filter": None,
102 "roll": 0,
103 "with_born": False,
104 }
105 # PostProcesseur Instanciation that compute an epistemics lvl score
106 Anom_proc = UQProc.Anomscore_processor(KPI_parameters=Anom_param)
108 reduc_filter_pred = None
109 if model == "RF_UQ":
110 UQEstimator_initializer = RF_UQEstimator
111 if model_params is None:
112 estimator = RandomForestRegressor(
113 min_samples_leaf=5,
114 n_estimators=75,
115 max_depth=16,
116 ccp_alpha=0.00001,
117 max_samples=0.7,
118 max_features=0.75,
119 random_state=random_state,
120 )
122 UQEstimator_parameters = {
123 "estimator": estimator,
124 "var_min": 0.002,
125 "type_UQ": "var_A&E",
126 "rescale": True,
127 "random_state": random_state,
128 }
130 elif model == "MLP_MC_DROPOUT":
131 type_output = "MC_Dropout" # 'Deep_ensemble'
132 UQEstimator_initializer = NN_UQ
133 mlp_params = get_params_dict(X_shape, y_shape, type_output=type_output)
134 trainig_params = get_training_parameters(
135 epochs=[epochs], b_s=[64], l_r=[0.005], type_output=type_output
136 )
137 UQEstimator_initializer = NN_UQ
138 UQEstimator_parameters = {
139 "rescale": False,
140 "model_initializer": mlp,
141 "model_parameters": mlp_params,
142 "training_parameters": trainig_params,
143 "type_output": type_output,
144 "random_state": random_state,
145 }
147 elif model == "MLP_DEEP_ENSEMBLE":
148 type_output = "Deep_ensemble"
149 UQEstimator_initializer = NN_UQ
150 mlp_params = get_params_dict(X_shape, y_shape, type_output=type_output)
151 trainig_params = get_training_parameters(
152 epochs=[epochs], b_s=[64], l_r=[0.005], type_output=type_output
153 )
155 UQEstimator_parameters = {
156 "rescale": False,
157 "model_initializer": mlp,
158 "model_parameters": mlp_params,
159 "training_parameters": trainig_params,
160 "type_output": type_output,
161 "random_state": random_state,
162 }
164 UQ_proc = UQProc.UQKPI_Processor(
165 KPI_parameters={
166 "pred_and_UQ": True,
167 "reduc_filter": reduc_filter_pred,
168 "roll": 0,
169 "reduc_filter": reduc_filter_pred,
170 }
171 )
173 # Instanciation of the UQmodel modeling pipeline
174 UQModels = super().__init__(
175 UQEstimator_initializer,
176 UQEstimator_parameters,
177 preprocessor=Formalizer,
178 name="UQModels",
179 predictor=None,
180 list_predict_KPI_processors=[UQ_proc],
181 list_score_KPI_processors=[Anom_proc],
182 reduc_filter=reduc_filter_pred,
183 cache_manager=cache_manager,
184 random_state=random_state,
185 )
186 return UQModels
189class UQModel_KPI(UQModel):
190 def __init__(
191 self,
192 UQEstimator_initializer,
193 UQEstimator_params,
194 # Necesite with_prediction or to provide a predictor.
195 name="UQModel",
196 predictor=None,
197 preprocessor=None,
198 list_alpha=[0.025, 0.16, 0.84, 0.975],
199 list_percent_escore=[0.50, 0.80, 0.95, 0.98, 0.995, 1],
200 reduc_filter_pred=None,
201 reduc_filter_KPI=None,
202 roll_KPI=1,
203 anom_with_born=False,
204 beta=0.01,
205 var_min=0.001,
206 cache_manager=Cache_manager(),
207 q_Eratio=3,
208 mode_epistemic_indicator="levels",
209 random_state=None,
210 ):
212 UQ_proc = UQProc.UQKPI_Processor(
213 KPI_parameters={
214 "pred_and_UQ": True,
215 "reduc_filter": reduc_filter_pred,
216 "roll": 0,
217 }
218 )
220 # PostProcesseur that compute Predictive intervals
221 PIs_proc = UQProc.NormalPIs_processor(
222 KPI_parameters={
223 "list_alpha": list_alpha,
224 "reduc_filter": reduc_filter_pred,
225 "roll": 0,
226 }
227 )
229 # PostProcesseur that compute an epistemics lvl score
230 Elvl_proc = UQProc.Epistemicscorelvl_processor(
231 KPI_parameters={
232 "list_percent": list_percent_escore,
233 "reduc_filter": reduc_filter_pred,
234 "roll": 0,
235 "mode": mode_epistemic_indicator,
236 "q_Eratio": q_Eratio,
237 "var_min": var_min,
238 }
239 )
241 # PostProcesseur Instanciation that compute an epistemics lvl score
242 Anom_proc = UQProc.Anomscore_processor(
243 KPI_parameters={
244 "beta": beta,
245 "d": 2,
246 "var_min": var_min,
247 "q_var": 1,
248 "k_var_e": 1,
249 "q_var_e": 1,
250 "q_Eratio": 3,
251 "filt": [0.05, 0.15, 0.8, 0, 0],
252 "with_born": anom_with_born,
253 "reduc_filter": reduc_filter_KPI,
254 "roll": roll_KPI,
255 "debug": False,
256 }
257 )
259 list_predict_KPI_processors = [UQ_proc, PIs_proc, Elvl_proc]
260 list_score_KPI_processors = [UQ_proc, Anom_proc, PIs_proc, Elvl_proc]
262 super().__init__(
263 UQEstimator_initializer=UQEstimator_initializer,
264 UQEstimator_params=UQEstimator_params,
265 name=name,
266 predictor=predictor,
267 preprocessor=preprocessor,
268 list_predict_KPI_processors=list_predict_KPI_processors,
269 list_score_KPI_processors=list_score_KPI_processors,
270 reduc_filter=reduc_filter_pred,
271 cache_manager=cache_manager,
272 list_alpha=list_alpha,
273 list_percent_escore=list_percent_escore,
274 reduc_filter_pred=reduc_filter_pred,
275 reduc_filter_KPI=reduc_filter_KPI,
276 roll_KPI=roll_KPI,
277 anom_with_born=anom_with_born,
278 beta=beta,
279 var_min=var_min,
280 q_Eratio=q_Eratio,
281 mode_epistemic_indicator=mode_epistemic_indicator,
282 random_state=random_state,
283 )
286# Complex UQmodels link to EMS use case #################################################
289class MultiDEEPUQModel(UQModel):
290 """UQModel class for UQestimators that perform multisource forecast with UQ."""
292 def __init__(
293 self,
294 UQEstimator_initializer,
295 UQEstimator_params,
296 list_sources,
297 cut_params=(0.001, 0.999),
298 multiscale_anomscore_params=None,
299 name="MultiDEEPUQModel",
300 cache_manager=Cache_manager(),
301 save_result=True,
302 save_models=True,
303 with_generator=True,
304 reduc_filter=None,
305 random_state=None,
306 ):
307 """Instanciation of UQModels for UQestimators that perform multisource forecast with UQ
308 # No predict_KPIs_processor
309 # Multiscale_Anomscore_processor as score_predict_KPIS_processor :
310 # to product multidimensional anomaly score matrix
313 Args:
314 UQEstimator_initializer (obj_init): init method for instanciate an UQEstimator
315 UQEstimator_params (dict_params): params for the init method
316 list_sources (List_str): Name of source for storage purpose
317 cut_params (tuple, optional): Lower and upper quantile to threshold data and remove outliers during
318 learning phase. Defaults to (0.001, 0.999).
319 multiscale_anomscore_params : params link to postprocessing.UQ_processor.Multiscale_Anomscore_processor
320 -> to see defaults parameters.
321 name (str, optional): Wrapper name . Defaults to 'MultiDEEPUQModel'.
322 cache_manager (cache_manager, optional): cache_manager. Defaults to None.
323 """
324 self.futur_horizon = (
325 UQEstimator_params["model_parameters"]["dim_horizon"]
326 * UQEstimator_params["model_parameters"]["step"]
327 )
328 if multiscale_anomscore_params is None:
329 multiscale_anomscore_params = {
330 "type_norm": "Nsigma_local",
331 "q_var": 1,
332 "d": 2,
333 "beta": 0.001,
334 "beta_source": 0.001,
335 "beta_global": 0.001,
336 "min_cut": 0.002,
337 "max_cut": 0.998,
338 "per_seuil": 0.999,
339 "reduc_filter": np.ones(self.futur_horizon),
340 "roll": 1,
341 "dim_chan": 1,
342 "type_fusion": "mahalanobis",
343 "filt": [0.1, 0.2, 0.5, 0.2, 0.1],
344 }
346 list_score_KPI_processors = [
347 custom_UQProc.Multiscale_Anomscore_processor(
348 KPI_parameters=multiscale_anomscore_params
349 )
350 ]
352 super().__init__(
353 UQEstimator_initializer,
354 UQEstimator_params,
355 name,
356 predictor=None,
357 list_predict_KPI_processors=[],
358 list_score_KPI_processors=list_score_KPI_processors,
359 cache_manager=cache_manager,
360 save_result=save_result,
361 save_models=save_models,
362 random_state=random_state,
363 )
365 if reduc_filter is None:
366 self.reduc_filter = np.zeros(self.futur_horizon) == 1
367 self.reduc_filter[0] = True
368 else:
369 self.reduc_filter = reduc_filter
371 self.with_generator = with_generator
372 self.list_sources = list_sources
373 self.list_chan = ["Mean", "Std", "Extremum", "Count"]
374 self.cut_params = cut_params
376 def multi_score_reshape(self, y=None, pred=None, UQ=None, mask=None):
377 """Reshape from (n_sample,n_sources*s_chan) to List of n_sources (n_sample,n_chan) elements
379 Args:
380 y (np.array, optional): y to reshape or None. Defaults to None.
381 pred (np.array, optional): pred to reshape or None. Defaults to None.
382 UQ (np.array, optional): UQ to reshape or None. Defaults to None.
383 return:
384 list_y,list_pred,list_UQ
385 """
386 n_sources = len(self.list_sources)
387 n_chan = len(self.list_chan)
389 list_y = None
390 if y is not None:
391 size_data = len(y)
392 list_y = [
393 np.squeeze(y[:, mask, n_chan * i : n_chan * (i + 1)])
394 for i in range(n_sources)
395 ]
397 # Issues : Reshape DL
398 list_pred = None
399 if pred is not None:
400 size_data = len(pred)
401 list_pred = [
402 np.squeeze(pred[:, mask, n_chan * i : n_chan * (i + 1)])
403 for i in range(n_sources)
404 ]
406 list_UQ = None
407 if UQ is not None:
408 # IF UQ measure is not composed
409 if (len(UQ.shape) == 2) & (size_data == UQ.shape[1]):
410 UQ = UQ[None]
411 list_UQ = [
412 np.squeeze(
413 np.array(
414 [
415 UQ_chan[:, mask, n_chan * i : n_chan * (i + 1)]
416 for UQ_chan in UQ
417 ]
418 )
419 )
420 for i in range(n_sources)
421 ]
423 return (list_y, list_pred, list_UQ)
425 def fit(
426 self, X, y, sample_weight=None, skip_UQEstimator=False, shuffle=True, **kwargs
427 ):
428 """Fit method that apply fit method of (predictor), UQEstimators, predict_KPI_processors, score_KPI_processors
429 Args:
430 X (np.array): Features
431 y (np.array): Targets/observations
432 sample_weight (np.array or None, optional): sample_weight. Defaults to None.
433 """
435 # Init deep learning model
436 if not self.UQEstimator:
437 self.UQEstimator = self.UQEstimator_initializer(**self.UQEstimator_params)
439 self.type_UQ = self.UQEstimator.type_UQ
440 self.type_UQ_params = None
441 if hasattr(self.UQEstimator, "type_UQ_params"):
442 self.type_UQ_params = self.UQEstimator.type_UQ_params
444 set_ = len(y)
445 train_deep = np.arange(set_) < (set_ * 4 / 6)
446 np.invert(train_deep)
448 # Call to factory method of model to transform features.
449 if not (self.with_generator) & hasattr(self.UQEstimator, "factory"):
450 train_deep = np.arange(set_) < (set_ * 4 / 6)
451 inputs, targets, _ = self.UQEstimator.factory(
452 X, y, train_deep, self.cut_params
453 )
455 else:
456 inputs, targets = X, y
458 # Call to fit method of model to perform multivarite fiting.
459 if not skip_UQEstimator:
460 self.UQEstimator.fit(
461 inputs,
462 targets,
463 sample_weight=sample_weight,
464 skip_format=True,
465 generator=self.with_generator,
466 shuffle=shuffle,
467 )
468 self.is_fitted = True
470 if self.save_result:
471 self.save()
473 # Then call to fit for the post-processing procedure
474 pred, UQ = self.UQEstimator.predict(
475 inputs, skip_format=True, generator=self.with_generator
476 )
478 _, y_bis, _ = self.UQEstimator.factory(
479 None, y, np.arange(len(y)), self.cut_params
480 )
482 y, pred, UQ = self.multi_score_reshape(
483 y_bis, pred, UQ, mask=(np.ones(self.futur_horizon) == 1)
484 )
486 self._fit_score_KPI_processors(UQ, pred, y, **kwargs)
488 def predict(self, X, name_save="output.p"):
489 """Predict method that apply predictor and UQestimators predict method, then compute predict_KPIs by use
490 transform methods of predict_KPI_Processors
492 Args:
493 X (np.array): feature
494 name_save (str, optional): file_name for (Predictor) and UQEstimator outputs save file.
495 Defaults to "output.p".
497 Returns:
498 pred, UQ : prediction and UQmeasure
499 """
500 if not (self.with_generator) & hasattr(self.UQEstimator, "factory"):
501 inputs, _, _ = self.UQEstimator.factory(
502 X, None, np.arange(len(X)), self.cut_params
503 )
505 else:
506 inputs, _ = X, None
508 pred, UQ = self.UQEstimator.predict(
509 inputs, beta=0.1, skip_format=True, generator=self.with_generator
510 )
512 mask = np.zeros(self.futur_horizon)
513 mask[0] = 1
515 _, list_pred, list_UQ = self.multi_score_reshape(
516 None, pred=pred, UQ=UQ, mask=(mask == 1)
517 )
519 if self.save_result:
520 # Save in a multi_folder by source ways model outputs
521 for n, source in enumerate(self.list_sources):
522 query = {"name": source + "_" + name_save}
523 self.cache_manager.save(query, (list_pred[n], list_UQ[n]))
524 return pred, UQ
526 def _recovers_KPI(self, mode, name_save="output.p", **kwargs):
527 if mode == "output":
528 if name_save is None:
529 name_save = "output.p"
530 query = {"name": name_save}
531 loaded_data = self.cache_manager.load(query)
533 if mode == "score":
534 if name_save is None:
535 name_save = "dict_res_anom.p"
536 query = {"name": name_save}
537 loaded_data = self.cache_manager.load(query)
538 return loaded_data
540 def score(self, X, y, **kwargs):
541 """Score method that produce score KPI that transform y observation and (pred,UQ)
542 UQestimator outputs into a KPI according to score_KPI_processors
544 Args:
545 X (np.array): Features
546 y (np.array): Targets/obserbations
548 Returns:
549 list_KPI_output: (List_Pred,list_UQ),KPI_anom
550 """
552 pred, UQ = self.predict(X)
553 _, y_bis, _ = self.UQEstimator.factory(
554 None, y, np.arange(len(y)), self.cut_params
555 )
557 list_y, list_pred, list_UQ = self.multi_score_reshape(
558 y=y_bis, pred=pred, UQ=UQ, mask=(np.ones(self.futur_horizon) == 1)
559 )
561 KPIs_anom = self._transform_score_KPI_processors(
562 list_UQ, list_pred, list_y, **kwargs
563 )
565 S_anom_chan, S_anom_agg, S_anom_sensor, list_bot, list_top = KPIs_anom
567 # Turn Multi-pred_horizon into
569 list_y, list_pred, list_UQ = self.multi_score_reshape(
570 y=y_bis, pred=pred, UQ=UQ, mask=self.reduc_filter
571 )
572 dict_res_anom = {
573 "name": self.name,
574 "S_anom_chan": S_anom_chan,
575 "S_anom_agg": S_anom_agg,
576 "S_anom_sensor": S_anom_sensor,
577 "list_y": list_y,
578 "list_pred": list_pred,
579 "list_UQ": list_UQ,
580 "list_bot": list_bot,
581 "list_top": list_top,
582 }
584 if self.save_result:
585 query = {"name": "dict_res_anom"}
586 self.cache_manager.save(query, dict_res_anom)
587 return (list_pred, list_UQ), KPIs_anom
590# @To do refactoring as UQestimator:
593class MultiUQModel(UQModel):
594 """Instanciation of UQModels that apply an UQestimator for each sources and combine results for compute
595 multidimensional anomaly score
597 No predict_KPIs_processor
598 Multiscale_Anomscore_processor as score_predict_KPIS_processor : to product multidimensional anomaly score matrix
599 """
601 def __init__(
602 self,
603 UQEstimator_initializer,
604 UQEstimator_params,
605 tunning_params,
606 list_sources,
607 list_delta=None,
608 target_delta=None,
609 multiscale_anomscore_params=None,
610 models_in_ram=True,
611 cut_params=(0.001, 0.999),
612 name="Multi_RFUQModels",
613 cache_manager=Cache_manager(),
614 save_models=True,
615 save_result=True,
616 random_state=None,
617 ):
618 """Initialization of MultiUQModel class
620 Args:
621 UQEstimator_initializer (obj_init): init method for instanciate an UQEstimator
622 UQEstimator_params (dict_params): params for the init method of the UQEstimator
623 tunning_params (dict_grid_params): grid params for tuning UQEstiamtor using scikit
624 list_sources (List_str): Name of source for storage purpose
625 models_in_ram : specify if manipulate list of UQestimators in ram (heavy in ram), or store and load.
626 cut_params (tuple, optional): Lower and upper quantile to threshold data and remove outliers during
627 learning phase. Defaults to (0.001, 0.999).
628 multiscale_anomscore_params : params link to postprocessing.UQ_processor.Multiscale_Anomscore_processor
629 -> to see defaults parameters.
630 name (str, optional): Wrapper name . Defaults to 'MultiDEEPUQModel'.
631 cache_manager (cache_manager, optional): cache_manager. Defaults to None.
632 """
633 if multiscale_anomscore_params is None:
634 multiscale_anomscore_params = {
635 "type_norm": "Nsigma_local",
636 "q_var": 1,
637 "d": 2,
638 "beta": 0.001,
639 "beta_source": 0.001,
640 "beta_global": 0.001,
641 "min_cut": 0.002,
642 "max_cut": 0.998,
643 "per_seuil": 0.999,
644 "type_fusion": "mahalanobis",
645 "filt": [0.1, 0.2, 0.5, 0.2, 0.1],
646 }
648 list_score_KPI_processors = [
649 custom_UQProc.Multiscale_Anomscore_processor(
650 KPI_parameters=multiscale_anomscore_params
651 )
652 ]
654 super().__init__(
655 UQEstimator_initializer,
656 UQEstimator_params,
657 name,
658 list_score_KPI_processors=list_score_KPI_processors,
659 cache_manager=cache_manager,
660 save_models=save_models,
661 save_result=save_result,
662 random_state=random_state,
663 )
664 self.tunning_params = tunning_params
665 self.list_sources = list_sources
666 self.list_delta = list_delta
667 self.target_delta = target_delta
668 self.UQEstimators_in_ram = models_in_ram
669 self.cut_params = cut_params
670 if self.UQEstimators_in_ram:
671 self.list_UQEstimators = []
672 for _ in list_sources:
673 self.list_UQEstimators.append([])
675 def get_model(self, id_source):
676 """Get model of an id_source
678 Args:
679 model (UQEstimator): UQEstimator to set
680 id_source (int): Id_source
681 """
682 print("get model", id_source)
683 if self.UQEstimators_in_ram:
684 idx = self.list_sources.index(id_source)
685 print("get model", idx)
686 model = self.list_UQEstimators[idx]
687 else:
688 query = {"name": id_source + "_" + self.name}
689 model = self.cache_manager.load(query)
690 return model
692 def set_model(self, model, id_source):
693 """Set model of an id_source
695 Args:
696 model (UQEstimator): UQEstimator to set
697 id_source (int): Id_source
698 """
699 if self.UQEstimators_in_ram:
700 idx = self.list_sources.index(id_source)
701 self.list_UQEstimators[idx] = model
702 else:
703 query = {"name": id_source + "_" + self.name}
704 self.cache_manager.save(query, model)
705 del model
707 def _aux_fit(
708 self,
709 X,
710 y,
711 sample_weight=None,
712 train=None,
713 skip_UQEstimator=False,
714 source=None,
715 **kwargs
716 ):
717 """Fit method that apply fit method of (predictor) for source, the
718 Args:
719 X (np.array): Features
720 y (np.array): Targets/observations
721 sample_weight (np.array or None, optional): sample_weight. Defaults to None.
722 """
724 if not skip_UQEstimator:
725 # Instanciate model
726 model = self.UQEstimator_initializer(**self.UQEstimator_params)
728 # Store type_UQ
729 self.type_UQ = model.type_UQ
730 self.type_UQ_params = None
731 if hasattr(model, "type_UQ_params"):
732 self.type_UQ_params = model.type_UQ_params
734 if train is None:
735 train = np.ones(len(X)) == 1
736 # Run tunning if having gridsearch params
737 if self.tunning_params is not None:
738 model._tuning(
739 X[train], y[train], n_esti=100, folds=4, params=self.tunning_params
740 )
742 print("Fitting model source :", source)
743 y = cut(y, self.cut_params[0], self.cut_params[1])
744 model.fit(X[train], y[train], sample_weight=sample_weight[train], **kwargs)
746 self.set_model(model, source)
748 def _recovers_all_results(self, mode):
749 """auxiliar function aim to load stored output for each source_UQEstimators
751 Args:
752 mode (str): specify 'output' to load output, score to load Anom kpi
754 Returns:
755 results: List_pred,List_UQ if output, Anom-KPIs if 'score'
756 """
758 if mode == "output":
759 # recover pred,output for each source_UQestimator
761 list_outputs = [
762 self.cache_manager.load({"name": source + "_output"})
763 for source in self.list_sources
764 ]
765 loaded_data = (
766 [output[0] for output in list_outputs],
767 [output[1] for output in list_outputs],
768 )
769 del list_outputs
771 if mode == "score":
772 query = {"name": "dict_res_anom"}
773 loaded_data = self.cache_manager.load(query)
775 return loaded_data
777 def fit(self, X, y, sample_weight=None, skip_UQEstimator=False, **kwargs):
778 """Fit method that apply fit method of (predictor) for eachs source_UQEstimators,
779 then fit the Anom_KPI_processors.
781 Args:
782 X (np.array): Features
783 y (np.array): Targets/observations
784 sample_weight (np.array or None, optional): sample_weight. Defaults to None.
785 """
786 for n, (X_, y_) in enumerate(zip(X, y)):
787 source = self.list_sources[n]
788 if sample_weight is not None:
789 sample_weight_ = sample_weight[n]
790 self._aux_fit(
791 X_,
792 y_,
793 sample_weight_,
794 train=None,
795 skip_UQEstimator=skip_UQEstimator,
796 source=source,
797 **kwargs
798 )
799 del X_, y_
800 self.is_fitted = True
801 list_pred, list_UQ = self.predict(X, recovers_at_end=False, **kwargs)
802 self._fit_score_KPI_processors(list_UQ, list_pred, y, **kwargs)
803 if self.save_models:
804 self.save()
806 def fit_with_generator(
807 self, data_generator, skip_UQEstimator=False, shuffle=True, **kwargs
808 ):
809 """Specific fit method that handle data_generator
811 Args:
812 data_generator (datagenerator): Iterative object that provide : X, y, sample_weight, x_split, context,
813 objective, source (see data_generator)
814 shuffle (bool, optional): use shuffle or not. Defaults to True.
815 """
816 list_y = []
817 list_UQ = []
818 list_pred = []
819 for _n, dataset in enumerate(data_generator):
820 # Recovers data from data_generator
821 X, y, sample_weight, x_split, _context, _objective, source = dataset
822 train = None
823 if x_split is not None:
824 train = x_split == 1
825 X, y = apply_mask(X, train), apply_mask(y, train)
826 if sample_weight is not None:
827 sample_weight = sample_weight[train]
828 # Called fit procedure for each dataset
829 self._aux_fit(
830 X,
831 y,
832 sample_weight=sample_weight,
833 train=None,
834 skip_UQEstimator=skip_UQEstimator,
835 source=source,
836 **kwargs
837 )
838 pred, UQ = self._aux_predict(X, source, **kwargs)
839 list_y.append(y)
840 list_pred.append(pred)
841 list_UQ.append(UQ)
842 self._fit_score_KPI_processors(list_UQ, list_pred, list_y, **kwargs)
844 def _aux_predict(self, X, source, **kwargs):
845 model = self.get_model(source)
847 pred, UQ = model.predict(X, **kwargs)
848 del model
850 # Store results
851 if self.save_result:
852 query = {"name": source + "_output.p"}
853 self.cache_manager.save(query, (pred, UQ))
855 return pred, UQ
857 def predict(self, X, recovers_at_end=False, **kwargs):
858 """Predict method that applies predictor and UQestimators predict method, then computes predict_KPIs
859 by using transform methods of predict_KPI_Processors.
861 Args:
862 X (np.array): feature
863 name_save (str, optional): file_name for (Predictor) and UQEstimator outputs save file.
864 Defaults to "output.p".
866 Returns:
867 pred, UQ : prediction and UQmeasure
868 """
869 list_pred = []
870 list_UQ = []
871 for n, X_ in enumerate(X):
872 source = self.list_sources[n]
873 pred, UQ = self._aux_predict(X_, source, **kwargs)
874 if not recovers_at_end:
875 list_pred.append(pred)
876 list_UQ.append(UQ)
877 del pred, UQ, X_
879 if recovers_at_end:
880 pred, UQ = self._recovers_at_end("output")
882 return (pred, UQ)
884 def predict_with_generator(self, data_generator, recovers_at_end=True, **kwargs):
885 list_pred = []
886 list_UQ = []
887 for _n, (X, _, _, _, _, _, source) in enumerate(data_generator):
888 # Recovers data from data_generator
889 output = self._aux_predict(X, source, **kwargs)
890 if not (recovers_at_end):
891 list_pred.append(output[0])
892 list_UQ.append(output[1])
893 del output, X
895 if recovers_at_end:
896 list_pred, list_UQ = self._recovers_all_results("output")
897 return (list_pred, list_UQ)
899 def _aux_score(self, list_y, list_pred, list_UQ, **kwargs):
900 if (self.list_delta is not None) & (self.target_delta is not None):
901 for n in np.arange(len(list_y)):
902 if not self.list_delta[n] == self.target_delta:
903 current_delta = pre_struc.check_delta(self.list_delta[n])
904 target_delta = pre_struc.check_delta(self.target_delta)
905 ratio = current_delta / target_delta
907 # Scale différent entre capteurs
908 x = np.arange(0, list_y[n])
909 x_new = np.arange(0, len(list_y[n]), ratio)
911 list_y[n] = pre_pre.interpolate(
912 x=x, y=list_y[n], xnew=x_new, type_interpolation="previous"
913 )[1]
915 list_pred[n] = pre_pre.interpolate(
916 x=x, y=list_pred[n], xnew=x_new, type_interpolation="previous"
917 )[1]
919 UQ_temp = [
920 pre_pre.interpolate(
921 x=x, y=UQ_part, xnew=x_new, type_interpolation="previous"
922 )[1]
923 for UQ_part in list_UQ
924 ]
925 if len(UQ_temp) == 1:
926 UQ_temp = UQ_temp[0]
928 list_UQ[n] = UQ_temp
930 KPIs_anom = self._transform_score_KPI_processors(
931 list_UQ, list_pred, list_y, **kwargs
932 )
933 S_anom_chan, S_anom_agg, S_anom_sensor, list_bot, list_top = KPIs_anom
935 dict_res_anom = {
936 "name": self.name,
937 "list_y": list_y,
938 "list_pred": list_pred,
939 "list_UQ": list_UQ,
940 "S_anom_chan": S_anom_chan,
941 "S_anom_agg": S_anom_agg,
942 "S_anom_sensor": S_anom_sensor,
943 "list_bot": list_bot,
944 "list_top": list_top,
945 }
947 if self.cache_manager is not None:
948 query = {"name": "dict_res_anom"}
949 self.cache_manager.save(query, dict_res_anom)
951 return (S_anom_chan, S_anom_agg, S_anom_sensor)
953 def score(self, X, y, **kwargs):
954 """Score method that produces score KPI by transforming y observation and (pred,UQ) UQestimator outputs
955 into a KPI according to score_KPI_processors.
957 Args:
958 X (np.array): Features
959 y (np.array): Targets/obserbations
961 Returns:
962 list_KPI_output: list_KPI_output or KPI_ouput if len(list)==1
963 """
964 list_pred, list_UQ = self.predict(X)
965 KPI_anom = self._aux_score(y, list_pred, list_UQ)
966 return (list_pred, list_UQ), KPI_anom
968 def score_with_generator(self, data_generator, recovers_at_end=True, **kwargs):
969 list_y = []
970 list_pred = []
971 list_UQ = []
972 for _n, (X, y, _, _, _, _, source) in enumerate(data_generator):
973 list_y.append(y)
974 output = self._aux_predict(X, source, **kwargs)
975 if not recovers_at_end:
976 list_pred.append(output[1])
977 list_UQ.append(output[2])
978 del output, X, y
980 if recovers_at_end:
981 list_pred, list_UQ = self._recovers_all_results("output")
983 KPI_anom = self._aux_score(list_y, list_pred, list_UQ)
984 return (list_pred, list_UQ), KPI_anom