gitlabds 2.1.6__tar.gz → 2.1.7__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.
- {gitlabds-2.1.6 → gitlabds-2.1.7}/PKG-INFO +1 -1
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/model_evaluator.py +64 -22
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds.egg-info/PKG-INFO +1 -1
- {gitlabds-2.1.6 → gitlabds-2.1.7}/LICENSE +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/README.md +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/__init__.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/baselines.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/config_generator.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/dummy.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/feature_reduction.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/insights.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/memory_optimization.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/missing.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/missing_check.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/missing_fill.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/monitoring_metrics.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/outliers.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/split_data.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds/trends.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds.egg-info/SOURCES.txt +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds.egg-info/dependency_links.txt +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds.egg-info/requires.txt +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/gitlabds.egg-info/top_level.txt +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/setup.cfg +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/setup.py +0 -0
- {gitlabds-2.1.6 → gitlabds-2.1.7}/tests/__init__.py +0 -0
|
@@ -1938,7 +1938,6 @@ class ModelEvaluator:
|
|
|
1938
1938
|
ax.set_yticks([])
|
|
1939
1939
|
ax.set_title(f"Class {class_idx}")
|
|
1940
1940
|
|
|
1941
|
-
|
|
1942
1941
|
def plot_shap_beeswarm(
|
|
1943
1942
|
self,
|
|
1944
1943
|
n_features: int = 20,
|
|
@@ -1954,6 +1953,13 @@ class ModelEvaluator:
|
|
|
1954
1953
|
) -> None:
|
|
1955
1954
|
"""
|
|
1956
1955
|
Create a SHAP beeswarm plot for feature importance.
|
|
1956
|
+
|
|
1957
|
+
Parameters
|
|
1958
|
+
----------
|
|
1959
|
+
class_index : int, optional
|
|
1960
|
+
For multi-class classification, specify which class to plot.
|
|
1961
|
+
If None, plots global importance (averaged across classes).
|
|
1962
|
+
Only applicable for multi-class models.
|
|
1957
1963
|
"""
|
|
1958
1964
|
# Set defaults if not provided
|
|
1959
1965
|
save_plot = self.save_plots if save_plot is None else save_plot
|
|
@@ -1986,33 +1992,62 @@ class ModelEvaluator:
|
|
|
1986
1992
|
# Get SHAP values
|
|
1987
1993
|
shap_values = explainer(X)
|
|
1988
1994
|
|
|
1989
|
-
# For multi-class classification
|
|
1995
|
+
# For multi-class classification
|
|
1990
1996
|
if self.classification and self.n_classes > 2:
|
|
1991
|
-
# For multi-class, we need to create a 2D representation for beeswarm
|
|
1992
1997
|
if hasattr(shap_values, 'values') and len(shap_values.values.shape) == 3:
|
|
1993
|
-
#
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
1998
|
+
# Validate class_index if provided
|
|
1999
|
+
if class_index is not None:
|
|
2000
|
+
if not isinstance(class_index, int) or class_index < 0 or class_index >= self.n_classes:
|
|
2001
|
+
logger.warning(f"Invalid class_index {class_index}. Must be integer between 0 and {self.n_classes-1}. Using global view.")
|
|
2002
|
+
class_index = None
|
|
2003
|
+
|
|
2004
|
+
if class_index is not None:
|
|
2005
|
+
# Plot for specific class
|
|
2006
|
+
class_values = shap_values.values[:, :, class_index]
|
|
2007
|
+
class_exp = shap.Explanation(
|
|
2008
|
+
values=class_values,
|
|
2009
|
+
data=X.values,
|
|
2010
|
+
feature_names=X.columns.tolist()
|
|
2011
|
+
)
|
|
2012
|
+
|
|
2013
|
+
# Create a figure first
|
|
2014
|
+
plt.figure(figsize=(12, 8))
|
|
2015
|
+
|
|
2016
|
+
# Use the class-specific explanation for plotting
|
|
2017
|
+
if plot_type == "beeswarm":
|
|
2018
|
+
shap.plots.beeswarm(class_exp, max_display=n_features, show=False)
|
|
2019
|
+
else:
|
|
2020
|
+
shap.plots.bar(class_exp, max_display=n_features, show=False)
|
|
2021
|
+
|
|
2022
|
+
plt.title(f"SHAP Values for Class {class_index} ({dataset.title()} Data)")
|
|
2023
|
+
|
|
2007
2024
|
else:
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2025
|
+
# Create global explanation by taking the mean across the class dimension
|
|
2026
|
+
global_values = shap_values.values.mean(axis=2)
|
|
2027
|
+
global_exp = shap.Explanation(
|
|
2028
|
+
values=global_values,
|
|
2029
|
+
data=X.values,
|
|
2030
|
+
feature_names=X.columns.tolist()
|
|
2031
|
+
)
|
|
2032
|
+
|
|
2033
|
+
# Create a figure first
|
|
2034
|
+
plt.figure(figsize=(12, 8))
|
|
2035
|
+
|
|
2036
|
+
# Use the global explanation for plotting
|
|
2037
|
+
if plot_type == "beeswarm":
|
|
2038
|
+
shap.plots.beeswarm(global_exp, max_display=n_features, show=False)
|
|
2039
|
+
else:
|
|
2040
|
+
shap.plots.bar(global_exp, max_display=n_features, show=False)
|
|
2041
|
+
|
|
2042
|
+
plt.title(f"SHAP Values - Global View ({dataset.title()} Data)")
|
|
2011
2043
|
|
|
2012
|
-
# Handle saving
|
|
2044
|
+
# Handle saving and showing
|
|
2013
2045
|
if save_plot:
|
|
2014
2046
|
os.makedirs(plot_dir, exist_ok=True)
|
|
2015
|
-
|
|
2047
|
+
if class_index is not None:
|
|
2048
|
+
save_path = os.path.join(plot_dir, f"{plot_name}_class_{class_index}.{plot_save_format}")
|
|
2049
|
+
else:
|
|
2050
|
+
save_path = os.path.join(plot_dir, f"{plot_name}.{plot_save_format}")
|
|
2016
2051
|
plt.savefig(save_path, format=plot_save_format, dpi=plot_save_dpi, bbox_inches="tight")
|
|
2017
2052
|
|
|
2018
2053
|
# Show or close
|
|
@@ -2024,10 +2059,15 @@ class ModelEvaluator:
|
|
|
2024
2059
|
return
|
|
2025
2060
|
else:
|
|
2026
2061
|
# If the SHAP values don't have the expected format
|
|
2062
|
+
if class_index is not None:
|
|
2063
|
+
logger.warning("Multi-class SHAP values don't have expected format for class-specific plotting. Using global view.")
|
|
2027
2064
|
logger.warning("Multi-class SHAP values don't have expected format. Unable to create beeswarm plot.")
|
|
2028
2065
|
return
|
|
2029
2066
|
|
|
2030
2067
|
# Binary classification or regression - use the original behavior
|
|
2068
|
+
if class_index is not None:
|
|
2069
|
+
logger.warning(f"class_index parameter ignored for {('binary classification' if self.classification else 'regression')} model.")
|
|
2070
|
+
|
|
2031
2071
|
# Create a figure first
|
|
2032
2072
|
plt.figure(figsize=(12, 8))
|
|
2033
2073
|
|
|
@@ -2056,6 +2096,8 @@ class ModelEvaluator:
|
|
|
2056
2096
|
print(f"Error: {str(e)}")
|
|
2057
2097
|
|
|
2058
2098
|
|
|
2099
|
+
|
|
2100
|
+
|
|
2059
2101
|
def plot_score_distribution(
|
|
2060
2102
|
self,
|
|
2061
2103
|
bins=None,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|