diff --git a/sklearn/manifold/tests/test_locally_linear.py b/sklearn/manifold/tests/test_locally_linear.py index ff93a15c0704d..4272aa05b71a0 100644 --- a/sklearn/manifold/tests/test_locally_linear.py +++ b/sklearn/manifold/tests/test_locally_linear.py @@ -1,9 +1,8 @@ from itertools import product import numpy as np -from numpy.testing import ( - assert_almost_equal, - assert_array_almost_equal, +from sklearn.utils._testing import ( + assert_allclose, assert_array_equal, ) from scipy import linalg @@ -19,18 +18,22 @@ # ---------------------------------------------------------------------- # Test utility routines -def test_barycenter_kneighbors_graph(): - X = np.array([[0, 1], [1.01, 1.0], [2, 0]]) +def test_barycenter_kneighbors_graph(global_dtype): + X = np.array([[0, 1], [1.01, 1.0], [2, 0]], dtype=global_dtype) - A = barycenter_kneighbors_graph(X, 1) - assert_array_almost_equal( - A.toarray(), [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]] + graph = barycenter_kneighbors_graph(X, 1) + expected_graph = np.array( + [[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=global_dtype ) - A = barycenter_kneighbors_graph(X, 2) + assert graph.dtype == global_dtype + + assert_allclose(graph.toarray(), expected_graph) + + graph = barycenter_kneighbors_graph(X, 2) # check that columns sum to one - assert_array_almost_equal(np.sum(A.toarray(), 1), np.ones(3)) - pred = np.dot(A.toarray(), X) + assert_allclose(np.sum(graph.toarray(), axis=1), np.ones(3)) + pred = np.dot(graph.toarray(), X) assert linalg.norm(pred - X) / X.shape[0] < 1 @@ -38,7 +41,7 @@ def test_barycenter_kneighbors_graph(): # Test LLE by computing the reconstruction error on some manifolds. -def test_lle_simple_grid(): +def test_lle_simple_grid(global_dtype): # note: ARPACK is numerically unstable, so this test will fail for # some random seeds. We choose 42 because the tests pass. # for arm64 platforms 2 makes the test fail. @@ -49,6 +52,8 @@ def test_lle_simple_grid(): # grid of equidistant points in 2D, n_components = n_dim X = np.array(list(product(range(5), repeat=2))) X = X + 1e-10 * rng.uniform(size=X.shape) + X = X.astype(global_dtype, copy=False) + n_components = 2 clf = manifold.LocallyLinearEmbedding( n_neighbors=5, n_components=n_components, random_state=rng @@ -68,44 +73,46 @@ def test_lle_simple_grid(): ) assert reconstruction_error < tol - assert_almost_equal(clf.reconstruction_error_, reconstruction_error, decimal=1) + assert_allclose(clf.reconstruction_error_, reconstruction_error, atol=1e-1) # re-embed a noisy version of X using the transform method - noise = rng.randn(*X.shape) / 100 + noise = rng.randn(*X.shape).astype(global_dtype, copy=False) / 100 X_reembedded = clf.transform(X + noise) assert linalg.norm(X_reembedded - clf.embedding_) < tol -def test_lle_manifold(): +@pytest.mark.parametrize("method", ["standard", "hessian", "modified", "ltsa"]) +@pytest.mark.parametrize("solver", eigen_solvers) +def test_lle_manifold(global_dtype, method, solver): rng = np.random.RandomState(0) # similar test on a slightly more complex manifold X = np.array(list(product(np.arange(18), repeat=2))) X = np.c_[X, X[:, 0] ** 2 / 18] X = X + 1e-10 * rng.uniform(size=X.shape) + X = X.astype(global_dtype, copy=False) n_components = 2 - for method in ["standard", "hessian", "modified", "ltsa"]: - clf = manifold.LocallyLinearEmbedding( - n_neighbors=6, n_components=n_components, method=method, random_state=0 - ) - tol = 1.5 if method == "standard" else 3 - N = barycenter_kneighbors_graph(X, clf.n_neighbors).toarray() - reconstruction_error = linalg.norm(np.dot(N, X) - X) - assert reconstruction_error < tol + clf = manifold.LocallyLinearEmbedding( + n_neighbors=6, n_components=n_components, method=method, random_state=0 + ) + tol = 1.5 if method == "standard" else 3 - for solver in eigen_solvers: - clf.set_params(eigen_solver=solver) - clf.fit(X) - assert clf.embedding_.shape[1] == n_components - reconstruction_error = ( - linalg.norm(np.dot(N, clf.embedding_) - clf.embedding_, "fro") ** 2 - ) - details = "solver: %s, method: %s" % (solver, method) - assert reconstruction_error < tol, details - assert ( - np.abs(clf.reconstruction_error_ - reconstruction_error) - < tol * reconstruction_error - ), details + N = barycenter_kneighbors_graph(X, clf.n_neighbors).toarray() + reconstruction_error = linalg.norm(np.dot(N, X) - X) + assert reconstruction_error < tol + + clf.set_params(eigen_solver=solver) + clf.fit(X) + assert clf.embedding_.shape[1] == n_components + reconstruction_error = ( + linalg.norm(np.dot(N, clf.embedding_) - clf.embedding_, "fro") ** 2 + ) + details = "solver: %s, method: %s" % (solver, method) + assert reconstruction_error < tol, details + assert ( + np.abs(clf.reconstruction_error_ - reconstruction_error) + < tol * reconstruction_error + ), details # Test the error raised when parameter passed to lle is invalid