validmind 2.7.5__py3-none-any.whl → 2.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. validmind/__version__.py +1 -1
  2. validmind/datasets/credit_risk/lending_club.py +354 -88
  3. validmind/tests/data_validation/HighPearsonCorrelation.py +12 -2
  4. validmind/tests/ongoing_monitoring/CalibrationCurveDrift.py +218 -0
  5. validmind/tests/ongoing_monitoring/ClassDiscriminationDrift.py +153 -0
  6. validmind/tests/ongoing_monitoring/ClassImbalanceDrift.py +144 -0
  7. validmind/tests/ongoing_monitoring/ClassificationAccuracyDrift.py +146 -0
  8. validmind/tests/ongoing_monitoring/ConfusionMatrixDrift.py +191 -0
  9. validmind/tests/ongoing_monitoring/CumulativePredictionProbabilitiesDrift.py +176 -0
  10. validmind/tests/ongoing_monitoring/FeatureDrift.py +120 -121
  11. validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py +18 -23
  12. validmind/tests/ongoing_monitoring/PredictionCorrelation.py +86 -45
  13. validmind/tests/ongoing_monitoring/PredictionProbabilitiesHistogramDrift.py +202 -0
  14. validmind/tests/ongoing_monitoring/PredictionQuantilesAcrossFeatures.py +97 -0
  15. validmind/tests/ongoing_monitoring/ROCCurveDrift.py +149 -0
  16. validmind/tests/ongoing_monitoring/ScoreBandsDrift.py +210 -0
  17. validmind/tests/ongoing_monitoring/ScorecardHistogramDrift.py +207 -0
  18. validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +91 -14
  19. validmind/vm_models/dataset/dataset.py +0 -4
  20. {validmind-2.7.5.dist-info → validmind-2.7.6.dist-info}/METADATA +2 -2
  21. {validmind-2.7.5.dist-info → validmind-2.7.6.dist-info}/RECORD +24 -13
  22. {validmind-2.7.5.dist-info → validmind-2.7.6.dist-info}/LICENSE +0 -0
  23. {validmind-2.7.5.dist-info → validmind-2.7.6.dist-info}/WHEEL +0 -0
  24. {validmind-2.7.5.dist-info → validmind-2.7.6.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,210 @@
1
+ # Copyright © 2023-2024 ValidMind Inc. All rights reserved.
2
+ # See the LICENSE file in the root of this repository for details.
3
+ # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+ from typing import List
8
+ from validmind import tags, tasks
9
+ from validmind.vm_models import VMDataset, VMModel
10
+
11
+
12
+ @tags("visualization", "credit_risk", "scorecard")
13
+ @tasks("classification")
14
+ def ScoreBandsDrift(
15
+ datasets: List[VMDataset],
16
+ model: VMModel,
17
+ score_column: str = "score",
18
+ score_bands: list = None,
19
+ drift_threshold: float = 20.0,
20
+ ):
21
+ """
22
+ Analyzes drift in population distribution and default rates across score bands.
23
+
24
+ ### Purpose
25
+
26
+ The Score Bands Drift test is designed to evaluate changes in score-based risk segmentation
27
+ over time. By comparing population distribution and default rates across score bands between
28
+ reference and monitoring datasets, this test helps identify whether the model's risk
29
+ stratification remains stable in production. This is crucial for understanding if the model's
30
+ scoring behavior maintains its intended risk separation and whether specific score ranges
31
+ have experienced significant shifts.
32
+
33
+ ### Test Mechanism
34
+
35
+ This test proceeds by segmenting scores into predefined bands and analyzing three key metrics
36
+ across these bands: population distribution, predicted default rates, and observed default
37
+ rates. For each band, it computes these metrics for both reference and monitoring datasets
38
+ and quantifies drift as percentage changes. The test provides both detailed band-by-band
39
+ comparisons and overall stability assessment, with special attention to bands showing
40
+ significant drift.
41
+
42
+ ### Signs of High Risk
43
+
44
+ - Large shifts in population distribution across bands
45
+ - Significant changes in default rates within bands
46
+ - Inconsistent drift patterns between adjacent bands
47
+ - Divergence between predicted and observed rates
48
+ - Systematic shifts in risk concentration
49
+ - Empty or sparse score bands in monitoring data
50
+
51
+ ### Strengths
52
+
53
+ - Provides comprehensive view of score-based drift
54
+ - Identifies specific score ranges with instability
55
+ - Enables comparison of multiple risk metrics
56
+ - Includes both distribution and performance drift
57
+ - Supports business-relevant score segmentation
58
+ - Maintains interpretable drift thresholds
59
+
60
+ ### Limitations
61
+
62
+ - Sensitive to choice of score band boundaries
63
+ - Requires sufficient samples in each band
64
+ - Cannot suggest optimal band adjustments
65
+ - May not capture within-band distribution changes
66
+ - Limited to predefined scoring metrics
67
+ - Complex interpretation with multiple drift signals
68
+ """
69
+ # Validate score column
70
+ if score_column not in datasets[0].df.columns:
71
+ raise ValueError(
72
+ f"Score column '{score_column}' not found in reference dataset"
73
+ )
74
+ if score_column not in datasets[1].df.columns:
75
+ raise ValueError(
76
+ f"Score column '{score_column}' not found in monitoring dataset"
77
+ )
78
+
79
+ # Default score bands if none provided
80
+ if score_bands is None:
81
+ score_bands = [410, 440, 470]
82
+
83
+ # Create band labels
84
+ band_labels = [
85
+ f"{score_bands[i]}-{score_bands[i+1]}" for i in range(len(score_bands) - 1)
86
+ ]
87
+ band_labels.insert(0, f"<{score_bands[0]}")
88
+ band_labels.append(f">{score_bands[-1]}")
89
+
90
+ # Process reference and monitoring datasets
91
+ def process_dataset(dataset, model):
92
+ df = dataset.df.copy()
93
+ df["score_band"] = pd.cut(
94
+ df[score_column],
95
+ bins=[-np.inf] + score_bands + [np.inf],
96
+ labels=band_labels,
97
+ )
98
+ y_pred = dataset.y_pred(model)
99
+
100
+ results = {}
101
+ total_population = len(df)
102
+
103
+ # Store min and max scores
104
+ min_score = df[score_column].min()
105
+ max_score = df[score_column].max()
106
+
107
+ for band in band_labels:
108
+ band_mask = df["score_band"] == band
109
+ population = band_mask.sum()
110
+
111
+ results[band] = {
112
+ "Population (%)": population / total_population * 100,
113
+ "Predicted Default Rate (%)": (
114
+ y_pred[band_mask].sum() / population * 100 if population > 0 else 0
115
+ ),
116
+ "Observed Default Rate (%)": (
117
+ df[band_mask][dataset.target_column].sum() / population * 100
118
+ if population > 0
119
+ else 0
120
+ ),
121
+ }
122
+
123
+ results["min_score"] = min_score
124
+ results["max_score"] = max_score
125
+ return results
126
+
127
+ # Get metrics for both datasets
128
+ ref_results = process_dataset(datasets[0], model)
129
+ mon_results = process_dataset(datasets[1], model)
130
+
131
+ # Create the three comparison tables
132
+ tables = {}
133
+ all_passed = True
134
+
135
+ metrics = [
136
+ ("Population Distribution (%)", "Population (%)"),
137
+ ("Predicted Default Rates (%)", "Predicted Default Rate (%)"),
138
+ ("Observed Default Rates (%)", "Observed Default Rate (%)"),
139
+ ]
140
+
141
+ for table_name, metric in metrics:
142
+ rows = []
143
+ metric_passed = True
144
+
145
+ for band in band_labels:
146
+ ref_val = ref_results[band][metric]
147
+ mon_val = mon_results[band][metric]
148
+
149
+ # Calculate drift - using absolute difference when reference is 0
150
+ drift = (
151
+ abs(mon_val - ref_val)
152
+ if ref_val == 0
153
+ else ((mon_val - ref_val) / abs(ref_val)) * 100
154
+ )
155
+ passed = abs(drift) < drift_threshold
156
+ metric_passed &= passed
157
+
158
+ rows.append(
159
+ {
160
+ "Score Band": band,
161
+ "Reference": round(ref_val, 4),
162
+ "Monitoring": round(mon_val, 4),
163
+ "Drift (%)": round(drift, 2),
164
+ "Pass/Fail": "Pass" if passed else "Fail",
165
+ }
166
+ )
167
+
168
+ # Add total row for all metrics
169
+ if metric == "Population (%)":
170
+ ref_total = 100.0
171
+ mon_total = 100.0
172
+ drift_total = 0.0
173
+ passed_total = True
174
+ else:
175
+ ref_total = sum(
176
+ ref_results[band][metric] * (ref_results[band]["Population (%)"] / 100)
177
+ for band in band_labels
178
+ )
179
+ mon_total = sum(
180
+ mon_results[band][metric] * (mon_results[band]["Population (%)"] / 100)
181
+ for band in band_labels
182
+ )
183
+ # Apply same drift calculation to totals
184
+ drift_total = (
185
+ abs(mon_total - ref_total)
186
+ if ref_total == 0
187
+ else ((mon_total - ref_total) / abs(ref_total)) * 100
188
+ )
189
+ passed_total = abs(drift_total) < drift_threshold
190
+
191
+ # Format total row with score ranges
192
+ total_label = (
193
+ f"Total ({ref_results['min_score']:.0f}-{ref_results['max_score']:.0f})"
194
+ )
195
+
196
+ rows.append(
197
+ {
198
+ "Score Band": total_label,
199
+ "Reference": round(ref_total, 4),
200
+ "Monitoring": round(mon_total, 4),
201
+ "Drift (%)": round(drift_total, 2),
202
+ "Pass/Fail": "Pass" if passed_total else "Fail",
203
+ }
204
+ )
205
+
206
+ metric_passed &= passed_total
207
+ tables[table_name] = pd.DataFrame(rows)
208
+ all_passed &= metric_passed
209
+
210
+ return tables, all_passed
@@ -0,0 +1,207 @@
1
+ # Copyright © 2023-2024 ValidMind Inc. All rights reserved.
2
+ # See the LICENSE file in the root of this repository for details.
3
+ # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ import plotly.graph_objects as go
8
+ from plotly.subplots import make_subplots
9
+ from scipy import stats
10
+ from typing import List
11
+ from validmind import tags, tasks
12
+ from validmind.vm_models import VMDataset
13
+
14
+
15
+ @tags("visualization", "credit_risk", "logistic_regression")
16
+ @tasks("classification")
17
+ def ScorecardHistogramDrift(
18
+ datasets: List[VMDataset],
19
+ score_column: str = "score",
20
+ title: str = "Scorecard Histogram Drift",
21
+ drift_pct_threshold: float = 20.0,
22
+ ):
23
+ """
24
+ Compares score distributions between reference and monitoring datasets for each class.
25
+
26
+ ### Purpose
27
+
28
+ The Scorecard Histogram Drift test is designed to evaluate changes in the model's scoring
29
+ patterns over time. By comparing score distributions between reference and monitoring datasets
30
+ for each class, this test helps identify whether the model's scoring behavior remains stable
31
+ in production. This is crucial for understanding if the model's risk assessment maintains
32
+ consistent patterns and whether specific score ranges have experienced significant shifts
33
+ in their distribution.
34
+
35
+ ### Test Mechanism
36
+
37
+ This test proceeds by generating histograms of scores for each class in both reference and
38
+ monitoring datasets. It analyzes distribution characteristics through multiple statistical
39
+ moments: mean, variance, skewness, and kurtosis. The test quantifies drift as percentage
40
+ changes in these moments between datasets, providing both visual and numerical assessments
41
+ of distribution stability. Special attention is paid to class-specific distribution changes.
42
+
43
+ ### Signs of High Risk
44
+
45
+ - Significant shifts in score distribution shapes
46
+ - Large drifts in distribution moments exceeding threshold
47
+ - Changes in the relative positioning of class distributions
48
+ - Appearance of new modes or peaks in monitoring data
49
+ - Unexpected changes in score spread or concentration
50
+ - Systematic shifts in class-specific scoring patterns
51
+
52
+ ### Strengths
53
+
54
+ - Provides class-specific distribution analysis
55
+ - Identifies detailed changes in scoring patterns
56
+ - Enables visual comparison of distributions
57
+ - Includes comprehensive moment analysis
58
+ - Supports multiple class evaluation
59
+ - Maintains interpretable score scale
60
+
61
+ ### Limitations
62
+
63
+ - Sensitive to binning choices in visualization
64
+ - Requires sufficient samples per class
65
+ - Cannot suggest score adjustments
66
+ - May not capture subtle distribution changes
67
+ - Complex interpretation with multiple classes
68
+ - Limited to univariate score analysis
69
+ """
70
+ # Verify score column exists
71
+ if score_column not in datasets[0].df.columns:
72
+ raise ValueError(
73
+ f"Score column '{score_column}' not found in reference dataset"
74
+ )
75
+ if score_column not in datasets[1].df.columns:
76
+ raise ValueError(
77
+ f"Score column '{score_column}' not found in monitoring dataset"
78
+ )
79
+
80
+ # Get reference and monitoring data
81
+ df_ref = datasets[0].df
82
+ df_mon = datasets[1].df
83
+
84
+ # Get unique classes
85
+ classes = sorted(df_ref[datasets[0].target_column].unique())
86
+
87
+ # Create subplots with more horizontal space for legends
88
+ fig = make_subplots(
89
+ rows=len(classes),
90
+ cols=1,
91
+ subplot_titles=[f"Class {cls}" for cls in classes],
92
+ horizontal_spacing=0.15,
93
+ )
94
+
95
+ # Define colors
96
+ ref_color = "rgba(31, 119, 180, 0.8)" # Blue with 0.8 opacity
97
+ mon_color = "rgba(255, 127, 14, 0.8)" # Orange with 0.8 opacity
98
+
99
+ # Dictionary to store tables for each class
100
+ tables = {}
101
+ all_passed = True # Track overall pass/fail
102
+
103
+ # Add histograms and create tables for each class
104
+ for i, class_value in enumerate(classes, start=1):
105
+ # Get scores for current class
106
+ ref_scores = df_ref[df_ref[datasets[0].target_column] == class_value][
107
+ score_column
108
+ ]
109
+ mon_scores = df_mon[df_mon[datasets[1].target_column] == class_value][
110
+ score_column
111
+ ]
112
+
113
+ # Calculate distribution moments
114
+ ref_stats = {
115
+ "Mean": np.mean(ref_scores),
116
+ "Variance": np.var(ref_scores),
117
+ "Skewness": stats.skew(ref_scores),
118
+ "Kurtosis": stats.kurtosis(ref_scores),
119
+ }
120
+
121
+ mon_stats = {
122
+ "Mean": np.mean(mon_scores),
123
+ "Variance": np.var(mon_scores),
124
+ "Skewness": stats.skew(mon_scores),
125
+ "Kurtosis": stats.kurtosis(mon_scores),
126
+ }
127
+
128
+ # Create table for this class
129
+ table_data = []
130
+ class_passed = True # Track pass/fail for this class
131
+
132
+ for stat_name in ["Mean", "Variance", "Skewness", "Kurtosis"]:
133
+ ref_val = ref_stats[stat_name]
134
+ mon_val = mon_stats[stat_name]
135
+ drift = (
136
+ ((mon_val - ref_val) / abs(ref_val)) * 100 if ref_val != 0 else np.inf
137
+ )
138
+ passed = abs(drift) < drift_pct_threshold
139
+ class_passed &= passed # Update class pass/fail
140
+
141
+ table_data.append(
142
+ {
143
+ "Statistic": stat_name,
144
+ "Reference": round(ref_val, 4),
145
+ "Monitoring": round(mon_val, 4),
146
+ "Drift (%)": round(drift, 2),
147
+ "Pass/Fail": "Pass" if passed else "Fail",
148
+ }
149
+ )
150
+
151
+ tables[f"Class {class_value}"] = pd.DataFrame(table_data)
152
+ all_passed &= class_passed # Update overall pass/fail
153
+
154
+ # Reference dataset histogram
155
+ fig.add_trace(
156
+ go.Histogram(
157
+ x=ref_scores,
158
+ name=f"Reference - Class {class_value}",
159
+ marker_color=ref_color,
160
+ showlegend=True,
161
+ legendrank=i * 2 - 1,
162
+ ),
163
+ row=i,
164
+ col=1,
165
+ )
166
+
167
+ # Monitoring dataset histogram
168
+ fig.add_trace(
169
+ go.Histogram(
170
+ x=mon_scores,
171
+ name=f"Monitoring - Class {class_value}",
172
+ marker_color=mon_color,
173
+ showlegend=True,
174
+ legendrank=i * 2,
175
+ ),
176
+ row=i,
177
+ col=1,
178
+ )
179
+
180
+ # Update layout
181
+ fig.update_layout(
182
+ title_text=title,
183
+ barmode="overlay",
184
+ height=300 * len(classes),
185
+ width=1000,
186
+ showlegend=True,
187
+ )
188
+
189
+ # Update axes labels and add separate legends for each subplot
190
+ for i in range(len(classes)):
191
+ fig.update_xaxes(title_text="Score", row=i + 1, col=1)
192
+ fig.update_yaxes(title_text="Frequency", row=i + 1, col=1)
193
+
194
+ # Add separate legend for each subplot
195
+ fig.update_layout(
196
+ **{
197
+ f'legend{i+1 if i > 0 else ""}': dict(
198
+ yanchor="middle",
199
+ y=1 - (i / len(classes)) - (0.5 / len(classes)),
200
+ xanchor="left",
201
+ x=1.05,
202
+ tracegroupgap=5,
203
+ )
204
+ }
205
+ )
206
+
207
+ return fig, tables, all_passed
@@ -2,15 +2,16 @@
2
2
  # See the LICENSE file in the root of this repository for details.
3
3
  # SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
4
4
 
5
- import matplotlib.pyplot as plt
6
- import seaborn as sns
7
-
5
+ import plotly.graph_objects as go
6
+ import plotly.figure_factory as ff
7
+ import pandas as pd
8
+ from scipy.stats import skew, kurtosis
8
9
  from validmind import tags, tasks
9
10
 
10
11
 
11
12
  @tags("visualization")
12
13
  @tasks("monitoring")
13
- def TargetPredictionDistributionPlot(datasets, model):
14
+ def TargetPredictionDistributionPlot(datasets, model, drift_pct_threshold=20):
14
15
  """
15
16
  Assesses differences in prediction distributions between a reference dataset and a monitoring dataset to identify
16
17
  potential data drift.
@@ -45,23 +46,99 @@ def TargetPredictionDistributionPlot(datasets, model):
45
46
  - Less effective if the differences in distributions are subtle and not easily visible.
46
47
  """
47
48
 
49
+ # Get predictions
48
50
  pred_ref = datasets[0].y_prob_df(model)
49
51
  pred_ref.columns = ["Reference Prediction"]
50
52
  pred_monitor = datasets[1].y_prob_df(model)
51
53
  pred_monitor.columns = ["Monitoring Prediction"]
52
54
 
53
- fig = plt.figure()
54
- plot = sns.kdeplot(
55
- pred_ref["Reference Prediction"], fill=True, label="Reference Prediction"
55
+ # Calculate distribution moments
56
+ moments = pd.DataFrame(
57
+ {
58
+ "Statistic": ["Mean", "Std", "Skewness", "Kurtosis"],
59
+ "Reference": [
60
+ pred_ref["Reference Prediction"].mean(),
61
+ pred_ref["Reference Prediction"].std(),
62
+ skew(pred_ref["Reference Prediction"]),
63
+ kurtosis(pred_ref["Reference Prediction"]),
64
+ ],
65
+ "Monitoring": [
66
+ pred_monitor["Monitoring Prediction"].mean(),
67
+ pred_monitor["Monitoring Prediction"].std(),
68
+ skew(pred_monitor["Monitoring Prediction"]),
69
+ kurtosis(pred_monitor["Monitoring Prediction"]),
70
+ ],
71
+ }
72
+ )
73
+
74
+ # Calculate drift percentage with direction
75
+ moments["Drift (%)"] = (
76
+ (moments["Monitoring"] - moments["Reference"])
77
+ / moments["Reference"].abs()
78
+ * 100
79
+ ).round(2)
80
+
81
+ # Add Pass/Fail column based on absolute drift
82
+ moments["Pass/Fail"] = (
83
+ moments["Drift (%)"]
84
+ .abs()
85
+ .apply(lambda x: "Pass" if x < drift_pct_threshold else "Fail")
86
+ )
87
+
88
+ # Set Statistic as index but keep it as a column
89
+ moments = moments.set_index("Statistic", drop=False)
90
+
91
+ # Create KDE for both distributions
92
+ ref_kde = ff.create_distplot(
93
+ [pred_ref["Reference Prediction"].values],
94
+ ["Reference"],
95
+ show_hist=False,
96
+ show_rug=False,
56
97
  )
57
- plot = sns.kdeplot(
58
- pred_monitor["Monitoring Prediction"], fill=True, label="Monitor Prediction"
98
+ monitor_kde = ff.create_distplot(
99
+ [pred_monitor["Monitoring Prediction"].values],
100
+ ["Monitoring"],
101
+ show_hist=False,
102
+ show_rug=False,
59
103
  )
60
- plot.set(
61
- xlabel="Prediction", title="Distribution of Reference & Monitor Predictions"
104
+
105
+ # Create new figure
106
+ fig = go.Figure()
107
+
108
+ # Add reference distribution
109
+ fig.add_trace(
110
+ go.Scatter(
111
+ x=ref_kde.data[0].x,
112
+ y=ref_kde.data[0].y,
113
+ fill="tozeroy",
114
+ name="Reference Prediction",
115
+ line=dict(color="blue", width=2),
116
+ opacity=0.6,
117
+ )
118
+ )
119
+
120
+ # Add monitoring distribution
121
+ fig.add_trace(
122
+ go.Scatter(
123
+ x=monitor_kde.data[0].x,
124
+ y=monitor_kde.data[0].y,
125
+ fill="tozeroy",
126
+ name="Monitor Prediction",
127
+ line=dict(color="red", width=2),
128
+ opacity=0.6,
129
+ )
130
+ )
131
+
132
+ # Update layout
133
+ fig.update_layout(
134
+ title="Distribution of Reference & Monitor Predictions",
135
+ xaxis_title="Prediction",
136
+ yaxis_title="Density",
137
+ showlegend=True,
138
+ template="plotly_white",
139
+ hovermode="x unified",
62
140
  )
63
- plot.legend()
64
141
 
65
- plt.close()
142
+ pass_fail_bool = (moments["Pass/Fail"] == "Pass").all()
66
143
 
67
- return fig
144
+ return ({"Distribution Moments": moments}, fig, pass_fail_bool)
@@ -369,10 +369,6 @@ class VMDataset(VMInput):
369
369
  # reset feature columns to exclude the new extra column
370
370
  self._set_feature_columns()
371
371
 
372
- logger.info(
373
- f"Extra column {column_name} with {len(column_values)} values added to the dataset"
374
- )
375
-
376
372
  @property
377
373
  def df(self) -> pd.DataFrame:
378
374
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: validmind
3
- Version: 2.7.5
3
+ Version: 2.7.6
4
4
  Summary: ValidMind Library
5
5
  License: Commercial License
6
6
  Author: Andres Rodriguez
@@ -44,7 +44,7 @@ Requires-Dist: python-dotenv
44
44
  Requires-Dist: ragas (>=0.2.3) ; extra == "all" or extra == "llm"
45
45
  Requires-Dist: rouge (>=1)
46
46
  Requires-Dist: rpy2 (>=3.5.10,<4.0.0) ; extra == "all" or extra == "r-support"
47
- Requires-Dist: scikit-learn (!=1.6.0)
47
+ Requires-Dist: scikit-learn (<1.6.0)
48
48
  Requires-Dist: scipy
49
49
  Requires-Dist: scorecardpy (>=0.1.9.6,<0.2.0.0)
50
50
  Requires-Dist: seaborn
@@ -1,5 +1,5 @@
1
1
  validmind/__init__.py,sha256=U-S6pV31O3sVsbcEzlriz0tootyfvPnPOu4PHzXz9tM,2688
2
- validmind/__version__.py,sha256=lBcjVwt4I0-VUeE_7gM1gQBbtKOi9jGT3DavJbzcYnQ,22
2
+ validmind/__version__.py,sha256=6xG2XfctNZV_iMAbDf3PscewWwjPfwfmAC2zaeMR2KI,22
3
3
  validmind/ai/test_descriptions.py,sha256=OpdMyLkZqlvegxjKfg2iJ0o4PwjnRv4_kEzePyuQiYs,7345
4
4
  validmind/ai/test_result_description/config.yaml,sha256=E1gPd-uv-MzdrWZA_rP6LSk8pVmkYijx6v78hZ8ceL0,787
5
5
  validmind/ai/test_result_description/context.py,sha256=ebKulFMpXTDLqd6lOHAsG200GmLNnhnu7sMDnbo2Dhc,2339
@@ -20,7 +20,7 @@ validmind/datasets/cluster/digits.py,sha256=E600pX6QPrqndfr73kwZ1sTNk0hC5kNj4Fhs
20
20
  validmind/datasets/credit_risk/__init__.py,sha256=vK0wyUcA2mpjasNR-EaBj_0MdPhJw5KK8xlrKj_xl68,295
21
21
  validmind/datasets/credit_risk/datasets/lending_club_biased.csv.gz,sha256=PdsyEqHtfShtfl_xoNWva2Ofyfx5hmrLhowPka4hLew,6266192
22
22
  validmind/datasets/credit_risk/datasets/lending_club_loan_data_2007_2014_clean.csv.gz,sha256=bAgdfmUxjYOdZMPvoHtKr_GLoXNAX04KUTfjn2L62eE,5493810
23
- validmind/datasets/credit_risk/lending_club.py,sha256=vBqEx3pK1Q7WpRIHRg692FcgJOv_Z1G7UprhlOPdlfE,25547
23
+ validmind/datasets/credit_risk/lending_club.py,sha256=m8VnZSkNo5ja-y-WSc7MbUavlGKKY2YqfGOV3Pzcg_4,34630
24
24
  validmind/datasets/credit_risk/lending_club_bias.py,sha256=8_Xf1qxCTUPv1wYHYkjabO2WtQsfVudJ6eje3phQUrc,4461
25
25
  validmind/datasets/llm/rag/__init__.py,sha256=v8BygB6rGECoMIXv2_I1lVUAfPJ_gVo0GgVKhzk60h4,264
26
26
  validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_1.csv,sha256=8Ae8TD5Yh6rQ67HMCu7iKipj5tyOOhzylZqLppAeKzs,24095
@@ -113,7 +113,7 @@ validmind/tests/data_validation/Duplicates.py,sha256=HAEHRFwFZovJU-wBWea0KJREsJC
113
113
  validmind/tests/data_validation/EngleGrangerCoint.py,sha256=kNBbxLYweF8qTF5JVRzcyXq3aKLhkN_1iv3mwwskTBU,4503
114
114
  validmind/tests/data_validation/FeatureTargetCorrelationPlot.py,sha256=OwEEavtIY23HRH1CcdCJnTlbj1hn9mCLe9mG8Yw0EOs,4249
115
115
  validmind/tests/data_validation/HighCardinality.py,sha256=nXANbDQPogdFzYLJ9xJIdjWjNJ7yhteAdkcUWrm4Lrg,3362
116
- validmind/tests/data_validation/HighPearsonCorrelation.py,sha256=hc-DvaFz4Ew1Lc6uV3xiPAL7M_srwro-MeHVafmxxsk,3537
116
+ validmind/tests/data_validation/HighPearsonCorrelation.py,sha256=KiWKgkqHY387GaYS7HmgHQFuwKiV95Su3eXS-h8paJs,3703
117
117
  validmind/tests/data_validation/IQROutliersBarPlot.py,sha256=8E7onPlknLcci_zHrM1RbZJnYLrLhFMWblwadCqFozQ,4978
118
118
  validmind/tests/data_validation/IQROutliersTable.py,sha256=_YoqYw-rATiPuY9sOYJAT1jKdGm_VFnYqfbugMkoM6w,3962
119
119
  validmind/tests/data_validation/IsolationForestOutliers.py,sha256=bjkPF4Dczt-dzPZsElGZPv6G_fRkSB9sSeCwj42tZrg,3881
@@ -266,10 +266,21 @@ validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImporta
266
266
  validmind/tests/model_validation/statsmodels/ScorecardHistogram.py,sha256=0hnB6icasRKT_Cl0YxMEpIuaUKgi5scXHmV_nP9RmkI,4650
267
267
  validmind/tests/model_validation/statsmodels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
268
268
  validmind/tests/model_validation/statsmodels/statsutils.py,sha256=s1J7lHJ4kAcp_gGI0LAsaIFxbSqPrqXanxgtDI_Kig0,495
269
- validmind/tests/ongoing_monitoring/FeatureDrift.py,sha256=qsBoolRGgW6sdUa8F-c4gsf6liFTyO4hCY-2lJv7YNY,6234
270
- validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py,sha256=QDaYzf2b3n4yU_Rq3kBRJA49jIl1RP-n2d4KikZ76_c,3323
271
- validmind/tests/ongoing_monitoring/PredictionCorrelation.py,sha256=15GqFODz986m0c-62fc1UffSRLndGv4WiB2Uz503zak,3449
272
- validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py,sha256=KVJvMGpNg0fsCJ9ZkUmlRZ-L1Gy9xLj1YS_C-p5bsXc,2498
269
+ validmind/tests/ongoing_monitoring/CalibrationCurveDrift.py,sha256=VHWKOE317SMv6I_9Ua8unsV9CalpMVZqPLn8HGp9wqo,7843
270
+ validmind/tests/ongoing_monitoring/ClassDiscriminationDrift.py,sha256=ZdqrZf9Wr5gWhMICEx2RopL3CE-CJekDWNForo1JdHM,5706
271
+ validmind/tests/ongoing_monitoring/ClassImbalanceDrift.py,sha256=tdzhDbA2WrAFjUJmKYWraXCYArAK0hZOk9Fp2AyU0AY,5059
272
+ validmind/tests/ongoing_monitoring/ClassificationAccuracyDrift.py,sha256=C1FqCd_3C5J9BhgOlxtAtS6onOkxdF39-22XI-R5yEQ,4990
273
+ validmind/tests/ongoing_monitoring/ConfusionMatrixDrift.py,sha256=RokHTnbKGzDx5dsuXSuTT9kC-yIPEkjfq67bCM1UYug,6946
274
+ validmind/tests/ongoing_monitoring/CumulativePredictionProbabilitiesDrift.py,sha256=rXbK344BXCk-MI0ERylewMF8lL1jXdgoQZWdoYQexpk,6199
275
+ validmind/tests/ongoing_monitoring/FeatureDrift.py,sha256=Mgry31V2juaIWGyPVBJUxeHD5zC1PJpAWYQImwcrNJc,6191
276
+ validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py,sha256=ngIS8Ybp4GzAqIZdVMxH4PvKtulMkxfsh6lSM6Gp1g0,3052
277
+ validmind/tests/ongoing_monitoring/PredictionCorrelation.py,sha256=W2nEdmGTvNN6v3y3Xscsh2V8lwtWxdcCHjwuyrn_91o,5020
278
+ validmind/tests/ongoing_monitoring/PredictionProbabilitiesHistogramDrift.py,sha256=qGLWPzWUHFatC1LC2JkMTSJaiPLR5G1KRzWe8cbWSLY,7130
279
+ validmind/tests/ongoing_monitoring/PredictionQuantilesAcrossFeatures.py,sha256=MMICygVYq2sN9w52apo3H6ajhWezNkKgTkTM93gYC_U,3251
280
+ validmind/tests/ongoing_monitoring/ROCCurveDrift.py,sha256=ST8QvyPnjSI4_qv7N0n-c157Ej6oGykCzaAVj35i3FQ,5121
281
+ validmind/tests/ongoing_monitoring/ScoreBandsDrift.py,sha256=FewqXl8eeZZR2Z_4qZxZGjnh8mRVcOsC7-prl3lBTT0,7496
282
+ validmind/tests/ongoing_monitoring/ScorecardHistogramDrift.py,sha256=7hD4JSyTKik1NHVG-FJ02IMcqWnoqAjox1JvYJZDoFg,7258
283
+ validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py,sha256=osC9QUPYJjR4hU3EnfVr7S5r5oLCh8txn3bgDl8CaB4,4863
273
284
  validmind/tests/output.py,sha256=1kY9FJWUOpZ2BofxKQ5scxkg10Pvb24_OxypegHeh04,4029
274
285
  validmind/tests/prompt_validation/Bias.py,sha256=UFtC7l8aXBkyzfpvZ2db2JlO5SZOssp2mCrUk5HKyTY,5702
275
286
  validmind/tests/prompt_validation/Clarity.py,sha256=KA1hFtsUHO02epDEIc4W1LtuU3BoXCg3xkQsuIUKeuI,4825
@@ -303,7 +314,7 @@ validmind/unit_metrics/regression/RootMeanSquaredError.py,sha256=uIDsSpy75Z7W3zu
303
314
  validmind/utils.py,sha256=WvjKXskGmVGupEVYvEiy5-0cBT_jwpKfpH2HsCfy_B8,18655
304
315
  validmind/vm_models/__init__.py,sha256=lcqf9q2aRzrVrNN6R--81IkrnSa6BXPbhJ8SnkT_hcI,702
305
316
  validmind/vm_models/dataset/__init__.py,sha256=U4CxZjdoc0dd9u2AqBl5PJh1UVbzXWNrmundmjLF-qE,346
306
- validmind/vm_models/dataset/dataset.py,sha256=Zzquc3FhPGTMZhFxNlAIHf4AGXq5idpJmr-fkXUpi6A,26498
317
+ validmind/vm_models/dataset/dataset.py,sha256=F6_rc5pjccRLnB7UcIMiGMbD-qMVUW5v4TnZTNSXTbo,26370
307
318
  validmind/vm_models/dataset/utils.py,sha256=VMcPEgwW9oW5D0MCa_MqXCq_sEzzsLLRmS4RaYrsif0,5530
308
319
  validmind/vm_models/figure.py,sha256=7VNOIsbOsUKyXvgxaY10H_Wvy2HEFte3nwdx09SZu20,6297
309
320
  validmind/vm_models/input.py,sha256=qLdqz_bktr4v0YcPha2vFdDvmkC-btT1pH9zBIkt1OY,1046
@@ -316,8 +327,8 @@ validmind/vm_models/test_suite/runner.py,sha256=Cpl9WKwHzJD5Zvrh71FzbEhGZkHM0x0M
316
327
  validmind/vm_models/test_suite/summary.py,sha256=Ug3nMvpPL2DSTDujWagWMCrFiW9oDy0AqJL_zXN8pH0,4642
317
328
  validmind/vm_models/test_suite/test.py,sha256=uImjmPlBlLrlVPavsUzbaDK55bvpOn3PuFyWeyYyTac,3908
318
329
  validmind/vm_models/test_suite/test_suite.py,sha256=5Jppt2UXSMgvJ6FO5LIAKA4oN_-hh9SMr8APAFJzk9g,5080
319
- validmind-2.7.5.dist-info/LICENSE,sha256=XonPUfwjvrC5Ombl3y-ko0Wubb1xdG_7nzvIbkZRKHw,35772
320
- validmind-2.7.5.dist-info/METADATA,sha256=O6Wiic_-q2EBgaNPpb6hBTaa-tvW9QbZ9WVL-ZiB_4k,6124
321
- validmind-2.7.5.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
322
- validmind-2.7.5.dist-info/entry_points.txt,sha256=HuW7YyOv9u_OEWpViQXtv0nfoI67uieJHawKWA4Hv9A,76
323
- validmind-2.7.5.dist-info/RECORD,,
330
+ validmind-2.7.6.dist-info/LICENSE,sha256=XonPUfwjvrC5Ombl3y-ko0Wubb1xdG_7nzvIbkZRKHw,35772
331
+ validmind-2.7.6.dist-info/METADATA,sha256=ce1HwawW3_UDY7y7PJjoRgx6Fp2Ta9FgIuJur5T3w1o,6123
332
+ validmind-2.7.6.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
333
+ validmind-2.7.6.dist-info/entry_points.txt,sha256=HuW7YyOv9u_OEWpViQXtv0nfoI67uieJHawKWA4Hv9A,76
334
+ validmind-2.7.6.dist-info/RECORD,,