classifier-toolkit 0.3.3__tar.gz → 0.3.5__tar.gz
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.
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.gitignore +1 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/PKG-INFO +3 -3
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/predictive_power.py +162 -55
- classifier_toolkit-0.3.5/classifier_toolkit/feature_selection/utils/scoring.py +226 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/rfe.py +79 -32
- classifier_toolkit-0.3.5/docs/examples/feature_selection_advanced.md +111 -0
- classifier_toolkit-0.3.5/docs/examples/feature_selection_example.md +123 -0
- classifier_toolkit-0.3.5/docs/feature_reduction/predictive_power.md +55 -0
- classifier_toolkit-0.3.5/docs/feature_selection/overview.md +89 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/combination_search.md +1 -1
- classifier_toolkit-0.3.5/docs/index.md +92 -0
- classifier_toolkit-0.3.5/docs/model_training/overview.md +51 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/predictive_power.md +25 -7
- classifier_toolkit-0.3.5/examples/example_bayesian_search.ipynb +4475 -0
- classifier_toolkit-0.3.5/examples/example_combination_feature_search.ipynb +4262 -0
- classifier_toolkit-0.3.5/examples/example_explainability_catboost.ipynb +1565 -0
- classifier_toolkit-0.3.5/examples/example_explainability_lgbm.ipynb +1625 -0
- classifier_toolkit-0.3.5/examples/example_feature_reduction.ipynb +2280 -0
- classifier_toolkit-0.3.5/examples/example_grid_search.ipynb +1975 -0
- classifier_toolkit-0.3.5/examples/example_model_training_catboost.ipynb +133 -0
- classifier_toolkit-0.3.5/examples/example_model_training_lgbm.ipynb +133 -0
- classifier_toolkit-0.3.5/examples/example_recursive_feature_eliminator.ipynb +862 -0
- classifier_toolkit-0.3.5/examples/example_train_test_partition.ipynb +446 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/mkdocs.yml +2 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/pyproject.toml +2 -2
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_predictive_power.py +193 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_rfe.py +83 -1
- classifier_toolkit-0.3.5/tests/feature_selection/test_scoring.py +188 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/uv.lock +1 -1
- classifier_toolkit-0.3.3/classifier_toolkit/feature_selection/utils/scoring.py +0 -121
- classifier_toolkit-0.3.3/docs/examples/feature_selection_advanced.md +0 -115
- classifier_toolkit-0.3.3/docs/examples/feature_selection_example.md +0 -105
- classifier_toolkit-0.3.3/docs/feature_reduction/predictive_power.md +0 -34
- classifier_toolkit-0.3.3/docs/feature_selection/overview.md +0 -103
- classifier_toolkit-0.3.3/docs/index.md +0 -63
- classifier_toolkit-0.3.3/examples/example.py +0 -19
- classifier_toolkit-0.3.3/examples/selected_features.json +0 -189
- classifier_toolkit-0.3.3/tests/feature_selection/test_scoring.py +0 -70
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/pull_request_template/default.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/checks.yaml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/docs.yml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/master.yaml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/release.yaml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/working-branch.yaml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.python-version +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.sqlfluff +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/LICENSE +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/Makefile +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/README.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/data_preprocess.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/optimize_data.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/split_train_test.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/bivariate_analysis.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/eda_toolkit.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/feature_engineering.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/first_glance.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/univariate_analysis.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/visualizations.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/automated_warnings.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/default_warnings.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/base.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/interactions.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/misclassification.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/plots.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/toolkit.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/tree_explainer.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/base.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/correlation.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/counter_intuitive.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/drift.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/expert_rules.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/low_variance.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/reducer.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/base.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/embedded_methods/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/embedded_methods/elastic_net.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/feature_stability.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/meta_selector.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/data_handling.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/feature_type_constraints.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/plottings.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/bayesian_search.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/boruta.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/combination_search.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/recursive_feature_eliminator.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/rfe_catboost.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/sequential_selection.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/hyper_parameter_tuning/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/hyper_parameter_tuning/tuner.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/base.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/ensemble_methods.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/utils/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/utils/params.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/CNAME +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/changelog.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/data_preprocess.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/optimize_data.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/split_train_test.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/bivariate_analysis.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/eda_toolkit.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/feature_engineering.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/first_glance.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/univariate_analysis.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/visualizations.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/warnings/default_warnings.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/warnings/warning_system.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/examples/eda_example.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/interactions.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/misclassification.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/plots.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/toolkit.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/tree_explainer.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/correlation.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/counter_intuitive.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/drift.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/expert_rules.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/low_variance.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/reducer.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/embedded_methods/elastic_net.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/feature_stability.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/meta_selector.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/utils/data_handling.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/utils/scoring.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/bayesian_search.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/boruta.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/recursive_feature_eliminator.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/rfe.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/sequential_selection.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/model_training/tuner.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/data_preprocess.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/optimize_data.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/split_train_test.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/bivariate_analysis.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/eda_toolkit.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/feature_engineering.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/first_glance.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/univariate_analysis.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/visualizations.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/warnings/default_warnings.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/warnings/warning_system.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/interactions.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/misclassification.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/plots.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/toolkit.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/tree_explainer.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/base.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/correlation.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/counter_intuitive.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/drift.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/expert_rules.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/low_variance.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/reducer.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/base.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/embedded_methods/elastic_net.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/feature_stability.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/meta_selector.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/overview.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/data_handling.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/plottings.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/scoring.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/bayesian_search.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/boruta.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/combination_search.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/recursive_feature_eliminator.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/rfe.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/sequential_selection.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/model_training/params.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/tuner/tuner.md +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/stylesheets/extra.css +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/examples/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/main.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/notebooks/paylater_removed.json +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/ruff.toml +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/conftest.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_data_preprocess.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_optimize_data.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_split_train_test.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_bivariate_analysis.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_feature_engineering.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_first_glance.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_univariate_analysis.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_visualizations.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_warnings.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_catboost_e2e.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_misclassification.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_plots.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_smoke.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_toolkit.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_tree_explainer.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_correlation.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_counter_intuitive.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_drift.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_expert_rules.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_low_variance.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_reducer.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_smoke.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/__init__.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_bayesian_search.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_boruta.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_combination_search.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_elastic_net.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_feature_stability.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_recursive_feature_eliminator.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_rfe_catboost.py +0 -0
- {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_sequential_selection.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: classifier-toolkit
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Project-URL: Documentation,
|
|
3
|
+
Version: 0.3.5
|
|
4
|
+
Project-URL: Documentation, https://supreme-adventure-jg5qkyr.pages.github.io/
|
|
5
5
|
Author-email: "senih.yilmaz" <senih.yilmaz@qonto.com>, "jeremy.fraoua" <jeremy.fraoua@qonto.com>, "gauthier.marquand" <gauthier.marquand@qonto.com>, "arnaud.alepee" <arnaud.alepee@qonto.com>
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Requires-Python: <3.14,>=3.9
|
|
@@ -13,6 +13,13 @@ A feature is removed when *either* metric falls below its threshold.
|
|
|
13
13
|
Features with ``NaN`` metrics (constant, insufficient data, computation error)
|
|
14
14
|
are also removed — they cannot be trusted.
|
|
15
15
|
|
|
16
|
+
For **multiclass targets** (``k > 2``) the metrics are computed One-vs-Rest
|
|
17
|
+
(OVR) per destination class and the **maximum** across classes is used as the
|
|
18
|
+
aggregate score. A feature is kept if it clears the threshold for *at least
|
|
19
|
+
one* class — this ensures rare-class predictors (e.g. S2→D) are not discarded
|
|
20
|
+
because they are uninformative for the common transitions. Both binary and
|
|
21
|
+
multiclass paths reduce to the same result when ``k == 2``.
|
|
22
|
+
|
|
16
23
|
Two classes are exposed:
|
|
17
24
|
|
|
18
25
|
- :class:`PredictivePowerAnalyser`: computes per-feature Gini and PR-AUC lift
|
|
@@ -25,7 +32,7 @@ Two classes are exposed:
|
|
|
25
32
|
|
|
26
33
|
import logging
|
|
27
34
|
import warnings
|
|
28
|
-
from typing import
|
|
35
|
+
from typing import Any, Optional
|
|
29
36
|
|
|
30
37
|
import numpy as np
|
|
31
38
|
import pandas as pd
|
|
@@ -40,8 +47,8 @@ warnings.filterwarnings("ignore", category=UserWarning, module="sklearn")
|
|
|
40
47
|
_PREVIEW_LIMIT = 5
|
|
41
48
|
|
|
42
49
|
|
|
43
|
-
def _gini(feature: pd.Series, y: pd.Series) ->
|
|
44
|
-
"""Direction-agnostic Gini for one numerical feature.
|
|
50
|
+
def _gini(feature: pd.Series, y: pd.Series) -> tuple[float, str]:
|
|
51
|
+
"""Direction-agnostic Gini for one numerical feature against a binary target.
|
|
45
52
|
|
|
46
53
|
Returns (gini, direction). Direction is ``"positive"``, ``"negative"``,
|
|
47
54
|
``"n/a"`` (constant / insufficient data), or ``"error"``.
|
|
@@ -59,8 +66,35 @@ def _gini(feature: pd.Series, y: pd.Series) -> Tuple[float, str]:
|
|
|
59
66
|
return np.nan, "error"
|
|
60
67
|
|
|
61
68
|
|
|
62
|
-
def
|
|
63
|
-
"""
|
|
69
|
+
def _gini_ovr(feature: pd.Series, y: pd.Series) -> tuple[float, str, dict[Any, float]]:
|
|
70
|
+
"""OVR Gini for one feature against a multiclass target.
|
|
71
|
+
|
|
72
|
+
Collapses to a c-vs-rest binary problem for each class ``c`` and delegates
|
|
73
|
+
to :func:`_gini`. The aggregate score is the maximum Gini across classes so
|
|
74
|
+
that a feature predictive for only one rare class is not discarded.
|
|
75
|
+
|
|
76
|
+
Returns ``(max_gini, best_direction, {class: gini_c})``.
|
|
77
|
+
"""
|
|
78
|
+
classes = sorted(y.dropna().unique())
|
|
79
|
+
per_class: dict[Any, float] = {}
|
|
80
|
+
best_gini = -np.inf
|
|
81
|
+
best_direction = "n/a"
|
|
82
|
+
|
|
83
|
+
for c in classes:
|
|
84
|
+
y_binary = (y == c).astype(int)
|
|
85
|
+
g, direction = _gini(feature, y_binary)
|
|
86
|
+
per_class[c] = g
|
|
87
|
+
if not np.isnan(g) and g > best_gini:
|
|
88
|
+
best_gini = g
|
|
89
|
+
best_direction = direction
|
|
90
|
+
|
|
91
|
+
if best_gini == -np.inf:
|
|
92
|
+
return np.nan, "n/a", per_class
|
|
93
|
+
return float(best_gini), best_direction, per_class
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _pr_auc_lift(feature: pd.Series, y: pd.Series) -> tuple[float, float, str]:
|
|
97
|
+
"""PR-AUC and lift (%) for one numerical feature against a binary target.
|
|
64
98
|
|
|
65
99
|
Lift = (PR-AUC - baseline) / baseline x 100, where baseline = prevalence.
|
|
66
100
|
Both directions are tried; the better one is kept.
|
|
@@ -85,6 +119,37 @@ def _pr_auc_lift(feature: pd.Series, y: pd.Series) -> Tuple[float, float, str]:
|
|
|
85
119
|
return np.nan, np.nan, "error"
|
|
86
120
|
|
|
87
121
|
|
|
122
|
+
def _pr_auc_lift_ovr(
|
|
123
|
+
feature: pd.Series, y: pd.Series
|
|
124
|
+
) -> tuple[float, float, str, dict[Any, float]]:
|
|
125
|
+
"""OVR PR-AUC lift for one feature against a multiclass target.
|
|
126
|
+
|
|
127
|
+
Collapses to a c-vs-rest binary problem for each class ``c`` and delegates
|
|
128
|
+
to :func:`_pr_auc_lift`. The aggregate score is the maximum PR-AUC across
|
|
129
|
+
classes.
|
|
130
|
+
|
|
131
|
+
Returns ``(max_prauc, best_lift_pct, best_direction, {class: prauc_c})``.
|
|
132
|
+
"""
|
|
133
|
+
classes = sorted(y.dropna().unique())
|
|
134
|
+
per_class: dict[Any, float] = {}
|
|
135
|
+
best_prauc = -np.inf
|
|
136
|
+
best_lift: float = np.nan
|
|
137
|
+
best_direction = "n/a"
|
|
138
|
+
|
|
139
|
+
for c in classes:
|
|
140
|
+
y_binary = (y == c).astype(int)
|
|
141
|
+
pr_auc, lift_pct, direction = _pr_auc_lift(feature, y_binary)
|
|
142
|
+
per_class[c] = pr_auc
|
|
143
|
+
if not np.isnan(pr_auc) and pr_auc > best_prauc:
|
|
144
|
+
best_prauc = pr_auc
|
|
145
|
+
best_lift = lift_pct
|
|
146
|
+
best_direction = direction
|
|
147
|
+
|
|
148
|
+
if best_prauc == -np.inf:
|
|
149
|
+
return np.nan, np.nan, "n/a", per_class
|
|
150
|
+
return float(best_prauc), float(best_lift), best_direction, per_class
|
|
151
|
+
|
|
152
|
+
|
|
88
153
|
# ---------------------------------------------------------------------------
|
|
89
154
|
# Standalone public helpers
|
|
90
155
|
# ---------------------------------------------------------------------------
|
|
@@ -111,16 +176,21 @@ _PRAUC_LIFT_LABELS = [
|
|
|
111
176
|
def calculate_feature_gini(
|
|
112
177
|
df: pd.DataFrame,
|
|
113
178
|
target: str,
|
|
114
|
-
exclude: Optional[
|
|
179
|
+
exclude: Optional[list[str]] = None,
|
|
115
180
|
) -> pd.DataFrame:
|
|
116
181
|
"""Compute direction-agnostic Gini for every numeric feature.
|
|
117
182
|
|
|
183
|
+
For binary targets the Gini is computed directly. For multiclass targets
|
|
184
|
+
(``k > 2``) One-vs-Rest Gini is computed per class and the maximum across
|
|
185
|
+
classes is reported as ``Gini``; individual per-class values appear in
|
|
186
|
+
additional ``Gini_{class}`` columns.
|
|
187
|
+
|
|
118
188
|
Parameters
|
|
119
189
|
----------
|
|
120
190
|
df : pd.DataFrame
|
|
121
191
|
DataFrame containing features and target.
|
|
122
192
|
target : str
|
|
123
|
-
Name of the binary
|
|
193
|
+
Name of the target column (binary 0/1 or multiclass integer/string).
|
|
124
194
|
exclude : List[str], optional
|
|
125
195
|
Additional columns to exclude from scoring.
|
|
126
196
|
|
|
@@ -128,30 +198,37 @@ def calculate_feature_gini(
|
|
|
128
198
|
-------
|
|
129
199
|
pd.DataFrame
|
|
130
200
|
One row per numeric feature, sorted by ``Gini`` descending, with
|
|
131
|
-
columns ``Feature``, ``Gini``, ``Direction``, ``Interpretation
|
|
201
|
+
columns ``Feature``, ``Gini``, ``Direction``, ``Interpretation`` and,
|
|
202
|
+
for multiclass targets, additional ``Gini_{class}`` columns.
|
|
132
203
|
"""
|
|
133
204
|
skip = set(exclude or []) | {target}
|
|
205
|
+
k = df[target].nunique()
|
|
134
206
|
rows = []
|
|
135
207
|
for col in df.columns:
|
|
136
208
|
if col in skip:
|
|
137
209
|
continue
|
|
138
210
|
if not np.issubdtype(df[col].dtype, np.number):
|
|
139
211
|
continue
|
|
140
|
-
|
|
212
|
+
if k > 2:
|
|
213
|
+
gini, direction, per_class = _gini_ovr(df[col], df[target])
|
|
214
|
+
else:
|
|
215
|
+
gini, direction = _gini(df[col], df[target])
|
|
216
|
+
per_class = {}
|
|
141
217
|
if np.isnan(gini):
|
|
142
218
|
interp = "Cannot be calculated"
|
|
143
219
|
else:
|
|
144
220
|
interp = next(
|
|
145
221
|
label for threshold, label in _GINI_LABELS if gini < threshold
|
|
146
222
|
)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
223
|
+
row: dict[str, Any] = {
|
|
224
|
+
"Feature": col,
|
|
225
|
+
"Gini": gini,
|
|
226
|
+
"Direction": direction,
|
|
227
|
+
"Interpretation": interp,
|
|
228
|
+
}
|
|
229
|
+
for c, g in per_class.items():
|
|
230
|
+
row[f"Gini_{c}"] = g
|
|
231
|
+
rows.append(row)
|
|
155
232
|
return (
|
|
156
233
|
pd.DataFrame(rows)
|
|
157
234
|
.sort_values("Gini", ascending=False, na_position="last")
|
|
@@ -162,16 +239,22 @@ def calculate_feature_gini(
|
|
|
162
239
|
def calculate_feature_prauc(
|
|
163
240
|
df: pd.DataFrame,
|
|
164
241
|
target: str,
|
|
165
|
-
exclude: Optional[
|
|
242
|
+
exclude: Optional[list[str]] = None,
|
|
166
243
|
) -> pd.DataFrame:
|
|
167
244
|
"""Compute PR-AUC and lift over baseline for every numeric feature.
|
|
168
245
|
|
|
246
|
+
For binary targets the PR-AUC is computed directly. For multiclass targets
|
|
247
|
+
(``k > 2``) One-vs-Rest PR-AUC is computed per class and the maximum across
|
|
248
|
+
classes is reported as ``PR_AUC``; individual per-class values appear in
|
|
249
|
+
additional ``PR_AUC_{class}`` columns. ``Baseline_PR_AUC`` reports the
|
|
250
|
+
macro-average class prevalence in the multiclass case.
|
|
251
|
+
|
|
169
252
|
Parameters
|
|
170
253
|
----------
|
|
171
254
|
df : pd.DataFrame
|
|
172
255
|
DataFrame containing features and target.
|
|
173
256
|
target : str
|
|
174
|
-
Name of the binary
|
|
257
|
+
Name of the target column (binary 0/1 or multiclass integer/string).
|
|
175
258
|
exclude : List[str], optional
|
|
176
259
|
Additional columns to exclude from scoring.
|
|
177
260
|
|
|
@@ -180,17 +263,25 @@ def calculate_feature_prauc(
|
|
|
180
263
|
pd.DataFrame
|
|
181
264
|
One row per numeric feature, sorted by ``PR_AUC`` descending, with
|
|
182
265
|
columns ``Feature``, ``PR_AUC``, ``Baseline_PR_AUC``, ``Lift_%``,
|
|
183
|
-
``Direction``, ``Interpretation
|
|
266
|
+
``Direction``, ``Interpretation`` and, for multiclass targets,
|
|
267
|
+
additional ``PR_AUC_{class}`` columns.
|
|
184
268
|
"""
|
|
185
269
|
skip = set(exclude or []) | {target}
|
|
186
|
-
|
|
270
|
+
k = df[target].nunique()
|
|
271
|
+
baseline = float(df[target].mean()) if k == 2 else float(1 / k)
|
|
187
272
|
rows = []
|
|
188
273
|
for col in df.columns:
|
|
189
274
|
if col in skip:
|
|
190
275
|
continue
|
|
191
276
|
if not np.issubdtype(df[col].dtype, np.number):
|
|
192
277
|
continue
|
|
193
|
-
|
|
278
|
+
if k > 2:
|
|
279
|
+
pr_auc, lift_pct, direction, per_class = _pr_auc_lift_ovr(
|
|
280
|
+
df[col], df[target]
|
|
281
|
+
)
|
|
282
|
+
else:
|
|
283
|
+
pr_auc, lift_pct, direction = _pr_auc_lift(df[col], df[target])
|
|
284
|
+
per_class = {}
|
|
194
285
|
if np.isnan(pr_auc):
|
|
195
286
|
interp = "Cannot be calculated"
|
|
196
287
|
else:
|
|
@@ -198,16 +289,17 @@ def calculate_feature_prauc(
|
|
|
198
289
|
interp = next(
|
|
199
290
|
label for threshold, label in _PRAUC_LIFT_LABELS if ratio < threshold
|
|
200
291
|
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
292
|
+
row: dict[str, Any] = {
|
|
293
|
+
"Feature": col,
|
|
294
|
+
"PR_AUC": pr_auc,
|
|
295
|
+
"Baseline_PR_AUC": baseline,
|
|
296
|
+
"Lift_%": lift_pct,
|
|
297
|
+
"Direction": direction,
|
|
298
|
+
"Interpretation": interp,
|
|
299
|
+
}
|
|
300
|
+
for c, p in per_class.items():
|
|
301
|
+
row[f"PR_AUC_{c}"] = p
|
|
302
|
+
rows.append(row)
|
|
211
303
|
return (
|
|
212
304
|
pd.DataFrame(rows)
|
|
213
305
|
.sort_values("PR_AUC", ascending=False, na_position="last")
|
|
@@ -218,7 +310,7 @@ def calculate_feature_prauc(
|
|
|
218
310
|
def calculate_feature_predictive_metrics(
|
|
219
311
|
df: pd.DataFrame,
|
|
220
312
|
target: str,
|
|
221
|
-
exclude: Optional[
|
|
313
|
+
exclude: Optional[list[str]] = None,
|
|
222
314
|
) -> pd.DataFrame:
|
|
223
315
|
"""Compute Gini and PR-AUC metrics for every numeric feature.
|
|
224
316
|
|
|
@@ -273,7 +365,8 @@ class PredictivePowerAnalyser:
|
|
|
273
365
|
:meth:`transform`.
|
|
274
366
|
power_stats_ : Optional[pd.DataFrame]
|
|
275
367
|
Per-feature statistics with columns ``feature``, ``gini``,
|
|
276
|
-
``pr_auc``, ``pr_auc_lift_pct``, ``direction``, ``removed
|
|
368
|
+
``pr_auc``, ``pr_auc_lift_pct``, ``direction``, ``removed`` and,
|
|
369
|
+
for multiclass targets, additional ``gini_{class}`` columns.
|
|
277
370
|
``None`` if fit was called with no features.
|
|
278
371
|
"""
|
|
279
372
|
|
|
@@ -285,9 +378,9 @@ class PredictivePowerAnalyser:
|
|
|
285
378
|
self.gini_threshold = gini_threshold
|
|
286
379
|
self.prauc_lift_threshold = prauc_lift_threshold
|
|
287
380
|
|
|
288
|
-
self.removed_features_:
|
|
289
|
-
self.remaining_features_:
|
|
290
|
-
self.skipped_features_:
|
|
381
|
+
self.removed_features_: list[str] = []
|
|
382
|
+
self.remaining_features_: list[str] = []
|
|
383
|
+
self.skipped_features_: list[str] = []
|
|
291
384
|
self.power_stats_: Optional[pd.DataFrame] = None
|
|
292
385
|
self._fitted: bool = False
|
|
293
386
|
|
|
@@ -295,17 +388,24 @@ class PredictivePowerAnalyser:
|
|
|
295
388
|
self,
|
|
296
389
|
X: pd.DataFrame,
|
|
297
390
|
y: pd.Series,
|
|
298
|
-
numerical_features: Optional[
|
|
391
|
+
numerical_features: Optional[list[str]] = None,
|
|
299
392
|
) -> "PredictivePowerAnalyser":
|
|
300
393
|
"""
|
|
301
394
|
Compute Gini and PR-AUC lift for each feature and flag weak ones.
|
|
302
395
|
|
|
396
|
+
For binary targets (``k == 2``) the metrics are computed directly. For
|
|
397
|
+
multiclass targets (``k > 2``) One-vs-Rest metrics are computed per
|
|
398
|
+
class and the maximum across classes is used as the aggregate score —
|
|
399
|
+
a feature is kept if it clears the threshold for *at least one* class.
|
|
400
|
+
Per-class Gini values are stored as ``gini_{class}`` columns in
|
|
401
|
+
``power_stats_`` for downstream use (e.g. Stage 1.5 direction logic).
|
|
402
|
+
|
|
303
403
|
Parameters
|
|
304
404
|
----------
|
|
305
405
|
X : pd.DataFrame
|
|
306
406
|
Feature matrix.
|
|
307
407
|
y : pd.Series
|
|
308
|
-
|
|
408
|
+
Target variable (binary 0/1 or multiclass integer/string).
|
|
309
409
|
numerical_features : List[str], optional
|
|
310
410
|
Numerical columns to evaluate. If ``None``, numeric columns are
|
|
311
411
|
auto-detected from dtypes; non-numeric columns are added to
|
|
@@ -341,11 +441,17 @@ class PredictivePowerAnalyser:
|
|
|
341
441
|
self._fitted = True
|
|
342
442
|
return self
|
|
343
443
|
|
|
444
|
+
k = y.nunique()
|
|
344
445
|
rows = []
|
|
345
446
|
|
|
346
447
|
for col in cols_to_score:
|
|
347
|
-
|
|
348
|
-
|
|
448
|
+
if k > 2:
|
|
449
|
+
gini, gini_dir, per_class_gini = _gini_ovr(X[col], y)
|
|
450
|
+
pr_auc, lift_pct, pr_dir, _ = _pr_auc_lift_ovr(X[col], y)
|
|
451
|
+
else:
|
|
452
|
+
gini, gini_dir = _gini(X[col], y)
|
|
453
|
+
pr_auc, lift_pct, pr_dir = _pr_auc_lift(X[col], y)
|
|
454
|
+
per_class_gini = {}
|
|
349
455
|
|
|
350
456
|
direction = gini_dir if gini_dir not in ("n/a", "error") else pr_dir
|
|
351
457
|
|
|
@@ -359,16 +465,17 @@ class PredictivePowerAnalyser:
|
|
|
359
465
|
if should_remove:
|
|
360
466
|
self.removed_features_.append(col)
|
|
361
467
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
468
|
+
row: dict[str, Any] = {
|
|
469
|
+
"feature": col,
|
|
470
|
+
"gini": gini,
|
|
471
|
+
"pr_auc": pr_auc,
|
|
472
|
+
"pr_auc_lift_pct": lift_pct,
|
|
473
|
+
"direction": direction,
|
|
474
|
+
"removed": should_remove,
|
|
475
|
+
}
|
|
476
|
+
for c, g in per_class_gini.items():
|
|
477
|
+
row[f"gini_{c}"] = g
|
|
478
|
+
rows.append(row)
|
|
372
479
|
|
|
373
480
|
self.remaining_features_ = [
|
|
374
481
|
c for c in cols_to_score if c not in self.removed_features_
|
|
@@ -413,7 +520,7 @@ class PredictivePowerAnalyser:
|
|
|
413
520
|
self,
|
|
414
521
|
X: pd.DataFrame,
|
|
415
522
|
y: pd.Series,
|
|
416
|
-
numerical_features: Optional[
|
|
523
|
+
numerical_features: Optional[list[str]] = None,
|
|
417
524
|
) -> pd.DataFrame:
|
|
418
525
|
"""
|
|
419
526
|
Fit the analyser and transform the dataset in one step.
|
|
@@ -423,7 +530,7 @@ class PredictivePowerAnalyser:
|
|
|
423
530
|
X : pd.DataFrame
|
|
424
531
|
Feature matrix.
|
|
425
532
|
y : pd.Series
|
|
426
|
-
|
|
533
|
+
Target variable (binary 0/1 or multiclass integer/string).
|
|
427
534
|
numerical_features : List[str], optional
|
|
428
535
|
Columns to evaluate.
|
|
429
536
|
|
|
@@ -519,7 +626,7 @@ class WeakPredictiveFilter(BaseFeatureReducer):
|
|
|
519
626
|
|
|
520
627
|
def __init__(
|
|
521
628
|
self,
|
|
522
|
-
numerical_features: Optional[
|
|
629
|
+
numerical_features: Optional[list[str]] = None,
|
|
523
630
|
gini_threshold: float = 0.01,
|
|
524
631
|
prauc_lift_threshold: float = 0.0,
|
|
525
632
|
) -> None:
|
|
@@ -543,7 +650,7 @@ class WeakPredictiveFilter(BaseFeatureReducer):
|
|
|
543
650
|
X : pd.DataFrame
|
|
544
651
|
Feature matrix.
|
|
545
652
|
y : pd.Series
|
|
546
|
-
|
|
653
|
+
Target variable (binary 0/1 or multiclass integer/string). Required.
|
|
547
654
|
**kwargs
|
|
548
655
|
Ignored.
|
|
549
656
|
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
from typing import Callable, Dict, Union
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.typing import ArrayLike, NDArray
|
|
5
|
+
from sklearn.metrics import (
|
|
6
|
+
accuracy_score,
|
|
7
|
+
average_precision_score,
|
|
8
|
+
confusion_matrix,
|
|
9
|
+
f1_score,
|
|
10
|
+
make_scorer,
|
|
11
|
+
precision_score,
|
|
12
|
+
recall_score,
|
|
13
|
+
roc_auc_score,
|
|
14
|
+
)
|
|
15
|
+
from sklearn.preprocessing import label_binarize
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def roc_auc_ovr(y_true: ArrayLike, y_pred_proba: ArrayLike) -> float:
|
|
19
|
+
"""
|
|
20
|
+
ROC-AUC that transparently handles both binary and multiclass targets.
|
|
21
|
+
|
|
22
|
+
Binary targets (``k <= 2``) use today's exact behaviour (probability of
|
|
23
|
+
the positive class). Multiclass targets (``k > 2``) use One-vs-Rest with
|
|
24
|
+
macro averaging, which reduces to the binary formula when ``k == 2``.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
y_true : ArrayLike
|
|
29
|
+
True labels.
|
|
30
|
+
y_pred_proba : ArrayLike
|
|
31
|
+
Predicted class probabilities from ``predict_proba``.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
float
|
|
36
|
+
ROC-AUC score.
|
|
37
|
+
"""
|
|
38
|
+
y_pred_proba = np.asarray(y_pred_proba)
|
|
39
|
+
if y_pred_proba.ndim == 1 or y_pred_proba.shape[1] <= 2:
|
|
40
|
+
proba = y_pred_proba[:, 1] if y_pred_proba.ndim > 1 else y_pred_proba
|
|
41
|
+
return float(roc_auc_score(y_true, proba))
|
|
42
|
+
return float(
|
|
43
|
+
roc_auc_score(y_true, y_pred_proba, multi_class="ovr", average="macro")
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def macro_average_precision_score(y_true: ArrayLike, y_pred_proba: ArrayLike) -> float:
|
|
48
|
+
"""
|
|
49
|
+
Macro-averaged One-vs-Rest PR-AUC across all classes.
|
|
50
|
+
|
|
51
|
+
Binary targets (``k <= 2``) use today's exact ``average_precision_score``
|
|
52
|
+
behaviour. Multiclass targets (``k > 2``) binarize each class against the
|
|
53
|
+
rest and average the per-class PR-AUC.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
y_true : ArrayLike
|
|
58
|
+
True labels.
|
|
59
|
+
y_pred_proba : ArrayLike
|
|
60
|
+
Predicted class probabilities from ``predict_proba``.
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
float
|
|
65
|
+
Macro-averaged PR-AUC score.
|
|
66
|
+
"""
|
|
67
|
+
y_pred_proba = np.asarray(y_pred_proba)
|
|
68
|
+
if y_pred_proba.ndim == 1 or y_pred_proba.shape[1] <= 2:
|
|
69
|
+
proba = y_pred_proba[:, 1] if y_pred_proba.ndim > 1 else y_pred_proba
|
|
70
|
+
return float(average_precision_score(y_true, proba))
|
|
71
|
+
|
|
72
|
+
classes = np.unique(y_true)
|
|
73
|
+
y_true_bin = label_binarize(y_true, classes=classes)
|
|
74
|
+
per_class_scores = [
|
|
75
|
+
average_precision_score(y_true_bin[:, i], y_pred_proba[:, i])
|
|
76
|
+
for i in range(len(classes))
|
|
77
|
+
]
|
|
78
|
+
return float(np.mean(per_class_scores))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def make_d_class_pr_auc_scorer(d_class_label: Union[str, int]) -> Callable:
|
|
82
|
+
"""
|
|
83
|
+
Build a PR-AUC scorer for a single class treated as One-vs-Rest positive.
|
|
84
|
+
|
|
85
|
+
Used to track the "D" (default) class separately from the primary
|
|
86
|
+
macro-averaged metric, since it is the class that ultimately gets priced.
|
|
87
|
+
|
|
88
|
+
Parameters
|
|
89
|
+
----------
|
|
90
|
+
d_class_label : Union[str, int]
|
|
91
|
+
The class value that represents the "D" (default) state.
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
Callable
|
|
96
|
+
A function ``(y_true, y_pred_proba, classes) -> float`` computing the
|
|
97
|
+
OVR PR-AUC for ``d_class_label``.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
def _d_class_pr_auc(
|
|
101
|
+
y_true: ArrayLike, y_pred_proba: ArrayLike, classes: ArrayLike
|
|
102
|
+
) -> float:
|
|
103
|
+
classes = np.asarray(classes)
|
|
104
|
+
y_pred_proba = np.asarray(y_pred_proba)
|
|
105
|
+
matches = np.where(classes == d_class_label)[0]
|
|
106
|
+
if len(matches) == 0:
|
|
107
|
+
raise ValueError(
|
|
108
|
+
f"d_class_label={d_class_label!r} not found among classes {classes.tolist()}"
|
|
109
|
+
)
|
|
110
|
+
class_idx = matches[0]
|
|
111
|
+
y_true_bin = (np.asarray(y_true) == d_class_label).astype(int)
|
|
112
|
+
return float(average_precision_score(y_true_bin, y_pred_proba[:, class_idx]))
|
|
113
|
+
|
|
114
|
+
return _d_class_pr_auc
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# Define scorers with updated best practices
|
|
118
|
+
SCORERS = {
|
|
119
|
+
"accuracy": make_scorer(accuracy_score),
|
|
120
|
+
"f1": make_scorer(f1_score, average="weighted"),
|
|
121
|
+
"precision": make_scorer(precision_score, average="weighted"),
|
|
122
|
+
"recall": make_scorer(recall_score, average="weighted"),
|
|
123
|
+
"roc_auc": make_scorer(roc_auc_ovr, response_method="predict_proba"),
|
|
124
|
+
"average_precision": make_scorer(
|
|
125
|
+
average_precision_score, response_method="predict_proba"
|
|
126
|
+
),
|
|
127
|
+
"macro_average_precision": make_scorer(
|
|
128
|
+
macro_average_precision_score, response_method="predict_proba"
|
|
129
|
+
),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Keep the original scoring functions for backward compatibility
|
|
133
|
+
SCORING_FUNCTIONS: Dict[str, Callable] = {
|
|
134
|
+
"accuracy": accuracy_score,
|
|
135
|
+
"f1": f1_score,
|
|
136
|
+
"precision": precision_score,
|
|
137
|
+
"recall": recall_score,
|
|
138
|
+
"roc_auc": roc_auc_score,
|
|
139
|
+
"average_precision": average_precision_score,
|
|
140
|
+
"macro_average_precision": macro_average_precision_score,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def get_scorer(metric: Union[str, Callable]) -> Callable:
|
|
145
|
+
"""
|
|
146
|
+
Get a scorer function for the specified metric.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
metric : Union[str, Callable]
|
|
151
|
+
The metric to use for scoring. Can be a string identifier or a callable.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
Callable
|
|
156
|
+
A scorer function compatible with scikit-learn.
|
|
157
|
+
|
|
158
|
+
Raises
|
|
159
|
+
------
|
|
160
|
+
ValueError
|
|
161
|
+
If the metric is not recognized.
|
|
162
|
+
"""
|
|
163
|
+
if isinstance(metric, str):
|
|
164
|
+
if metric in SCORERS:
|
|
165
|
+
return SCORERS[metric]
|
|
166
|
+
elif metric in SCORING_FUNCTIONS:
|
|
167
|
+
# For backward compatibility
|
|
168
|
+
return make_scorer(SCORING_FUNCTIONS[metric])
|
|
169
|
+
else:
|
|
170
|
+
raise ValueError(
|
|
171
|
+
f"Unrecognized metric: {metric}. Available metrics are: {', '.join(SCORERS.keys())}"
|
|
172
|
+
)
|
|
173
|
+
elif callable(metric):
|
|
174
|
+
return make_scorer(metric)
|
|
175
|
+
else:
|
|
176
|
+
raise ValueError("metric must be either a string or a callable")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def false_positive_rate(y_true: ArrayLike, y_pred: ArrayLike) -> float:
|
|
180
|
+
"""
|
|
181
|
+
Calculate the false positive rate.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
y_true : ArrayLike
|
|
186
|
+
True labels.
|
|
187
|
+
y_pred : ArrayLike
|
|
188
|
+
Predicted labels.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
float
|
|
193
|
+
False positive rate.
|
|
194
|
+
"""
|
|
195
|
+
tn, fp, _, _ = confusion_matrix(y_true, y_pred).ravel()
|
|
196
|
+
return fp / (fp + tn)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def true_positive_rate(
|
|
200
|
+
y_true: ArrayLike, y_pred: ArrayLike
|
|
201
|
+
) -> Union[float, NDArray[np.float64]]:
|
|
202
|
+
"""
|
|
203
|
+
Calculate the true positive rate (recall/sensitivity).
|
|
204
|
+
|
|
205
|
+
Parameters
|
|
206
|
+
----------
|
|
207
|
+
y_true : ArrayLike
|
|
208
|
+
True labels.
|
|
209
|
+
y_pred : ArrayLike
|
|
210
|
+
Predicted labels.
|
|
211
|
+
|
|
212
|
+
Returns
|
|
213
|
+
-------
|
|
214
|
+
Union[float, NDArray[np.float64]]
|
|
215
|
+
True positive rate.
|
|
216
|
+
"""
|
|
217
|
+
return recall_score(y_true, y_pred) # type: ignore
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
# Add custom scorers for FPR and TPR
|
|
221
|
+
SCORERS["fpr"] = make_scorer(false_positive_rate, greater_is_better=False)
|
|
222
|
+
SCORERS["tpr"] = make_scorer(true_positive_rate, greater_is_better=True)
|
|
223
|
+
|
|
224
|
+
# Add to SCORING_FUNCTIONS for backward compatibility
|
|
225
|
+
SCORING_FUNCTIONS["fpr"] = false_positive_rate
|
|
226
|
+
SCORING_FUNCTIONS["tpr"] = true_positive_rate
|