Prompt48 commited on
Commit
b71845e
·
verified ·
1 Parent(s): f40a973

Upload edit\Qwen3-TTS-test\.venv\Lib\site-packages\sklearn\decomposition\tests\test_kernel_pca.py with huggingface_hub

Browse files
edit//Qwen3-TTS-test//.venv//Lib//site-packages//sklearn//decomposition//tests//test_kernel_pca.py ADDED
@@ -0,0 +1,566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import warnings
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ import sklearn
7
+ from sklearn.datasets import load_iris, make_blobs, make_circles
8
+ from sklearn.decomposition import PCA, KernelPCA
9
+ from sklearn.exceptions import NotFittedError
10
+ from sklearn.linear_model import Perceptron
11
+ from sklearn.metrics.pairwise import rbf_kernel
12
+ from sklearn.model_selection import GridSearchCV
13
+ from sklearn.pipeline import Pipeline
14
+ from sklearn.preprocessing import StandardScaler
15
+ from sklearn.utils._testing import (
16
+ assert_allclose,
17
+ assert_array_almost_equal,
18
+ assert_array_equal,
19
+ )
20
+ from sklearn.utils.fixes import CSR_CONTAINERS
21
+ from sklearn.utils.validation import _check_psd_eigenvalues
22
+
23
+
24
+ def test_kernel_pca(global_random_seed):
25
+ """Nominal test for all solvers and all known kernels + a custom one
26
+
27
+ It tests
28
+ - that fit_transform is equivalent to fit+transform
29
+ - that the shapes of transforms and inverse transforms are correct
30
+ """
31
+ rng = np.random.RandomState(global_random_seed)
32
+ X_fit = rng.random_sample((5, 4))
33
+ X_pred = rng.random_sample((2, 4))
34
+
35
+ def histogram(x, y, **kwargs):
36
+ # Histogram kernel implemented as a callable.
37
+ assert kwargs == {} # no kernel_params that we didn't ask for
38
+ return np.minimum(x, y).sum()
39
+
40
+ for eigen_solver in ("auto", "dense", "arpack", "randomized"):
41
+ for kernel in ("linear", "rbf", "poly", histogram):
42
+ # histogram kernel produces singular matrix inside linalg.solve
43
+ # XXX use a least-squares approximation?
44
+ inv = not callable(kernel)
45
+
46
+ # transform fit data
47
+ kpca = KernelPCA(
48
+ 4, kernel=kernel, eigen_solver=eigen_solver, fit_inverse_transform=inv
49
+ )
50
+ X_fit_transformed = kpca.fit_transform(X_fit)
51
+ X_fit_transformed2 = kpca.fit(X_fit).transform(X_fit)
52
+ assert_array_almost_equal(
53
+ np.abs(X_fit_transformed), np.abs(X_fit_transformed2)
54
+ )
55
+
56
+ # non-regression test: previously, gamma would be 0 by default,
57
+ # forcing all eigenvalues to 0 under the poly kernel
58
+ assert X_fit_transformed.size != 0
59
+
60
+ # transform new data
61
+ X_pred_transformed = kpca.transform(X_pred)
62
+ assert X_pred_transformed.shape[1] == X_fit_transformed.shape[1]
63
+
64
+ # inverse transform
65
+ if inv:
66
+ X_pred2 = kpca.inverse_transform(X_pred_transformed)
67
+ assert X_pred2.shape == X_pred.shape
68
+
69
+
70
+ def test_kernel_pca_invalid_parameters():
71
+ """Check that kPCA raises an error if the parameters are invalid
72
+
73
+ Tests fitting inverse transform with a precomputed kernel raises a
74
+ ValueError.
75
+ """
76
+ estimator = KernelPCA(
77
+ n_components=10, fit_inverse_transform=True, kernel="precomputed"
78
+ )
79
+ err_ms = "Cannot fit_inverse_transform with a precomputed kernel"
80
+ with pytest.raises(ValueError, match=err_ms):
81
+ estimator.fit(np.random.randn(10, 10))
82
+
83
+
84
+ def test_kernel_pca_consistent_transform(global_random_seed):
85
+ """Check robustness to mutations in the original training array
86
+
87
+ Test that after fitting a kPCA model, it stays independent of any
88
+ mutation of the values of the original data object by relying on an
89
+ internal copy.
90
+ """
91
+ # X_fit_ needs to retain the old, unmodified copy of X
92
+ state = np.random.RandomState(global_random_seed)
93
+ X = state.rand(10, 10)
94
+ kpca = KernelPCA(random_state=state).fit(X)
95
+ transformed1 = kpca.transform(X)
96
+
97
+ X_copy = X.copy()
98
+ X[:, 0] = 666
99
+ transformed2 = kpca.transform(X_copy)
100
+ assert_array_almost_equal(transformed1, transformed2)
101
+
102
+
103
+ def test_kernel_pca_deterministic_output(global_random_seed):
104
+ """Test that Kernel PCA produces deterministic output
105
+
106
+ Tests that the same inputs and random state produce the same output.
107
+ """
108
+ rng = np.random.RandomState(global_random_seed)
109
+ X = rng.rand(10, 10)
110
+ eigen_solver = ("arpack", "dense")
111
+
112
+ for solver in eigen_solver:
113
+ transformed_X = np.zeros((20, 2))
114
+ for i in range(20):
115
+ kpca = KernelPCA(n_components=2, eigen_solver=solver, random_state=rng)
116
+ transformed_X[i, :] = kpca.fit_transform(X)[0]
117
+ assert_allclose(transformed_X, np.tile(transformed_X[0, :], 20).reshape(20, 2))
118
+
119
+
120
+ @pytest.mark.parametrize("csr_container", CSR_CONTAINERS)
121
+ def test_kernel_pca_sparse(csr_container, global_random_seed):
122
+ """Test that kPCA works on a sparse data input.
123
+
124
+ Same test as ``test_kernel_pca except inverse_transform`` since it's not
125
+ implemented for sparse matrices.
126
+ """
127
+ rng = np.random.RandomState(global_random_seed)
128
+ X_fit = csr_container(rng.random_sample((5, 4)))
129
+ X_pred = csr_container(rng.random_sample((2, 4)))
130
+
131
+ for eigen_solver in ("auto", "arpack", "randomized"):
132
+ for kernel in ("linear", "rbf", "poly"):
133
+ # transform fit data
134
+ kpca = KernelPCA(
135
+ 4,
136
+ kernel=kernel,
137
+ eigen_solver=eigen_solver,
138
+ fit_inverse_transform=False,
139
+ random_state=0,
140
+ )
141
+ X_fit_transformed = kpca.fit_transform(X_fit)
142
+ X_fit_transformed2 = kpca.fit(X_fit).transform(X_fit)
143
+ assert_array_almost_equal(
144
+ np.abs(X_fit_transformed), np.abs(X_fit_transformed2)
145
+ )
146
+
147
+ # transform new data
148
+ X_pred_transformed = kpca.transform(X_pred)
149
+ assert X_pred_transformed.shape[1] == X_fit_transformed.shape[1]
150
+
151
+ # inverse transform: not available for sparse matrices
152
+ # XXX: should we raise another exception type here? For instance:
153
+ # NotImplementedError.
154
+ with pytest.raises(NotFittedError):
155
+ kpca.inverse_transform(X_pred_transformed)
156
+
157
+
158
+ @pytest.mark.parametrize("solver", ["auto", "dense", "arpack", "randomized"])
159
+ @pytest.mark.parametrize("n_features", [4, 10])
160
+ def test_kernel_pca_linear_kernel(solver, n_features, global_random_seed):
161
+ """Test that kPCA with linear kernel is equivalent to PCA for all solvers.
162
+
163
+ KernelPCA with linear kernel should produce the same output as PCA.
164
+ """
165
+ rng = np.random.RandomState(global_random_seed)
166
+ X_fit = rng.random_sample((5, n_features))
167
+ X_pred = rng.random_sample((2, n_features))
168
+
169
+ # for a linear kernel, kernel PCA should find the same projection as PCA
170
+ # modulo the sign (direction)
171
+ # fit only the first four components: fifth is near zero eigenvalue, so
172
+ # can be trimmed due to roundoff error
173
+ n_comps = 3 if solver == "arpack" else 4
174
+ assert_array_almost_equal(
175
+ np.abs(KernelPCA(n_comps, eigen_solver=solver).fit(X_fit).transform(X_pred)),
176
+ np.abs(
177
+ PCA(n_comps, svd_solver=solver if solver != "dense" else "full")
178
+ .fit(X_fit)
179
+ .transform(X_pred)
180
+ ),
181
+ )
182
+
183
+
184
+ def test_kernel_pca_n_components():
185
+ """Test that `n_components` is correctly taken into account for projections
186
+
187
+ For all solvers this tests that the output has the correct shape depending
188
+ on the selected number of components.
189
+ """
190
+ rng = np.random.RandomState(0)
191
+ X_fit = rng.random_sample((5, 4))
192
+ X_pred = rng.random_sample((2, 4))
193
+
194
+ for eigen_solver in ("dense", "arpack", "randomized"):
195
+ for c in [1, 2, 4]:
196
+ kpca = KernelPCA(n_components=c, eigen_solver=eigen_solver)
197
+ shape = kpca.fit(X_fit).transform(X_pred).shape
198
+
199
+ assert shape == (2, c)
200
+
201
+
202
+ def test_remove_zero_eig():
203
+ """Check that the ``remove_zero_eig`` parameter works correctly.
204
+
205
+ Tests that the null-space (Zero) eigenvalues are removed when
206
+ remove_zero_eig=True, whereas they are not by default.
207
+ """
208
+ X = np.array([[1 - 1e-30, 1], [1, 1], [1, 1 - 1e-20]])
209
+
210
+ # n_components=None (default) => remove_zero_eig is True
211
+ kpca = KernelPCA()
212
+ Xt = kpca.fit_transform(X)
213
+ assert Xt.shape == (3, 0)
214
+
215
+ kpca = KernelPCA(n_components=2)
216
+ Xt = kpca.fit_transform(X)
217
+ assert Xt.shape == (3, 2)
218
+
219
+ kpca = KernelPCA(n_components=2, remove_zero_eig=True)
220
+ Xt = kpca.fit_transform(X)
221
+ assert Xt.shape == (3, 0)
222
+
223
+
224
+ def test_leave_zero_eig():
225
+ """Non-regression test for issue #12141 (PR #12143)
226
+
227
+ This test checks that fit().transform() returns the same result as
228
+ fit_transform() in case of non-removed zero eigenvalue.
229
+ """
230
+ X_fit = np.array([[1, 1], [0, 0]])
231
+
232
+ # Assert that even with all np warnings on, there is no div by zero warning
233
+ with warnings.catch_warnings():
234
+ # There might be warnings about the kernel being badly conditioned,
235
+ # but there should not be warnings about division by zero.
236
+ # (Numpy division by zero warning can have many message variants, but
237
+ # at least we know that it is a RuntimeWarning so let's check only this)
238
+ warnings.simplefilter("error", RuntimeWarning)
239
+ with np.errstate(all="warn"):
240
+ k = KernelPCA(n_components=2, remove_zero_eig=False, eigen_solver="dense")
241
+ # Fit, then transform
242
+ A = k.fit(X_fit).transform(X_fit)
243
+ # Do both at once
244
+ B = k.fit_transform(X_fit)
245
+ # Compare
246
+ assert_array_almost_equal(np.abs(A), np.abs(B))
247
+
248
+
249
+ def test_kernel_pca_precomputed(global_random_seed):
250
+ """Test that kPCA works with a precomputed kernel, for all solvers"""
251
+ rng = np.random.RandomState(global_random_seed)
252
+ X_fit = rng.random_sample((5, 4))
253
+ X_pred = rng.random_sample((2, 4))
254
+
255
+ for eigen_solver in ("dense", "arpack", "randomized"):
256
+ X_kpca = (
257
+ KernelPCA(4, eigen_solver=eigen_solver, random_state=0)
258
+ .fit(X_fit)
259
+ .transform(X_pred)
260
+ )
261
+
262
+ X_kpca2 = (
263
+ KernelPCA(
264
+ 4, eigen_solver=eigen_solver, kernel="precomputed", random_state=0
265
+ )
266
+ .fit(np.dot(X_fit, X_fit.T))
267
+ .transform(np.dot(X_pred, X_fit.T))
268
+ )
269
+
270
+ X_kpca_train = KernelPCA(
271
+ 4, eigen_solver=eigen_solver, kernel="precomputed", random_state=0
272
+ ).fit_transform(np.dot(X_fit, X_fit.T))
273
+
274
+ X_kpca_train2 = (
275
+ KernelPCA(
276
+ 4, eigen_solver=eigen_solver, kernel="precomputed", random_state=0
277
+ )
278
+ .fit(np.dot(X_fit, X_fit.T))
279
+ .transform(np.dot(X_fit, X_fit.T))
280
+ )
281
+
282
+ assert_array_almost_equal(np.abs(X_kpca), np.abs(X_kpca2))
283
+
284
+ assert_array_almost_equal(np.abs(X_kpca_train), np.abs(X_kpca_train2))
285
+
286
+
287
+ @pytest.mark.parametrize("solver", ["auto", "dense", "arpack", "randomized"])
288
+ def test_kernel_pca_precomputed_non_symmetric(solver):
289
+ """Check that the kernel centerer works.
290
+
291
+ Tests that a non symmetric precomputed kernel is actually accepted
292
+ because the kernel centerer does its job correctly.
293
+ """
294
+
295
+ # a non symmetric gram matrix
296
+ K = [[1, 2], [3, 40]]
297
+ kpca = KernelPCA(
298
+ kernel="precomputed", eigen_solver=solver, n_components=1, random_state=0
299
+ )
300
+ kpca.fit(K) # no error
301
+
302
+ # same test with centered kernel
303
+ Kc = [[9, -9], [-9, 9]]
304
+ kpca_c = KernelPCA(
305
+ kernel="precomputed", eigen_solver=solver, n_components=1, random_state=0
306
+ )
307
+ kpca_c.fit(Kc)
308
+
309
+ # comparison between the non-centered and centered versions
310
+ assert_array_equal(kpca.eigenvectors_, kpca_c.eigenvectors_)
311
+ assert_array_equal(kpca.eigenvalues_, kpca_c.eigenvalues_)
312
+
313
+
314
+ def test_gridsearch_pipeline():
315
+ """Check that kPCA works as expected in a grid search pipeline
316
+
317
+ Test if we can do a grid-search to find parameters to separate
318
+ circles with a perceptron model.
319
+ """
320
+ X, y = make_circles(n_samples=400, factor=0.3, noise=0.05, random_state=0)
321
+ kpca = KernelPCA(kernel="rbf", n_components=2)
322
+ pipeline = Pipeline([("kernel_pca", kpca), ("Perceptron", Perceptron(max_iter=5))])
323
+ param_grid = dict(kernel_pca__gamma=2.0 ** np.arange(-2, 2))
324
+ grid_search = GridSearchCV(pipeline, cv=3, param_grid=param_grid)
325
+ grid_search.fit(X, y)
326
+ assert grid_search.best_score_ == 1
327
+
328
+
329
+ def test_gridsearch_pipeline_precomputed():
330
+ """Check that kPCA works as expected in a grid search pipeline (2)
331
+
332
+ Test if we can do a grid-search to find parameters to separate
333
+ circles with a perceptron model. This test uses a precomputed kernel.
334
+ """
335
+ X, y = make_circles(n_samples=400, factor=0.3, noise=0.05, random_state=0)
336
+ kpca = KernelPCA(kernel="precomputed", n_components=2)
337
+ pipeline = Pipeline([("kernel_pca", kpca), ("Perceptron", Perceptron(max_iter=5))])
338
+ param_grid = dict(Perceptron__max_iter=np.arange(1, 5))
339
+ grid_search = GridSearchCV(pipeline, cv=3, param_grid=param_grid)
340
+ X_kernel = rbf_kernel(X, gamma=2.0)
341
+ grid_search.fit(X_kernel, y)
342
+ assert grid_search.best_score_ == 1
343
+
344
+
345
+ def test_nested_circles():
346
+ """Check that kPCA projects in a space where nested circles are separable
347
+
348
+ Tests that 2D nested circles become separable with a perceptron when
349
+ projected in the first 2 kPCA using an RBF kernel, while raw samples
350
+ are not directly separable in the original space.
351
+ """
352
+ X, y = make_circles(n_samples=400, factor=0.3, noise=0.05, random_state=0)
353
+
354
+ # 2D nested circles are not linearly separable
355
+ train_score = Perceptron(max_iter=5).fit(X, y).score(X, y)
356
+ assert train_score < 0.8
357
+
358
+ # Project the circles data into the first 2 components of a RBF Kernel
359
+ # PCA model.
360
+ # Note that the gamma value is data dependent. If this test breaks
361
+ # and the gamma value has to be updated, the Kernel PCA example will
362
+ # have to be updated too.
363
+ kpca = KernelPCA(
364
+ kernel="rbf", n_components=2, fit_inverse_transform=True, gamma=2.0
365
+ )
366
+ X_kpca = kpca.fit_transform(X)
367
+
368
+ # The data is perfectly linearly separable in that space
369
+ train_score = Perceptron(max_iter=5).fit(X_kpca, y).score(X_kpca, y)
370
+ assert train_score == 1.0
371
+
372
+
373
+ def test_kernel_conditioning():
374
+ """Check that ``_check_psd_eigenvalues`` is correctly called in kPCA
375
+
376
+ Non-regression test for issue #12140 (PR #12145).
377
+ """
378
+
379
+ # create a pathological X leading to small non-zero eigenvalue
380
+ X = [[5, 1], [5 + 1e-8, 1e-8], [5 + 1e-8, 0]]
381
+ kpca = KernelPCA(kernel="linear", n_components=2, fit_inverse_transform=True)
382
+ kpca.fit(X)
383
+
384
+ # check that the small non-zero eigenvalue was correctly set to zero
385
+ assert kpca.eigenvalues_.min() == 0
386
+ assert np.all(kpca.eigenvalues_ == _check_psd_eigenvalues(kpca.eigenvalues_))
387
+
388
+
389
+ @pytest.mark.parametrize("solver", ["auto", "dense", "arpack", "randomized"])
390
+ def test_precomputed_kernel_not_psd(solver):
391
+ """Check how KernelPCA works with non-PSD kernels depending on n_components
392
+
393
+ Tests for all methods what happens with a non PSD gram matrix (this
394
+ can happen in an isomap scenario, or with custom kernel functions, or
395
+ maybe with ill-posed datasets).
396
+
397
+ When ``n_component`` is large enough to capture a negative eigenvalue, an
398
+ error should be raised. Otherwise, KernelPCA should run without error
399
+ since the negative eigenvalues are not selected.
400
+ """
401
+
402
+ # a non PSD kernel with large eigenvalues, already centered
403
+ # it was captured from an isomap call and multiplied by 100 for compacity
404
+ K = [
405
+ [4.48, -1.0, 8.07, 2.33, 2.33, 2.33, -5.76, -12.78],
406
+ [-1.0, -6.48, 4.5, -1.24, -1.24, -1.24, -0.81, 7.49],
407
+ [8.07, 4.5, 15.48, 2.09, 2.09, 2.09, -11.1, -23.23],
408
+ [2.33, -1.24, 2.09, 4.0, -3.65, -3.65, 1.02, -0.9],
409
+ [2.33, -1.24, 2.09, -3.65, 4.0, -3.65, 1.02, -0.9],
410
+ [2.33, -1.24, 2.09, -3.65, -3.65, 4.0, 1.02, -0.9],
411
+ [-5.76, -0.81, -11.1, 1.02, 1.02, 1.02, 4.86, 9.75],
412
+ [-12.78, 7.49, -23.23, -0.9, -0.9, -0.9, 9.75, 21.46],
413
+ ]
414
+ # this gram matrix has 5 positive eigenvalues and 3 negative ones
415
+ # [ 52.72, 7.65, 7.65, 5.02, 0. , -0. , -6.13, -15.11]
416
+
417
+ # 1. ask for enough components to get a significant negative one
418
+ kpca = KernelPCA(kernel="precomputed", eigen_solver=solver, n_components=7)
419
+ # make sure that the appropriate error is raised
420
+ with pytest.raises(ValueError, match="There are significant negative eigenvalues"):
421
+ kpca.fit(K)
422
+
423
+ # 2. ask for a small enough n_components to get only positive ones
424
+ kpca = KernelPCA(kernel="precomputed", eigen_solver=solver, n_components=2)
425
+ if solver == "randomized":
426
+ # the randomized method is still inconsistent with the others on this
427
+ # since it selects the eigenvalues based on the largest 2 modules, not
428
+ # on the largest 2 values.
429
+ #
430
+ # At least we can ensure that we return an error instead of returning
431
+ # the wrong eigenvalues
432
+ with pytest.raises(
433
+ ValueError, match="There are significant negative eigenvalues"
434
+ ):
435
+ kpca.fit(K)
436
+ else:
437
+ # general case: make sure that it works
438
+ kpca.fit(K)
439
+
440
+
441
+ @pytest.mark.parametrize("n_components", [4, 10, 20])
442
+ def test_kernel_pca_solvers_equivalence(n_components):
443
+ """Check that 'dense' 'arpack' & 'randomized' solvers give similar results"""
444
+
445
+ # Generate random data
446
+ n_train, n_test = 1_000, 100
447
+ X, _ = make_circles(
448
+ n_samples=(n_train + n_test), factor=0.3, noise=0.05, random_state=0
449
+ )
450
+ X_fit, X_pred = X[:n_train, :], X[n_train:, :]
451
+
452
+ # reference (full)
453
+ ref_pred = (
454
+ KernelPCA(n_components, eigen_solver="dense", random_state=0)
455
+ .fit(X_fit)
456
+ .transform(X_pred)
457
+ )
458
+
459
+ # arpack
460
+ a_pred = (
461
+ KernelPCA(n_components, eigen_solver="arpack", random_state=0)
462
+ .fit(X_fit)
463
+ .transform(X_pred)
464
+ )
465
+ # check that the result is still correct despite the approx
466
+ assert_array_almost_equal(np.abs(a_pred), np.abs(ref_pred))
467
+
468
+ # randomized
469
+ r_pred = (
470
+ KernelPCA(n_components, eigen_solver="randomized", random_state=0)
471
+ .fit(X_fit)
472
+ .transform(X_pred)
473
+ )
474
+ # check that the result is still correct despite the approximation
475
+ assert_array_almost_equal(np.abs(r_pred), np.abs(ref_pred))
476
+
477
+
478
+ def test_kernel_pca_inverse_transform_reconstruction():
479
+ """Test if the reconstruction is a good approximation.
480
+
481
+ Note that in general it is not possible to get an arbitrarily good
482
+ reconstruction because of kernel centering that does not
483
+ preserve all the information of the original data.
484
+ """
485
+ X, *_ = make_blobs(n_samples=100, n_features=4, random_state=0)
486
+
487
+ kpca = KernelPCA(
488
+ n_components=20, kernel="rbf", fit_inverse_transform=True, alpha=1e-3
489
+ )
490
+ X_trans = kpca.fit_transform(X)
491
+ X_reconst = kpca.inverse_transform(X_trans)
492
+ assert np.linalg.norm(X - X_reconst) / np.linalg.norm(X) < 1e-1
493
+
494
+
495
+ def test_kernel_pca_raise_not_fitted_error():
496
+ X = np.random.randn(15).reshape(5, 3)
497
+ kpca = KernelPCA()
498
+ kpca.fit(X)
499
+ with pytest.raises(NotFittedError):
500
+ kpca.inverse_transform(X)
501
+
502
+
503
+ def test_32_64_decomposition_shape():
504
+ """Test that the decomposition is similar for 32 and 64 bits data
505
+
506
+ Non regression test for
507
+ https://github.com/scikit-learn/scikit-learn/issues/18146
508
+ """
509
+ X, y = make_blobs(
510
+ n_samples=30, centers=[[0, 0, 0], [1, 1, 1]], random_state=0, cluster_std=0.1
511
+ )
512
+ X = StandardScaler().fit_transform(X)
513
+ X -= X.min()
514
+
515
+ # Compare the shapes (corresponds to the number of non-zero eigenvalues)
516
+ kpca = KernelPCA()
517
+ assert kpca.fit_transform(X).shape == kpca.fit_transform(X.astype(np.float32)).shape
518
+
519
+
520
+ def test_kernel_pca_feature_names_out():
521
+ """Check feature names out for KernelPCA."""
522
+ X, *_ = make_blobs(n_samples=100, n_features=4, random_state=0)
523
+ kpca = KernelPCA(n_components=2).fit(X)
524
+
525
+ names = kpca.get_feature_names_out()
526
+ assert_array_equal([f"kernelpca{i}" for i in range(2)], names)
527
+
528
+
529
+ def test_kernel_pca_inverse_correct_gamma(global_random_seed):
530
+ """Check that gamma is set correctly when not provided.
531
+
532
+ Non-regression test for #26280
533
+ """
534
+ rng = np.random.RandomState(global_random_seed)
535
+ X = rng.random_sample((5, 4))
536
+
537
+ kwargs = {
538
+ "n_components": 2,
539
+ "random_state": rng,
540
+ "fit_inverse_transform": True,
541
+ "kernel": "rbf",
542
+ }
543
+
544
+ expected_gamma = 1 / X.shape[1]
545
+ kpca1 = KernelPCA(gamma=None, **kwargs).fit(X)
546
+ kpca2 = KernelPCA(gamma=expected_gamma, **kwargs).fit(X)
547
+
548
+ assert kpca1.gamma_ == expected_gamma
549
+ assert kpca2.gamma_ == expected_gamma
550
+
551
+ X1_recon = kpca1.inverse_transform(kpca1.transform(X))
552
+ X2_recon = kpca2.inverse_transform(kpca1.transform(X))
553
+
554
+ assert_allclose(X1_recon, X2_recon)
555
+
556
+
557
+ def test_kernel_pca_pandas_output():
558
+ """Check that KernelPCA works with pandas output when the solver is arpack.
559
+
560
+ Non-regression test for:
561
+ https://github.com/scikit-learn/scikit-learn/issues/27579
562
+ """
563
+ pytest.importorskip("pandas")
564
+ X, _ = load_iris(as_frame=True, return_X_y=True)
565
+ with sklearn.config_context(transform_output="pandas"):
566
+ KernelPCA(n_components=2, eigen_solver="arpack").fit_transform(X)