-
-
Notifications
You must be signed in to change notification settings - Fork 26.3k
FEA Add array API support for temperature scaling in CalibratedClassifierCV #32246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
FEA Add array API support for temperature scaling in CalibratedClassifierCV #32246
Conversation
Note: Since this is a DRAFT PR for now I left the bench.py file so that we can experiment if required. |
Has this problem already been reported upstream?
I think it's fair for meta estimators to only support array API when the base estimator does (and let any exception raised by the underlying estimator bubble up otherwise).
How is that a problem? I think our cross-validation tools support array API, no? If not, we should fix that first.
Have you tried to use a profiler to understand the performance difference between scipy versions with torch/mps? Ideally, this should be reported as a performance regression upstream along with a minimal reproducer that does not involve scikit-learn. |
@ogrisel Also I haven't reported either of the scipy issues that I noted. But wouldn't it be better for someone else to confirm my observations as well? |
Ah ok. This should indeed be addressed in a dedicated PR then. |
I confirm that I observe a similar performance regression using SciPy 1.16 (vs 1.15) using the |
I opened a scipy issue with respect to the slower runtimes that we noted: scipy/scipy#23670 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is some preliminary feedback, some of which we already discussed in over discord.
sklearn/calibration.py
Outdated
calibrators.append(calibrator) | ||
elif method == "temperature": | ||
max_float_dtype = _max_precision_float_dtype(xp, xp_device) | ||
predictions = xp.asarray(predictions, dtype=max_float_dtype, device=xp_device) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be needed if the underlying classifier supports array API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think since we are going for the path in which we are supporting array API when the underlying estimator also supports array API, then yes these kinds of conversions in the CalibratedClassiferCV
fit
method and over here can be removed but I think we would first need to support array API for at least the cross_val_predict
function so that we can deal with the case when ensemble=False
. I think maybe this first PR should focus on ensemble
being False. Because when we have ensemble=True
I think our cv splitters are returning ndarrays
for train, test indices
which won't work when we are dealing with the array API. What do you think?
with config_context(array_api_dispatch=True): | ||
cal_clf_xp = CalibratedClassifierCV( | ||
FrozenEstimator(clf), cv=3, method="temperature", ensemble=False | ||
).fit(X_cal_xp, y_cal_xp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should test with y_cal
being an array of str
instances here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Array API version _half_multinomial_loss
should be okay. I did some tests to compare it with HalfMultinomialLoss
in addition to running test_half_multinomal_loss
, and they all passed.
Thank you for verifying |
Reference Issues/PRs
Address #31869
What does this implement/fix? Explain your changes.
Notes:
find_minimum
fromscipy.optimize.elementwise
that supports the array API doesn't quite work because it works with arrays and if we use arrays as inputs and outputs it breaks forarray-api-strict
. If we stick with scalars it breaks at a point where an array is expected.minimize_scalar
which we use currently simply uses scalar values within it's main computation loops, I convert the input to the array API when entering the_half_multinomial_loss
function and converting to a float when returning from it. This has the drawback of converting back and forth between the cpu and gpu._TemperatureScaling
class on google colab and my local mac M1, the results are as follows which show they vary based on the scipy version:I noted the significant performance with scipy == 1.15.3 because I also tried running the benchmarks on a Kaggle kernel and since that supports Python 3.10 something the maximum scipy version that we can get there is 1.15.3.
Any other comments?
CC: @ogrisel @betatim @virchan @lesteve
What is your opinion? Should we support array API for this class?