Repository: scikit-learn/scikit-learn
File: sklearn/metrics/tests/test_common.py (Python)

Code before:
            yield metric, checker


@pytest.mark.parametrize(
    "array_namespace, device, dtype_name",
    yield_namespace_device_dtype_combinations(),
    ids=_get_namespace_device_dtype_ids,
)
@pytest.mark.parametrize("metric, check_func", yield_metric_checker_combinations())
def test_array_api_compliance(metric, array_namespace, device, dtype_name, check_func):
    check_func(metric, array_namespace, device, dtype_name)
    if (
        getattr(metric, "__name__", None) == "median_absolute_error"
        and array_namespace == "array_api_strict"
    ):
        try:
            import array_api_strict
        except ImportError:
            pass
        else:
            if device == array_api_strict.Device("device1"):
                # See https://github.com/data-apis/array-api-strict/issues/134
                pytest.xfail(
                    "`_weighted_percentile` is affected by array_api_strict bug when "
                    "indexing with tuple of arrays on non-'CPU_DEVICE' devices."
                )


@pytest.mark.parametrize("df_lib_name", ["pandas", "polars"])
@pytest.mark.parametrize("metric_name", sorted(ALL_METRICS))
def test_metrics_dataframe_series(metric_name, df_lib_name):
    df_lib = pytest.importorskip(df_lib_name)

    y_pred = df_lib.Series([0.0, 1.0, 0, 1.0])
    y_true = df_lib.Series([1.0, 0.0, 0.0, 0.0])

    metric = ALL_METRICS[metric_name]
    try:
        expected_metric = metric(y_pred.to_numpy(), y_true.to_numpy())
    except ValueError:
        pytest.skip(f"{metric_name} can not deal with 1d inputs")

    assert_allclose(metric(y_pred, y_true), expected_metric)


def _get_metric_kwargs_for_array_api_testing(metric, params):
    """Helper function to enable specifying a variety of additional params and
    their corresponding values, so that they can be passed to a metric function
    when testing for array api compliance."""
    metric_kwargs_combinations = [{}]
    for param, values in params.items():

Review comment (bug):
This is not ideal. We have a similar xfail in a `_weighted_percentile` test:

https://github.com/scikit-learn/scikit-learn/blob/398e8feb73f3e422c9d51d5863eb270709af4742/sklearn/utils/tests/test_stats.py#L186-L196

Note that as we add array API support for more regression metrics, we will need to add them to the xfail, as several others use `_weighted_percentile`.

(Note that this bug has been fixed but we'd need a new release of array-api-strict to see it)

@ev-br - you did mention there could be an array-api-strict release soon though?



Code after:
    mean_absolute_percentage_error: [
        check_array_api_regression_metric,
        check_array_api_regression_metric_multioutput,
    ],
    chi2_kernel: [check_array_api_metric_pairwise],
    paired_euclidean_distances: [check_array_api_metric_pairwise],
    cosine_distances: [check_array_api_metric_pairwise],
    euclidean_distances: [check_array_api_metric_pairwise],
    linear_kernel: [check_array_api_metric_pairwise],
    polynomial_kernel: [check_array_api_metric_pairwise],
    rbf_kernel: [check_array_api_metric_pairwise],
    root_mean_squared_error: [
        check_array_api_regression_metric,
        check_array_api_regression_metric_multioutput,
    ],
    root_mean_squared_log_error: [
        check_array_api_regression_metric,
        check_array_api_regression_metric_multioutput,
    ],
    sigmoid_kernel: [check_array_api_metric_pairwise],
}


def yield_metric_checker_combinations(metric_checkers=array_api_metric_checkers):
    for metric, checkers in metric_checkers.items():
        for checker in checkers:
            yield metric, checker


@pytest.mark.parametrize(
    "array_namespace, device, dtype_name",
    yield_namespace_device_dtype_combinations(),
    ids=_get_namespace_device_dtype_ids,
)
@pytest.mark.parametrize("metric, check_func", yield_metric_checker_combinations())
def test_array_api_compliance(metric, array_namespace, device, dtype_name, check_func):
    # TODO: Remove once array-api-strict > 2.3.1
    # https://github.com/data-apis/array-api-strict/issues/134 has been fixed but
    # not released yet.
    if (
        getattr(metric, "__name__", None) == "median_absolute_error"
        and array_namespace == "array_api_strict"
    ):
        try:
            import array_api_strict
        except ImportError:
            pass
        else:
            if device == array_api_strict.Device("device1"):
                pytest.xfail(
                    "`_weighted_percentile` is affected by array_api_strict bug when "