2021-04-09 17:40:37 +08:00
|
|
|
import re
|
|
|
|
|
|
2011-11-12 01:58:24 +08:00
|
|
|
import numpy as np
|
2011-12-24 17:38:58 +08:00
|
|
|
from scipy.sparse import csr_matrix
|
2018-10-12 02:56:37 +08:00
|
|
|
import pytest
|
2011-11-12 01:58:24 +08:00
|
|
|
|
2019-10-29 00:28:56 +08:00
|
|
|
from sklearn.utils._testing import assert_array_equal
|
2021-04-09 17:40:37 +08:00
|
|
|
from sklearn.utils._testing import assert_array_almost_equal
|
2012-10-25 14:31:35 +08:00
|
|
|
|
2013-03-18 10:08:01 +08:00
|
|
|
from sklearn.metrics.pairwise import kernel_metrics
|
2012-01-10 12:35:15 +08:00
|
|
|
from sklearn.kernel_approximation import RBFSampler
|
|
|
|
|
from sklearn.kernel_approximation import AdditiveChi2Sampler
|
|
|
|
|
from sklearn.kernel_approximation import SkewedChi2Sampler
|
2012-11-27 06:39:43 +08:00
|
|
|
from sklearn.kernel_approximation import Nystroem
|
2020-08-18 14:44:20 +08:00
|
|
|
from sklearn.kernel_approximation import PolynomialCountSketch
|
2021-09-02 22:14:36 +08:00
|
|
|
from sklearn.datasets import make_classification
|
2017-07-01 00:16:10 +08:00
|
|
|
from sklearn.metrics.pairwise import polynomial_kernel, rbf_kernel, chi2_kernel
|
2011-11-12 01:58:24 +08:00
|
|
|
|
|
|
|
|
# generate data
|
2012-05-06 22:22:39 +08:00
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X = rng.random_sample(size=(300, 50))
|
|
|
|
|
Y = rng.random_sample(size=(300, 50))
|
2011-11-12 01:58:24 +08:00
|
|
|
X /= X.sum(axis=1)[:, np.newaxis]
|
|
|
|
|
Y /= Y.sum(axis=1)[:, np.newaxis]
|
|
|
|
|
|
2011-11-21 02:55:30 +08:00
|
|
|
|
2020-08-18 14:44:20 +08:00
|
|
|
@pytest.mark.parametrize("degree", [-1, 0])
|
|
|
|
|
def test_polynomial_count_sketch_raises_if_degree_lower_than_one(degree):
|
|
|
|
|
with pytest.raises(ValueError, match=f"degree={degree} should be >=1."):
|
|
|
|
|
ps_transform = PolynomialCountSketch(degree=degree)
|
|
|
|
|
ps_transform.fit(X, Y)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("X", [X, csr_matrix(X)])
|
|
|
|
|
@pytest.mark.parametrize("Y", [Y, csr_matrix(Y)])
|
|
|
|
|
@pytest.mark.parametrize("gamma", [0.1, 1, 2.5])
|
|
|
|
|
@pytest.mark.parametrize("degree", [1, 2, 3])
|
|
|
|
|
@pytest.mark.parametrize("coef0", [0, 1, 2.5])
|
|
|
|
|
def test_polynomial_count_sketch(X, Y, gamma, degree, coef0):
|
|
|
|
|
# test that PolynomialCountSketch approximates polynomial
|
|
|
|
|
# kernel on random data
|
|
|
|
|
|
|
|
|
|
# compute exact kernel
|
|
|
|
|
kernel = polynomial_kernel(X, Y, gamma=gamma, degree=degree, coef0=coef0)
|
|
|
|
|
|
|
|
|
|
# approximate kernel mapping
|
|
|
|
|
ps_transform = PolynomialCountSketch(
|
|
|
|
|
n_components=5000, gamma=gamma, coef0=coef0, degree=degree, random_state=42
|
|
|
|
|
)
|
|
|
|
|
X_trans = ps_transform.fit_transform(X)
|
|
|
|
|
Y_trans = ps_transform.transform(Y)
|
|
|
|
|
kernel_approx = np.dot(X_trans, Y_trans.T)
|
|
|
|
|
|
|
|
|
|
error = kernel - kernel_approx
|
|
|
|
|
assert np.abs(np.mean(error)) <= 0.05 # close to unbiased
|
|
|
|
|
np.abs(error, out=error)
|
|
|
|
|
assert np.max(error) <= 0.1 # nothing too far off
|
|
|
|
|
assert np.mean(error) <= 0.05 # mean is fairly close
|
|
|
|
|
|
|
|
|
|
|
2020-02-16 21:41:26 +08:00
|
|
|
def _linear_kernel(X, Y):
|
|
|
|
|
return np.dot(X, Y.T)
|
|
|
|
|
|
|
|
|
|
|
2011-11-21 02:53:01 +08:00
|
|
|
def test_additive_chi2_sampler():
|
2015-03-21 13:22:08 +08:00
|
|
|
# test that AdditiveChi2Sampler approximates kernel on random data
|
2011-11-21 02:53:01 +08:00
|
|
|
|
|
|
|
|
# compute exact kernel
|
2015-12-08 02:13:40 +08:00
|
|
|
# abbreviations for easier formula
|
2011-11-21 02:53:01 +08:00
|
|
|
X_ = X[:, np.newaxis, :]
|
|
|
|
|
Y_ = Y[np.newaxis, :, :]
|
|
|
|
|
|
|
|
|
|
large_kernel = 2 * X_ * Y_ / (X_ + Y_)
|
|
|
|
|
|
|
|
|
|
# reduce to n_samples_x x n_samples_y by summing over features
|
|
|
|
|
kernel = large_kernel.sum(axis=2)
|
|
|
|
|
|
2013-09-13 22:29:42 +08:00
|
|
|
# approximate kernel mapping
|
2011-12-19 23:31:50 +08:00
|
|
|
transform = AdditiveChi2Sampler(sample_steps=3)
|
|
|
|
|
X_trans = transform.fit_transform(X)
|
2011-11-21 02:53:01 +08:00
|
|
|
Y_trans = transform.transform(Y)
|
2012-12-13 04:49:40 +08:00
|
|
|
|
2011-11-21 02:53:01 +08:00
|
|
|
kernel_approx = np.dot(X_trans, Y_trans.T)
|
|
|
|
|
|
2012-10-25 14:31:35 +08:00
|
|
|
assert_array_almost_equal(kernel, kernel_approx, 1)
|
2011-11-20 21:25:00 +08:00
|
|
|
|
2012-06-22 23:12:51 +08:00
|
|
|
X_sp_trans = transform.fit_transform(csr_matrix(X))
|
|
|
|
|
Y_sp_trans = transform.transform(csr_matrix(Y))
|
|
|
|
|
|
2012-10-25 14:31:35 +08:00
|
|
|
assert_array_equal(X_trans, X_sp_trans.A)
|
|
|
|
|
assert_array_equal(Y_trans, Y_sp_trans.A)
|
2012-06-22 23:12:51 +08:00
|
|
|
|
2012-12-13 04:49:40 +08:00
|
|
|
# test error is raised on negative input
|
|
|
|
|
Y_neg = Y.copy()
|
|
|
|
|
Y_neg[0, 0] = -1
|
2021-04-09 17:40:37 +08:00
|
|
|
msg = "Negative values in data passed to"
|
|
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
|
|
|
transform.transform(Y_neg)
|
2012-12-13 04:49:40 +08:00
|
|
|
|
|
|
|
|
# test error on invalid sample_steps
|
|
|
|
|
transform = AdditiveChi2Sampler(sample_steps=4)
|
2021-04-09 17:40:37 +08:00
|
|
|
msg = re.escape(
|
|
|
|
|
"If sample_steps is not in [1, 2, 3], you need to provide sample_interval"
|
|
|
|
|
)
|
|
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
|
|
|
transform.fit(X)
|
2014-04-18 02:50:07 +08:00
|
|
|
|
2014-04-17 06:57:26 +08:00
|
|
|
# test that the sample interval is set correctly
|
2014-04-18 02:50:07 +08:00
|
|
|
sample_steps_available = [1, 2, 3]
|
2014-04-17 06:57:26 +08:00
|
|
|
for sample_steps in sample_steps_available:
|
2014-04-18 02:50:07 +08:00
|
|
|
|
2014-04-17 06:57:26 +08:00
|
|
|
# test that the sample_interval is initialized correctly
|
|
|
|
|
transform = AdditiveChi2Sampler(sample_steps=sample_steps)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert transform.sample_interval is None
|
2014-04-18 02:50:07 +08:00
|
|
|
|
2014-04-17 06:57:26 +08:00
|
|
|
# test that the sample_interval is changed in the fit method
|
|
|
|
|
transform.fit(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert transform.sample_interval_ is not None
|
2014-04-18 02:50:07 +08:00
|
|
|
|
2014-04-17 06:57:26 +08:00
|
|
|
# test that the sample_interval is set correctly
|
|
|
|
|
sample_interval = 0.3
|
2014-04-18 02:50:07 +08:00
|
|
|
transform = AdditiveChi2Sampler(sample_steps=4, sample_interval=sample_interval)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert transform.sample_interval == sample_interval
|
2014-04-17 06:57:26 +08:00
|
|
|
transform.fit(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert transform.sample_interval_ == sample_interval
|
2012-12-13 04:49:40 +08:00
|
|
|
|
2011-11-21 02:55:30 +08:00
|
|
|
|
2011-11-12 01:58:24 +08:00
|
|
|
def test_skewed_chi2_sampler():
|
2015-03-21 13:22:08 +08:00
|
|
|
# test that RBFSampler approximates kernel on random data
|
2011-11-12 01:58:24 +08:00
|
|
|
|
|
|
|
|
# compute exact kernel
|
|
|
|
|
c = 0.03
|
2017-05-19 02:17:10 +08:00
|
|
|
# set on negative component but greater than c to ensure that the kernel
|
|
|
|
|
# approximation is valid on the group (-c; +\infty) endowed with the skewed
|
|
|
|
|
# multiplication.
|
|
|
|
|
Y[0, 0] = -c / 2.0
|
|
|
|
|
|
2015-12-08 02:13:40 +08:00
|
|
|
# abbreviations for easier formula
|
2011-11-12 01:58:24 +08:00
|
|
|
X_c = (X + c)[:, np.newaxis, :]
|
|
|
|
|
Y_c = (Y + c)[np.newaxis, :, :]
|
|
|
|
|
|
|
|
|
|
# we do it in log-space in the hope that it's more stable
|
|
|
|
|
# this array is n_samples_x x n_samples_y big x n_features
|
2012-12-13 04:49:40 +08:00
|
|
|
log_kernel = (
|
|
|
|
|
(np.log(X_c) / 2.0) + (np.log(Y_c) / 2.0) + np.log(2.0) - np.log(X_c + Y_c)
|
|
|
|
|
)
|
2011-11-12 01:58:24 +08:00
|
|
|
# reduce to n_samples_x x n_samples_y by summing over features in log-space
|
|
|
|
|
kernel = np.exp(log_kernel.sum(axis=2))
|
|
|
|
|
|
2013-09-13 22:29:42 +08:00
|
|
|
# approximate kernel mapping
|
2011-12-24 02:12:52 +08:00
|
|
|
transform = SkewedChi2Sampler(skewedness=c, n_components=1000, random_state=42)
|
2011-11-12 01:58:24 +08:00
|
|
|
X_trans = transform.fit_transform(X)
|
|
|
|
|
Y_trans = transform.transform(Y)
|
2012-12-13 04:49:40 +08:00
|
|
|
|
2011-11-12 01:58:24 +08:00
|
|
|
kernel_approx = np.dot(X_trans, Y_trans.T)
|
2012-10-25 14:31:35 +08:00
|
|
|
assert_array_almost_equal(kernel, kernel_approx, 1)
|
2018-11-28 09:16:26 +08:00
|
|
|
assert np.isfinite(kernel).all(), "NaNs found in the Gram matrix"
|
|
|
|
|
assert np.isfinite(kernel_approx).all(), "NaNs found in the approximate Gram matrix"
|
2011-11-12 01:58:24 +08:00
|
|
|
|
2017-05-19 02:17:10 +08:00
|
|
|
# test error is raised on when inputs contains values smaller than -c
|
2012-12-13 04:49:40 +08:00
|
|
|
Y_neg = Y.copy()
|
2017-05-19 02:17:10 +08:00
|
|
|
Y_neg[0, 0] = -c * 2.0
|
2021-04-09 17:40:37 +08:00
|
|
|
msg = "X may not contain entries smaller than -skewedness"
|
|
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
|
|
|
transform.transform(Y_neg)
|
2012-12-13 04:49:40 +08:00
|
|
|
|
2011-12-24 02:12:52 +08:00
|
|
|
|
2020-02-01 19:29:09 +08:00
|
|
|
def test_additive_chi2_sampler_exceptions():
|
|
|
|
|
"""Ensures correct error message"""
|
|
|
|
|
transformer = AdditiveChi2Sampler()
|
|
|
|
|
X_neg = X.copy()
|
|
|
|
|
X_neg[0, 0] = -1
|
|
|
|
|
with pytest.raises(ValueError, match="X in AdditiveChi2Sampler.fit"):
|
|
|
|
|
transformer.fit(X_neg)
|
|
|
|
|
with pytest.raises(ValueError, match="X in AdditiveChi2Sampler.transform"):
|
|
|
|
|
transformer.fit(X)
|
|
|
|
|
transformer.transform(X_neg)
|
|
|
|
|
|
|
|
|
|
|
2011-11-12 01:58:24 +08:00
|
|
|
def test_rbf_sampler():
|
2015-03-21 13:22:08 +08:00
|
|
|
# test that RBFSampler approximates kernel on random data
|
2011-11-12 01:58:24 +08:00
|
|
|
# compute exact kernel
|
|
|
|
|
gamma = 10.0
|
2012-01-10 12:35:15 +08:00
|
|
|
kernel = rbf_kernel(X, Y, gamma=gamma)
|
2011-11-12 01:58:24 +08:00
|
|
|
|
2013-09-13 22:29:42 +08:00
|
|
|
# approximate kernel mapping
|
2011-12-19 23:31:50 +08:00
|
|
|
rbf_transform = RBFSampler(gamma=gamma, n_components=1000, random_state=42)
|
2011-11-12 01:58:24 +08:00
|
|
|
X_trans = rbf_transform.fit_transform(X)
|
|
|
|
|
Y_trans = rbf_transform.transform(Y)
|
|
|
|
|
kernel_approx = np.dot(X_trans, Y_trans.T)
|
|
|
|
|
|
2014-09-11 14:59:09 +08:00
|
|
|
error = kernel - kernel_approx
|
2019-07-01 21:13:32 +08:00
|
|
|
assert np.abs(np.mean(error)) <= 0.01 # close to unbiased
|
2014-09-11 14:59:09 +08:00
|
|
|
np.abs(error, out=error)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert np.max(error) <= 0.1 # nothing too far off
|
|
|
|
|
assert np.mean(error) <= 0.05 # mean is fairly close
|
2011-11-12 01:58:24 +08:00
|
|
|
|
2011-12-24 17:38:58 +08:00
|
|
|
|
|
|
|
|
def test_input_validation():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Regression test: kernel approx. transformers should work on lists
|
|
|
|
|
# No assertions; the old versions would simply crash
|
2011-12-24 17:38:58 +08:00
|
|
|
X = [[1, 2], [3, 4], [5, 6]]
|
|
|
|
|
AdditiveChi2Sampler().fit(X).transform(X)
|
|
|
|
|
SkewedChi2Sampler().fit(X).transform(X)
|
|
|
|
|
RBFSampler().fit(X).transform(X)
|
|
|
|
|
|
|
|
|
|
X = csr_matrix(X)
|
|
|
|
|
RBFSampler().fit(X).transform(X)
|
|
|
|
|
|
|
|
|
|
|
2013-03-18 19:50:19 +08:00
|
|
|
def test_nystroem_approximation():
|
2012-11-27 06:39:43 +08:00
|
|
|
# some basic tests
|
|
|
|
|
rnd = np.random.RandomState(0)
|
|
|
|
|
X = rnd.uniform(size=(10, 4))
|
|
|
|
|
|
|
|
|
|
# With n_components = n_samples this is exact
|
|
|
|
|
X_transformed = Nystroem(n_components=X.shape[0]).fit_transform(X)
|
|
|
|
|
K = rbf_kernel(X)
|
|
|
|
|
assert_array_almost_equal(np.dot(X_transformed, X_transformed.T), K)
|
|
|
|
|
|
|
|
|
|
trans = Nystroem(n_components=2, random_state=rnd)
|
|
|
|
|
X_transformed = trans.fit(X).transform(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert X_transformed.shape == (X.shape[0], 2)
|
2012-11-27 06:39:43 +08:00
|
|
|
|
|
|
|
|
# test callable kernel
|
2020-02-16 21:41:26 +08:00
|
|
|
trans = Nystroem(n_components=2, kernel=_linear_kernel, random_state=rnd)
|
2012-11-27 06:39:43 +08:00
|
|
|
X_transformed = trans.fit(X).transform(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert X_transformed.shape == (X.shape[0], 2)
|
2012-11-27 06:39:43 +08:00
|
|
|
|
2013-03-18 10:08:01 +08:00
|
|
|
# test that available kernels fit and transform
|
|
|
|
|
kernels_available = kernel_metrics()
|
|
|
|
|
for kern in kernels_available:
|
|
|
|
|
trans = Nystroem(n_components=2, kernel=kern, random_state=rnd)
|
|
|
|
|
X_transformed = trans.fit(X).transform(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert X_transformed.shape == (X.shape[0], 2)
|
2013-03-18 10:08:01 +08:00
|
|
|
|
2012-11-27 06:39:43 +08:00
|
|
|
|
2017-07-01 00:16:10 +08:00
|
|
|
def test_nystroem_default_parameters():
|
|
|
|
|
rnd = np.random.RandomState(42)
|
|
|
|
|
X = rnd.uniform(size=(10, 4))
|
|
|
|
|
|
|
|
|
|
# rbf kernel should behave as gamma=None by default
|
|
|
|
|
# aka gamma = 1 / n_features
|
|
|
|
|
nystroem = Nystroem(n_components=10)
|
|
|
|
|
X_transformed = nystroem.fit_transform(X)
|
|
|
|
|
K = rbf_kernel(X, gamma=None)
|
|
|
|
|
K2 = np.dot(X_transformed, X_transformed.T)
|
|
|
|
|
assert_array_almost_equal(K, K2)
|
|
|
|
|
|
|
|
|
|
# chi2 kernel should behave as gamma=1 by default
|
|
|
|
|
nystroem = Nystroem(kernel="chi2", n_components=10)
|
|
|
|
|
X_transformed = nystroem.fit_transform(X)
|
|
|
|
|
K = chi2_kernel(X, gamma=1)
|
|
|
|
|
K2 = np.dot(X_transformed, X_transformed.T)
|
|
|
|
|
assert_array_almost_equal(K, K2)
|
|
|
|
|
|
|
|
|
|
|
2015-01-30 01:11:52 +08:00
|
|
|
def test_nystroem_singular_kernel():
|
|
|
|
|
# test that nystroem works with singular kernel matrix
|
|
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X = rng.rand(10, 20)
|
|
|
|
|
X = np.vstack([X] * 2) # duplicate samples
|
|
|
|
|
|
|
|
|
|
gamma = 100
|
|
|
|
|
N = Nystroem(gamma=gamma, n_components=X.shape[0]).fit(X)
|
|
|
|
|
X_transformed = N.transform(X)
|
|
|
|
|
|
|
|
|
|
K = rbf_kernel(X, gamma=gamma)
|
|
|
|
|
|
|
|
|
|
assert_array_almost_equal(K, np.dot(X_transformed, X_transformed.T))
|
2018-11-11 09:05:34 +08:00
|
|
|
assert np.all(np.isfinite(Y))
|
2015-01-30 01:11:52 +08:00
|
|
|
|
|
|
|
|
|
2013-03-18 19:50:19 +08:00
|
|
|
def test_nystroem_poly_kernel_params():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Non-regression: Nystroem should pass other parameters beside gamma.
|
2013-03-18 19:50:19 +08:00
|
|
|
rnd = np.random.RandomState(37)
|
|
|
|
|
X = rnd.uniform(size=(10, 4))
|
|
|
|
|
|
|
|
|
|
K = polynomial_kernel(X, degree=3.1, coef0=0.1)
|
|
|
|
|
nystroem = Nystroem(
|
|
|
|
|
kernel="polynomial", n_components=X.shape[0], degree=3.1, coef0=0.1
|
|
|
|
|
)
|
|
|
|
|
X_transformed = nystroem.fit_transform(X)
|
|
|
|
|
assert_array_almost_equal(np.dot(X_transformed, X_transformed.T), K)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_nystroem_callable():
|
2015-03-21 13:22:08 +08:00
|
|
|
# Test Nystroem on a callable.
|
2013-03-18 19:50:19 +08:00
|
|
|
rnd = np.random.RandomState(42)
|
|
|
|
|
n_samples = 10
|
|
|
|
|
X = rnd.uniform(size=(n_samples, 4))
|
|
|
|
|
|
|
|
|
|
def logging_histogram_kernel(x, y, log):
|
|
|
|
|
"""Histogram kernel that writes to a log."""
|
|
|
|
|
log.append(1)
|
|
|
|
|
return np.minimum(x, y).sum()
|
|
|
|
|
|
|
|
|
|
kernel_log = []
|
2014-03-05 20:13:57 +08:00
|
|
|
X = list(X) # test input validation
|
2013-03-18 19:50:19 +08:00
|
|
|
Nystroem(
|
|
|
|
|
kernel=logging_histogram_kernel,
|
|
|
|
|
n_components=(n_samples - 1),
|
|
|
|
|
kernel_params={"log": kernel_log},
|
|
|
|
|
).fit(X)
|
2019-07-01 21:13:32 +08:00
|
|
|
assert len(kernel_log) == n_samples * (n_samples - 1) / 2
|
2017-07-01 00:16:10 +08:00
|
|
|
|
2021-07-13 16:53:42 +08:00
|
|
|
# if degree, gamma or coef0 is passed, we raise a ValueError
|
2018-10-12 02:56:37 +08:00
|
|
|
msg = "Don't pass gamma, coef0 or degree to Nystroem"
|
2017-07-01 00:16:10 +08:00
|
|
|
params = ({"gamma": 1}, {"coef0": 1}, {"degree": 2})
|
|
|
|
|
for param in params:
|
2021-07-13 16:53:42 +08:00
|
|
|
ny = Nystroem(kernel=_linear_kernel, n_components=(n_samples - 1), **param)
|
2018-10-12 02:56:37 +08:00
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
|
|
|
ny.fit(X)
|
2019-08-29 05:43:48 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_nystroem_precomputed_kernel():
|
|
|
|
|
# Non-regression: test Nystroem on precomputed kernel.
|
|
|
|
|
# PR - 14706
|
|
|
|
|
rnd = np.random.RandomState(12)
|
|
|
|
|
X = rnd.uniform(size=(10, 4))
|
|
|
|
|
|
|
|
|
|
K = polynomial_kernel(X, degree=2, coef0=0.1)
|
|
|
|
|
nystroem = Nystroem(kernel="precomputed", n_components=X.shape[0])
|
|
|
|
|
X_transformed = nystroem.fit_transform(K)
|
|
|
|
|
assert_array_almost_equal(np.dot(X_transformed, X_transformed.T), K)
|
|
|
|
|
|
|
|
|
|
# if degree, gamma or coef0 is passed, we raise a ValueError
|
|
|
|
|
msg = "Don't pass gamma, coef0 or degree to Nystroem"
|
|
|
|
|
params = ({"gamma": 1}, {"coef0": 1}, {"degree": 2})
|
|
|
|
|
for param in params:
|
|
|
|
|
ny = Nystroem(kernel="precomputed", n_components=X.shape[0], **param)
|
|
|
|
|
with pytest.raises(ValueError, match=msg):
|
|
|
|
|
ny.fit(K)
|
2021-09-02 22:14:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_nystroem_component_indices():
|
|
|
|
|
"""Check that `component_indices_` corresponds to the subset of
|
|
|
|
|
training points used to construct the feature map.
|
|
|
|
|
Non-regression test for:
|
|
|
|
|
https://github.com/scikit-learn/scikit-learn/issues/20474
|
|
|
|
|
"""
|
|
|
|
|
X, _ = make_classification(n_samples=100, n_features=20)
|
|
|
|
|
feature_map_nystroem = Nystroem(
|
|
|
|
|
n_components=10,
|
|
|
|
|
random_state=0,
|
|
|
|
|
)
|
|
|
|
|
feature_map_nystroem.fit(X)
|
|
|
|
|
assert feature_map_nystroem.component_indices_.shape == (10,)
|
2022-03-08 21:01:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
"Estimator", [PolynomialCountSketch, RBFSampler, SkewedChi2Sampler, Nystroem]
|
|
|
|
|
)
|
|
|
|
|
def test_get_feature_names_out(Estimator):
|
|
|
|
|
"""Check get_feature_names_out"""
|
|
|
|
|
est = Estimator().fit(X)
|
|
|
|
|
X_trans = est.transform(X)
|
|
|
|
|
|
|
|
|
|
names_out = est.get_feature_names_out()
|
|
|
|
|
class_name = Estimator.__name__.lower()
|
|
|
|
|
expected_names = [f"{class_name}{i}" for i in range(X_trans.shape[1])]
|
|
|
|
|
assert_array_equal(names_out, expected_names)
|
2022-03-08 22:02:18 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_additivechi2sampler_get_feature_names_out():
|
|
|
|
|
"""Check get_feature_names_out for for AdditiveChi2Sampler."""
|
|
|
|
|
rng = np.random.RandomState(0)
|
|
|
|
|
X = rng.random_sample(size=(300, 3))
|
|
|
|
|
|
|
|
|
|
chi2_sampler = AdditiveChi2Sampler(sample_steps=3).fit(X)
|
|
|
|
|
input_names = ["f0", "f1", "f2"]
|
|
|
|
|
suffixes = [
|
|
|
|
|
"f0_sqrt",
|
|
|
|
|
"f1_sqrt",
|
|
|
|
|
"f2_sqrt",
|
|
|
|
|
"f0_cos1",
|
|
|
|
|
"f1_cos1",
|
|
|
|
|
"f2_cos1",
|
|
|
|
|
"f0_sin1",
|
|
|
|
|
"f1_sin1",
|
|
|
|
|
"f2_sin1",
|
|
|
|
|
"f0_cos2",
|
|
|
|
|
"f1_cos2",
|
|
|
|
|
"f2_cos2",
|
|
|
|
|
"f0_sin2",
|
|
|
|
|
"f1_sin2",
|
|
|
|
|
"f2_sin2",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
names_out = chi2_sampler.get_feature_names_out(input_features=input_names)
|
|
|
|
|
expected_names = [f"additivechi2sampler_{suffix}" for suffix in suffixes]
|
|
|
|
|
assert_array_equal(names_out, expected_names)
|