What’s new in skore — July 2026#
summarize().frame() is now a long-format table#
The default format of summarize()’s frame() is now long-format rather than wide-format. It is now easier to retrieve data from the default DataFrame since its index is no longer a pandas.MultiIndex. See #3094 by @glemaitre.
metrics = report.metrics.summarize().frame()
# before
metrics.loc["Accuracy"].iloc[0, 0]
# after
metrics.loc["accuracy"]
metrics.summarize() now catches failing metrics#
summarize() no longer aborts the whole computation if one of the
metrics raised (e.g. if a custom scorer encounters an edge case). Instead, exceptions are
caught and shown as warnings, and the output DataFrame has NaN for failed metrics. See
#3124 by @auguste-probabl.
def fail(y_true, y_pred):
return 1 / 0
report.metrics.add(fail)
report.metrics.summarize().frame()
# # before
# ZeroDivisionError: division by zero
#
# # after
# UserWarning: Metric 'fail' has failed: ZeroDivisionError('division by zero')
# fail NaN
# accuracy 0.925000
# precision_0 1.000000
# ...
Custom metric methods are now shown in .help()#
Metrics added via add() were invisible to help(), since they are defined dynamically. They are now listed alongside the built-ins. See #3139 by @auguste-probabl.
report.metrics.add(lambda estimator, X, y: 1, name="custom")
report.metrics.help()
# ╭────────────────────────────────── Metrics accessor ──────────────────────────────────╮
# │ EstimatorReport │
# │ └── .metrics │
# │ ├── .accuracy(...) - Accuracy classification score. │
# │ ... │
# │ ├── .custom(...) - Custom │
# │ ... │
Pipelines no longer get a spurious score metric in the summary#
skore used to always include a score metric in the summary sklearn Pipeline estimators.
It now inspects the Pipeline’s last step to recover the default score. See #3110 by @jeromedockes.
report = skore.evaluate(make_pipeline(PCA(), RandomForestClassifier()), X, y)
report.metrics.summarize().frame(flat_index=False, verbose_name=True)
# # before
# Score ...
# Accuracy ...
# ...
#
# # after
# Accuracy ...
# ...
prediction_error(data_source="both") is now officially supported#
prediction_error() with data_source="both" has worked for a long time, but it was not documented, and in fact its legend was broken. This is now fixed. See #3154 by @direkkakkar319-ops.
CrossValidationReport.metrics.summarize() no longer crashes with n_jobs set#
Computing a summary with process-based parallelism (n_jobs > 1) used to trigger infinite recursion in summarize(). See #3178 by @glemaitre.
Baseline checks now support multi-output regression#
Appropriate dummy/fast/performance baselines have been added to support this ML task. See #3116 by @GaetandeCast.
report = skore.evaluate(DummyRegressor(), X, y_multioutput, splitter=3)
report.checks.summarize().frame(section="issue")["code"]
# # before
# CheckNotApplicable: Unsupported ML task. Supported tasks are: binary-classification,
# multiclass-classification, regression. Got multioutput-regression.
#
# # after
# 1 SKD002 # underfits vs. baseline
# 8 SKD009 # worse than baseline
report.checks no longer loses column names after preprocessing#
When a sklearn Pipeline’s preprocessing output a plain numpy array, the data-quality checks used generic column labels in their explanations. Column names are now retrieved from the pipeline’s final step, so check explanations are clearer. See #3155 by @GaetandeCast.
report = skore.evaluate(
make_pipeline(StandardScaler(), LinearRegression()),
pd.DataFrame(X, columns=["col_0", "col_1", "col_2"]),
y,
)
report.checks.summarize()
# # before
# "A model trained on feature(s) ['Feature 0', 'Feature 1'] alone has similar
# performance to a model trained on all the features..."
#
# # after
# "A model trained on feature(s) ['col_0', 'col_1'] alone has similar
# performance to a model trained on all the features..."
project.put() is now faster for reports with plots#
put() no longer computes SVGs for skrub TableReport plots, thanks to improvements in skrub 0.10. This makes it up to 35% faster. Note that the minimum supported version of skrub is now 0.10. See #3138 by @auguste-probabl.
project.summarize() no longer silently truncates the list of reports#
Listing reports from the Hub now returns all reports, rather than the 500 first ones, via summarize(). See #3125 and #3164 by @thomass-dev.
Thanks to the following contributors for their work this month (in no particular order):