PyIAML 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iaml/__init__.py +56 -0
- iaml/actionable.py +11 -0
- iaml/actionables/__init__.py +21 -0
- iaml/actionables/boosting/__init__.py +4 -0
- iaml/actionables/boosting/act_adaboost.py +59 -0
- iaml/actionables/cleaning/__init__.py +26 -0
- iaml/actionables/cleaning/act_categorical_imputer.py +124 -0
- iaml/actionables/cleaning/act_count_vectorizer.py +204 -0
- iaml/actionables/cleaning/act_drop_categorical_column.py +51 -0
- iaml/actionables/cleaning/act_drop_date_column.py +48 -0
- iaml/actionables/cleaning/act_drop_high_cardinality_categorical.py +337 -0
- iaml/actionables/cleaning/act_drop_numerical_column.py +75 -0
- iaml/actionables/cleaning/act_drop_textual_column.py +51 -0
- iaml/actionables/cleaning/act_encode_target_column.py +56 -0
- iaml/actionables/cleaning/act_frequency_encoder.py +127 -0
- iaml/actionables/cleaning/act_hashing_vectorizer.py +186 -0
- iaml/actionables/cleaning/act_knn_imputer.py +152 -0
- iaml/actionables/cleaning/act_mean_column.py +79 -0
- iaml/actionables/cleaning/act_mice.py +464 -0
- iaml/actionables/cleaning/act_missing_count_feature.py +109 -0
- iaml/actionables/cleaning/act_missing_indicator.py +124 -0
- iaml/actionables/cleaning/act_onehot.py +65 -0
- iaml/actionables/cleaning/act_ordinal_encoder.py +177 -0
- iaml/actionables/cleaning/act_rare_category_grouper.py +173 -0
- iaml/actionables/cleaning/act_simple_imputer.py +109 -0
- iaml/actionables/cleaning/act_split_date.py +68 -0
- iaml/actionables/cleaning/act_target_encoder.py +274 -0
- iaml/actionables/cleaning/act_text_normalizer.py +241 -0
- iaml/actionables/cleaning/act_tf_idf.py +80 -0
- iaml/actionables/cleaning/act_word2vec.py +150 -0
- iaml/actionables/features_precleaning/__init__.py +12 -0
- iaml/actionables/features_precleaning/act_coerce_numeric_strings.py +194 -0
- iaml/actionables/features_precleaning/act_date_converter.py +99 -0
- iaml/actionables/features_precleaning/act_drop_bad_quality_rows.py +77 -0
- iaml/actionables/features_precleaning/act_drop_duplicate_rows.py +131 -0
- iaml/actionables/features_precleaning/act_drop_high_missing_columns.py +94 -0
- iaml/actionables/features_precleaning/act_drop_id_like_columns.py +294 -0
- iaml/actionables/features_precleaning/act_normalize_column_names.py +157 -0
- iaml/actionables/features_precleaning/act_sentinel_to_na_n.py +270 -0
- iaml/actionables/features_precleaning/act_trim_space.py +79 -0
- iaml/actionables/features_preprocessing/__init__.py +18 -0
- iaml/actionables/features_preprocessing/act_cyclical_date_encoding.py +212 -0
- iaml/actionables/features_preprocessing/act_fast_ica.py +161 -0
- iaml/actionables/features_preprocessing/act_feature_agglomeration.py +90 -0
- iaml/actionables/features_preprocessing/act_k_bins_discretizer.py +207 -0
- iaml/actionables/features_preprocessing/act_k_means_features.py +296 -0
- iaml/actionables/features_preprocessing/act_kernel_pca.py +143 -0
- iaml/actionables/features_preprocessing/act_log_transformer.py +122 -0
- iaml/actionables/features_preprocessing/act_nystroem.py +100 -0
- iaml/actionables/features_preprocessing/act_pca.py +77 -0
- iaml/actionables/features_preprocessing/act_polynomial_features.py +86 -0
- iaml/actionables/features_preprocessing/act_power_transformer.py +106 -0
- iaml/actionables/features_preprocessing/act_quantile_transformer.py +114 -0
- iaml/actionables/features_preprocessing/act_rbf_sampler.py +88 -0
- iaml/actionables/features_preprocessing/act_select_percentile.py +112 -0
- iaml/actionables/features_preprocessing/act_sparse_random_projection.py +157 -0
- iaml/actionables/features_preprocessing/act_truncated_svd.py +137 -0
- iaml/actionables/features_selection/__init__.py +8 -0
- iaml/actionables/features_selection/act_permutation_importance_selector.py +421 -0
- iaml/actionables/features_selection/act_remove_high_correlated_column.py +70 -0
- iaml/actionables/features_selection/act_remove_low_variance_column.py +74 -0
- iaml/actionables/features_selection/act_rfe.py +214 -0
- iaml/actionables/features_selection/act_select_from_model.py +325 -0
- iaml/actionables/features_selection/act_select_k_best.py +181 -0
- iaml/actionables/features_selection/act_vif_selector.py +130 -0
- iaml/actionables/imbalance/__init__.py +10 -0
- iaml/actionables/imbalance/act_adasyn.py +150 -0
- iaml/actionables/imbalance/act_borderline_smote.py +171 -0
- iaml/actionables/imbalance/act_near_miss.py +158 -0
- iaml/actionables/imbalance/act_random_over_sampling.py +60 -0
- iaml/actionables/imbalance/act_random_under_sampler.py +135 -0
- iaml/actionables/imbalance/act_smote.py +162 -0
- iaml/actionables/imbalance/act_smote_tomek.py +182 -0
- iaml/actionables/imbalance/act_smoteenn.py +193 -0
- iaml/actionables/imbalance/act_tomek_links.py +138 -0
- iaml/actionables/normalize/__init__.py +6 -0
- iaml/actionables/normalize/act_max_abs_scaler.py +78 -0
- iaml/actionables/normalize/act_minmax_scaler.py +56 -0
- iaml/actionables/normalize/act_normalizer.py +95 -0
- iaml/actionables/normalize/act_robust_scaler.py +111 -0
- iaml/actionables/normalize/act_standard_scaler.py +55 -0
- iaml/actionables/predictors/__init__.py +6 -0
- iaml/actionables/predictors/_xgboost.py +16 -0
- iaml/actionables/predictors/classifier/__init__.py +26 -0
- iaml/actionables/predictors/classifier/act_bagging_classifier.py +113 -0
- iaml/actionables/predictors/classifier/act_bernoulli_nb.py +89 -0
- iaml/actionables/predictors/classifier/act_catboost_classifier.py +135 -0
- iaml/actionables/predictors/classifier/act_complement_nb.py +106 -0
- iaml/actionables/predictors/classifier/act_decision_tree_classifier.py +117 -0
- iaml/actionables/predictors/classifier/act_extra_trees_classifier.py +115 -0
- iaml/actionables/predictors/classifier/act_gaussian_nb.py +53 -0
- iaml/actionables/predictors/classifier/act_hist_gradient_boosting_classifier.py +144 -0
- iaml/actionables/predictors/classifier/act_knn.py +86 -0
- iaml/actionables/predictors/classifier/act_light_gbm_classifier.py +211 -0
- iaml/actionables/predictors/classifier/act_linear_discriminant_analysis.py +63 -0
- iaml/actionables/predictors/classifier/act_linear_svc.py +134 -0
- iaml/actionables/predictors/classifier/act_logistic_regression.py +92 -0
- iaml/actionables/predictors/classifier/act_mlp_classifier.py +107 -0
- iaml/actionables/predictors/classifier/act_multinomial_nb.py +76 -0
- iaml/actionables/predictors/classifier/act_passive_aggressive_classifier.py +141 -0
- iaml/actionables/predictors/classifier/act_quadratic_discriminant_analysis.py +72 -0
- iaml/actionables/predictors/classifier/act_randomforest.py +113 -0
- iaml/actionables/predictors/classifier/act_ridge_classifier.py +116 -0
- iaml/actionables/predictors/classifier/act_sgd_classifier.py +149 -0
- iaml/actionables/predictors/classifier/act_svm_svc.py +88 -0
- iaml/actionables/predictors/classifier/act_xgboost.py +111 -0
- iaml/actionables/predictors/regressor/__init__.py +27 -0
- iaml/actionables/predictors/regressor/act_ada_boost_regressor.py +75 -0
- iaml/actionables/predictors/regressor/act_ard_regression.py +95 -0
- iaml/actionables/predictors/regressor/act_catboost_regressor.py +134 -0
- iaml/actionables/predictors/regressor/act_decision_tree_regressor.py +111 -0
- iaml/actionables/predictors/regressor/act_elastic_net_regressor.py +109 -0
- iaml/actionables/predictors/regressor/act_extra_trees_regressor.py +113 -0
- iaml/actionables/predictors/regressor/act_gaussian_process_regressor.py +55 -0
- iaml/actionables/predictors/regressor/act_gboost_regressor.py +95 -0
- iaml/actionables/predictors/regressor/act_hist_gradient_boosting_regressor.py +105 -0
- iaml/actionables/predictors/regressor/act_huber_regressor.py +101 -0
- iaml/actionables/predictors/regressor/act_knn_regressor.py +86 -0
- iaml/actionables/predictors/regressor/act_lasso_regressor.py +103 -0
- iaml/actionables/predictors/regressor/act_light_gbm_regressor.py +201 -0
- iaml/actionables/predictors/regressor/act_linear_regression.py +43 -0
- iaml/actionables/predictors/regressor/act_mlp_regressor.py +104 -0
- iaml/actionables/predictors/regressor/act_poisson_regressor.py +111 -0
- iaml/actionables/predictors/regressor/act_quantile_regressor.py +87 -0
- iaml/actionables/predictors/regressor/act_randomforest_regressor.py +116 -0
- iaml/actionables/predictors/regressor/act_ransac_regressor.py +106 -0
- iaml/actionables/predictors/regressor/act_ridge_regressor.py +107 -0
- iaml/actionables/predictors/regressor/act_sgd_regressor.py +106 -0
- iaml/actionables/predictors/regressor/act_svm_svr.py +81 -0
- iaml/actionables/predictors/regressor/act_xgboost_regressor.py +97 -0
- iaml/actionables/predictors/survival/__init__.py +12 -0
- iaml/actionables/predictors/survival/act_aalen_additive_model.py +83 -0
- iaml/actionables/predictors/survival/act_cox.py +110 -0
- iaml/actionables/predictors/survival/act_coxnet_survival_analysis.py +134 -0
- iaml/actionables/predictors/survival/act_extra_survival_trees.py +101 -0
- iaml/actionables/predictors/survival/act_fast_survival_svm.py +102 -0
- iaml/actionables/predictors/survival/act_gradient_boosting_survival_analysis.py +93 -0
- iaml/actionables/predictors/survival/act_random_survival_forest.py +91 -0
- iaml/actionables/predictors/survival/act_survival_component_wise_gboost.py +80 -0
- iaml/actionables/predictors/survival/act_survival_tree.py +120 -0
- iaml/actionables/predictors/survival/act_survival_xgboost.py +9 -0
- iaml/actionables/predictors/survival/act_weibull_aft.py +230 -0
- iaml/cache.py +61 -0
- iaml/cache_keys.py +57 -0
- iaml/candidate.py +736 -0
- iaml/core_dispatcher.py +125 -0
- iaml/data_type.py +11 -0
- iaml/dataset.py +506 -0
- iaml/decorators/__init__.py +3 -0
- iaml/decorators/all.py +4 -0
- iaml/decorators/is_step.py +45 -0
- iaml/decorators/runner.py +100 -0
- iaml/explanation.py +112 -0
- iaml/iaml.py +1072 -0
- iaml/iaml_pipeline.py +600 -0
- iaml/logger.py +138 -0
- iaml/meta_explorer_step.py +62 -0
- iaml/meta_ordered_step.py +28 -0
- iaml/meta_partial_explorer_step.py +34 -0
- iaml/meta_singleton.py +24 -0
- iaml/metastep.py +211 -0
- iaml/metric.py +111 -0
- iaml/metric_plot.py +82 -0
- iaml/metrics/__init__.py +21 -0
- iaml/metrics/_classification.py +28 -0
- iaml/metrics/_survival_times.py +22 -0
- iaml/metrics/accuracy_metric.py +59 -0
- iaml/metrics/balanced_accuracy_metric.py +67 -0
- iaml/metrics/brier_score.py +90 -0
- iaml/metrics/classification_error_metric.py +66 -0
- iaml/metrics/concordance_index_ipcw.py +84 -0
- iaml/metrics/concordance_index_metric.py +67 -0
- iaml/metrics/cumulative_dynamic_auc.py +119 -0
- iaml/metrics/f1_score_metric.py +71 -0
- iaml/metrics/integrated_brier_score.py +98 -0
- iaml/metrics/integrated_brier_score_loss.py +41 -0
- iaml/metrics/mean_absolute_error_metric.py +46 -0
- iaml/metrics/mean_squared_error_metric.py +46 -0
- iaml/metrics/mean_squared_log_error_metric.py +49 -0
- iaml/metrics/median_absolute_error_metric.py +48 -0
- iaml/metrics/precision_metric.py +63 -0
- iaml/metrics/r2_score_metric.py +45 -0
- iaml/metrics/recall_metric.py +65 -0
- iaml/metrics/roc_auc_metric.py +50 -0
- iaml/metrics/specificity_metric.py +44 -0
- iaml/metrics/specificity_multiclass_metric.py +55 -0
- iaml/metrics/specificity_multilabel_metric.py +60 -0
- iaml/optimizers/__init__.py +5 -0
- iaml/optimizers/bayesian_optimizer.py +193 -0
- iaml/optimizers/genetic_optimizer.py +284 -0
- iaml/optimizers/optimizer.py +31 -0
- iaml/optimizers/random_optimizer.py +101 -0
- iaml/plot.py +138 -0
- iaml/plots/__init__.py +32 -0
- iaml/plots/bar_plot.py +141 -0
- iaml/plots/box_plot.py +166 -0
- iaml/plots/class_prediction_error_plot.py +37 -0
- iaml/plots/classification_report_plot.py +35 -0
- iaml/plots/confusion_matrix_plot.py +34 -0
- iaml/plots/correlation_heatmap_plot.py +201 -0
- iaml/plots/cumulative_hazard_plot.py +72 -0
- iaml/plots/density_plot.py +210 -0
- iaml/plots/histogram_plot.py +179 -0
- iaml/plots/kaplan_meier_comparison_plot.py +89 -0
- iaml/plots/line_plot.py +70 -0
- iaml/plots/missingness_heatmap_plot.py +203 -0
- iaml/plots/outlier_plot.py +217 -0
- iaml/plots/pair_plot.py +228 -0
- iaml/plots/precision_recall_curve_plot.py +86 -0
- iaml/plots/prediction_error_plot.py +34 -0
- iaml/plots/qq_plot.py +220 -0
- iaml/plots/residual_plot.py +38 -0
- iaml/plots/roc_dynamique_curve_plot.py +79 -0
- iaml/plots/rocauc_plot.py +96 -0
- iaml/plots/shap_plot.py +187 -0
- iaml/plots/target_distribution_plot.py +241 -0
- iaml/plots/violin_plot.py +206 -0
- iaml/predictor.py +139 -0
- iaml/reference.py +65 -0
- iaml/shared_cache.py +90 -0
- iaml/sklearn_preprocessor.py +74 -0
- iaml/splitters/__init__.py +3 -0
- iaml/splitters/kfold_splitter.py +32 -0
- iaml/splitters/random_splitter.py +26 -0
- iaml/stack.py +39 -0
- iaml/statistic.py +66 -0
- iaml/statistics/__init__.py +77 -0
- iaml/statistics/anova_statistic.py +80 -0
- iaml/statistics/cardinality_ratio_statistic.py +63 -0
- iaml/statistics/category_cooccurrence_statistic.py +79 -0
- iaml/statistics/chi_square_statistic.py +81 -0
- iaml/statistics/coef_variation_statistic.py +72 -0
- iaml/statistics/correlation_with_target.py +105 -0
- iaml/statistics/count.py +72 -0
- iaml/statistics/data_type_summary_statistic.py +74 -0
- iaml/statistics/duplicate_row_statistic.py +56 -0
- iaml/statistics/effect_size_statistic.py +129 -0
- iaml/statistics/entropy_statistic.py +69 -0
- iaml/statistics/event_rate_statistic.py +52 -0
- iaml/statistics/grouped_mean_statistic.py +60 -0
- iaml/statistics/iqr_statistic.py +66 -0
- iaml/statistics/kurtosis.py +50 -0
- iaml/statistics/mad_statistic.py +66 -0
- iaml/statistics/mean.py +61 -0
- iaml/statistics/median_statistic.py +61 -0
- iaml/statistics/minmax.py +60 -0
- iaml/statistics/missing_rate_statistic.py +62 -0
- iaml/statistics/mode.py +47 -0
- iaml/statistics/most_frequent_ratio.py +81 -0
- iaml/statistics/outlier_count_iqr_statistic.py +76 -0
- iaml/statistics/quantile.py +59 -0
- iaml/statistics/range.py +53 -0
- iaml/statistics/rare_category_rate.py +92 -0
- iaml/statistics/skewness.py +53 -0
- iaml/statistics/stdev.py +50 -0
- iaml/statistics/summary_table_statistic.py +60 -0
- iaml/statistics/time_by_group_statistic.py +83 -0
- iaml/statistics/time_summary_statistic.py +56 -0
- iaml/statistics/top_k_value_counts.py +68 -0
- iaml/statistics/unique_count_statistic.py +57 -0
- iaml/statistics/value_counts.py +63 -0
- iaml/statistics/variance.py +51 -0
- iaml/statistics/violin.py +63 -0
- iaml/step.py +600 -0
- iaml/step_cache.py +87 -0
- iaml/step_wrapper.py +79 -0
- iaml/timed_pool_executor.py +492 -0
- iaml/type_of_target.py +68 -0
- iaml/void_step.py +101 -0
- iaml/worker_manager.py +169 -0
- iaml/wrapper/__init__.py +4 -0
- iaml/wrapper/wrap_basic_gridsearch.py +68 -0
- iaml/wrapper/wrap_genetic_gridsearch.py +293 -0
- iaml/wrapper/wrap_iterative_gridsearch.py +399 -0
- pyiaml-1.0.0.dist-info/METADATA +802 -0
- pyiaml-1.0.0.dist-info/RECORD +279 -0
- pyiaml-1.0.0.dist-info/WHEEL +5 -0
- pyiaml-1.0.0.dist-info/licenses/LICENSE +674 -0
- pyiaml-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Step.run() decorator."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
from ..logger import Logger
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ..candidate import Candidate
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def runner(func: callable) -> callable:
|
|
13
|
+
"""runner MUST decorate your run() method. It you manage every boring things for you.
|
|
14
|
+
|
|
15
|
+
- Store results in cache
|
|
16
|
+
- Send information to Destroyers
|
|
17
|
+
- Put results in good shape
|
|
18
|
+
- And maybe more
|
|
19
|
+
|
|
20
|
+
:param callable func: decorated method.
|
|
21
|
+
:return: edited method.
|
|
22
|
+
"""
|
|
23
|
+
def runner_wrapper(self, candidates: list[Candidate]) -> list[Candidate]:
|
|
24
|
+
"""Wrapping decorated method
|
|
25
|
+
|
|
26
|
+
:param list[Candidate] candidates: Candidates to apply wrapper to.
|
|
27
|
+
:return: All generated candidates.
|
|
28
|
+
"""
|
|
29
|
+
# Avoid circular import
|
|
30
|
+
from ..candidate import Candidate # pylint: disable=import-outside-toplevel
|
|
31
|
+
|
|
32
|
+
if candidates.__class__ in [Candidate]:
|
|
33
|
+
candidates = [candidates]
|
|
34
|
+
|
|
35
|
+
def _shape_from_candidate(candidate: Candidate) -> str:
|
|
36
|
+
try:
|
|
37
|
+
dataset = candidate.dataset
|
|
38
|
+
if dataset is None or dataset.X is None:
|
|
39
|
+
return "None"
|
|
40
|
+
return f"{dataset.X.shape[0]}x{dataset.X.shape[1]}"
|
|
41
|
+
except Exception: # pylint: disable=broad-except
|
|
42
|
+
return "?"
|
|
43
|
+
|
|
44
|
+
def _summarize_shapes(cands: list[Candidate]) -> str:
|
|
45
|
+
if not cands:
|
|
46
|
+
return "none"
|
|
47
|
+
counts: dict[str, int] = {}
|
|
48
|
+
for cand in cands:
|
|
49
|
+
shape = _shape_from_candidate(cand)
|
|
50
|
+
counts[shape] = counts.get(shape, 0) + 1
|
|
51
|
+
parts = []
|
|
52
|
+
for shape in sorted(counts.keys()):
|
|
53
|
+
count = counts[shape]
|
|
54
|
+
if count == 1:
|
|
55
|
+
parts.append(shape)
|
|
56
|
+
else:
|
|
57
|
+
parts.append(f"{shape} (x{count})")
|
|
58
|
+
return ", ".join(parts)
|
|
59
|
+
|
|
60
|
+
logger = Logger()
|
|
61
|
+
log_timing = logger.verbose > 1
|
|
62
|
+
step_label = None
|
|
63
|
+
start_time = None
|
|
64
|
+
input_shapes = None
|
|
65
|
+
if log_timing:
|
|
66
|
+
try:
|
|
67
|
+
step_label = self.to_rich_str()
|
|
68
|
+
except Exception: # pylint: disable=broad-except
|
|
69
|
+
step_label = self.__class__.__name__
|
|
70
|
+
logger.info(f'running step: {step_label}')
|
|
71
|
+
start_time = time.perf_counter()
|
|
72
|
+
input_shapes = _summarize_shapes(candidates)
|
|
73
|
+
|
|
74
|
+
result: list[Candidate] = []
|
|
75
|
+
|
|
76
|
+
for current_candidate in candidates:
|
|
77
|
+
if self.suitable(current_candidate.dataset) and self.enable:
|
|
78
|
+
candidate = self.from_cache(current_candidate)
|
|
79
|
+
if not candidate:
|
|
80
|
+
candidate = func(self, current_candidate)
|
|
81
|
+
self.add_cache(current_candidate, candidate)
|
|
82
|
+
else: # If the step is disabled or not suitable for the dataset, do nothing
|
|
83
|
+
candidate = current_candidate
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
result = result + ([candidate] if type(candidate) in [Candidate] else candidate)
|
|
87
|
+
|
|
88
|
+
if log_timing and start_time is not None:
|
|
89
|
+
elapsed = time.perf_counter() - start_time
|
|
90
|
+
output_shapes = _summarize_shapes(result)
|
|
91
|
+
logger.info(
|
|
92
|
+
f'finished step: {step_label} in {elapsed:.2f}s '
|
|
93
|
+
f'(outputs={len(result)}, data={input_shapes}->{output_shapes})'
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
self.candidate = result
|
|
97
|
+
|
|
98
|
+
return result
|
|
99
|
+
|
|
100
|
+
return runner_wrapper
|
iaml/explanation.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Enables steps to "explain" their processings and prediction results."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import textwrap
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import shap
|
|
8
|
+
|
|
9
|
+
from .plots.shap_plot import ShapPlot
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Explanation:
|
|
13
|
+
"""Enables steps to "explain" their processings and prediction results.
|
|
14
|
+
|
|
15
|
+
:param shap.Explanation, optional shap_values: Shap values to append to the explanation.
|
|
16
|
+
Default to None.
|
|
17
|
+
"""
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
shap_values: shap.Explanation = None) -> None:
|
|
21
|
+
self.shap_values = shap_values
|
|
22
|
+
"""Shap values to append to the explanation."""
|
|
23
|
+
|
|
24
|
+
def to_plot(
|
|
25
|
+
self,
|
|
26
|
+
plot: str,
|
|
27
|
+
ps: slice = None,
|
|
28
|
+
scatter_feature: list[str] = None) -> ShapPlot:
|
|
29
|
+
"""Plot SHAP values.
|
|
30
|
+
|
|
31
|
+
:param str plot: Plot to generate (one of "force", "scatter",
|
|
32
|
+
"beeswarm", "heatmap", "bar"). Refer to the SHAP
|
|
33
|
+
documentation for more details on these plots.
|
|
34
|
+
:param slice, optional ps: Specify the indexes of the SHAP values
|
|
35
|
+
to plot. Defaults to all predictions. If plot is
|
|
36
|
+
"force" or "waterfall", it will pick the first
|
|
37
|
+
prediction matching the provided slice (defaults to
|
|
38
|
+
first of all). Default to None.
|
|
39
|
+
:param list[str], optional scatter_feature: Specify the feature to
|
|
40
|
+
plot in the scatter plot (defaults to first). Default to None.
|
|
41
|
+
:raise RuntimeError: Cannot generate plots for this explanation without SHAP values.
|
|
42
|
+
:return: object containing shap plot
|
|
43
|
+
"""
|
|
44
|
+
if self.shap_values is None:
|
|
45
|
+
raise RuntimeError('Cannot generate plots for this explanation without SHAP values.')
|
|
46
|
+
|
|
47
|
+
shap_plot = None
|
|
48
|
+
if plot == 'scatter':
|
|
49
|
+
shap_plot = ShapPlot(plot, self.shap_values, ps=ps, scatter_feature=scatter_feature)
|
|
50
|
+
else:
|
|
51
|
+
shap_plot = ShapPlot(plot, self.shap_values, ps=ps)
|
|
52
|
+
|
|
53
|
+
return shap_plot
|
|
54
|
+
|
|
55
|
+
def to_plots(self, plots: list[str] = None) -> list[ShapPlot]:
|
|
56
|
+
"""Generate several plots
|
|
57
|
+
|
|
58
|
+
:param list[str], optional plots: list of plots to generate. If None are provided, it will
|
|
59
|
+
generate ['force', 'waterfall', 'beeswarm', 'scatter', 'heatmap', 'bar'].
|
|
60
|
+
:return: list of plots
|
|
61
|
+
"""
|
|
62
|
+
if plots is None:
|
|
63
|
+
plots = ['force', 'waterfall', 'beeswarm', 'scatter', 'heatmap', 'bar']
|
|
64
|
+
return [self.to_plot(p) for p in plots]
|
|
65
|
+
|
|
66
|
+
def features_importance(self) -> dict[str, str]:
|
|
67
|
+
"""Return features importance
|
|
68
|
+
|
|
69
|
+
:return: name and impact of each feature
|
|
70
|
+
"""
|
|
71
|
+
if self.shap_values is None:
|
|
72
|
+
return []
|
|
73
|
+
|
|
74
|
+
feature_names = self.shap_values.feature_names
|
|
75
|
+
feature_values = np.abs(self.shap_values.values).mean(axis=0)
|
|
76
|
+
|
|
77
|
+
return dict(zip(feature_names, feature_values))
|
|
78
|
+
|
|
79
|
+
def to_markdown_shap(self) -> str:
|
|
80
|
+
"""Renders SHAP values for this explanation as Markdown text.
|
|
81
|
+
|
|
82
|
+
:return: Markdown document.
|
|
83
|
+
"""
|
|
84
|
+
if self.shap_values is None:
|
|
85
|
+
return ''
|
|
86
|
+
|
|
87
|
+
feature_importance = '\n '.join([
|
|
88
|
+
f'| `{name}` | **{np.mean(value):.3f}** |'
|
|
89
|
+
for name, value in self.features_importance().items()
|
|
90
|
+
])
|
|
91
|
+
|
|
92
|
+
return textwrap.dedent(f"""\
|
|
93
|
+
### Features impact
|
|
94
|
+
| Feature | Mean impact (SHAP value) |
|
|
95
|
+
| ------- | ------------------------ |
|
|
96
|
+
{feature_importance}
|
|
97
|
+
""")
|
|
98
|
+
|
|
99
|
+
def to_markdown_plots(self, plots: list[str] = None) -> str:
|
|
100
|
+
"""Generates SHAP plots for this explanation, and renders them as
|
|
101
|
+
Markdown text.
|
|
102
|
+
|
|
103
|
+
:param list[str], optional plots: list of plots to generate
|
|
104
|
+
:return: Markdown text.
|
|
105
|
+
"""
|
|
106
|
+
if plots is None:
|
|
107
|
+
plots = ['force', 'waterfall', 'beeswarm', 'scatter', 'heatmap', 'bar']
|
|
108
|
+
|
|
109
|
+
if self.shap_values is None or len(plots) == 0:
|
|
110
|
+
return ""
|
|
111
|
+
|
|
112
|
+
return '\n'.join([ p.to_markdown() for p in self.to_plots(plots) ])
|