Talip7/scikit-learn-issues-multilabel huggingface dataset:
`_safe_indexing` triggers `SettingWithCopyWarning` when used with `slice`

### Describe the bug

Here's something I noticed while looking into https://github.com/scikit-learn/scikit-learn/pull/31127

The test
```
pytest sklearn/utils/tests/test_indexing.py::test_safe_indexing_pandas_no_settingwithcopy_warning
```
checks that a copy is produced, and that no `SettingWithCopyWarning` is produced

Indeed, no copy is raised, but why is using `_safe_indexing` with a slice allowed to not make a copy? Is this intentional?

Based on responses, I can suggest what to do instead in https://github.com/scikit-learn/scikit-learn/pull/31127

(I am a little surprised that this always makes copies, given that a lot of the discussion in https://github.com/scikit-learn/scikit-learn/issues/28341 centered around wanting to avoid copies)

### Steps/Code to Reproduce

```python
import numpy as np

from sklearn.utils import _safe_indexing
import pandas as pd

X = pd.DataFrame({"a": [1, 2, 3], "b": [3, 4, 5]})
subset = _safe_indexing(X, slice(0, 2), axis=0)
subset.iloc[0, 0] = 10
```

### Expected Results

No `SettingWithCopyWarning`

### Actual Results

```
/home/marcogorelli/scikit-learn-dev/t.py:13: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  subset.iloc[0, 0] = 10
```

### Versions

```shell
System:
    python: 3.11.11 (main, Dec  4 2024, 08:55:07) [GCC 11.4.0]
executable: /home/marcogorelli/scikit-learn-dev/.venv/bin/python
   machine: Linux-5.15.167.4-microsoft-standard-WSL2-x86_64-with-glibc2.35

Python dependencies:
      sklearn: 1.7.dev0
          pip: 24.2
   setuptools: None
        numpy: 2.1.0
        scipy: 1.14.0
       Cython: 3.0.11
       pandas: 2.2.2
   matplotlib: None
       joblib: 1.4.2
threadpoolctl: 3.5.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /home/marcogorelli/scikit-learn-dev/.venv/lib/python3.11/site-packages/numpy.libs/libscipy_openblas64_-ff651d7f.so
        version: 0.3.27
threading_layer: pthreads
   architecture: SkylakeX

       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libscipy_openblas
       filepath: /home/marcogorelli/scikit-learn-dev/.venv/lib/python3.11/site-packages/scipy.libs/libscipy_openblas-c128ec02.so
        version: 0.3.27.dev
threading_layer: pthreads
   architecture: SkylakeX

       user_api: openmp
   internal_api: openmp
    num_threads: 16
         prefix: libgomp
       filepath: /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0
        version: None
```

COMMENT:
What's the consensus so far?
- Deprecate slice in _safe_indexing

Labels: Bug
`make_scorer(needs_sample_weight=True)` wrongly injects `needs_sample_weight` into the scoring function

### Describe the bug


When using `make_scorer(..., needs_sample_weight=True)`, the generated scorer unexpectedly passes `needs_sample_weight=True` as a keyword argument to the scoring function itself, leading to `TypeError` unless **kwargs is manually added.


### Steps/Code to Reproduce


Minimal example:
```
import numpy as np
from sklearn.datasets import make_regression
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer

def weighted_mape(y_true, y_pred, sample_weight=None):
    return np.average(np.abs((y_true - y_pred) / (y_true + 1e-8)), weights=sample_weight)

scoring = make_scorer(weighted_mape, greater_is_better=False, needs_sample_weight=True)

X, y = make_regression(n_samples=100, n_features=5, random_state=0)
weights = np.random.rand(100)

model = GradientBoostingRegressor()
grid = GridSearchCV(model, param_grid={"n_estimators": [10]}, scoring=scoring, cv=3)
grid.fit(X, y, sample_weight=weights)
```



### Expected Results

**Expected behavior:**

`make_scorer(..., needs_sample_weight=True)` should cause `sample_weight` to be passed during cross-validation scoring.

The scoring function should not receive `needs_sample_weight=True` as a kwarg.




### Actual Results

**Actual behavior:**

The scoring function raises:

>TypeError: weighted_mape() got an unexpected keyword argument 'needs_sample_weight'
unless manually patched with **kwargs.

### Versions

```shell
System:
    python: 3.10.12 (main, Feb  4 2025, 14:57:36) [GCC 11.4.0]
executable: /home/X/XX/pax_env/bin/python
   machine: Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35

Python dependencies:
      sklearn: 1.2.2
          pip: 22.0.2
   setuptools: 59.6.0
        numpy: 1.26.0
        scipy: 1.15.2
       Cython: None
       pandas: 1.5.3
   matplotlib: 3.7.1
       joblib: 1.2.0
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: openmp
   internal_api: openmp
    num_threads: 14
         prefix: libgomp
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libopenblas
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/numpy.libs/libopenblas64_p-r0-0cf96a72.3.23.dev.so
        version: 0.3.23.dev
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libscipy_openblas
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/scipy.libs/libscipy_openblas-68440149.so
        version: 0.3.28
threading_layer: pthreads
   architecture: Haswell
```

COMMENT:
I believe that i can solve this issue , so please assign this to me I will give my best to it 
Thankyou!

Labels: Bug, Needs Triage
`make_scorer(needs_sample_weight=True)` wrongly injects `needs_sample_weight` into the scoring function

### Describe the bug


When using `make_scorer(..., needs_sample_weight=True)`, the generated scorer unexpectedly passes `needs_sample_weight=True` as a keyword argument to the scoring function itself, leading to `TypeError` unless **kwargs is manually added.


### Steps/Code to Reproduce


Minimal example:
```
import numpy as np
from sklearn.datasets import make_regression
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import make_scorer

def weighted_mape(y_true, y_pred, sample_weight=None):
    return np.average(np.abs((y_true - y_pred) / (y_true + 1e-8)), weights=sample_weight)

scoring = make_scorer(weighted_mape, greater_is_better=False, needs_sample_weight=True)

X, y = make_regression(n_samples=100, n_features=5, random_state=0)
weights = np.random.rand(100)

model = GradientBoostingRegressor()
grid = GridSearchCV(model, param_grid={"n_estimators": [10]}, scoring=scoring, cv=3)
grid.fit(X, y, sample_weight=weights)
```



### Expected Results

**Expected behavior:**

`make_scorer(..., needs_sample_weight=True)` should cause `sample_weight` to be passed during cross-validation scoring.

The scoring function should not receive `needs_sample_weight=True` as a kwarg.




### Actual Results

**Actual behavior:**

The scoring function raises:

>TypeError: weighted_mape() got an unexpected keyword argument 'needs_sample_weight'
unless manually patched with **kwargs.

### Versions

```shell
System:
    python: 3.10.12 (main, Feb  4 2025, 14:57:36) [GCC 11.4.0]
executable: /home/X/XX/pax_env/bin/python
   machine: Linux-5.15.153.1-microsoft-standard-WSL2-x86_64-with-glibc2.35

Python dependencies:
      sklearn: 1.2.2
          pip: 22.0.2
   setuptools: 59.6.0
        numpy: 1.26.0
        scipy: 1.15.2
       Cython: None
       pandas: 1.5.3
   matplotlib: 3.7.1
       joblib: 1.2.0
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: openmp
   internal_api: openmp
    num_threads: 14
         prefix: libgomp
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libopenblas
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/numpy.libs/libopenblas64_p-r0-0cf96a72.3.23.dev.so
        version: 0.3.23.dev
threading_layer: pthreads
   architecture: Haswell

       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libscipy_openblas
       filepath: /home/X/XX/pax_env/lib/python3.10/site-packages/scipy.libs/libscipy_openblas-68440149.so
        version: 0.3.28
threading_layer: pthreads
   architecture: Haswell
```

COMMENT:
`make_scorer` does not have a `needs_sample_weight` parameter?
https://scikit-learn.org/stable/modules/generated/sklearn.metrics.make_scorer.html

Labels: Bug, Needs Triage
⚠️ CI failed on Linux_Nightly.pylatest_pip_scipy_dev (last failure: May 05, 2025) ⚠️

**CI is still failing on [Linux_Nightly.pylatest_pip_scipy_dev](https://dev.azure.com/scikit-learn/scikit-learn/_build/results?buildId=76198&view=logs&j=dfe99b15-50db-5d7b-b1e9-4105c42527cf)** (May 05, 2025)
- Test Collection Failure

COMMENT:
This seems to be related to #31269 although in a different CI environment. Note that this particular build does not use the free-threaded version of CPython.

I think this is related to a recent change in Cython that will be included in the future 3.1 but I am not sure which.

Labels: Bug, cython
⚠️ CI failed on Linux_free_threaded.pylatest_free_threaded (last failure: May 05, 2025) ⚠️

**CI is still failing on [Linux_free_threaded.pylatest_free_threaded](https://dev.azure.com/scikit-learn/scikit-learn/_build/results?buildId=76198&view=logs&j=c10228e9-6cf7-5c29-593f-d74f893ca1bd)** (May 05, 2025)
- Test Collection Failure

COMMENT:
This seems to be related to #31269 although in a different CI environment.

Labels: Build / CI, cython
Automatically move `y_true` to the same device and namespace as `y_pred` for metrics

This is closely linked to #28668 but separate enough to warrant it's own issue (https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2814771519). This is mostly a summary of discussions so far. If we are happy with a decision, we can move to updating the documentation.

---

For classification metrics to support array API, there is a problem in the case where `y_pred` is not in the same namespace/device as `y_true`.

`y_pred` is likely to be the output of `predict_proba` or `decision_function` and would be in the same namespace/device as `X` (if we decide in #28668 that "everything should follow X").
`y_true` could be an integer array or a numpy array or pandas series (this is pertinent as `y_true` may be string labels)

Motivating use case:

Using e.g., `GridSearchCV` or `cross_validate` with a pipeline that moves `X` to GPU.
Consider a pipeline like below (copied from https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2154958666): 

```python
pipeline = make_pipeline(
   SomeDataFrameAwareFeatureExtractor(),
   MoveFeaturesToPyTorch(device="cuda"),
   SomeArrayAPICapableClassifier(),
)
```

Pipelines do not ever touch `y` so we are not able to alter `y` within the pipeline.
We would need to pass a metric to `GridSearchCV` or `cross_validate`, which would be passed `y_true` and `y_pred` on different namespace / devices.

Thus the motivation to automatically move `y_true` to the same namespace / device as `y_pred`, in metrics functions.

(Note another example is discussed in https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2531072292)

As it is more likely that `y_pred` is on GPU, `y_true` follow `y_pred` was slightly preferred over `y_pred` follows `y_true`. Computation wise, CPU vs GPU is probably similar for metrics like log-loss, but for metrics that require sorting (e.g., ROC AUC) GPU may be faster? (see https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2532238196 for more discussion on this point)


Question for my own clarification, the main motivation is for usability, so the user does not have to manually convert `y_true` ? Would a helper function to help the user convert `y_true` to the correct namespace/device be interesting?


cc @ogrisel @betatim

COMMENT:
+1 for this proposal and +1 for a PR to make that policy explicit in `array_api.rst`.

Labels: API, Array API
Automatically move `y_true` to the same device and namespace as `y_pred` for metrics

This is closely linked to #28668 but separate enough to warrant it's own issue (https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2814771519). This is mostly a summary of discussions so far. If we are happy with a decision, we can move to updating the documentation.

---

For classification metrics to support array API, there is a problem in the case where `y_pred` is not in the same namespace/device as `y_true`.

`y_pred` is likely to be the output of `predict_proba` or `decision_function` and would be in the same namespace/device as `X` (if we decide in #28668 that "everything should follow X").
`y_true` could be an integer array or a numpy array or pandas series (this is pertinent as `y_true` may be string labels)

Motivating use case:

Using e.g., `GridSearchCV` or `cross_validate` with a pipeline that moves `X` to GPU.
Consider a pipeline like below (copied from https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2154958666): 

```python
pipeline = make_pipeline(
   SomeDataFrameAwareFeatureExtractor(),
   MoveFeaturesToPyTorch(device="cuda"),
   SomeArrayAPICapableClassifier(),
)
```

Pipelines do not ever touch `y` so we are not able to alter `y` within the pipeline.
We would need to pass a metric to `GridSearchCV` or `cross_validate`, which would be passed `y_true` and `y_pred` on different namespace / devices.

Thus the motivation to automatically move `y_true` to the same namespace / device as `y_pred`, in metrics functions.

(Note another example is discussed in https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2531072292)

As it is more likely that `y_pred` is on GPU, `y_true` follow `y_pred` was slightly preferred over `y_pred` follows `y_true`. Computation wise, CPU vs GPU is probably similar for metrics like log-loss, but for metrics that require sorting (e.g., ROC AUC) GPU may be faster? (see https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2532238196 for more discussion on this point)


Question for my own clarification, the main motivation is for usability, so the user does not have to manually convert `y_true` ? Would a helper function to help the user convert `y_true` to the correct namespace/device be interesting?


cc @ogrisel @betatim

COMMENT:
Thanks @ogrisel I had not considered that.

I didn't attend the meeting but are we mostly in consensus about this? Happy to move forward with doc + implementation if so.

Labels: API, Array API
Automatically move `y_true` to the same device and namespace as `y_pred` for metrics

This is closely linked to #28668 but separate enough to warrant it's own issue (https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2814771519). This is mostly a summary of discussions so far. If we are happy with a decision, we can move to updating the documentation.

---

For classification metrics to support array API, there is a problem in the case where `y_pred` is not in the same namespace/device as `y_true`.

`y_pred` is likely to be the output of `predict_proba` or `decision_function` and would be in the same namespace/device as `X` (if we decide in #28668 that "everything should follow X").
`y_true` could be an integer array or a numpy array or pandas series (this is pertinent as `y_true` may be string labels)

Motivating use case:

Using e.g., `GridSearchCV` or `cross_validate` with a pipeline that moves `X` to GPU.
Consider a pipeline like below (copied from https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2154958666): 

```python
pipeline = make_pipeline(
   SomeDataFrameAwareFeatureExtractor(),
   MoveFeaturesToPyTorch(device="cuda"),
   SomeArrayAPICapableClassifier(),
)
```

Pipelines do not ever touch `y` so we are not able to alter `y` within the pipeline.
We would need to pass a metric to `GridSearchCV` or `cross_validate`, which would be passed `y_true` and `y_pred` on different namespace / devices.

Thus the motivation to automatically move `y_true` to the same namespace / device as `y_pred`, in metrics functions.

(Note another example is discussed in https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2531072292)

As it is more likely that `y_pred` is on GPU, `y_true` follow `y_pred` was slightly preferred over `y_pred` follows `y_true`. Computation wise, CPU vs GPU is probably similar for metrics like log-loss, but for metrics that require sorting (e.g., ROC AUC) GPU may be faster? (see https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2532238196 for more discussion on this point)


Question for my own clarification, the main motivation is for usability, so the user does not have to manually convert `y_true` ? Would a helper function to help the user convert `y_true` to the correct namespace/device be interesting?


cc @ogrisel @betatim

COMMENT:
I think `y_true` follows `y_pred` makes sense, so it has my vote.

Labels: API, Array API
Automatically move `y_true` to the same device and namespace as `y_pred` for metrics

This is closely linked to #28668 but separate enough to warrant it's own issue (https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2814771519). This is mostly a summary of discussions so far. If we are happy with a decision, we can move to updating the documentation.

---

For classification metrics to support array API, there is a problem in the case where `y_pred` is not in the same namespace/device as `y_true`.

`y_pred` is likely to be the output of `predict_proba` or `decision_function` and would be in the same namespace/device as `X` (if we decide in #28668 that "everything should follow X").
`y_true` could be an integer array or a numpy array or pandas series (this is pertinent as `y_true` may be string labels)

Motivating use case:

Using e.g., `GridSearchCV` or `cross_validate` with a pipeline that moves `X` to GPU.
Consider a pipeline like below (copied from https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2154958666): 

```python
pipeline = make_pipeline(
   SomeDataFrameAwareFeatureExtractor(),
   MoveFeaturesToPyTorch(device="cuda"),
   SomeArrayAPICapableClassifier(),
)
```

Pipelines do not ever touch `y` so we are not able to alter `y` within the pipeline.
We would need to pass a metric to `GridSearchCV` or `cross_validate`, which would be passed `y_true` and `y_pred` on different namespace / devices.

Thus the motivation to automatically move `y_true` to the same namespace / device as `y_pred`, in metrics functions.

(Note another example is discussed in https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2531072292)

As it is more likely that `y_pred` is on GPU, `y_true` follow `y_pred` was slightly preferred over `y_pred` follows `y_true`. Computation wise, CPU vs GPU is probably similar for metrics like log-loss, but for metrics that require sorting (e.g., ROC AUC) GPU may be faster? (see https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2532238196 for more discussion on this point)


Question for my own clarification, the main motivation is for usability, so the user does not have to manually convert `y_true` ? Would a helper function to help the user convert `y_true` to the correct namespace/device be interesting?


cc @ogrisel @betatim

COMMENT:
Just checking if anyone else is interested in offering their opinion on this @StefanieSenger @OmarManzoor @lucascolley maybe?

Labels: API, Array API
Automatically move `y_true` to the same device and namespace as `y_pred` for metrics

This is closely linked to #28668 but separate enough to warrant it's own issue (https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2814771519). This is mostly a summary of discussions so far. If we are happy with a decision, we can move to updating the documentation.

---

For classification metrics to support array API, there is a problem in the case where `y_pred` is not in the same namespace/device as `y_true`.

`y_pred` is likely to be the output of `predict_proba` or `decision_function` and would be in the same namespace/device as `X` (if we decide in #28668 that "everything should follow X").
`y_true` could be an integer array or a numpy array or pandas series (this is pertinent as `y_true` may be string labels)

Motivating use case:

Using e.g., `GridSearchCV` or `cross_validate` with a pipeline that moves `X` to GPU.
Consider a pipeline like below (copied from https://github.com/scikit-learn/scikit-learn/issues/28668#issuecomment-2154958666): 

```python
pipeline = make_pipeline(
   SomeDataFrameAwareFeatureExtractor(),
   MoveFeaturesToPyTorch(device="cuda"),
   SomeArrayAPICapableClassifier(),
)
```

Pipelines do not ever touch `y` so we are not able to alter `y` within the pipeline.
We would need to pass a metric to `GridSearchCV` or `cross_validate`, which would be passed `y_true` and `y_pred` on different namespace / devices.

Thus the motivation to automatically move `y_true` to the same namespace / device as `y_pred`, in metrics functions.

(Note another example is discussed in https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2531072292)

As it is more likely that `y_pred` is on GPU, `y_true` follow `y_pred` was slightly preferred over `y_pred` follows `y_true`. Computation wise, CPU vs GPU is probably similar for metrics like log-loss, but for metrics that require sorting (e.g., ROC AUC) GPU may be faster? (see https://github.com/scikit-learn/scikit-learn/pull/30439#issuecomment-2532238196 for more discussion on this point)


Question for my own clarification, the main motivation is for usability, so the user does not have to manually convert `y_true` ? Would a helper function to help the user convert `y_true` to the correct namespace/device be interesting?


cc @ogrisel @betatim

COMMENT:
Yes, this makes a lot of sense to me. +1 from my side.

Labels: API, Array API