Make `zero_division` parameter consistent in the different metric

This is an issue to report the step to actually take over the work of @marctorsoc in https://github.com/scikit-learn/scikit-learn/pull/23183 and split the PR into smaller one to facilitate the review process.

The intend is to make the `zero_division` parameter consistent across different metrics in scikit-learn. In this regards, we have the following TODO list:

- [x] Introduce the `zero_division` parameter to the `accuracy_score` function when `y_true` and `y_pred` are empty.
    - https://github.com/scikit-learn/scikit-learn/pull/29213
- [x] Introduce the `zero_division` parameter to the `class_likelihood_ratios` and remove `raise_warning`.
    - https://github.com/scikit-learn/scikit-learn/pull/31331
- [x] Introduce the `zero_division` parameter to the `cohen_kappa_score` function
  - https://github.com/scikit-learn/scikit-learn/pull/29210
- [x] Introduce the `zero_division` parameter to the `matthew_corr_coeff` function
  - #23183
  - #28509
- [ ] <del>Open a PR to make sure the empty input lead to `np.nan` in `classification_report` function.</del> `classification_report` should raise an error instead: see https://github.com/scikit-learn/scikit-learn/issues/29048#issuecomment-2857931743

All those items have been addressed in #23183 and can be extracted in individual PRs. The changelog presenting the changes should acknowledge @marctorsoc.

In addition, we should investigate #27047 and check if we should add the `zero_division` parameter to the `precision_recall_curve` and `roc_curve` as well. This might add two additional items to the list above.

COMMENT:
> I'm not sure what you mean by neutralise. The "ignore" option is the one neutralising which we want to include.

I mean to impute the nans with something neutral. Then for instance, when we calculate a mean of `[1.0, 3.0, np.nan, np.nan, np.nan]`, ignoring and neutralising would be the same, but calculation the mode would not be.
I am not sure how much of a practical relevance this has, but I have seen in SplineTransformer, that we sometimes need to make this distinction.

> We only warn, not error, and that's not as good as returning np.nan. People don't read warnings, or the code is deep in some system where they don't even see the warnings. 

Agree. Would to error be better as a default then?

> Otherwise if the user sets it to np.nan, then it's silently converted to nan,

It is documented but I see how users can miss this.

> Having a collection of things in a single param doesn't look like good API design. As I wrote, we can add the second parameter for warning later, for now we can always warn if there's a division by zero.

Alright.

> Keeping the old param name would mean we would have to first deprecate the meaning of np.nan for that argument, since we want its semantics to change. For metrics which do aggregation, we basically want the old np.nan to mean "ignore", and for np.nan to mean "return nan please". This change causes a painful an 2 year long deprecation cycle, which introducing a new argument and simply deprecating the old argument helps us to avoid. Also, replace_undefined_by is more explicit in what the argument does.

Okay, I see this now.

But still, could you please move slower. This thing seems to have been discussed in a private call and implementation started in a matter of an afternoon. This issue had been presented to me as something I can do as a beginner and your speed in changing the direction here is overwhelming.

Labels: Enhancement