Skip to content

Conversation

@MarieSacksick
Copy link
Contributor

@MarieSacksick MarieSacksick commented Apr 4, 2025

As part of issue #1782, turn the report_metrics of ComparisonReport into a display. The plot of this display will be a pair plot to visualize one metric against another.

Add documentation.

This is part of the narrative "I have several models, how can I choose the best one?". The user will need:

  • a comparison report
  • and plots to compare.

blocked by #1788.

@MarieSacksick MarieSacksick changed the title enh: Add timing plot in comparison report feat: Add timing plot in comparison report Apr 4, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Apr 4, 2025

Coverage

Coverage Report for backend
FileStmtsMissCoverMissing
venv/lib/python3.12/site-packages/skore
   __init__.py220100% 
   _config.py280100% 
   exceptions.py440%4–23
venv/lib/python3.12/site-packages/skore/persistence
   __init__.py00100% 
venv/lib/python3.12/site-packages/skore/persistence/item
   __init__.py55198%97
   altair_chart_item.py19191%14
   item.py22195%86
   matplotlib_figure_item.py36195%19
   media_item.py220100% 
   numpy_array_item.py27194%16
   pandas_dataframe_item.py29194%14
   pandas_series_item.py29194%14
   pickle_item.py220100% 
   pillow_image_item.py25193%15
   plotly_figure_item.py20192%14
   polars_dataframe_item.py27194%14
   polars_series_item.py22192%14
   primitive_item.py23291%13–15
   sklearn_base_estimator_item.py29194%15
venv/lib/python3.12/site-packages/skore/persistence/repository
   __init__.py20100% 
   item_repository.py59591%15–16, 202–203, 226
venv/lib/python3.12/site-packages/skore/persistence/storage
   __init__.py40100% 
   abstract_storage.py220100% 
   disk_cache_storage.py33195%44
   in_memory_storage.py200100% 
venv/lib/python3.12/site-packages/skore/project
   __init__.py20100% 
   project.py84298%282, 394
venv/lib/python3.12/site-packages/skore/sklearn
   __init__.py60100% 
   _base.py1701492%44, 57, 125, 128, 181–190, 202–>208, 223, 226–227
   find_ml_task.py61099%136–>145
   types.py13285%34, 62
venv/lib/python3.12/site-packages/skore/sklearn/_comparison
   __init__.py50100% 
   metrics_accessor.py167298%166, 167–>169, 1281
   report.py811380%18, 252–>255, 401–431
venv/lib/python3.12/site-packages/skore/sklearn/_cross_validation
   __init__.py50100% 
   metrics_accessor.py180099%144–>146, 146–>148
   report.py110198%23
venv/lib/python3.12/site-packages/skore/sklearn/_estimator
   __init__.py70100% 
   feature_importance_accessor.py133099%485–>491, 571–>580
   metrics_accessor.py3451096%170–179, 207–>216, 215, 245, 256–>258, 286, 313–317, 332, 367, 368–>370
   report.py143198%24, 253–>255
venv/lib/python3.12/site-packages/skore/sklearn/_plot
   __init__.py20100% 
   base.py60100% 
   style.py280100% 
   utils.py122595%51, 75–77, 81
venv/lib/python3.12/site-packages/skore/sklearn/_plot/metrics
   __init__.py40100% 
   precision_recall_curve.py170199%656
   prediction_error.py1620100% 
   roc_curve.py173199%646
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split
   __init__.py00100% 
   train_test_split.py51196%16, 154–>158
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split/warning
   __init__.py80100% 
   high_class_imbalance_too_few_examples_warning.py17190%79
   high_class_imbalance_warning.py180100% 
   random_state_unset_warning.py12188%15
   shuffle_true_warning.py10183%46
   stratify_is_set_warning.py12188%15
   time_based_column_warning.py23286%17, 73
   train_test_split_warning.py5180%21
venv/lib/python3.12/site-packages/skore/utils
   __init__.py60100% 
   _accessor.py42196%94
   _environment.py27097%30–>35
   _fixes.py80100% 
   _index.py50100% 
   _logger.py22485%15–19
   _measure_time.py100100% 
   _parallel.py38388%23–33, 124
   _patch.py13553%21–37
   _progress_bar.py340100% 
   _show_versions.py33295%65–66
TOTAL31749996% 

Tests Skipped Failures Errors Time
793 8 💤 0 ❌ 0 🔥 58.266s ⏱️

@github-actions
Copy link
Contributor

github-actions bot commented Apr 4, 2025

Documentation preview @ a63dd79

@glemaitre
Copy link
Member

From speaking with @GaelVaroquaux, it looks like this plot should be more general meaning that it should be a pairwise plot (comparing 2 scores). Time vs score is probably a good default but we should make it possible to tweak via the parameters.

@github-actions
Copy link
Contributor

Coverage

Coverage Report for backend
FileStmtsMissCoverMissing
venv/lib/python3.12/site-packages/skore
   __init__.py220100% 
   _config.py280100% 
   exceptions.py440%4–23
venv/lib/python3.12/site-packages/skore/persistence
   __init__.py00100% 
venv/lib/python3.12/site-packages/skore/persistence/item
   __init__.py55198%97
   altair_chart_item.py19191%14
   item.py22195%86
   matplotlib_figure_item.py36195%19
   media_item.py220100% 
   numpy_array_item.py27194%16
   pandas_dataframe_item.py29194%14
   pandas_series_item.py29194%14
   pickle_item.py220100% 
   pillow_image_item.py25193%15
   plotly_figure_item.py20192%14
   polars_dataframe_item.py27194%14
   polars_series_item.py22192%14
   primitive_item.py23291%13–15
   sklearn_base_estimator_item.py29194%15
venv/lib/python3.12/site-packages/skore/persistence/repository
   __init__.py20100% 
   item_repository.py59591%15–16, 202–203, 226
venv/lib/python3.12/site-packages/skore/persistence/storage
   __init__.py40100% 
   abstract_storage.py220100% 
   disk_cache_storage.py33195%44
   in_memory_storage.py200100% 
venv/lib/python3.12/site-packages/skore/project
   __init__.py20100% 
   project.py83298%280, 392
venv/lib/python3.12/site-packages/skore/sklearn
   __init__.py60100% 
   _base.py1711492%45, 58, 126, 129, 182–191, 203–>209, 224, 227–228
   find_ml_task.py61099%136–>145
   types.py130100% 
venv/lib/python3.12/site-packages/skore/sklearn/_comparison
   __init__.py50100% 
   metrics_accessor.py165297%163, 164–>166, 1278
   report.py811380%18, 250–>253, 399–429
venv/lib/python3.12/site-packages/skore/sklearn/_cross_validation
   __init__.py50100% 
   metrics_accessor.py190099%153–>155, 155–>157
   report.py110198%23
venv/lib/python3.12/site-packages/skore/sklearn/_estimator
   __init__.py70100% 
   feature_importance_accessor.py133099%483–>489, 569–>578
   metrics_accessor.py3441096%174–183, 211–>220, 219, 249, 260–>262, 290, 317–321, 336, 371, 372–>374
   report.py148198%24, 253–>255
venv/lib/python3.12/site-packages/skore/sklearn/_plot
   __init__.py20100% 
   base.py60100% 
   style.py280100% 
   utils.py122595%51, 75–77, 81
venv/lib/python3.12/site-packages/skore/sklearn/_plot/metrics
   __init__.py40100% 
   precision_recall_curve.py173199%660
   prediction_error.py1640100% 
   roc_curve.py176199%649
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split
   __init__.py00100% 
   train_test_split.py51196%16, 154–>158
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split/warning
   __init__.py80100% 
   high_class_imbalance_too_few_examples_warning.py17190%79
   high_class_imbalance_warning.py180100% 
   random_state_unset_warning.py12188%15
   shuffle_true_warning.py10183%46
   stratify_is_set_warning.py12188%15
   time_based_column_warning.py23286%17, 73
   train_test_split_warning.py40100% 
venv/lib/python3.12/site-packages/skore/utils
   __init__.py60100% 
   _accessor.py46197%102
   _environment.py27097%30–>35
   _fixes.py80100% 
   _index.py50100% 
   _logger.py22485%15–19
   _measure_time.py100100% 
   _parallel.py38388%23–33, 124
   _patch.py13553%21–37
   _progress_bar.py360100% 
   _show_versions.py330100% 
TOTAL31999496% 

Tests Skipped Failures Errors Time
814 8 💤 0 ❌ 0 🔥 54.175s ⏱️

@github-actions
Copy link
Contributor

github-actions bot commented May 13, 2025

Coverage

Coverage Report for skore/
FileStmtsMissCoverMissing
venv/lib/python3.12/site-packages/skore
   __init__.py230100% 
   _config.py280100% 
   exceptions.py440%4, 15, 19, 23
venv/lib/python3.12/site-packages/skore/project
   __init__.py20100% 
   metadata.py670100% 
   project.py430100% 
   reports.py110100% 
   widget.py138596%375–377, 447–448
venv/lib/python3.12/site-packages/skore/sklearn
   __init__.py60100% 
   _base.py1691491%45, 58, 126, 129, 182, 185–186, 188–191, 224, 227–228
   find_ml_task.py610100% 
   types.py26196%26
   utils.py10100% 
venv/lib/python3.12/site-packages/skore/sklearn/_comparison
   __init__.py50100% 
   metrics_accessor.py203398%170, 334, 1288
   report.py980100% 
   utils.py550100% 
venv/lib/python3.12/site-packages/skore/sklearn/_cross_validation
   __init__.py50100% 
   metrics_accessor.py211199%334
   report.py125199%480
venv/lib/python3.12/site-packages/skore/sklearn/_estimator
   __init__.py70100% 
   feature_importance_accessor.py143298%216–217
   metrics_accessor.py382997%162, 191, 193, 200, 291, 360, 364, 379, 414
   report.py166298%454–455
venv/lib/python3.12/site-packages/skore/sklearn/_plot
   __init__.py20100% 
   base.py50100% 
   style.py280100% 
   utils.py118595%50, 74–76, 80
venv/lib/python3.12/site-packages/skore/sklearn/_plot/metrics
   __init__.py60100% 
   confusion_matrix.py69494%90, 98, 120, 228
   pair_plot.py67888%54, 57, 89, 150, 164, 174, 178, 219
   precision_recall_curve.py230199%716
   prediction_error.py1600100% 
   roc_curve.py242498%380, 497, 598, 791
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split
   __init__.py00100% 
   train_test_split.py490100% 
venv/lib/python3.12/site-packages/skore/sklearn/train_test_split/warning
   __init__.py80100% 
   high_class_imbalance_too_few_examples_warning.py17194%80
   high_class_imbalance_warning.py180100% 
   random_state_unset_warning.py100100% 
   shuffle_true_warning.py10190%46
   stratify_is_set_warning.py100100% 
   time_based_column_warning.py21195%73
   train_test_split_warning.py40100% 
venv/lib/python3.12/site-packages/skore/utils
   __init__.py6266%8, 13
   _accessor.py52296%67, 108
   _environment.py270100% 
   _fixes.py80100% 
   _index.py50100% 
   _logger.py22481%15–17, 19
   _measure_time.py100100% 
   _parallel.py38392%23, 33, 124
   _patch.py13561%21, 23–24, 35, 37
   _progress_bar.py450100% 
   _show_versions.py33293%65–66
   _testing.py370100% 
TOTAL33498597% 

Tests Skipped Failures Errors Time
830 5 💤 0 ❌ 0 🔥 1m 1s ⏱️

@MarieSacksick MarieSacksick marked this pull request as ready for review May 23, 2025 09:11
@MarieSacksick MarieSacksick changed the title feat: Add timing plot in comparison report feat: Add pair plot in comparison report May 26, 2025
@thomass-dev
Copy link
Collaborator

thomass-dev commented May 26, 2025

[automated comment] Please update your PR with main, so that the pytest workflow status will be reported.

@glemaitre glemaitre self-requested a review May 27, 2025 09:00
Copy link
Member

@glemaitre glemaitre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we should think about the API question before to go further. It would have an impact on how the display will be created.

If we have a display with report_metrics, it only means that we will share a common display and the kind parameters will decide to show a representation or another.

@@ -0,0 +1,220 @@
import matplotlib.pyplot as plt

from skore.sklearn._plot.base import Display
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Display is a Python protocol (https://peps.python.org/pep-0544/) and we don't need to inherit from it.
It only allows to specify the methods that an object should be implementing when calling isinstance(obj, Display).

Suggested change
from skore.sklearn._plot.base import Display

self.ax_ = None
self.text_ = None

def plot(self, ax=None, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is this method that would benefit from the style.

Suggested change
def plot(self, ax=None, **kwargs):
@StyleDisplayMixin.style_plot
def plot(self, ax=None, **kwargs):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need ax anymore. We decided with @auguste-probabl to reduce the API here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also remove kwargs because it is unused.

Comment on lines +105 to +112
@classmethod
def from_metrics(
cls,
metrics,
perf_metric_x,
perf_metric_y,
data_source=None,
):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The display should not expose this public function. The idea is that the reporters will be the only object that can create an instance of Display.

You can have a look at RocCurveDisplay (or PrecisionRecallDisplay). Basically I think we should keep the name _compute_data_for_display. However, we can adapt the input parameters.

# - add kwargs (later)

return PairPlotDisplay.from_metrics(
metrics=self.metrics.report_metrics(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that I realized with the implementation now is that we are going to want most of the parameters to pass them to report_metrics.

Now, I'm thinking that it would means that the PairPlotDisplay is just a kind of plot associated with report_metrics. In short, I think that it would make sense to be able to write:

report.metrics.report_metrics().plot(kind="pair", x="fit_time", y="accuracy")

but also

report.metrics.report_metrics().plot(kind="bar")

And it allows to pass the arguments as:

report.metrics.report_metrics(data_source="train", ...).plot(kind="pair")

Comment on lines +67 to +69
self.figure_ = None
self.ax_ = None
self.text_ = None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, those are created only when plot is called. We can see in a subsequent PR if we want to make consistent this behaviour with an initialization.

Comment on lines +135 to +136
x_label = _SCORE_OR_LOSS_INFO.get(perf_metric_x, {}).get("name", perf_metric_x)
y_label = _SCORE_OR_LOSS_INFO.get(perf_metric_y, {}).get("name", perf_metric_y)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that those should be passed directly by the methods from the report. It would be handy because we would have access to the dictionary _SCORE_OR_LOSS_INFO in the report side.

@MarieSacksick MarieSacksick marked this pull request as draft May 30, 2025 12:55
@MarieSacksick MarieSacksick changed the title feat: Add pair plot in comparison report feat: Turn report_metrics of ComparisonReport into Displays Jun 2, 2025
@MarieSacksick
Copy link
Contributor Author

Closing - fresh start in #1816.

@MarieSacksick MarieSacksick deleted the timing_plot branch July 23, 2025 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants