From 353a5a485e0f156cde6cf88a9b4b465bedb2ad58 Mon Sep 17 00:00:00 2001 From: Tialo Date: Fri, 31 May 2024 01:41:15 +0300 Subject: [PATCH 1/5] array api for additive_chi2_kernel --- sklearn/metrics/pairwise.py | 23 +++++++++++++++++------ sklearn/metrics/tests/test_pairwise.py | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/sklearn/metrics/pairwise.py b/sklearn/metrics/pairwise.py index e3faffa77ae51..1b0766607f3e9 100644 --- a/sklearn/metrics/pairwise.py +++ b/sklearn/metrics/pairwise.py @@ -1718,7 +1718,7 @@ def additive_chi2_kernel(X, Y=None): Returns ------- - kernel : ndarray of shape (n_samples_X, n_samples_Y) + kernel : array-like of shape (n_samples_X, n_samples_Y) The kernel matrix. See Also @@ -1750,15 +1750,26 @@ def additive_chi2_kernel(X, Y=None): array([[-1., -2.], [-2., -1.]]) """ + xp, _ = get_namespace(X, Y) X, Y = check_pairwise_arrays(X, Y, accept_sparse=False) - if (X < 0).any(): + if xp.any(X < 0): raise ValueError("X contains negative values.") - if Y is not X and (Y < 0).any(): + if Y is not X and xp.any(Y < 0): raise ValueError("Y contains negative values.") - result = np.zeros((X.shape[0], Y.shape[0]), dtype=X.dtype) - _chi2_kernel_fast(X, Y, result) - return result + if _is_numpy_namespace(xp): + result = np.zeros((X.shape[0], Y.shape[0]), dtype=X.dtype) + _chi2_kernel_fast(X, Y, result) + return result + else: + dtype = _find_matching_floating_dtype(X, Y, xp=xp) + xb = X[:, None, :] + yb = Y[None, :, :] + nom = -((xb - yb) ** 2) + denom = xb + yb + nom = xp.where(denom == 0, xp.asarray(0, dtype=dtype), nom) + denom = xp.where(denom == 0, xp.asarray(1, dtype=dtype), denom) + return xp.sum(nom / denom, axis=2) @validate_params( diff --git a/sklearn/metrics/tests/test_pairwise.py b/sklearn/metrics/tests/test_pairwise.py index 03d22e0f6d344..f4549da37dd61 100644 --- a/sklearn/metrics/tests/test_pairwise.py +++ b/sklearn/metrics/tests/test_pairwise.py @@ -56,7 +56,12 @@ sigmoid_kernel, ) from sklearn.preprocessing import normalize +from sklearn.utils._array_api import ( + _convert_to_numpy, + yield_namespace_device_dtype_combinations, +) from sklearn.utils._testing import ( + _array_api_for_tests, assert_allclose, assert_almost_equal, assert_array_equal, @@ -1290,6 +1295,22 @@ def test_chi_square_kernel(): chi2_kernel([[0, 1]], [[0.2, 0.2, 0.6]]) +@pytest.mark.parametrize( + "array_namespace, deivce, _", yield_namespace_device_dtype_combinations() +) +def test_additive_chi2_kernel_array_api(array_namespace, deivce, _): + rng = np.random.RandomState(0) + X = rng.random_sample((5, 4)) + Y = rng.random_sample((10, 4)) + K_add = additive_chi2_kernel(X, Y) + with config_context(array_api_dispatch=True): + xp = _array_api_for_tests(array_namespace, deivce) + X_xp = xp.asarray(X) + Y_xp = xp.asarray(Y) + K_xp = additive_chi2_kernel(X_xp, Y_xp) + assert_allclose(_convert_to_numpy(K_xp, xp), K_add) + + @pytest.mark.parametrize( "kernel", ( From 668c10f5850be84ee951263dc800c46ad0dd7440 Mon Sep 17 00:00:00 2001 From: Tialo Date: Fri, 31 May 2024 01:49:19 +0300 Subject: [PATCH 2/5] use common test --- sklearn/metrics/tests/test_common.py | 3 ++- sklearn/metrics/tests/test_pairwise.py | 21 --------------------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/sklearn/metrics/tests/test_common.py b/sklearn/metrics/tests/test_common.py index 42f2a36445642..34311d57ebf63 100644 --- a/sklearn/metrics/tests/test_common.py +++ b/sklearn/metrics/tests/test_common.py @@ -51,7 +51,7 @@ zero_one_loss, ) from sklearn.metrics._base import _average_binary_score -from sklearn.metrics.pairwise import cosine_similarity +from sklearn.metrics.pairwise import additive_chi2_kernel, cosine_similarity from sklearn.preprocessing import LabelBinarizer from sklearn.utils import shuffle from sklearn.utils._array_api import ( @@ -1938,6 +1938,7 @@ def check_array_api_metric_pairwise(metric, array_namespace, device, dtype_name) check_array_api_regression_metric, check_array_api_multioutput_regression_metric, ], + additive_chi2_kernel: [check_array_api_metric_pairwise], } diff --git a/sklearn/metrics/tests/test_pairwise.py b/sklearn/metrics/tests/test_pairwise.py index f4549da37dd61..03d22e0f6d344 100644 --- a/sklearn/metrics/tests/test_pairwise.py +++ b/sklearn/metrics/tests/test_pairwise.py @@ -56,12 +56,7 @@ sigmoid_kernel, ) from sklearn.preprocessing import normalize -from sklearn.utils._array_api import ( - _convert_to_numpy, - yield_namespace_device_dtype_combinations, -) from sklearn.utils._testing import ( - _array_api_for_tests, assert_allclose, assert_almost_equal, assert_array_equal, @@ -1295,22 +1290,6 @@ def test_chi_square_kernel(): chi2_kernel([[0, 1]], [[0.2, 0.2, 0.6]]) -@pytest.mark.parametrize( - "array_namespace, deivce, _", yield_namespace_device_dtype_combinations() -) -def test_additive_chi2_kernel_array_api(array_namespace, deivce, _): - rng = np.random.RandomState(0) - X = rng.random_sample((5, 4)) - Y = rng.random_sample((10, 4)) - K_add = additive_chi2_kernel(X, Y) - with config_context(array_api_dispatch=True): - xp = _array_api_for_tests(array_namespace, deivce) - X_xp = xp.asarray(X) - Y_xp = xp.asarray(Y) - K_xp = additive_chi2_kernel(X_xp, Y_xp) - assert_allclose(_convert_to_numpy(K_xp, xp), K_add) - - @pytest.mark.parametrize( "kernel", ( From 12eb6ccd383d53024e6ba2e179b5d20a77c21ae2 Mon Sep 17 00:00:00 2001 From: Tialo Date: Fri, 31 May 2024 01:50:22 +0300 Subject: [PATCH 3/5] whatsnew --- doc/whats_new/v1.6.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/whats_new/v1.6.rst b/doc/whats_new/v1.6.rst index bc27f894ff9a1..0c17d0d8aa358 100644 --- a/doc/whats_new/v1.6.rst +++ b/doc/whats_new/v1.6.rst @@ -36,7 +36,8 @@ See :ref:`array_api` for more details. inputs. :pr:`28106` by :user:`Thomas Li `; - :func:`sklearn.metrics.mean_absolute_error` :pr:`27736` by :user:`Edoardo Abati `; -- :func:`sklearn.metrics.pairwise.cosine_similarity` :pr:`29014` by :user:`Edoardo Abati `. +- :func:`sklearn.metrics.pairwise.cosine_similarity` :pr:`29014` by :user:`Edoardo Abati `; +- :func:`sklearn.metrics.pairwise.additive_chi2_kernel` :pr:`29144` by :user:`Yaroslav Korobko `. **Classes:** From 91165385b211e3dc8dd056173ed1593afc325265 Mon Sep 17 00:00:00 2001 From: Tialo Date: Fri, 7 Jun 2024 20:17:27 +0300 Subject: [PATCH 4/5] array_api.rst --- doc/modules/array_api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/modules/array_api.rst b/doc/modules/array_api.rst index 48d95434e64cb..823443aaa58a6 100644 --- a/doc/modules/array_api.rst +++ b/doc/modules/array_api.rst @@ -117,6 +117,7 @@ Metrics - :func:`sklearn.metrics.mean_absolute_error` - :func:`sklearn.metrics.mean_squared_error` - :func:`sklearn.metrics.mean_tweedie_deviance` +- :func:`sklearn.metrics.pairwise.additive_chi2_kernel` - :func:`sklearn.metrics.pairwise.cosine_similarity` - :func:`sklearn.metrics.pairwise.paired_cosine_distances` - :func:`sklearn.metrics.r2_score` From edef1c970c6aa4046b3586816f6b37cee5b44c24 Mon Sep 17 00:00:00 2001 From: Tim Head Date: Thu, 13 Jun 2024 17:01:46 +0200 Subject: [PATCH 5/5] Fix syntax error --- sklearn/metrics/tests/test_common.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sklearn/metrics/tests/test_common.py b/sklearn/metrics/tests/test_common.py index 4bafc9648c4a4..51ecc82e2880c 100644 --- a/sklearn/metrics/tests/test_common.py +++ b/sklearn/metrics/tests/test_common.py @@ -1959,12 +1959,9 @@ def check_array_api_metric_pairwise(metric, array_namespace, device, dtype_name) check_array_api_regression_metric, ], paired_cosine_distances: [check_array_api_metric_pairwise], -<<<<<<< array-api/additive_chi2_kernel -- Incoming Change additive_chi2_kernel: [check_array_api_metric_pairwise], -======= mean_gamma_deviance: [check_array_api_regression_metric], max_error: [check_array_api_regression_metric], ->>>>>>> main -- Current Change }