SuperModelingFactory 0.3.6__tar.gz → 0.3.8__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 (105) hide show
  1. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Explainability/Model_Explainer.py +159 -4
  2. supermodelingfactory-0.3.8/Modeling_Tool/Feature/Weighted_Screen.py +548 -0
  3. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/__init__.py +8 -0
  4. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/_common.py +126 -0
  5. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/credit_model.py +111 -70
  6. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/__init__.py +5 -1
  7. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/PKG-INFO +2 -2
  8. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/README.md +1 -1
  9. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/PKG-INFO +2 -2
  10. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/SOURCES.txt +1 -0
  11. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/pyproject.toml +1 -1
  12. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/setup.py +1 -1
  13. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/ExcelMaster/ExcelFormatTool.py +0 -0
  14. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/ExcelMaster/ExcelMaster.py +0 -0
  15. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/ExcelMaster/Template.py +0 -0
  16. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/ExcelMaster/Utility.py +0 -0
  17. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/ExcelMaster/__init__.py +0 -0
  18. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/LICENSE +0 -0
  19. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/MANIFEST.in +0 -0
  20. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Binning_Tool.py +0 -0
  21. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Binning_Tool.pyi +0 -0
  22. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Check_DuckDB_Compatibility.py +0 -0
  23. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Json_Data_Converter.py +0 -0
  24. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Model_Registry_Tool.py +0 -0
  25. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/ODPS_Tool.py +0 -0
  26. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Parallel_Engine.py +0 -0
  27. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Parallel_ODPS_Manager.py +0 -0
  28. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Proc_Compare.py +0 -0
  29. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Slope_Tool.py +0 -0
  30. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/Slope_Tool.pyi +0 -0
  31. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/XOR_Encryptor.py +0 -0
  32. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/XOR_Encryptor.pyi +0 -0
  33. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/__init__.py +0 -0
  34. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/kDataFrame.py +0 -0
  35. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/kDataFrame.pyi +0 -0
  36. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/sample_weight_utils.py +0 -0
  37. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Core/utils.py +0 -0
  38. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/Evaluation_Tool.py +0 -0
  39. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/Evaluation_Tool.pyi +0 -0
  40. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/Model_Eval_Tool.py +0 -0
  41. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/Model_Eval_Tool.pyi +0 -0
  42. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/__init__.py +0 -0
  43. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/evaluate_model.py +0 -0
  44. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/evaluate_model.pyi +0 -0
  45. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Eval/weighted_eval_utils.py +0 -0
  46. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Explainability/Coalition_Structure.py +0 -0
  47. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Explainability/__init__.py +0 -0
  48. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/Distribution_Tool.py +0 -0
  49. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/Distribution_Tool.pyi +0 -0
  50. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/Feature_Insights.py +0 -0
  51. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/Feature_Insights.pyi +0 -0
  52. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/PSI_Tool.py +0 -0
  53. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/PSI_Tool.pyi +0 -0
  54. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Feature/WOE_Engine_Feature_Patch.py +0 -0
  55. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/Backward_Tool.py +0 -0
  56. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/Backward_Tool.pyi +0 -0
  57. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/GBM_Search_Tool.py +0 -0
  58. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/GBM_Tool.py +0 -0
  59. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/GBM_Tool.pyi +0 -0
  60. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/LRM_Tool.py +0 -0
  61. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/LRM_Tool.pyi +0 -0
  62. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Model/__init__.py +0 -0
  63. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/__init__.py +0 -0
  64. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/feature_validation.py +0 -0
  65. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/mock_sample.py +0 -0
  66. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/reject_inference.py +0 -0
  67. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/sample_analysis.py +0 -0
  68. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/score_comparison.py +0 -0
  69. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Pipeline/score_consistency_uat.py +0 -0
  70. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Distribution_Adaptation.py +0 -0
  71. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Distribution_Adaptation.pyi +0 -0
  72. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Reject_Infer.py +0 -0
  73. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Reject_Infer.pyi +0 -0
  74. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Sample_Split.py +0 -0
  75. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/Sample_Split.pyi +0 -0
  76. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/Sample/__init__.py +0 -0
  77. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/UAT/UAT_Consistency_Checker.py +0 -0
  78. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/UAT/__init__.py +0 -0
  79. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Adapter.py +0 -0
  80. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Adapter.pyi +0 -0
  81. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Master.py +0 -0
  82. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Master.pyi +0 -0
  83. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Monotone_Binner.py +0 -0
  84. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Monotone_Binner.pyi +0 -0
  85. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Plot_Tool.py +0 -0
  86. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Plot_Tool.pyi +0 -0
  87. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Report_Builder.py +0 -0
  88. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Report_Builder.pyi +0 -0
  89. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Tool.py +0 -0
  90. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/WOE_Tool.pyi +0 -0
  91. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/__init__.py +0 -0
  92. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/plot_woe_tool.py +0 -0
  93. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/WOE/plot_woe_tool.pyi +0 -0
  94. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/ref_font/KaiTi.ttf +0 -0
  95. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/ref_font/WeiRuanYaHei.ttf +0 -0
  96. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/ref_font/__init__.py +0 -0
  97. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Modeling_Tool/ref_font/simsun.ttc +0 -0
  98. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Report/Report_Tool.py +0 -0
  99. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/Report/__init__.py +0 -0
  100. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/dependency_links.txt +0 -0
  101. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/not-zip-safe +0 -0
  102. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/requires.txt +0 -0
  103. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/SuperModelingFactory.egg-info/top_level.txt +0 -0
  104. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/requirements.txt +0 -0
  105. {supermodelingfactory-0.3.6 → supermodelingfactory-0.3.8}/setup.cfg +0 -0
@@ -22,6 +22,7 @@ from __future__ import annotations
22
22
  import ast
23
23
  import importlib.metadata
24
24
  import sys
25
+ import warnings
25
26
 
26
27
  import numpy as np
27
28
  import pandas as pd
@@ -848,6 +849,125 @@ class ModelExplainer:
848
849
  # ------------------------------------------------------------------ #
849
850
  # LIME
850
851
  # ------------------------------------------------------------------ #
852
+ @staticmethod
853
+ def _lime_missing_mask(frame: pd.DataFrame) -> pd.Series:
854
+ numeric = frame.select_dtypes(include=[np.number])
855
+ if numeric.empty:
856
+ return pd.Series(False, index=frame.index)
857
+ return numeric.isna().any(axis=1)
858
+
859
+ @classmethod
860
+ def _warn_lime_missing(
861
+ cls,
862
+ frame: pd.DataFrame,
863
+ *,
864
+ role: str,
865
+ missing_strategy: str,
866
+ n_before: int,
867
+ n_after: int,
868
+ fill_values: dict[str, float] | None = None,
869
+ ) -> None:
870
+ numeric = frame.select_dtypes(include=[np.number])
871
+ if numeric.empty:
872
+ return
873
+ null_cols = [col for col in numeric.columns if numeric[col].isna().any()]
874
+ if not null_cols:
875
+ return
876
+ details = []
877
+ for col in null_cols:
878
+ count = int(numeric[col].isna().sum())
879
+ pct = 100.0 * count / len(frame) if len(frame) else 0.0
880
+ detail = f"{col}: {count}/{len(frame)} ({pct:.1f}%)"
881
+ if fill_values and col in fill_values:
882
+ detail += f", median_fill={fill_values[col]:.6g}"
883
+ details.append(detail)
884
+ msg = (
885
+ f"LIME missing_strategy={missing_strategy!r} on {role}: "
886
+ f"null columns={null_cols}; " + "; ".join(details)
887
+ )
888
+ if missing_strategy == "drop":
889
+ msg += f"; rows {n_before} -> {n_after}"
890
+ warnings.warn(msg, UserWarning, stacklevel=3)
891
+
892
+ @classmethod
893
+ def _prepare_lime_data(
894
+ cls,
895
+ train: pd.DataFrame,
896
+ rows: pd.DataFrame | None = None,
897
+ *,
898
+ train_role: str = "X_train",
899
+ rows_role: str = "x_row",
900
+ missing_strategy: str = "median",
901
+ ) -> tuple[pd.DataFrame, pd.DataFrame | None]:
902
+ if missing_strategy not in {"median", "drop"}:
903
+ raise ValueError("missing_strategy must be 'median' or 'drop'")
904
+
905
+ train_clean = train.copy()
906
+ rows_clean = rows.copy() if rows is not None else None
907
+ numeric_cols = list(train_clean.select_dtypes(include=[np.number]).columns)
908
+
909
+ if missing_strategy == "median":
910
+ fill_values: dict[str, float] = {}
911
+ for col in numeric_cols:
912
+ if train_clean[col].isna().any() or (
913
+ rows_clean is not None and rows_clean[col].isna().any()
914
+ ):
915
+ median_val = float(train_clean[col].median())
916
+ fill_values[col] = median_val
917
+ train_clean[col] = train_clean[col].fillna(median_val)
918
+ if rows_clean is not None:
919
+ rows_clean[col] = rows_clean[col].fillna(median_val)
920
+ cls._warn_lime_missing(
921
+ train,
922
+ role=train_role,
923
+ missing_strategy=missing_strategy,
924
+ n_before=len(train),
925
+ n_after=len(train_clean),
926
+ fill_values=fill_values or None,
927
+ )
928
+ if rows_clean is not None:
929
+ cls._warn_lime_missing(
930
+ rows,
931
+ role=rows_role,
932
+ missing_strategy=missing_strategy,
933
+ n_before=len(rows),
934
+ n_after=len(rows_clean),
935
+ fill_values=fill_values or None,
936
+ )
937
+ return train_clean, rows_clean
938
+
939
+ n_train_before = len(train_clean)
940
+ train_clean = train_clean.loc[~cls._lime_missing_mask(train_clean)].copy()
941
+ cls._warn_lime_missing(
942
+ train,
943
+ role=train_role,
944
+ missing_strategy=missing_strategy,
945
+ n_before=n_train_before,
946
+ n_after=len(train_clean),
947
+ )
948
+ if train_clean.empty:
949
+ raise ValueError(
950
+ f"LIME missing_strategy='drop' removed all rows from {train_role} "
951
+ f"({n_train_before} -> 0). Provide complete training data or use missing_strategy='median'."
952
+ )
953
+
954
+ if rows_clean is not None:
955
+ n_rows_before = len(rows_clean)
956
+ rows_clean = rows_clean.loc[~cls._lime_missing_mask(rows_clean)].copy()
957
+ cls._warn_lime_missing(
958
+ rows,
959
+ role=rows_role,
960
+ missing_strategy=missing_strategy,
961
+ n_before=n_rows_before,
962
+ n_after=len(rows_clean),
963
+ )
964
+ if rows_clean.empty:
965
+ raise ValueError(
966
+ f"LIME missing_strategy='drop' removed all rows from {rows_role} "
967
+ f"({n_rows_before} -> 0). Impute missing values or use missing_strategy='median'."
968
+ )
969
+ return train_clean, rows_clean
970
+
851
971
  def _build_lime_explainer(self, X_train, num_features=None, random_state=None, **lime_kwargs):
852
972
  LimeTabularExplainer = _lazy_lime()
853
973
  train = self._as_frame(X_train if X_train is not None else self.background_data)
@@ -864,7 +984,16 @@ class ModelExplainer:
864
984
  **lime_kwargs,
865
985
  )
866
986
 
867
- def lime_explain_instance(self, x_row, X_train=None, num_features=10, num_samples=5000, random_state=None, **lime_kwargs):
987
+ def lime_explain_instance(
988
+ self,
989
+ x_row,
990
+ X_train=None,
991
+ num_features=10,
992
+ num_samples=5000,
993
+ random_state=None,
994
+ missing_strategy="median",
995
+ **lime_kwargs,
996
+ ):
868
997
  """Explain one sample with LIME."""
869
998
  if isinstance(x_row, pd.Series):
870
999
  x_row = x_row.to_frame().T
@@ -874,7 +1003,14 @@ class ModelExplainer:
874
1003
  if frame.shape[0] != 1:
875
1004
  frame = frame.iloc[[0]]
876
1005
 
877
- train = X_train if X_train is not None else self.background_data
1006
+ train_raw = self._as_frame(X_train if X_train is not None else self.background_data)
1007
+ train, frame = self._prepare_lime_data(
1008
+ train_raw,
1009
+ frame,
1010
+ train_role="X_train",
1011
+ rows_role="x_row",
1012
+ missing_strategy=missing_strategy,
1013
+ )
878
1014
  explainer = self._build_lime_explainer(train, num_features, random_state, **lime_kwargs)
879
1015
  explanation = explainer.explain_instance(
880
1016
  data_row=np.asarray(frame.iloc[0]),
@@ -896,17 +1032,36 @@ class ModelExplainer:
896
1032
  out.attrs["score"] = explanation.score
897
1033
  return out
898
1034
 
899
- def lime_global_importance(self, X, X_train=None, num_features=10, num_samples=2000, sample_size=100, random_state=None, **lime_kwargs):
1035
+ def lime_global_importance(
1036
+ self,
1037
+ X,
1038
+ X_train=None,
1039
+ num_features=10,
1040
+ num_samples=2000,
1041
+ sample_size=100,
1042
+ random_state=None,
1043
+ missing_strategy="median",
1044
+ **lime_kwargs,
1045
+ ):
900
1046
  """Aggregate LIME local weights across a sample as global importance."""
1047
+ train_raw = self._as_frame(X_train if X_train is not None else self.background_data)
901
1048
  frame = self._sample_frame(X, sample_size=sample_size, random_state=random_state)
1049
+ train, frame = self._prepare_lime_data(
1050
+ train_raw,
1051
+ frame,
1052
+ train_role="X_train",
1053
+ rows_role="X",
1054
+ missing_strategy=missing_strategy,
1055
+ )
902
1056
  rows = []
903
1057
  for _, row in frame.iterrows():
904
1058
  local = self.lime_explain_instance(
905
1059
  row,
906
- X_train=X_train,
1060
+ X_train=train,
907
1061
  num_features=num_features,
908
1062
  num_samples=num_samples,
909
1063
  random_state=random_state,
1064
+ missing_strategy="median",
910
1065
  **lime_kwargs,
911
1066
  )
912
1067
  rows.append(local)