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.
Files changed (228) hide show
  1. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.gitignore +1 -0
  2. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/PKG-INFO +3 -3
  3. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/predictive_power.py +162 -55
  4. classifier_toolkit-0.3.5/classifier_toolkit/feature_selection/utils/scoring.py +226 -0
  5. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/rfe.py +79 -32
  6. classifier_toolkit-0.3.5/docs/examples/feature_selection_advanced.md +111 -0
  7. classifier_toolkit-0.3.5/docs/examples/feature_selection_example.md +123 -0
  8. classifier_toolkit-0.3.5/docs/feature_reduction/predictive_power.md +55 -0
  9. classifier_toolkit-0.3.5/docs/feature_selection/overview.md +89 -0
  10. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/combination_search.md +1 -1
  11. classifier_toolkit-0.3.5/docs/index.md +92 -0
  12. classifier_toolkit-0.3.5/docs/model_training/overview.md +51 -0
  13. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/predictive_power.md +25 -7
  14. classifier_toolkit-0.3.5/examples/example_bayesian_search.ipynb +4475 -0
  15. classifier_toolkit-0.3.5/examples/example_combination_feature_search.ipynb +4262 -0
  16. classifier_toolkit-0.3.5/examples/example_explainability_catboost.ipynb +1565 -0
  17. classifier_toolkit-0.3.5/examples/example_explainability_lgbm.ipynb +1625 -0
  18. classifier_toolkit-0.3.5/examples/example_feature_reduction.ipynb +2280 -0
  19. classifier_toolkit-0.3.5/examples/example_grid_search.ipynb +1975 -0
  20. classifier_toolkit-0.3.5/examples/example_model_training_catboost.ipynb +133 -0
  21. classifier_toolkit-0.3.5/examples/example_model_training_lgbm.ipynb +133 -0
  22. classifier_toolkit-0.3.5/examples/example_recursive_feature_eliminator.ipynb +862 -0
  23. classifier_toolkit-0.3.5/examples/example_train_test_partition.ipynb +446 -0
  24. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/mkdocs.yml +2 -0
  25. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/pyproject.toml +2 -2
  26. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_predictive_power.py +193 -0
  27. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_rfe.py +83 -1
  28. classifier_toolkit-0.3.5/tests/feature_selection/test_scoring.py +188 -0
  29. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/uv.lock +1 -1
  30. classifier_toolkit-0.3.3/classifier_toolkit/feature_selection/utils/scoring.py +0 -121
  31. classifier_toolkit-0.3.3/docs/examples/feature_selection_advanced.md +0 -115
  32. classifier_toolkit-0.3.3/docs/examples/feature_selection_example.md +0 -105
  33. classifier_toolkit-0.3.3/docs/feature_reduction/predictive_power.md +0 -34
  34. classifier_toolkit-0.3.3/docs/feature_selection/overview.md +0 -103
  35. classifier_toolkit-0.3.3/docs/index.md +0 -63
  36. classifier_toolkit-0.3.3/examples/example.py +0 -19
  37. classifier_toolkit-0.3.3/examples/selected_features.json +0 -189
  38. classifier_toolkit-0.3.3/tests/feature_selection/test_scoring.py +0 -70
  39. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/pull_request_template/default.md +0 -0
  40. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/checks.yaml +0 -0
  41. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/docs.yml +0 -0
  42. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/master.yaml +0 -0
  43. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/release.yaml +0 -0
  44. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.github/workflows/working-branch.yaml +0 -0
  45. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.python-version +0 -0
  46. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/.sqlfluff +0 -0
  47. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/LICENSE +0 -0
  48. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/Makefile +0 -0
  49. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/README.md +0 -0
  50. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/__init__.py +0 -0
  51. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/data_preprocess.py +0 -0
  52. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/optimize_data.py +0 -0
  53. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/data_partition/split_train_test.py +0 -0
  54. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/__init__.py +0 -0
  55. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/bivariate_analysis.py +0 -0
  56. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/eda_toolkit.py +0 -0
  57. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/feature_engineering.py +0 -0
  58. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/first_glance.py +0 -0
  59. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/univariate_analysis.py +0 -0
  60. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/visualizations.py +0 -0
  61. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/__init__.py +0 -0
  62. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/automated_warnings.py +0 -0
  63. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/eda/warnings/default_warnings.py +0 -0
  64. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/__init__.py +0 -0
  65. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/base.py +0 -0
  66. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/interactions.py +0 -0
  67. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/misclassification.py +0 -0
  68. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/plots.py +0 -0
  69. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/toolkit.py +0 -0
  70. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/explainability/tree_explainer.py +0 -0
  71. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/__init__.py +0 -0
  72. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/base.py +0 -0
  73. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/correlation.py +0 -0
  74. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/counter_intuitive.py +0 -0
  75. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/drift.py +0 -0
  76. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/expert_rules.py +0 -0
  77. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/low_variance.py +0 -0
  78. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_reduction/reducer.py +0 -0
  79. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/__init__.py +0 -0
  80. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/base.py +0 -0
  81. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/embedded_methods/__init__.py +0 -0
  82. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/embedded_methods/elastic_net.py +0 -0
  83. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/feature_stability.py +0 -0
  84. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/meta_selector.py +0 -0
  85. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/__init__.py +0 -0
  86. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/data_handling.py +0 -0
  87. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/feature_type_constraints.py +0 -0
  88. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/utils/plottings.py +0 -0
  89. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/__init__.py +0 -0
  90. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/bayesian_search.py +0 -0
  91. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/boruta.py +0 -0
  92. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/combination_search.py +0 -0
  93. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/recursive_feature_eliminator.py +0 -0
  94. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/rfe_catboost.py +0 -0
  95. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/feature_selection/wrapper_methods/sequential_selection.py +0 -0
  96. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/__init__.py +0 -0
  97. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/hyper_parameter_tuning/__init__.py +0 -0
  98. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/hyper_parameter_tuning/tuner.py +0 -0
  99. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/__init__.py +0 -0
  100. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/base.py +0 -0
  101. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/models/ensemble_methods.py +0 -0
  102. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/utils/__init__.py +0 -0
  103. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/classifier_toolkit/model_training/utils/params.py +0 -0
  104. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/CNAME +0 -0
  105. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/changelog.md +0 -0
  106. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/data_preprocess.md +0 -0
  107. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/optimize_data.md +0 -0
  108. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/overview.md +0 -0
  109. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/data_partition/split_train_test.md +0 -0
  110. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/bivariate_analysis.md +0 -0
  111. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/eda_toolkit.md +0 -0
  112. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/feature_engineering.md +0 -0
  113. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/first_glance.md +0 -0
  114. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/overview.md +0 -0
  115. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/univariate_analysis.md +0 -0
  116. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/visualizations.md +0 -0
  117. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/warnings/default_warnings.md +0 -0
  118. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/eda/warnings/warning_system.md +0 -0
  119. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/examples/eda_example.md +0 -0
  120. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/interactions.md +0 -0
  121. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/misclassification.md +0 -0
  122. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/overview.md +0 -0
  123. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/plots.md +0 -0
  124. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/toolkit.md +0 -0
  125. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/explainability/tree_explainer.md +0 -0
  126. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/correlation.md +0 -0
  127. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/counter_intuitive.md +0 -0
  128. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/drift.md +0 -0
  129. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/expert_rules.md +0 -0
  130. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/low_variance.md +0 -0
  131. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/overview.md +0 -0
  132. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_reduction/reducer.md +0 -0
  133. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/embedded_methods/elastic_net.md +0 -0
  134. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/feature_stability.md +0 -0
  135. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/meta_selector.md +0 -0
  136. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/utils/data_handling.md +0 -0
  137. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/utils/scoring.md +0 -0
  138. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/bayesian_search.md +0 -0
  139. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/boruta.md +0 -0
  140. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/recursive_feature_eliminator.md +0 -0
  141. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/rfe.md +0 -0
  142. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/feature_selection/wrapper_methods/sequential_selection.md +0 -0
  143. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/model_training/tuner.md +0 -0
  144. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/data_preprocess.md +0 -0
  145. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/optimize_data.md +0 -0
  146. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/overview.md +0 -0
  147. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/data_partition/split_train_test.md +0 -0
  148. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/bivariate_analysis.md +0 -0
  149. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/eda_toolkit.md +0 -0
  150. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/feature_engineering.md +0 -0
  151. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/first_glance.md +0 -0
  152. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/overview.md +0 -0
  153. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/univariate_analysis.md +0 -0
  154. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/visualizations.md +0 -0
  155. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/warnings/default_warnings.md +0 -0
  156. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/eda/warnings/warning_system.md +0 -0
  157. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/interactions.md +0 -0
  158. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/misclassification.md +0 -0
  159. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/overview.md +0 -0
  160. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/plots.md +0 -0
  161. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/toolkit.md +0 -0
  162. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/explainability/tree_explainer.md +0 -0
  163. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/base.md +0 -0
  164. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/correlation.md +0 -0
  165. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/counter_intuitive.md +0 -0
  166. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/drift.md +0 -0
  167. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/expert_rules.md +0 -0
  168. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/low_variance.md +0 -0
  169. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/overview.md +0 -0
  170. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_reduction/reducer.md +0 -0
  171. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/base.md +0 -0
  172. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/embedded_methods/elastic_net.md +0 -0
  173. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/feature_stability.md +0 -0
  174. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/meta_selector.md +0 -0
  175. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/overview.md +0 -0
  176. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/data_handling.md +0 -0
  177. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/plottings.md +0 -0
  178. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/utils/scoring.md +0 -0
  179. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/bayesian_search.md +0 -0
  180. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/boruta.md +0 -0
  181. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/combination_search.md +0 -0
  182. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/recursive_feature_eliminator.md +0 -0
  183. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/rfe.md +0 -0
  184. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/feature_selection/wrapper_methods/sequential_selection.md +0 -0
  185. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/model_training/params.md +0 -0
  186. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/reference/tuner/tuner.md +0 -0
  187. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/docs/stylesheets/extra.css +0 -0
  188. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/examples/__init__.py +0 -0
  189. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/main.py +0 -0
  190. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/notebooks/paylater_removed.json +0 -0
  191. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/ruff.toml +0 -0
  192. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/__init__.py +0 -0
  193. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/conftest.py +0 -0
  194. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/__init__.py +0 -0
  195. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_data_preprocess.py +0 -0
  196. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_optimize_data.py +0 -0
  197. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/data_partition/test_split_train_test.py +0 -0
  198. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/__init__.py +0 -0
  199. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_bivariate_analysis.py +0 -0
  200. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_feature_engineering.py +0 -0
  201. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_first_glance.py +0 -0
  202. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_univariate_analysis.py +0 -0
  203. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_visualizations.py +0 -0
  204. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/eda/test_warnings.py +0 -0
  205. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/__init__.py +0 -0
  206. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_catboost_e2e.py +0 -0
  207. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_misclassification.py +0 -0
  208. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_plots.py +0 -0
  209. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_smoke.py +0 -0
  210. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_toolkit.py +0 -0
  211. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/explainability/test_tree_explainer.py +0 -0
  212. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/__init__.py +0 -0
  213. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_correlation.py +0 -0
  214. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_counter_intuitive.py +0 -0
  215. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_drift.py +0 -0
  216. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_expert_rules.py +0 -0
  217. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_low_variance.py +0 -0
  218. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_reducer.py +0 -0
  219. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_reduction/test_smoke.py +0 -0
  220. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/__init__.py +0 -0
  221. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_bayesian_search.py +0 -0
  222. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_boruta.py +0 -0
  223. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_combination_search.py +0 -0
  224. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_elastic_net.py +0 -0
  225. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_feature_stability.py +0 -0
  226. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_recursive_feature_eliminator.py +0 -0
  227. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_rfe_catboost.py +0 -0
  228. {classifier_toolkit-0.3.3 → classifier_toolkit-0.3.5}/tests/feature_selection/test_sequential_selection.py +0 -0
@@ -78,6 +78,7 @@ target/
78
78
  # Jupyter Notebook
79
79
  .ipynb_checkpoints
80
80
  *.ipynb
81
+ !examples/*.ipynb
81
82
 
82
83
  # IPython
83
84
  profile_default/
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: classifier-toolkit
3
- Version: 0.3.3
4
- Project-URL: Documentation, http://classifier-toolkit.gh-pages.qonto.co/
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 List, Optional, Tuple
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) -> Tuple[float, str]:
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 _pr_auc_lift(feature: pd.Series, y: pd.Series) -> Tuple[float, float, str]:
63
- """PR-AUC and lift (%) for one numerical feature.
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[List[str]] = None,
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 target column.
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
- gini, direction = _gini(df[col], df[target])
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
- rows.append(
148
- {
149
- "Feature": col,
150
- "Gini": gini,
151
- "Direction": direction,
152
- "Interpretation": interp,
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[List[str]] = None,
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 target column.
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
- baseline = float(df[target].mean())
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
- pr_auc, lift_pct, direction = _pr_auc_lift(df[col], df[target])
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
- rows.append(
202
- {
203
- "Feature": col,
204
- "PR_AUC": pr_auc,
205
- "Baseline_PR_AUC": baseline,
206
- "Lift_%": lift_pct,
207
- "Direction": direction,
208
- "Interpretation": interp,
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[List[str]] = None,
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_: List[str] = []
289
- self.remaining_features_: List[str] = []
290
- self.skipped_features_: List[str] = []
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[List[str]] = None,
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
- Binary target variable (0/1).
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
- gini, gini_dir = _gini(X[col], y)
348
- pr_auc, lift_pct, pr_dir = _pr_auc_lift(X[col], y)
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
- rows.append(
363
- {
364
- "feature": col,
365
- "gini": gini,
366
- "pr_auc": pr_auc,
367
- "pr_auc_lift_pct": lift_pct,
368
- "direction": direction,
369
- "removed": should_remove,
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[List[str]] = None,
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
- Binary target variable.
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[List[str]] = None,
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
- Binary target variable (0/1). Required.
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