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:
> But comment: sometimes we might not want to ignore, but to neutralise

I'm not sure what you mean by neutralise. The `"ignore"` option is the one neutralising which we want to include.

> Isn't there the default behaviour of warning/erroring, which we keep from before? Raising an warning/error is basically as good as returning a single np.nan for a score that aggregates.

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. So returning `np.nan` is very different than raising a warning. The issue here is that for metrics that do aggregation, since we use `nanmean`, there's no way for them to return `nan` at the moment.

> Why not? Users can chose between default "warn" and np.nan and it's documented that only the first option raises a warning.

Users get a warning only in the case where it's replaced by 0. Otherwise if the user sets it to `np.nan`, then it's silently converted to nan, and no warning is raised, and through `nanmean`, that `np.nan` becomes a hidden bug.

> The only option to get around such things is to use two different params to control this, but we can also define a collection of things to happen when setting just one param, if we have curated them well. I think we are doing this all over the project.

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.

> Do we have other reasons in our code for a scoring function to be undefined at certain values? Otherwise we could maybe keep the old param name and only add an "ignore" option for functions that aggregate several values into one?

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.

Labels: Enhancement