validmind 2.13.7__tar.gz → 2.13.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.
- {validmind-2.13.7 → validmind-2.13.8}/PKG-INFO +1 -1
- {validmind-2.13.7 → validmind-2.13.8}/pyproject.toml +1 -1
- validmind-2.13.8/validmind/__version__.py +1 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/api_client.py +2 -2
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/PopulationStabilityIndex.py +31 -46
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/PrecisionRecallCurve.py +18 -40
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ROCCurve.py +18 -41
- validmind-2.13.8/validmind/tests/model_validation/sklearn/_multiclass_proba.py +150 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/GINITable.py +19 -41
- validmind-2.13.7/validmind/__version__.py +0 -1
- {validmind-2.13.7 → validmind-2.13.8}/.gitignore +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/LICENSE +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/README.pypi.md +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/ai/test_descriptions.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/ai/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/client.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/client_config.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/credentials_store.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/config.json +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/customer_churn.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/datasets/bank_customer_churn.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/datasets/taiwan_credit.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/classification/taiwan_credit.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/cluster/digits.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/credit_risk/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/credit_risk/datasets/lending_club_biased.csv.gz +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/credit_risk/datasets/lending_club_loan_data_2007_2014_clean.csv.gz +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/credit_risk/lending_club.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/credit_risk/lending_club_bias.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/agent_dataset.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_1.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_2.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_3.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_4.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/datasets/rfp_existing_questions_client_5.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/llm/rag/rfp.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/cnn_dailymail.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/datasets/Covid_19.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/datasets/cnn_dailymail_100_with_predictions.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/datasets/cnn_dailymail_500_with_predictions.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/datasets/sentiments_with_predictions.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/nlp/twitter_covid_19.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/california_housing.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/california_housing.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/CPIAUCSL.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/CSUSHPISA.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/DRSFRMACBS.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/FEDFUNDS.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/GDP.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/GDPC1.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/GS10.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/GS3.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/GS5.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/MORTGAGE30US.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred/UNRATE.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates_test_1.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates_test_2.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates_test_3.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates_test_4.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/fred_loan_rates_test_5.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/datasets/leanding_club_loan_rates.csv +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/fred.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/fred_timeseries.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/generate_california_housing_csv.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/datasets/regression/lending_club.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/errors.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/experimental/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/experimental/agents.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/html_templates/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/html_templates/content_blocks.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/input_registry.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/logging.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/foundation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/function.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/huggingface.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/metadata.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/pipeline.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/pytorch.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/r_model.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/models/sklearn.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/oidc_device.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/AbsoluteError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/BrierScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/CalibrationError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/ClassBalance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/Confidence.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/Correctness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/LogLoss.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/OutlierScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/ProbabilityError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/Uncertainty.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/classification/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/AnswerRelevancy.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/ArgumentCorrectness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/Bias.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/ContextualPrecision.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/ContextualRecall.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/ContextualRelevancy.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/Faithfulness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/GEval.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/Hallucination.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/PlanAdherence.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/PlanQuality.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/Summarization.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/TaskCompletion.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/ToolCorrectness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/scorers/llm/deepeval/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/template.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/classifier.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/cluster.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/embeddings.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/llm.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/nlp.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/parameters_optimization.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/regression.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/statsmodels_timeseries.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/summarization.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/tabular_datasets.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/text_data.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/test_suites/time_series.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/__types__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/_store.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/comparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ACFandPACFPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ADF.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/AutoAR.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/AutoMA.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/AutoStationarity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/BivariateScatterPlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/BoxPierce.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ChiSquaredFeaturesTable.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ClassImbalance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/DatasetDescription.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/DatasetSplit.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/DescriptiveStatistics.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/DickeyFullerGLS.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/Duplicates.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/EngleGrangerCoint.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/FeatureTargetCorrelationPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/HighCardinality.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/HighPearsonCorrelation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/IQROutliersBarPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/IQROutliersTable.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/IsolationForestOutliers.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/JarqueBera.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/KPSS.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/LJungBox.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/LaggedCorrelationHeatmap.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/MissingValues.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/MissingValuesBarPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/MutualInformation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/PearsonCorrelationMatrix.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/PhillipsPerronArch.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ProtectedClassesCombination.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ProtectedClassesDescription.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ProtectedClassesDisparity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ProtectedClassesThresholdOptimizer.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/RollingStatsPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/RunsTest.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ScatterPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ScoreBandDefaultRates.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/SeasonalDecompose.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ShapiroWilk.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/Skewness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/SpreadPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TabularCategoricalBarPlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TabularDateTimeHistograms.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TabularDescriptionTables.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TabularNumericalHistograms.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TargetRateBarPlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesDescription.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesDescriptiveStatistics.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesFrequency.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesHistogram.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesLinePlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesMissingValues.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TimeSeriesOutliers.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/TooManyZeroValues.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/UniqueRows.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/WOEBinPlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/WOEBinTable.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/ZivotAndrewsArch.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/CommonWords.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/Hashtags.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/LanguageDetection.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/Mentions.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/PolarityAndSubjectivity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/Punctuations.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/Sentiment.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/StopWords.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/TextDescription.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/Toxicity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/data_validation/nlp/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/decorator.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/load.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/BertScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/BleuScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ClusterSizeDistribution.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ContextualRecall.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/FeaturesAUC.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/MeteorScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ModelMetadata.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ModelPredictionResiduals.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/RegardScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/RegressionResidualsPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/RougeScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/TimeSeriesPredictionWithCI.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/TimeSeriesPredictionsPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/TimeSeriesR2SquareBySegments.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/TokenDisparity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ToxicityScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/ClusterDistribution.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/CosineSimilarityComparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/CosineSimilarityDistribution.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/CosineSimilarityHeatmap.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/DescriptiveAnalytics.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/EmbeddingsVisualization2D.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/EuclideanDistanceComparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/EuclideanDistanceHeatmap.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/PCAComponentsPairwisePlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/StabilityAnalysisKeyword.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/StabilityAnalysisRandomNoise.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/StabilityAnalysisSynonyms.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/StabilityAnalysisTranslation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/TSNEComponentsPairwisePlots.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/embeddings/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/AnswerCorrectness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/AspectCritic.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/ContextEntityRecall.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/ContextPrecision.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/ContextPrecisionWithoutReference.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/ContextRecall.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/Faithfulness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/NoiseSensitivity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/ResponseRelevancy.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/SemanticSimilarity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/ragas/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/AdjustedMutualInformation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/AdjustedRandIndex.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/CalibrationCurve.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ClassifierPerformance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ClassifierThresholdOptimization.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ClusterCosineSimilarity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ClusterPerformanceMetrics.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/CompletenessScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ConfusionMatrix.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/FeatureImportance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/FowlkesMallowsScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/HomogeneityScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/HyperParametersTuning.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/KMeansClustersOptimization.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/MinimumAccuracy.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/MinimumF1Score.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/MinimumROCAUCScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ModelParameters.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ModelsPerformanceComparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/OverfitDiagnosis.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/PermutationFeatureImportance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RegressionErrors.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RegressionErrorsComparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RegressionPerformance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RegressionR2Square.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RegressionR2SquareComparison.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/RobustnessDiagnosis.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/SHAPGlobalImportance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/ScoreProbabilityAlignment.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/SilhouettePlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/TrainingTestDegradation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/VMeasure.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/WeakspotsDiagnosis.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/sklearn/_diagnosis_metrics.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/AutoARIMA.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/CumulativePredictionProbabilities.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/DurbinWatsonTest.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/KolmogorovSmirnov.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/Lilliefors.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/PredictionProbabilitiesHistogram.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionCoeffs.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionFeatureSignificance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionModelForecastPlotLevels.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionModelSensitivityPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionModelSummary.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/RegressionPermutationFeatureImportance.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/ScorecardHistogram.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/statsutils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/CalibrationCurveDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ClassDiscriminationDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ClassImbalanceDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ClassificationAccuracyDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ConfusionMatrixDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/CumulativePredictionProbabilitiesDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/FeatureDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/PredictionAcrossEachFeature.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/PredictionCorrelation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/PredictionProbabilitiesHistogramDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/PredictionQuantilesAcrossFeatures.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ROCCurveDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ScoreBandsDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/ScorecardHistogramDrift.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/ongoing_monitoring/TargetPredictionDistributionPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/output.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/plots/BoxPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/plots/CorrelationHeatmap.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/plots/HistogramPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/plots/ViolinPlot.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/plots/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Bias.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Clarity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Conciseness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Delimitation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/NegativeInstruction.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Robustness.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/Specificity.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/prompt_validation/ai_powered_test.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/run.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/stats/CorrelationAnalysis.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/stats/DescriptiveStats.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/stats/NormalityTests.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/stats/OutlierDetection.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/stats/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/test_providers.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/tests/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/classification/Accuracy.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/classification/F1.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/classification/Precision.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/classification/ROC_AUC.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/classification/Recall.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/AdjustedRSquaredScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/GiniCoefficient.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/HuberLoss.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/KolmogorovSmirnovStatistic.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/MeanAbsoluteError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/MeanAbsolutePercentageError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/MeanBiasDeviation.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/MeanSquaredError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/QuantileLoss.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/RSquaredScore.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/unit_metrics/regression/RootMeanSquaredError.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/dataset/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/dataset/dataset.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/dataset/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/figure.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/html_progress.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/html_renderer.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/input.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/model.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/result/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/result/pii_filter.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/result/result.jinja +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/result/result.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/result/utils.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/test_suite/__init__.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/test_suite/runner.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/test_suite/summary.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/test_suite/test.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/test_suite/test_suite.py +0 -0
- {validmind-2.13.7 → validmind-2.13.8}/validmind/vm_models/text_generation_summary.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: validmind
|
|
3
|
-
Version: 2.13.
|
|
3
|
+
Version: 2.13.8
|
|
4
4
|
Summary: ValidMind Library
|
|
5
5
|
Author-email: Andres Rodriguez <andres@validmind.ai>, Juan Martinez <juan@validmind.ai>, Anil Sorathiya <anil@validmind.ai>, Luis Pallares <luis@validmind.ai>, John Walz <john@validmind.ai>
|
|
6
6
|
License: DUAL LICENSE NOTICE
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.13.8"
|
|
@@ -317,7 +317,7 @@ def init(
|
|
|
317
317
|
Can be set via env ``VM_OIDC_ISSUER``.
|
|
318
318
|
client_id (str, optional): OAuth public client id for device flow. Can be
|
|
319
319
|
set via env ``VM_OIDC_CLIENT_ID``.
|
|
320
|
-
scope (str, optional): OAuth scopes (default ``openid profile email``).
|
|
320
|
+
scope (str, optional): OAuth scopes (default ``openid profile email offline_access``).
|
|
321
321
|
Can be set via env ``VM_OIDC_SCOPE``.
|
|
322
322
|
audience (str, optional): Resource / API identifier for the access token
|
|
323
323
|
(e.g. Auth0 API Identifier). Use the same value the ValidMind backend
|
|
@@ -392,7 +392,7 @@ def init(
|
|
|
392
392
|
_api_key = None
|
|
393
393
|
_api_secret = None
|
|
394
394
|
_api_host = resolved_host
|
|
395
|
-
scope_val = oidc_scope or "openid profile email"
|
|
395
|
+
scope_val = oidc_scope or "openid profile email offline_access"
|
|
396
396
|
from .credentials_store import normalize_audience
|
|
397
397
|
|
|
398
398
|
oidc_audience_val = normalize_audience(
|
|
@@ -14,6 +14,8 @@ from validmind.errors import SkipTestError
|
|
|
14
14
|
from validmind.logging import get_logger
|
|
15
15
|
from validmind.vm_models import VMDataset, VMModel
|
|
16
16
|
|
|
17
|
+
from ._multiclass_proba import multiclass_proba, proba_matrix
|
|
18
|
+
|
|
17
19
|
logger = get_logger(__name__)
|
|
18
20
|
|
|
19
21
|
_PSI_PALETTE = ["#DE257E", "#1F77B4", "#2CA02C", "#FF7F0E", "#9467BD", "#8C564B"]
|
|
@@ -104,54 +106,37 @@ def _psi_table_rows(psi_results):
|
|
|
104
106
|
return rows_with_total, table_rows
|
|
105
107
|
|
|
106
108
|
|
|
107
|
-
def _multiclass_psi(datasets, model,
|
|
109
|
+
def _multiclass_psi(datasets, model, num_bins, mode):
|
|
108
110
|
"""One-vs-rest PSI for a multiclass model.
|
|
109
111
|
|
|
110
112
|
PSI needs a 1-D score distribution to compare across the two datasets. The
|
|
111
|
-
stored single probability column cannot represent every class, so
|
|
112
|
-
underlying estimator for the full per-class probability
|
|
113
|
-
ROC/PR curve tests)
|
|
114
|
-
|
|
113
|
+
stored single probability column cannot represent every class, so the shared
|
|
114
|
+
helper reaches the underlying estimator for the full per-class probability
|
|
115
|
+
matrix (mirroring the ROC/PR curve tests), aligning columns to the training
|
|
116
|
+
class order. The initial dataset drives the class alignment and the set of
|
|
117
|
+
classes actually present; the new dataset's matrix is validated against the
|
|
118
|
+
same class list. Models that cannot supply a matching matrix are skipped.
|
|
115
119
|
"""
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
try:
|
|
126
|
-
prob_initial = np.asarray(proba_fn(datasets[0].x_df()))
|
|
127
|
-
prob_new = np.asarray(proba_fn(datasets[1].x_df()))
|
|
128
|
-
except Exception as e:
|
|
129
|
-
raise SkipTestError(
|
|
130
|
-
"Multiclass Population Stability Index could not compute per-class "
|
|
131
|
-
f"probabilities ({type(e).__name__}). Skipping."
|
|
132
|
-
) from e
|
|
133
|
-
|
|
134
|
-
n_classes = len(classes)
|
|
135
|
-
for prob in (prob_initial, prob_new):
|
|
136
|
-
if prob.ndim != 2 or prob.shape[1] != n_classes:
|
|
137
|
-
raise SkipTestError(
|
|
138
|
-
"Multiclass Population Stability Index requires a per-class "
|
|
139
|
-
f"probability matrix with one column per class (got shape "
|
|
140
|
-
f"{getattr(prob, 'shape', None)} for {n_classes} classes). Skipping."
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# predict_proba columns are ordered by sorted class label == np.unique.
|
|
120
|
+
aligned = multiclass_proba(model, datasets[0], "Population Stability Index")
|
|
121
|
+
prob_initial = aligned.y_prob
|
|
122
|
+
prob_new = proba_matrix(
|
|
123
|
+
model, datasets[1], aligned.class_list, "Population Stability Index"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
classes_present = aligned.classes_present
|
|
127
|
+
n_present = len(classes_present)
|
|
128
|
+
|
|
144
129
|
fig = make_subplots(
|
|
145
|
-
rows=
|
|
130
|
+
rows=n_present,
|
|
146
131
|
cols=1,
|
|
147
|
-
specs=[[{"secondary_y": True}] for _ in range(
|
|
148
|
-
subplot_titles=[f"Class {cls}" for cls in
|
|
132
|
+
specs=[[{"secondary_y": True}] for _ in range(n_present)],
|
|
133
|
+
subplot_titles=[f"Class {cls}" for cls in classes_present],
|
|
149
134
|
vertical_spacing=0.08,
|
|
150
135
|
)
|
|
151
136
|
|
|
152
137
|
tables = {}
|
|
153
138
|
raw_per_class = {}
|
|
154
|
-
for i, cls in enumerate(
|
|
139
|
+
for plot_i, (i, cls) in enumerate(zip(aligned.present_indices, classes_present)):
|
|
155
140
|
psi_results = calculate_psi(
|
|
156
141
|
prob_initial[:, i].copy(),
|
|
157
142
|
prob_new[:, i].copy(),
|
|
@@ -159,17 +144,17 @@ def _multiclass_psi(datasets, model, classes, num_bins, mode):
|
|
|
159
144
|
mode=mode,
|
|
160
145
|
)
|
|
161
146
|
x = list(range(len(psi_results)))
|
|
162
|
-
color = _PSI_PALETTE[
|
|
147
|
+
color = _PSI_PALETTE[plot_i % len(_PSI_PALETTE)]
|
|
163
148
|
fig.add_trace(
|
|
164
149
|
go.Bar(
|
|
165
150
|
x=x,
|
|
166
151
|
y=[d["percent_initial"] for d in psi_results],
|
|
167
152
|
name="Initial",
|
|
168
153
|
marker=dict(color="#DE257E"),
|
|
169
|
-
showlegend=
|
|
154
|
+
showlegend=plot_i == 0,
|
|
170
155
|
legendgroup="initial",
|
|
171
156
|
),
|
|
172
|
-
row=
|
|
157
|
+
row=plot_i + 1,
|
|
173
158
|
col=1,
|
|
174
159
|
secondary_y=False,
|
|
175
160
|
)
|
|
@@ -179,10 +164,10 @@ def _multiclass_psi(datasets, model, classes, num_bins, mode):
|
|
|
179
164
|
y=[d["percent_new"] for d in psi_results],
|
|
180
165
|
name="New",
|
|
181
166
|
marker=dict(color="#E8B1F8"),
|
|
182
|
-
showlegend=
|
|
167
|
+
showlegend=plot_i == 0,
|
|
183
168
|
legendgroup="new",
|
|
184
169
|
),
|
|
185
|
-
row=
|
|
170
|
+
row=plot_i + 1,
|
|
186
171
|
col=1,
|
|
187
172
|
secondary_y=False,
|
|
188
173
|
)
|
|
@@ -192,10 +177,10 @@ def _multiclass_psi(datasets, model, classes, num_bins, mode):
|
|
|
192
177
|
y=[d["psi"] for d in psi_results],
|
|
193
178
|
name="PSI",
|
|
194
179
|
line=dict(color=color),
|
|
195
|
-
showlegend=
|
|
180
|
+
showlegend=plot_i == 0,
|
|
196
181
|
legendgroup="psi",
|
|
197
182
|
),
|
|
198
|
-
row=
|
|
183
|
+
row=plot_i + 1,
|
|
199
184
|
col=1,
|
|
200
185
|
secondary_y=True,
|
|
201
186
|
)
|
|
@@ -211,7 +196,7 @@ def _multiclass_psi(datasets, model, classes, num_bins, mode):
|
|
|
211
196
|
fig.update_layout(
|
|
212
197
|
title="Population Stability Index (PSI) — one-vs-rest per class",
|
|
213
198
|
barmode="group",
|
|
214
|
-
height=300 *
|
|
199
|
+
height=300 * n_present,
|
|
215
200
|
)
|
|
216
201
|
|
|
217
202
|
return (
|
|
@@ -291,7 +276,7 @@ def PopulationStabilityIndex(
|
|
|
291
276
|
|
|
292
277
|
classes = np.unique(datasets[0].y)
|
|
293
278
|
if len(classes) > 2:
|
|
294
|
-
return _multiclass_psi(datasets, model,
|
|
279
|
+
return _multiclass_psi(datasets, model, num_bins, mode)
|
|
295
280
|
|
|
296
281
|
psi_results = calculate_psi(
|
|
297
282
|
datasets[0].y_prob(model).copy(),
|
|
@@ -7,13 +7,14 @@ from typing import Tuple
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import plotly.graph_objects as go
|
|
9
9
|
from sklearn.metrics import average_precision_score, precision_recall_curve
|
|
10
|
-
from sklearn.preprocessing import label_binarize
|
|
11
10
|
|
|
12
11
|
from validmind import RawData, tags, tasks
|
|
13
12
|
from validmind.errors import SkipTestError
|
|
14
13
|
from validmind.models import FoundationModel
|
|
15
14
|
from validmind.vm_models import VMDataset, VMModel
|
|
16
15
|
|
|
16
|
+
from ._multiclass_proba import multiclass_proba
|
|
17
|
+
|
|
17
18
|
|
|
18
19
|
@tags(
|
|
19
20
|
"sklearn",
|
|
@@ -75,7 +76,7 @@ def PrecisionRecallCurve(
|
|
|
75
76
|
classes = np.unique(y_true)
|
|
76
77
|
|
|
77
78
|
if len(classes) > 2:
|
|
78
|
-
return _multiclass_pr_curve(model, dataset
|
|
79
|
+
return _multiclass_pr_curve(model, dataset)
|
|
79
80
|
|
|
80
81
|
precision, recall, _ = precision_recall_curve(y_true, dataset.y_prob(model))
|
|
81
82
|
|
|
@@ -105,53 +106,27 @@ def PrecisionRecallCurve(
|
|
|
105
106
|
|
|
106
107
|
|
|
107
108
|
def _multiclass_pr_curve(
|
|
108
|
-
model: VMModel, dataset: VMDataset
|
|
109
|
+
model: VMModel, dataset: VMDataset
|
|
109
110
|
) -> Tuple[go.Figure, RawData]:
|
|
110
111
|
"""One-vs-rest precision-recall curves for a multiclass model.
|
|
111
112
|
|
|
112
113
|
Needs the full per-class probability matrix, which the stored single
|
|
113
|
-
probability column cannot provide
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
probability column cannot provide; the shared helper reaches the underlying
|
|
115
|
+
estimator, aligns the probability columns to the training class order and
|
|
116
|
+
skips models that cannot supply a matching matrix.
|
|
116
117
|
"""
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
raw_model = getattr(model, "model", None)
|
|
121
|
-
proba_fn = getattr(raw_model, "predict_proba", None)
|
|
122
|
-
if not callable(proba_fn):
|
|
123
|
-
raise SkipTestError(
|
|
124
|
-
"Multiclass Precision-Recall Curve requires per-class probabilities "
|
|
125
|
-
"from the underlying model's predict_proba, which is not available "
|
|
126
|
-
"for this model (e.g. Foundation / metadata-only / precomputed "
|
|
127
|
-
"predictions). Skipping."
|
|
128
|
-
)
|
|
129
|
-
try:
|
|
130
|
-
y_prob = np.asarray(proba_fn(dataset.x_df()))
|
|
131
|
-
except Exception as e:
|
|
132
|
-
raise SkipTestError(
|
|
133
|
-
"Multiclass Precision-Recall Curve could not compute per-class "
|
|
134
|
-
f"probabilities ({type(e).__name__}). Skipping."
|
|
135
|
-
) from e
|
|
136
|
-
|
|
137
|
-
n_classes = len(classes)
|
|
138
|
-
if y_prob.ndim != 2 or y_prob.shape[1] != n_classes:
|
|
139
|
-
raise SkipTestError(
|
|
140
|
-
"Multiclass Precision-Recall Curve requires a per-class probability "
|
|
141
|
-
f"matrix with one column per class (got shape "
|
|
142
|
-
f"{getattr(y_prob, 'shape', None)} for {n_classes} classes). Skipping."
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
# One-hot the true labels in the same class order predict_proba columns use
|
|
146
|
-
# (sklearn orders predict_proba columns by sorted class label == np.unique).
|
|
147
|
-
y_bin = label_binarize(dataset.y.flatten(), classes=classes)
|
|
118
|
+
aligned = multiclass_proba(model, dataset, "Precision-Recall Curve")
|
|
119
|
+
y_bin = aligned.y_bin
|
|
120
|
+
y_prob = aligned.y_prob
|
|
148
121
|
|
|
149
122
|
traces = []
|
|
150
123
|
raw_precision = {}
|
|
151
124
|
raw_recall = {}
|
|
152
125
|
raw_ap = {}
|
|
153
126
|
palette = ["#DE257E", "#1F77B4", "#2CA02C", "#FF7F0E", "#9467BD", "#8C564B"]
|
|
154
|
-
for i, cls in enumerate(
|
|
127
|
+
for plot_i, (i, cls) in enumerate(
|
|
128
|
+
zip(aligned.present_indices, aligned.classes_present)
|
|
129
|
+
):
|
|
155
130
|
precision, recall, _ = precision_recall_curve(y_bin[:, i], y_prob[:, i])
|
|
156
131
|
ap = average_precision_score(y_bin[:, i], y_prob[:, i])
|
|
157
132
|
key = str(cls)
|
|
@@ -164,11 +139,14 @@ def _multiclass_pr_curve(
|
|
|
164
139
|
y=precision,
|
|
165
140
|
mode="lines",
|
|
166
141
|
name=f"Class {key} (AP = {ap:.2f})",
|
|
167
|
-
line=dict(color=palette[
|
|
142
|
+
line=dict(color=palette[plot_i % len(palette)]),
|
|
168
143
|
)
|
|
169
144
|
)
|
|
170
145
|
|
|
171
|
-
# Micro-average across
|
|
146
|
+
# Micro-average across the one-vs-rest decisions of the present classes.
|
|
147
|
+
present = aligned.present_indices
|
|
148
|
+
y_bin = y_bin[:, present]
|
|
149
|
+
y_prob = y_prob[:, present]
|
|
172
150
|
micro_precision, micro_recall, _ = precision_recall_curve(
|
|
173
151
|
y_bin.ravel(), y_prob.ravel()
|
|
174
152
|
)
|
|
@@ -7,12 +7,12 @@ from typing import Tuple
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import plotly.graph_objects as go
|
|
9
9
|
from sklearn.metrics import roc_auc_score, roc_curve
|
|
10
|
-
from sklearn.preprocessing import label_binarize
|
|
11
10
|
|
|
12
11
|
from validmind import RawData, tags, tasks
|
|
13
|
-
from validmind.errors import SkipTestError
|
|
14
12
|
from validmind.vm_models import VMDataset, VMModel
|
|
15
13
|
|
|
14
|
+
from ._multiclass_proba import multiclass_proba
|
|
15
|
+
|
|
16
16
|
|
|
17
17
|
@tags(
|
|
18
18
|
"sklearn",
|
|
@@ -76,7 +76,7 @@ def ROCCurve(model: VMModel, dataset: VMDataset) -> Tuple[go.Figure, RawData]:
|
|
|
76
76
|
classes = np.unique(dataset.y)
|
|
77
77
|
|
|
78
78
|
if len(classes) > 2:
|
|
79
|
-
return _multiclass_roc_curve(model, dataset
|
|
79
|
+
return _multiclass_roc_curve(model, dataset)
|
|
80
80
|
|
|
81
81
|
y_prob = dataset.y_prob(model)
|
|
82
82
|
y_true = dataset.y.astype(y_prob.dtype).flatten()
|
|
@@ -117,53 +117,27 @@ def ROCCurve(model: VMModel, dataset: VMDataset) -> Tuple[go.Figure, RawData]:
|
|
|
117
117
|
|
|
118
118
|
|
|
119
119
|
def _multiclass_roc_curve(
|
|
120
|
-
model: VMModel, dataset: VMDataset
|
|
120
|
+
model: VMModel, dataset: VMDataset
|
|
121
121
|
) -> Tuple[go.Figure, RawData]:
|
|
122
122
|
"""One-vs-rest ROC curves for a multiclass model.
|
|
123
123
|
|
|
124
124
|
Needs the full per-class probability matrix, which the stored single
|
|
125
|
-
probability column cannot provide
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
probability column cannot provide; the shared helper reaches the underlying
|
|
126
|
+
estimator, aligns the probability columns to the training class order and
|
|
127
|
+
skips models that cannot supply a matching matrix.
|
|
128
128
|
"""
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
raw_model = getattr(model, "model", None)
|
|
133
|
-
proba_fn = getattr(raw_model, "predict_proba", None)
|
|
134
|
-
if not callable(proba_fn):
|
|
135
|
-
raise SkipTestError(
|
|
136
|
-
"Multiclass ROC Curve requires per-class probabilities from the "
|
|
137
|
-
"underlying model's predict_proba, which is not available for this "
|
|
138
|
-
"model (e.g. metadata-only / precomputed predictions). Skipping."
|
|
139
|
-
)
|
|
140
|
-
try:
|
|
141
|
-
y_prob = np.asarray(proba_fn(dataset.x_df()))
|
|
142
|
-
except Exception as e:
|
|
143
|
-
raise SkipTestError(
|
|
144
|
-
"Multiclass ROC Curve could not compute per-class probabilities "
|
|
145
|
-
f"({type(e).__name__}). Skipping."
|
|
146
|
-
) from e
|
|
147
|
-
|
|
148
|
-
n_classes = len(classes)
|
|
149
|
-
if y_prob.ndim != 2 or y_prob.shape[1] != n_classes:
|
|
150
|
-
raise SkipTestError(
|
|
151
|
-
"Multiclass ROC Curve requires a per-class probability matrix with "
|
|
152
|
-
f"one column per class (got shape {getattr(y_prob, 'shape', None)} "
|
|
153
|
-
f"for {n_classes} classes). Skipping."
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
# One-hot the true labels in the same class order predict_proba columns use
|
|
157
|
-
# (sklearn orders predict_proba columns by sorted class label == np.unique).
|
|
158
|
-
y_true = dataset.y.flatten()
|
|
159
|
-
y_bin = label_binarize(y_true, classes=classes)
|
|
129
|
+
aligned = multiclass_proba(model, dataset, "ROC Curve")
|
|
130
|
+
y_bin = aligned.y_bin
|
|
131
|
+
y_prob = aligned.y_prob
|
|
160
132
|
|
|
161
133
|
traces = []
|
|
162
134
|
raw_fpr = {}
|
|
163
135
|
raw_tpr = {}
|
|
164
136
|
raw_auc = {}
|
|
165
137
|
palette = ["#DE257E", "#1F77B4", "#2CA02C", "#FF7F0E", "#9467BD", "#8C564B"]
|
|
166
|
-
for i, cls in enumerate(
|
|
138
|
+
for plot_i, (i, cls) in enumerate(
|
|
139
|
+
zip(aligned.present_indices, aligned.classes_present)
|
|
140
|
+
):
|
|
167
141
|
fpr, tpr, _ = roc_curve(y_bin[:, i], y_prob[:, i], drop_intermediate=False)
|
|
168
142
|
auc = roc_auc_score(y_bin[:, i], y_prob[:, i])
|
|
169
143
|
key = str(cls)
|
|
@@ -176,11 +150,14 @@ def _multiclass_roc_curve(
|
|
|
176
150
|
y=tpr,
|
|
177
151
|
mode="lines",
|
|
178
152
|
name=f"Class {key} (AUC = {auc:.2f})",
|
|
179
|
-
line=dict(color=palette[
|
|
153
|
+
line=dict(color=palette[plot_i % len(palette)]),
|
|
180
154
|
)
|
|
181
155
|
)
|
|
182
156
|
|
|
183
|
-
# Micro-average across
|
|
157
|
+
# Micro-average across the one-vs-rest decisions of the present classes.
|
|
158
|
+
present = aligned.present_indices
|
|
159
|
+
y_bin = y_bin[:, present]
|
|
160
|
+
y_prob = y_prob[:, present]
|
|
184
161
|
micro_fpr, micro_tpr, _ = roc_curve(y_bin.ravel(), y_prob.ravel())
|
|
185
162
|
micro_auc = roc_auc_score(y_bin, y_prob, average="micro", multi_class="ovr")
|
|
186
163
|
raw_fpr["micro"] = micro_fpr
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Copyright © 2023-2026 ValidMind Inc. All rights reserved.
|
|
2
|
+
# Refer to the LICENSE file in the root of this repository for details.
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0 AND ValidMind Commercial
|
|
4
|
+
|
|
5
|
+
"""Shared preamble for the one-vs-rest multiclass classification tests.
|
|
6
|
+
|
|
7
|
+
ROCCurve, PrecisionRecallCurve, PopulationStabilityIndex and GINITable all need
|
|
8
|
+
the full per-class probability matrix for a multiclass model. The VMModel wrapper
|
|
9
|
+
only stores/exposes the positive-class column, so every one of those tests reaches
|
|
10
|
+
the underlying estimator's ``predict_proba``, guards the cases where it is missing,
|
|
11
|
+
shaped wrong, trained on fewer than 3 classes, or evaluated against labels the
|
|
12
|
+
model never saw (raising ``SkipTestError`` with a test-specific message), and
|
|
13
|
+
one-hot encodes the true labels. This module holds that preamble in one place.
|
|
14
|
+
|
|
15
|
+
Column alignment matters: scikit-learn orders ``predict_proba`` columns by
|
|
16
|
+
``estimator.classes_`` (the classes seen in training), which is not necessarily
|
|
17
|
+
``np.unique(dataset.y)`` — a dataset slice can be missing a training class. We
|
|
18
|
+
align on ``classes_`` when available (falling back to ``np.unique``) so the
|
|
19
|
+
probability columns line up, binarize against that full training class list to
|
|
20
|
+
keep the columns aligned, and expose the subset of classes actually present in the
|
|
21
|
+
evaluated dataset's ``y`` (a class with no positives has no defined ROC) so callers
|
|
22
|
+
emit per-class output only for those. Consequently, callers that compute a
|
|
23
|
+
micro-average pool only the present classes' aligned columns, so when a training
|
|
24
|
+
class is absent from the evaluated slice the micro number deliberately excludes
|
|
25
|
+
that class's column rather than pooling the full training-class matrix.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from typing import Any, List, NamedTuple
|
|
29
|
+
|
|
30
|
+
import numpy as np
|
|
31
|
+
from sklearn.preprocessing import label_binarize
|
|
32
|
+
|
|
33
|
+
from validmind.errors import SkipTestError
|
|
34
|
+
from validmind.vm_models import VMDataset, VMModel
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class MulticlassProba(NamedTuple):
|
|
38
|
+
"""Aligned per-class probabilities for a multiclass one-vs-rest test.
|
|
39
|
+
|
|
40
|
+
``class_list`` is the full training class order used for column alignment and
|
|
41
|
+
binarization; ``classes_present``/``present_indices`` select the classes that
|
|
42
|
+
actually appear in the evaluated dataset's ``y`` (paired: ``present_indices[k]``
|
|
43
|
+
is the ``class_list``/``y_prob`` column for ``classes_present[k]``). ``y_bin`` is
|
|
44
|
+
the true labels one-hot encoded against ``class_list``; ``y_prob`` is the
|
|
45
|
+
estimator's per-class probability matrix in ``class_list`` column order.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
class_list: np.ndarray
|
|
49
|
+
classes_present: List[Any]
|
|
50
|
+
present_indices: List[int]
|
|
51
|
+
y_bin: np.ndarray
|
|
52
|
+
y_prob: np.ndarray
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def resolve_class_list(model: VMModel, dataset: VMDataset) -> np.ndarray:
|
|
56
|
+
"""Return the ``predict_proba`` column order for a multiclass model.
|
|
57
|
+
|
|
58
|
+
scikit-learn orders columns by ``estimator.classes_`` (training classes), so
|
|
59
|
+
prefer that; fall back to ``np.unique(dataset.y)`` for models that do not
|
|
60
|
+
expose it.
|
|
61
|
+
"""
|
|
62
|
+
raw_model = getattr(model, "model", None)
|
|
63
|
+
classes = getattr(raw_model, "classes_", None)
|
|
64
|
+
if classes is None:
|
|
65
|
+
classes = np.unique(dataset.y)
|
|
66
|
+
return np.asarray(classes)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def proba_matrix(
|
|
70
|
+
model: VMModel, dataset: VMDataset, class_list: np.ndarray, test_name: str
|
|
71
|
+
) -> np.ndarray:
|
|
72
|
+
"""Return the estimator's per-class probability matrix, or ``SkipTestError``.
|
|
73
|
+
|
|
74
|
+
The VMModel wrapper's ``predict_proba`` is binary-only (positive-class column
|
|
75
|
+
only), so reach the underlying estimator for the full per-class matrix. Skips
|
|
76
|
+
(rather than crashes) for models without a usable ``predict_proba``
|
|
77
|
+
(metadata-only / precomputed single-column predictions) or a matrix whose width
|
|
78
|
+
does not match ``class_list``.
|
|
79
|
+
"""
|
|
80
|
+
raw_model = getattr(model, "model", None)
|
|
81
|
+
proba_fn = getattr(raw_model, "predict_proba", None)
|
|
82
|
+
if not callable(proba_fn):
|
|
83
|
+
raise SkipTestError(
|
|
84
|
+
f"Multiclass {test_name} requires per-class probabilities from the "
|
|
85
|
+
"underlying model's predict_proba, which is not available for this "
|
|
86
|
+
"model (e.g. metadata-only / precomputed predictions). Skipping."
|
|
87
|
+
)
|
|
88
|
+
try:
|
|
89
|
+
y_prob = np.asarray(proba_fn(dataset.x_df()))
|
|
90
|
+
except Exception as e:
|
|
91
|
+
raise SkipTestError(
|
|
92
|
+
f"Multiclass {test_name} could not compute per-class probabilities "
|
|
93
|
+
f"({type(e).__name__}). Skipping."
|
|
94
|
+
) from e
|
|
95
|
+
|
|
96
|
+
n_classes = len(class_list)
|
|
97
|
+
if y_prob.ndim != 2 or y_prob.shape[1] != n_classes:
|
|
98
|
+
raise SkipTestError(
|
|
99
|
+
f"Multiclass {test_name} requires a per-class probability matrix with "
|
|
100
|
+
f"one column per class (got shape {getattr(y_prob, 'shape', None)} for "
|
|
101
|
+
f"{n_classes} classes). Skipping."
|
|
102
|
+
)
|
|
103
|
+
return y_prob
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def multiclass_proba(
|
|
107
|
+
model: VMModel, dataset: VMDataset, test_name: str
|
|
108
|
+
) -> MulticlassProba:
|
|
109
|
+
"""Resolve aligned per-class probabilities for a multiclass one-vs-rest test.
|
|
110
|
+
|
|
111
|
+
Aligns on the estimator's training classes, binarizes the true labels against
|
|
112
|
+
that full class list (so columns stay aligned even when the dataset is missing a
|
|
113
|
+
class), and reports which classes are actually present in the evaluated ``y``.
|
|
114
|
+
Raises ``SkipTestError`` for models that cannot supply a matching per-class
|
|
115
|
+
probability matrix, that were trained on fewer than 3 classes (one-vs-rest
|
|
116
|
+
multiclass metrics don't apply to a binary model), or when the evaluated
|
|
117
|
+
dataset's ``y`` contains a label the model was never trained on.
|
|
118
|
+
"""
|
|
119
|
+
class_list = resolve_class_list(model, dataset)
|
|
120
|
+
if len(class_list) < 3:
|
|
121
|
+
raise SkipTestError(
|
|
122
|
+
f"Multiclass {test_name} requires a model trained on at least 3 "
|
|
123
|
+
"classes for one-vs-rest multiclass metrics to apply, but this model "
|
|
124
|
+
f"appears to be binary (trained on {len(class_list)} classes). "
|
|
125
|
+
"Skipping."
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
y_prob = proba_matrix(model, dataset, class_list, test_name)
|
|
129
|
+
|
|
130
|
+
y_true = np.asarray(dataset.y).flatten()
|
|
131
|
+
y_bin = label_binarize(y_true, classes=class_list)
|
|
132
|
+
|
|
133
|
+
unknown_labels = sorted(set(np.unique(y_true)) - set(class_list))
|
|
134
|
+
if unknown_labels:
|
|
135
|
+
raise SkipTestError(
|
|
136
|
+
f"Multiclass {test_name} found label(s) {unknown_labels} in the "
|
|
137
|
+
"evaluated dataset that the model was not trained on (not present in "
|
|
138
|
+
"the estimator's classes_). Skipping."
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
present_indices = [i for i, cls in enumerate(class_list) if np.any(y_true == cls)]
|
|
142
|
+
classes_present = [class_list[i] for i in present_indices]
|
|
143
|
+
|
|
144
|
+
return MulticlassProba(
|
|
145
|
+
class_list=class_list,
|
|
146
|
+
classes_present=classes_present,
|
|
147
|
+
present_indices=present_indices,
|
|
148
|
+
y_bin=y_bin,
|
|
149
|
+
y_prob=y_prob,
|
|
150
|
+
)
|
{validmind-2.13.7 → validmind-2.13.8}/validmind/tests/model_validation/statsmodels/GINITable.py
RENAMED
|
@@ -7,10 +7,9 @@ from typing import Tuple
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pandas as pd
|
|
9
9
|
from sklearn.metrics import roc_auc_score, roc_curve
|
|
10
|
-
from sklearn.preprocessing import label_binarize
|
|
11
10
|
|
|
12
11
|
from validmind import RawData, tags, tasks
|
|
13
|
-
from validmind.
|
|
12
|
+
from validmind.tests.model_validation.sklearn._multiclass_proba import multiclass_proba
|
|
14
13
|
from validmind.vm_models import VMDataset, VMModel
|
|
15
14
|
|
|
16
15
|
|
|
@@ -71,7 +70,7 @@ def GINITable(dataset: VMDataset, model: VMModel) -> Tuple[pd.DataFrame, RawData
|
|
|
71
70
|
classes = np.unique(dataset.y)
|
|
72
71
|
|
|
73
72
|
if len(classes) > 2:
|
|
74
|
-
return _multiclass_gini_table(model, dataset
|
|
73
|
+
return _multiclass_gini_table(model, dataset)
|
|
75
74
|
|
|
76
75
|
y_true = np.ravel(dataset.y) # Flatten y_true to make it one-dimensional
|
|
77
76
|
y_prob = dataset.y_prob(model)
|
|
@@ -99,50 +98,24 @@ def GINITable(dataset: VMDataset, model: VMModel) -> Tuple[pd.DataFrame, RawData
|
|
|
99
98
|
|
|
100
99
|
|
|
101
100
|
def _multiclass_gini_table(
|
|
102
|
-
model: VMModel, dataset: VMDataset
|
|
101
|
+
model: VMModel, dataset: VMDataset
|
|
103
102
|
) -> Tuple[pd.DataFrame, RawData]:
|
|
104
103
|
"""One-vs-rest AUC/GINI/KS for a multiclass model.
|
|
105
104
|
|
|
106
105
|
Needs the full per-class probability matrix, which the stored single
|
|
107
|
-
probability column cannot provide
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
probability column cannot provide; the shared helper reaches the underlying
|
|
107
|
+
estimator, aligns the probability columns to the training class order and
|
|
108
|
+
skips models that cannot supply a matching matrix.
|
|
110
109
|
"""
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if not callable(proba_fn):
|
|
116
|
-
raise SkipTestError(
|
|
117
|
-
"Multiclass GINITable requires per-class probabilities from the "
|
|
118
|
-
"underlying model's predict_proba, which is not available for this "
|
|
119
|
-
"model (e.g. metadata-only / precomputed predictions). Skipping."
|
|
120
|
-
)
|
|
121
|
-
try:
|
|
122
|
-
y_prob = np.asarray(proba_fn(dataset.x_df()))
|
|
123
|
-
except Exception as e:
|
|
124
|
-
raise SkipTestError(
|
|
125
|
-
"Multiclass GINITable could not compute per-class probabilities "
|
|
126
|
-
f"({type(e).__name__}). Skipping."
|
|
127
|
-
) from e
|
|
128
|
-
|
|
129
|
-
n_classes = len(classes)
|
|
130
|
-
if y_prob.ndim != 2 or y_prob.shape[1] != n_classes:
|
|
131
|
-
raise SkipTestError(
|
|
132
|
-
"Multiclass GINITable requires a per-class probability matrix with "
|
|
133
|
-
f"one column per class (got shape {getattr(y_prob, 'shape', None)} "
|
|
134
|
-
f"for {n_classes} classes). Skipping."
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
# One-hot the true labels in the same class order predict_proba columns use
|
|
138
|
-
# (sklearn orders predict_proba columns by sorted class label == np.unique).
|
|
139
|
-
y_true = dataset.y.flatten()
|
|
140
|
-
y_bin = label_binarize(y_true, classes=classes)
|
|
110
|
+
aligned = multiclass_proba(model, dataset, "GINITable")
|
|
111
|
+
y_true = np.asarray(dataset.y).flatten()
|
|
112
|
+
y_bin = aligned.y_bin
|
|
113
|
+
y_prob = aligned.y_prob
|
|
141
114
|
|
|
142
115
|
rows = []
|
|
143
116
|
raw_fpr = {}
|
|
144
117
|
raw_tpr = {}
|
|
145
|
-
for i, cls in
|
|
118
|
+
for i, cls in zip(aligned.present_indices, aligned.classes_present):
|
|
146
119
|
fpr, tpr, _ = roc_curve(y_bin[:, i], y_prob[:, i])
|
|
147
120
|
auc = roc_auc_score(y_bin[:, i], y_prob[:, i])
|
|
148
121
|
key = str(cls)
|
|
@@ -152,9 +125,14 @@ def _multiclass_gini_table(
|
|
|
152
125
|
{"Class": key, "AUC": auc, "GINI": 2 * auc - 1, "KS": max(tpr - fpr)}
|
|
153
126
|
)
|
|
154
127
|
|
|
155
|
-
# Micro-average across
|
|
156
|
-
|
|
157
|
-
|
|
128
|
+
# Micro-average across the one-vs-rest decisions of the present classes.
|
|
129
|
+
present = aligned.present_indices
|
|
130
|
+
micro_fpr, micro_tpr, _ = roc_curve(
|
|
131
|
+
y_bin[:, present].ravel(), y_prob[:, present].ravel()
|
|
132
|
+
)
|
|
133
|
+
micro_auc = roc_auc_score(
|
|
134
|
+
y_bin[:, present], y_prob[:, present], average="micro", multi_class="ovr"
|
|
135
|
+
)
|
|
158
136
|
raw_fpr["micro"] = micro_fpr
|
|
159
137
|
raw_tpr["micro"] = micro_tpr
|
|
160
138
|
rows.append(
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.13.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|