From 67e4ea478c9d46c69daa1817680d0376a24476a3 Mon Sep 17 00:00:00 2001 From: Roman Yurchak Date: Sat, 26 May 2018 15:34:59 +0200 Subject: [PATCH 1/3] Pytest parametrize sklearn.feature_extraction --- .../tests/test_dict_vectorizer.py | 52 +++---- sklearn/feature_extraction/tests/test_text.py | 136 +++++++++--------- .../tests/test_feature_select.py | 5 - .../tests/test_mutual_info.py | 5 - 4 files changed, 93 insertions(+), 105 deletions(-) diff --git a/sklearn/feature_extraction/tests/test_dict_vectorizer.py b/sklearn/feature_extraction/tests/test_dict_vectorizer.py index 72ebbb1653c41..66d678421e90b 100644 --- a/sklearn/feature_extraction/tests/test_dict_vectorizer.py +++ b/sklearn/feature_extraction/tests/test_dict_vectorizer.py @@ -5,8 +5,10 @@ from random import Random import numpy as np import scipy.sparse as sp - from numpy.testing import assert_array_equal + +import pytest + from sklearn.utils.testing import (assert_equal, assert_in, assert_false, assert_true) @@ -14,34 +16,34 @@ from sklearn.feature_selection import SelectKBest, chi2 -def test_dictvectorizer(): +@pytest.mark.parametrize('sparse', (True, False)) +@pytest.mark.parametrize('dtype', (int, np.float32, np.int16)) +@pytest.mark.parametrize('sort', (True, False)) +@pytest.mark.parametrize('iterable', (True, False)) +def test_dictvectorizer(sparse, dtype, sort, iterable): D = [{"foo": 1, "bar": 3}, {"bar": 4, "baz": 2}, {"bar": 1, "quux": 1, "quuux": 2}] - for sparse in (True, False): - for dtype in (int, np.float32, np.int16): - for sort in (True, False): - for iterable in (True, False): - v = DictVectorizer(sparse=sparse, dtype=dtype, sort=sort) - X = v.fit_transform(iter(D) if iterable else D) - - assert_equal(sp.issparse(X), sparse) - assert_equal(X.shape, (3, 5)) - assert_equal(X.sum(), 14) - assert_equal(v.inverse_transform(X), D) - - if sparse: - # CSR matrices can't be compared for equality - assert_array_equal(X.A, v.transform(iter(D) if iterable - else D).A) - else: - assert_array_equal(X, v.transform(iter(D) if iterable - else D)) - - if sort: - assert_equal(v.feature_names_, - sorted(v.feature_names_)) + v = DictVectorizer(sparse=sparse, dtype=dtype, sort=sort) + X = v.fit_transform(iter(D) if iterable else D) + + assert_equal(sp.issparse(X), sparse) + assert_equal(X.shape, (3, 5)) + assert_equal(X.sum(), 14) + assert_equal(v.inverse_transform(X), D) + + if sparse: + # CSR matrices can't be compared for equality + assert_array_equal(X.A, v.transform(iter(D) if iterable + else D).A) + else: + assert_array_equal(X, v.transform(iter(D) if iterable + else D)) + + if sort: + assert_equal(v.feature_names_, + sorted(v.feature_names_)) def test_feature_selection(): diff --git a/sklearn/feature_extraction/tests/test_text.py b/sklearn/feature_extraction/tests/test_text.py index ff4dd6bd86a79..b0209f6bbe3ac 100644 --- a/sklearn/feature_extraction/tests/test_text.py +++ b/sklearn/feature_extraction/tests/test_text.py @@ -115,42 +115,42 @@ def test_to_ascii(): assert_equal(strip_accents_ascii(a), expected) -def test_word_analyzer_unigrams(): - for Vectorizer in (CountVectorizer, HashingVectorizer): - wa = Vectorizer(strip_accents='ascii').build_analyzer() - text = ("J'ai mang\xe9 du kangourou ce midi, " - "c'\xe9tait pas tr\xeas bon.") - expected = ['ai', 'mange', 'du', 'kangourou', 'ce', 'midi', - 'etait', 'pas', 'tres', 'bon'] - assert_equal(wa(text), expected) - - text = "This is a test, really.\n\n I met Harry yesterday." - expected = ['this', 'is', 'test', 'really', 'met', 'harry', - 'yesterday'] - assert_equal(wa(text), expected) - - wa = Vectorizer(input='file').build_analyzer() - text = StringIO("This is a test with a file-like object!") - expected = ['this', 'is', 'test', 'with', 'file', 'like', - 'object'] - assert_equal(wa(text), expected) - - # with custom preprocessor - wa = Vectorizer(preprocessor=uppercase).build_analyzer() - text = ("J'ai mang\xe9 du kangourou ce midi, " - " c'\xe9tait pas tr\xeas bon.") - expected = ['AI', 'MANGE', 'DU', 'KANGOUROU', 'CE', 'MIDI', - 'ETAIT', 'PAS', 'TRES', 'BON'] - assert_equal(wa(text), expected) - - # with custom tokenizer - wa = Vectorizer(tokenizer=split_tokenize, - strip_accents='ascii').build_analyzer() - text = ("J'ai mang\xe9 du kangourou ce midi, " - "c'\xe9tait pas tr\xeas bon.") - expected = ["j'ai", 'mange', 'du', 'kangourou', 'ce', 'midi,', - "c'etait", 'pas', 'tres', 'bon.'] - assert_equal(wa(text), expected) +@pytest.mark.parametrize('Vectorizer', (CountVectorizer, HashingVectorizer)) +def test_word_analyzer_unigrams(Vectorizer): + wa = Vectorizer(strip_accents='ascii').build_analyzer() + text = ("J'ai mang\xe9 du kangourou ce midi, " + "c'\xe9tait pas tr\xeas bon.") + expected = ['ai', 'mange', 'du', 'kangourou', 'ce', 'midi', + 'etait', 'pas', 'tres', 'bon'] + assert_equal(wa(text), expected) + + text = "This is a test, really.\n\n I met Harry yesterday." + expected = ['this', 'is', 'test', 'really', 'met', 'harry', + 'yesterday'] + assert_equal(wa(text), expected) + + wa = Vectorizer(input='file').build_analyzer() + text = StringIO("This is a test with a file-like object!") + expected = ['this', 'is', 'test', 'with', 'file', 'like', + 'object'] + assert_equal(wa(text), expected) + + # with custom preprocessor + wa = Vectorizer(preprocessor=uppercase).build_analyzer() + text = ("J'ai mang\xe9 du kangourou ce midi, " + " c'\xe9tait pas tr\xeas bon.") + expected = ['AI', 'MANGE', 'DU', 'KANGOUROU', 'CE', 'MIDI', + 'ETAIT', 'PAS', 'TRES', 'BON'] + assert_equal(wa(text), expected) + + # with custom tokenizer + wa = Vectorizer(tokenizer=split_tokenize, + strip_accents='ascii').build_analyzer() + text = ("J'ai mang\xe9 du kangourou ce midi, " + "c'\xe9tait pas tr\xeas bon.") + expected = ["j'ai", 'mange', 'du', 'kangourou', 'ce', 'midi,', + "c'etait", 'pas', 'tres', 'bon.'] + assert_equal(wa(text), expected) def test_word_analyzer_unigrams_and_bigrams(): @@ -574,22 +574,17 @@ def test_feature_names(): assert_equal(idx, cv.vocabulary_.get(name)) -def test_vectorizer_max_features(): - vec_factories = ( - CountVectorizer, - TfidfVectorizer, - ) - +@pytest.mark.parametrize('Vectorizer', (CountVectorizer, TfidfVectorizer)) +def test_vectorizer_max_features(Vectorizer): expected_vocabulary = set(['burger', 'beer', 'salad', 'pizza']) expected_stop_words = set([u'celeri', u'tomato', u'copyright', u'coke', u'sparkling', u'water', u'the']) - for vec_factory in vec_factories: - # test bounded number of extracted features - vectorizer = vec_factory(max_df=0.6, max_features=4) - vectorizer.fit(ALL_FOOD_DOCS) - assert_equal(set(vectorizer.vocabulary_), expected_vocabulary) - assert_equal(vectorizer.stop_words_, expected_stop_words) + # test bounded number of extracted features + vectorizer = Vectorizer(max_df=0.6, max_features=4) + vectorizer.fit(ALL_FOOD_DOCS) + assert_equal(set(vectorizer.vocabulary_), expected_vocabulary) + assert_equal(vectorizer.stop_words_, expected_stop_words) def test_count_vectorizer_max_features(): @@ -713,23 +708,24 @@ def test_hashed_binary_occurrences(): assert_equal(X.dtype, np.float64) -def test_vectorizer_inverse_transform(): +@pytest.mark.parametrize('Vectorizer', (CountVectorizer, TfidfVectorizer)) +def test_vectorizer_inverse_transform(Vectorizer): # raw documents data = ALL_FOOD_DOCS - for vectorizer in (TfidfVectorizer(), CountVectorizer()): - transformed_data = vectorizer.fit_transform(data) - inversed_data = vectorizer.inverse_transform(transformed_data) - analyze = vectorizer.build_analyzer() - for doc, inversed_terms in zip(data, inversed_data): - terms = np.sort(np.unique(analyze(doc))) - inversed_terms = np.sort(np.unique(inversed_terms)) - assert_array_equal(terms, inversed_terms) - - # Test that inverse_transform also works with numpy arrays - transformed_data = transformed_data.toarray() - inversed_data2 = vectorizer.inverse_transform(transformed_data) - for terms, terms2 in zip(inversed_data, inversed_data2): - assert_array_equal(np.sort(terms), np.sort(terms2)) + vectorizer = Vectorizer() + transformed_data = vectorizer.fit_transform(data) + inversed_data = vectorizer.inverse_transform(transformed_data) + analyze = vectorizer.build_analyzer() + for doc, inversed_terms in zip(data, inversed_data): + terms = np.sort(np.unique(analyze(doc))) + inversed_terms = np.sort(np.unique(inversed_terms)) + assert_array_equal(terms, inversed_terms) + + # Test that inverse_transform also works with numpy arrays + transformed_data = transformed_data.toarray() + inversed_data2 = vectorizer.inverse_transform(transformed_data) + for terms, terms2 in zip(inversed_data, inversed_data2): + assert_array_equal(np.sort(terms), np.sort(terms2)) def test_count_vectorizer_pipeline_grid_selection(): @@ -1030,16 +1026,16 @@ def test_vectorizer_vocab_clone(): assert_equal(vect_vocab_clone.vocabulary_, vect_vocab.vocabulary_) -def test_vectorizer_string_object_as_input(): +@pytest.mark.parametrize('Vectorizer', + (CountVectorizer, TfidfVectorizer, HashingVectorizer)) +def test_vectorizer_string_object_as_input(Vectorizer): message = ("Iterable over raw text documents expected, " "string object received.") - for vec in [CountVectorizer(), TfidfVectorizer(), HashingVectorizer()]: - assert_raise_message( + vec = Vectorizer() + assert_raise_message( ValueError, message, vec.fit_transform, "hello world!") - assert_raise_message( - ValueError, message, vec.fit, "hello world!") - assert_raise_message( - ValueError, message, vec.transform, "hello world!") + assert_raise_message(ValueError, message, vec.fit, "hello world!") + assert_raise_message(ValueError, message, vec.transform, "hello world!") @pytest.mark.parametrize("vec", [ diff --git a/sklearn/feature_selection/tests/test_feature_select.py b/sklearn/feature_selection/tests/test_feature_select.py index d3f1eca333cd1..14e621473090a 100644 --- a/sklearn/feature_selection/tests/test_feature_select.py +++ b/sklearn/feature_selection/tests/test_feature_select.py @@ -7,7 +7,6 @@ import numpy as np from scipy import stats, sparse -from numpy.testing import run_module_suite from sklearn.utils.testing import assert_equal from sklearn.utils.testing import assert_almost_equal from sklearn.utils.testing import assert_raises @@ -670,7 +669,3 @@ def test_mutual_info_regression(): gtruth = np.zeros(10) gtruth[:2] = 1 assert_array_equal(support, gtruth) - - -if __name__ == '__main__': - run_module_suite() diff --git a/sklearn/feature_selection/tests/test_mutual_info.py b/sklearn/feature_selection/tests/test_mutual_info.py index 615abf1c5b0a0..f05e0b52b3707 100644 --- a/sklearn/feature_selection/tests/test_mutual_info.py +++ b/sklearn/feature_selection/tests/test_mutual_info.py @@ -1,7 +1,6 @@ from __future__ import division import numpy as np -from numpy.testing import run_module_suite from scipy.sparse import csr_matrix from sklearn.utils import check_random_state @@ -200,7 +199,3 @@ def test_mutual_info_options(): assert_array_equal(mi_3, mi_4) assert_false(np.allclose(mi_1, mi_3)) - - -if __name__ == '__main__': - run_module_suite() From c876b2915927fe027890bf6a02a3b9897eb88f0a Mon Sep 17 00:00:00 2001 From: Roman Yurchak Date: Sat, 26 May 2018 15:37:08 +0200 Subject: [PATCH 2/3] Pytest parametrize sklearn.gaussian_process --- .../tests/test_gaussian_process.py | 17 +- sklearn/gaussian_process/tests/test_gpc.py | 124 +++---- sklearn/gaussian_process/tests/test_gpr.py | 264 +++++++------ .../gaussian_process/tests/test_kernels.py | 348 +++++++++--------- 4 files changed, 377 insertions(+), 376 deletions(-) diff --git a/sklearn/gaussian_process/tests/test_gaussian_process.py b/sklearn/gaussian_process/tests/test_gaussian_process.py index 37d872fc99fb5..6d6fa3ab81193 100644 --- a/sklearn/gaussian_process/tests/test_gaussian_process.py +++ b/sklearn/gaussian_process/tests/test_gaussian_process.py @@ -7,6 +7,8 @@ import numpy as np +import pytest + from sklearn.gaussian_process import GaussianProcess from sklearn.gaussian_process import regression_models as regression from sklearn.gaussian_process import correlation_models as correlation @@ -100,16 +102,17 @@ def test_wrong_number_of_outputs(): assert_raises(ValueError, gp.fit, [[1, 2, 3], [4, 5, 6]], [1, 2, 3]) -def test_more_builtin_correlation_models(random_start=1): +@pytest.mark.parametrize( + 'corr', + ['absolute_exponential', 'squared_exponential', 'cubic', 'linear']) +def test_more_builtin_correlation_models(corr): # Repeat test_1d and test_2d for several built-in correlation # models specified as strings. - all_corr = ['absolute_exponential', 'squared_exponential', 'cubic', - 'linear'] + random_start = 1 - for corr in all_corr: - test_1d(regr='constant', corr=corr, random_start=random_start) - test_2d(regr='constant', corr=corr, random_start=random_start) - test_2d_2d(regr='constant', corr=corr, random_start=random_start) + test_1d(regr='constant', corr=corr, random_start=random_start) + test_2d(regr='constant', corr=corr, random_start=random_start) + test_2d_2d(regr='constant', corr=corr, random_start=random_start) def test_ordinary_kriging(): diff --git a/sklearn/gaussian_process/tests/test_gpc.py b/sklearn/gaussian_process/tests/test_gpc.py index ba98cddb77f79..25aaa05fac3a8 100644 --- a/sklearn/gaussian_process/tests/test_gpc.py +++ b/sklearn/gaussian_process/tests/test_gpc.py @@ -7,6 +7,8 @@ from scipy.optimize import approx_fprime +import pytest + from sklearn.gaussian_process import GaussianProcessClassifier from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C @@ -31,62 +33,60 @@ def f(x): RBF(length_scale=1.0, length_scale_bounds=(1e-3, 1e3)), C(1.0, (1e-2, 1e2)) * RBF(length_scale=1.0, length_scale_bounds=(1e-3, 1e3))] +non_fixed_kernels = [kernel for kernel in kernels + if kernel != fixed_kernel] -def test_predict_consistent(): +@pytest.mark.parametrize('kernel', kernels) +def test_predict_consistent(kernel): # Check binary predict decision has also predicted probability above 0.5. - for kernel in kernels: - gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) - assert_array_equal(gpc.predict(X), - gpc.predict_proba(X)[:, 1] >= 0.5) + gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) + assert_array_equal(gpc.predict(X), + gpc.predict_proba(X)[:, 1] >= 0.5) -def test_lml_improving(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_lml_improving(kernel): # Test that hyperparameter-tuning improves log-marginal likelihood. - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) - assert_greater(gpc.log_marginal_likelihood(gpc.kernel_.theta), - gpc.log_marginal_likelihood(kernel.theta)) + gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) + assert_greater(gpc.log_marginal_likelihood(gpc.kernel_.theta), + gpc.log_marginal_likelihood(kernel.theta)) -def test_lml_precomputed(): +@pytest.mark.parametrize('kernel', kernels) +def test_lml_precomputed(kernel): # Test that lml of optimized kernel is stored correctly. - for kernel in kernels: - gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) - assert_almost_equal(gpc.log_marginal_likelihood(gpc.kernel_.theta), - gpc.log_marginal_likelihood(), 7) + gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) + assert_almost_equal(gpc.log_marginal_likelihood(gpc.kernel_.theta), + gpc.log_marginal_likelihood(), 7) -def test_converged_to_local_maximum(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_converged_to_local_maximum(kernel): # Test that we are in local maximum after hyperparameter-optimization. - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) + gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) - lml, lml_gradient = \ - gpc.log_marginal_likelihood(gpc.kernel_.theta, True) + lml, lml_gradient = \ + gpc.log_marginal_likelihood(gpc.kernel_.theta, True) - assert_true(np.all((np.abs(lml_gradient) < 1e-4) | - (gpc.kernel_.theta == gpc.kernel_.bounds[:, 0]) | - (gpc.kernel_.theta == gpc.kernel_.bounds[:, 1]))) + assert_true(np.all((np.abs(lml_gradient) < 1e-4) | + (gpc.kernel_.theta == gpc.kernel_.bounds[:, 0]) | + (gpc.kernel_.theta == gpc.kernel_.bounds[:, 1]))) -def test_lml_gradient(): +@pytest.mark.parametrize('kernel', kernels) +def test_lml_gradient(kernel): # Compare analytic and numeric gradient of log marginal likelihood. - for kernel in kernels: - gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) + gpc = GaussianProcessClassifier(kernel=kernel).fit(X, y) - lml, lml_gradient = gpc.log_marginal_likelihood(kernel.theta, True) - lml_gradient_approx = \ - approx_fprime(kernel.theta, - lambda theta: gpc.log_marginal_likelihood(theta, - False), - 1e-10) + lml, lml_gradient = gpc.log_marginal_likelihood(kernel.theta, True) + lml_gradient_approx = \ + approx_fprime(kernel.theta, + lambda theta: gpc.log_marginal_likelihood(theta, + False), + 1e-10) - assert_almost_equal(lml_gradient, lml_gradient_approx, 3) + assert_almost_equal(lml_gradient, lml_gradient_approx, 3) def test_random_starts(): @@ -110,7 +110,8 @@ def test_random_starts(): last_lml = lml -def test_custom_optimizer(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_custom_optimizer(kernel): # Test that GPC can use externally defined optimizers. # Define a dummy optimizer that simply tests 50 random hyperparameters def optimizer(obj_func, initial_theta, bounds): @@ -125,38 +126,35 @@ def optimizer(obj_func, initial_theta, bounds): theta_opt, func_min = theta, f return theta_opt, func_min - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpc = GaussianProcessClassifier(kernel=kernel, optimizer=optimizer) - gpc.fit(X, y_mc) - # Checks that optimizer improved marginal likelihood - assert_greater(gpc.log_marginal_likelihood(gpc.kernel_.theta), - gpc.log_marginal_likelihood(kernel.theta)) + gpc = GaussianProcessClassifier(kernel=kernel, optimizer=optimizer) + gpc.fit(X, y_mc) + # Checks that optimizer improved marginal likelihood + assert_greater(gpc.log_marginal_likelihood(gpc.kernel_.theta), + gpc.log_marginal_likelihood(kernel.theta)) -def test_multi_class(): +@pytest.mark.parametrize('kernel', kernels) +def test_multi_class(kernel): # Test GPC for multi-class classification problems. - for kernel in kernels: - gpc = GaussianProcessClassifier(kernel=kernel) - gpc.fit(X, y_mc) + gpc = GaussianProcessClassifier(kernel=kernel) + gpc.fit(X, y_mc) - y_prob = gpc.predict_proba(X2) - assert_almost_equal(y_prob.sum(1), 1) + y_prob = gpc.predict_proba(X2) + assert_almost_equal(y_prob.sum(1), 1) - y_pred = gpc.predict(X2) - assert_array_equal(np.argmax(y_prob, 1), y_pred) + y_pred = gpc.predict(X2) + assert_array_equal(np.argmax(y_prob, 1), y_pred) -def test_multi_class_n_jobs(): +@pytest.mark.parametrize('kernel', kernels) +def test_multi_class_n_jobs(kernel): # Test that multi-class GPC produces identical results with n_jobs>1. - for kernel in kernels: - gpc = GaussianProcessClassifier(kernel=kernel) - gpc.fit(X, y_mc) + gpc = GaussianProcessClassifier(kernel=kernel) + gpc.fit(X, y_mc) - gpc_2 = GaussianProcessClassifier(kernel=kernel, n_jobs=2) - gpc_2.fit(X, y_mc) + gpc_2 = GaussianProcessClassifier(kernel=kernel, n_jobs=2) + gpc_2.fit(X, y_mc) - y_prob = gpc.predict_proba(X2) - y_prob_2 = gpc_2.predict_proba(X2) - assert_almost_equal(y_prob, y_prob_2) + y_prob = gpc.predict_proba(X2) + y_prob_2 = gpc_2.predict_proba(X2) + assert_almost_equal(y_prob, y_prob_2) diff --git a/sklearn/gaussian_process/tests/test_gpr.py b/sklearn/gaussian_process/tests/test_gpr.py index 602b2b88ae9c9..18f82b00fb7f1 100644 --- a/sklearn/gaussian_process/tests/test_gpr.py +++ b/sklearn/gaussian_process/tests/test_gpr.py @@ -7,6 +7,8 @@ from scipy.optimize import approx_fprime +import pytest + from sklearn.gaussian_process import GaussianProcessRegressor from sklearn.gaussian_process.kernels \ import RBF, ConstantKernel as C, WhiteKernel @@ -37,110 +39,106 @@ def f(x): C(0.1, (1e-2, 1e2)) * RBF(length_scale=1.0, length_scale_bounds=(1e-3, 1e3)) + C(1e-5, (1e-5, 1e2))] +non_fixed_kernels = [kernel for kernel in kernels + if kernel != fixed_kernel] -def test_gpr_interpolation(): +@pytest.mark.parametrize('kernel', kernels) +def test_gpr_interpolation(kernel): # Test the interpolating property for different kernels. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - y_pred, y_cov = gpr.predict(X, return_cov=True) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + y_pred, y_cov = gpr.predict(X, return_cov=True) - assert_almost_equal(y_pred, y) - assert_almost_equal(np.diag(y_cov), 0.) + assert_almost_equal(y_pred, y) + assert_almost_equal(np.diag(y_cov), 0.) -def test_lml_improving(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_lml_improving(kernel): # Test that hyperparameter-tuning improves log-marginal likelihood. - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - assert_greater(gpr.log_marginal_likelihood(gpr.kernel_.theta), - gpr.log_marginal_likelihood(kernel.theta)) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + assert_greater(gpr.log_marginal_likelihood(gpr.kernel_.theta), + gpr.log_marginal_likelihood(kernel.theta)) -def test_lml_precomputed(): +@pytest.mark.parametrize('kernel', kernels) +def test_lml_precomputed(kernel): # Test that lml of optimized kernel is stored correctly. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - assert_equal(gpr.log_marginal_likelihood(gpr.kernel_.theta), - gpr.log_marginal_likelihood()) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + assert_equal(gpr.log_marginal_likelihood(gpr.kernel_.theta), + gpr.log_marginal_likelihood()) -def test_converged_to_local_maximum(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_converged_to_local_maximum(kernel): # Test that we are in local maximum after hyperparameter-optimization. - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - lml, lml_gradient = \ - gpr.log_marginal_likelihood(gpr.kernel_.theta, True) + lml, lml_gradient = \ + gpr.log_marginal_likelihood(gpr.kernel_.theta, True) - assert_true(np.all((np.abs(lml_gradient) < 1e-4) | - (gpr.kernel_.theta == gpr.kernel_.bounds[:, 0]) | - (gpr.kernel_.theta == gpr.kernel_.bounds[:, 1]))) + assert_true(np.all((np.abs(lml_gradient) < 1e-4) | + (gpr.kernel_.theta == gpr.kernel_.bounds[:, 0]) | + (gpr.kernel_.theta == gpr.kernel_.bounds[:, 1]))) -def test_solution_inside_bounds(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_solution_inside_bounds(kernel): # Test that hyperparameter-optimization remains in bounds# - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - bounds = gpr.kernel_.bounds - max_ = np.finfo(gpr.kernel_.theta.dtype).max - tiny = 1e-10 - bounds[~np.isfinite(bounds[:, 1]), 1] = max_ + bounds = gpr.kernel_.bounds + max_ = np.finfo(gpr.kernel_.theta.dtype).max + tiny = 1e-10 + bounds[~np.isfinite(bounds[:, 1]), 1] = max_ - assert_array_less(bounds[:, 0], gpr.kernel_.theta + tiny) - assert_array_less(gpr.kernel_.theta, bounds[:, 1] + tiny) + assert_array_less(bounds[:, 0], gpr.kernel_.theta + tiny) + assert_array_less(gpr.kernel_.theta, bounds[:, 1] + tiny) -def test_lml_gradient(): +@pytest.mark.parametrize('kernel', kernels) +def test_lml_gradient(kernel): # Compare analytic and numeric gradient of log marginal likelihood. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - lml, lml_gradient = gpr.log_marginal_likelihood(kernel.theta, True) - lml_gradient_approx = \ - approx_fprime(kernel.theta, - lambda theta: gpr.log_marginal_likelihood(theta, - False), - 1e-10) + lml, lml_gradient = gpr.log_marginal_likelihood(kernel.theta, True) + lml_gradient_approx = \ + approx_fprime(kernel.theta, + lambda theta: gpr.log_marginal_likelihood(theta, + False), + 1e-10) - assert_almost_equal(lml_gradient, lml_gradient_approx, 3) + assert_almost_equal(lml_gradient, lml_gradient_approx, 3) -def test_prior(): +@pytest.mark.parametrize('kernel', kernels) +def test_prior(kernel): # Test that GP prior has mean 0 and identical variances. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel) + gpr = GaussianProcessRegressor(kernel=kernel) - y_mean, y_cov = gpr.predict(X, return_cov=True) + y_mean, y_cov = gpr.predict(X, return_cov=True) - assert_almost_equal(y_mean, 0, 5) - if len(gpr.kernel.theta) > 1: - # XXX: quite hacky, works only for current kernels - assert_almost_equal(np.diag(y_cov), np.exp(kernel.theta[0]), 5) - else: - assert_almost_equal(np.diag(y_cov), 1, 5) + assert_almost_equal(y_mean, 0, 5) + if len(gpr.kernel.theta) > 1: + # XXX: quite hacky, works only for current kernels + assert_almost_equal(np.diag(y_cov), np.exp(kernel.theta[0]), 5) + else: + assert_almost_equal(np.diag(y_cov), 1, 5) -def test_sample_statistics(): +@pytest.mark.parametrize('kernel', kernels) +def test_sample_statistics(kernel): # Test that statistics of samples drawn from GP are correct. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - y_mean, y_cov = gpr.predict(X2, return_cov=True) + y_mean, y_cov = gpr.predict(X2, return_cov=True) - samples = gpr.sample_y(X2, 300000) + samples = gpr.sample_y(X2, 300000) - # More digits accuracy would require many more samples - assert_almost_equal(y_mean, np.mean(samples, 1), 1) - assert_almost_equal(np.diag(y_cov) / np.diag(y_cov).max(), - np.var(samples, 1) / np.diag(y_cov).max(), 1) + # More digits accuracy would require many more samples + assert_almost_equal(y_mean, np.mean(samples, 1), 1) + assert_almost_equal(np.diag(y_cov) / np.diag(y_cov).max(), + np.var(samples, 1) / np.diag(y_cov).max(), 1) def test_no_optimizer(): @@ -150,13 +148,13 @@ def test_no_optimizer(): assert_equal(np.exp(gpr.kernel_.theta), 1.0) -def test_predict_cov_vs_std(): +@pytest.mark.parametrize('kernel', kernels) +def test_predict_cov_vs_std(kernel): # Test that predicted std.-dev. is consistent with cov's diagonal. - for kernel in kernels: - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - y_mean, y_cov = gpr.predict(X2, return_cov=True) - y_mean, y_std = gpr.predict(X2, return_std=True) - assert_almost_equal(np.sqrt(np.diag(y_cov)), y_std) + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + y_mean, y_cov = gpr.predict(X2, return_cov=True) + y_mean, y_std = gpr.predict(X2, return_std=True) + assert_almost_equal(np.sqrt(np.diag(y_cov)), y_std) def test_anisotropic_kernel(): @@ -197,32 +195,33 @@ def test_random_starts(): last_lml = lml -def test_y_normalization(): +@pytest.mark.parametrize('kernel', kernels) +def test_y_normalization(kernel): # Test normalization of the target values in GP # Fitting non-normalizing GP on normalized y and fitting normalizing GP # on unnormalized y should yield identical results y_mean = y.mean(0) y_norm = y - y_mean - for kernel in kernels: - # Fit non-normalizing GP on normalized y - gpr = GaussianProcessRegressor(kernel=kernel) - gpr.fit(X, y_norm) - # Fit normalizing GP on unnormalized y - gpr_norm = GaussianProcessRegressor(kernel=kernel, normalize_y=True) - gpr_norm.fit(X, y) - # Compare predicted mean, std-devs and covariances - y_pred, y_pred_std = gpr.predict(X2, return_std=True) - y_pred = y_mean + y_pred - y_pred_norm, y_pred_std_norm = gpr_norm.predict(X2, return_std=True) + # Fit non-normalizing GP on normalized y + gpr = GaussianProcessRegressor(kernel=kernel) + gpr.fit(X, y_norm) + # Fit normalizing GP on unnormalized y + gpr_norm = GaussianProcessRegressor(kernel=kernel, normalize_y=True) + gpr_norm.fit(X, y) + + # Compare predicted mean, std-devs and covariances + y_pred, y_pred_std = gpr.predict(X2, return_std=True) + y_pred = y_mean + y_pred + y_pred_norm, y_pred_std_norm = gpr_norm.predict(X2, return_std=True) - assert_almost_equal(y_pred, y_pred_norm) - assert_almost_equal(y_pred_std, y_pred_std_norm) + assert_almost_equal(y_pred, y_pred_norm) + assert_almost_equal(y_pred_std, y_pred_std_norm) - _, y_cov = gpr.predict(X2, return_cov=True) - _, y_cov_norm = gpr_norm.predict(X2, return_cov=True) - assert_almost_equal(y_cov, y_cov_norm) + _, y_cov = gpr.predict(X2, return_cov=True) + _, y_cov_norm = gpr_norm.predict(X2, return_cov=True) + assert_almost_equal(y_cov, y_cov_norm) def test_y_multioutput(): @@ -268,7 +267,8 @@ def test_y_multioutput(): assert_almost_equal(gpr.kernel_.theta, gpr_2d.kernel_.theta, 4) -def test_custom_optimizer(): +@pytest.mark.parametrize('kernel', non_fixed_kernels) +def test_custom_optimizer(kernel): # Test that GPR can use externally defined optimizers. # Define a dummy optimizer that simply tests 50 random hyperparameters def optimizer(obj_func, initial_theta, bounds): @@ -283,14 +283,11 @@ def optimizer(obj_func, initial_theta, bounds): theta_opt, func_min = theta, f return theta_opt, func_min - for kernel in kernels: - if kernel == fixed_kernel: - continue - gpr = GaussianProcessRegressor(kernel=kernel, optimizer=optimizer) - gpr.fit(X, y) - # Checks that optimizer improved marginal likelihood - assert_greater(gpr.log_marginal_likelihood(gpr.kernel_.theta), - gpr.log_marginal_likelihood(gpr.kernel.theta)) + gpr = GaussianProcessRegressor(kernel=kernel, optimizer=optimizer) + gpr.fit(X, y) + # Checks that optimizer improved marginal likelihood + assert_greater(gpr.log_marginal_likelihood(gpr.kernel_.theta), + gpr.log_marginal_likelihood(gpr.kernel.theta)) def test_gpr_correct_error_message(): @@ -306,30 +303,28 @@ def test_gpr_correct_error_message(): % kernel, gpr.fit, X, y) -def test_duplicate_input(): +@pytest.mark.parametrize('kernel', kernels) +def test_duplicate_input(kernel): # Test GPR can handle two different output-values for the same input. - for kernel in kernels: - gpr_equal_inputs = \ - GaussianProcessRegressor(kernel=kernel, alpha=1e-2) - gpr_similar_inputs = \ - GaussianProcessRegressor(kernel=kernel, alpha=1e-2) + gpr_equal_inputs = GaussianProcessRegressor(kernel=kernel, alpha=1e-2) + gpr_similar_inputs = GaussianProcessRegressor(kernel=kernel, alpha=1e-2) - X_ = np.vstack((X, X[0])) - y_ = np.hstack((y, y[0] + 1)) - gpr_equal_inputs.fit(X_, y_) + X_ = np.vstack((X, X[0])) + y_ = np.hstack((y, y[0] + 1)) + gpr_equal_inputs.fit(X_, y_) - X_ = np.vstack((X, X[0] + 1e-15)) - y_ = np.hstack((y, y[0] + 1)) - gpr_similar_inputs.fit(X_, y_) + X_ = np.vstack((X, X[0] + 1e-15)) + y_ = np.hstack((y, y[0] + 1)) + gpr_similar_inputs.fit(X_, y_) - X_test = np.linspace(0, 10, 100)[:, None] - y_pred_equal, y_std_equal = \ - gpr_equal_inputs.predict(X_test, return_std=True) - y_pred_similar, y_std_similar = \ - gpr_similar_inputs.predict(X_test, return_std=True) + X_test = np.linspace(0, 10, 100)[:, None] + y_pred_equal, y_std_equal = \ + gpr_equal_inputs.predict(X_test, return_std=True) + y_pred_similar, y_std_similar = \ + gpr_similar_inputs.predict(X_test, return_std=True) - assert_almost_equal(y_pred_equal, y_pred_similar) - assert_almost_equal(y_std_equal, y_std_similar) + assert_almost_equal(y_pred_equal, y_pred_similar) + assert_almost_equal(y_std_equal, y_std_similar) def test_no_fit_default_predict(): @@ -348,19 +343,20 @@ def test_no_fit_default_predict(): assert_array_almost_equal(y_cov1, y_cov2) -def test_K_inv_reset(): +@pytest.mark.parametrize('kernel', kernels) +def test_K_inv_reset(kernel): y2 = f(X2).ravel() - for kernel in kernels: - # Test that self._K_inv is reset after a new fit - gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) - assert_true(hasattr(gpr, '_K_inv')) - assert_true(gpr._K_inv is None) - gpr.predict(X, return_std=True) - assert_true(gpr._K_inv is not None) - gpr.fit(X2, y2) - assert_true(gpr._K_inv is None) - gpr.predict(X2, return_std=True) - gpr2 = GaussianProcessRegressor(kernel=kernel).fit(X2, y2) - gpr2.predict(X2, return_std=True) - # the value of K_inv should be independent of the first fit - assert_array_equal(gpr._K_inv, gpr2._K_inv) + + # Test that self._K_inv is reset after a new fit + gpr = GaussianProcessRegressor(kernel=kernel).fit(X, y) + assert_true(hasattr(gpr, '_K_inv')) + assert_true(gpr._K_inv is None) + gpr.predict(X, return_std=True) + assert_true(gpr._K_inv is not None) + gpr.fit(X2, y2) + assert_true(gpr._K_inv is None) + gpr.predict(X2, return_std=True) + gpr2 = GaussianProcessRegressor(kernel=kernel).fit(X2, y2) + gpr2.predict(X2, return_std=True) + # the value of K_inv should be independent of the first fit + assert_array_equal(gpr._K_inv, gpr2._K_inv) diff --git a/sklearn/gaussian_process/tests/test_kernels.py b/sklearn/gaussian_process/tests/test_kernels.py index 8c40139480e1c..eeb367bc93fc2 100644 --- a/sklearn/gaussian_process/tests/test_kernels.py +++ b/sklearn/gaussian_process/tests/test_kernels.py @@ -3,6 +3,7 @@ # Author: Jan Hendrik Metzen # License: BSD 3 clause +import pytest import numpy as np from sklearn.utils.fixes import signature @@ -47,98 +48,100 @@ kernels.append(PairwiseKernel(gamma=1.0, metric=metric)) -def test_kernel_gradient(): +@pytest.mark.parametrize('kernel', kernels) +def test_kernel_gradient(kernel): # Compare analytic and numeric gradient of kernels. - for kernel in kernels: - K, K_gradient = kernel(X, eval_gradient=True) + K, K_gradient = kernel(X, eval_gradient=True) - assert_equal(K_gradient.shape[0], X.shape[0]) - assert_equal(K_gradient.shape[1], X.shape[0]) - assert_equal(K_gradient.shape[2], kernel.theta.shape[0]) + assert_equal(K_gradient.shape[0], X.shape[0]) + assert_equal(K_gradient.shape[1], X.shape[0]) + assert_equal(K_gradient.shape[2], kernel.theta.shape[0]) - def eval_kernel_for_theta(theta): - kernel_clone = kernel.clone_with_theta(theta) - K = kernel_clone(X, eval_gradient=False) - return K + def eval_kernel_for_theta(theta): + kernel_clone = kernel.clone_with_theta(theta) + K = kernel_clone(X, eval_gradient=False) + return K - K_gradient_approx = \ - _approx_fprime(kernel.theta, eval_kernel_for_theta, 1e-10) + K_gradient_approx = \ + _approx_fprime(kernel.theta, eval_kernel_for_theta, 1e-10) - assert_almost_equal(K_gradient, K_gradient_approx, 4) + assert_almost_equal(K_gradient, K_gradient_approx, 4) -def test_kernel_theta(): +@pytest.mark.parametrize( + 'kernel', + [kernel for kernel in kernels + if not (isinstance(kernel, KernelOperator) # skip non-basic kernels + or isinstance(kernel, Exponentiation))]) +def test_kernel_theta(kernel): # Check that parameter vector theta of kernel is set correctly. - for kernel in kernels: - if isinstance(kernel, KernelOperator) \ - or isinstance(kernel, Exponentiation): # skip non-basic kernels - continue - theta = kernel.theta - _, K_gradient = kernel(X, eval_gradient=True) - - # Determine kernel parameters that contribute to theta - init_sign = signature(kernel.__class__.__init__).parameters.values() - args = [p.name for p in init_sign if p.name != 'self'] - theta_vars = map(lambda s: s[0:-len("_bounds")], - filter(lambda s: s.endswith("_bounds"), args)) - assert_equal( - set(hyperparameter.name - for hyperparameter in kernel.hyperparameters), - set(theta_vars)) - - # Check that values returned in theta are consistent with - # hyperparameter values (being their logarithms) - for i, hyperparameter in enumerate(kernel.hyperparameters): - assert_equal(theta[i], - np.log(getattr(kernel, hyperparameter.name))) - - # Fixed kernel parameters must be excluded from theta and gradient. - for i, hyperparameter in enumerate(kernel.hyperparameters): - # create copy with certain hyperparameter fixed - params = kernel.get_params() - params[hyperparameter.name + "_bounds"] = "fixed" - kernel_class = kernel.__class__ - new_kernel = kernel_class(**params) - # Check that theta and K_gradient are identical with the fixed - # dimension left out - _, K_gradient_new = new_kernel(X, eval_gradient=True) - assert_equal(theta.shape[0], new_kernel.theta.shape[0] + 1) - assert_equal(K_gradient.shape[2], K_gradient_new.shape[2] + 1) - if i > 0: - assert_equal(theta[:i], new_kernel.theta[:i]) - assert_array_equal(K_gradient[..., :i], - K_gradient_new[..., :i]) - if i + 1 < len(kernel.hyperparameters): - assert_equal(theta[i + 1:], new_kernel.theta[i:]) - assert_array_equal(K_gradient[..., i + 1:], - K_gradient_new[..., i:]) - - # Check that values of theta are modified correctly - for i, hyperparameter in enumerate(kernel.hyperparameters): - theta[i] = np.log(42) - kernel.theta = theta - assert_almost_equal(getattr(kernel, hyperparameter.name), 42) - - setattr(kernel, hyperparameter.name, 43) - assert_almost_equal(kernel.theta[i], np.log(43)) - - -def test_auto_vs_cross(): + theta = kernel.theta + _, K_gradient = kernel(X, eval_gradient=True) + + # Determine kernel parameters that contribute to theta + init_sign = signature(kernel.__class__.__init__).parameters.values() + args = [p.name for p in init_sign if p.name != 'self'] + theta_vars = map(lambda s: s[0:-len("_bounds")], + filter(lambda s: s.endswith("_bounds"), args)) + assert_equal( + set(hyperparameter.name + for hyperparameter in kernel.hyperparameters), + set(theta_vars)) + + # Check that values returned in theta are consistent with + # hyperparameter values (being their logarithms) + for i, hyperparameter in enumerate(kernel.hyperparameters): + assert_equal(theta[i], + np.log(getattr(kernel, hyperparameter.name))) + + # Fixed kernel parameters must be excluded from theta and gradient. + for i, hyperparameter in enumerate(kernel.hyperparameters): + # create copy with certain hyperparameter fixed + params = kernel.get_params() + params[hyperparameter.name + "_bounds"] = "fixed" + kernel_class = kernel.__class__ + new_kernel = kernel_class(**params) + # Check that theta and K_gradient are identical with the fixed + # dimension left out + _, K_gradient_new = new_kernel(X, eval_gradient=True) + assert_equal(theta.shape[0], new_kernel.theta.shape[0] + 1) + assert_equal(K_gradient.shape[2], K_gradient_new.shape[2] + 1) + if i > 0: + assert_equal(theta[:i], new_kernel.theta[:i]) + assert_array_equal(K_gradient[..., :i], + K_gradient_new[..., :i]) + if i + 1 < len(kernel.hyperparameters): + assert_equal(theta[i + 1:], new_kernel.theta[i:]) + assert_array_equal(K_gradient[..., i + 1:], + K_gradient_new[..., i:]) + + # Check that values of theta are modified correctly + for i, hyperparameter in enumerate(kernel.hyperparameters): + theta[i] = np.log(42) + kernel.theta = theta + assert_almost_equal(getattr(kernel, hyperparameter.name), 42) + + setattr(kernel, hyperparameter.name, 43) + assert_almost_equal(kernel.theta[i], np.log(43)) + + +@pytest.mark.parametrize('kernel', + [kernel for kernel in kernels + # Identity is not satisfied on diagonal + if kernel != kernel_white]) +def test_auto_vs_cross(kernel): # Auto-correlation and cross-correlation should be consistent. - for kernel in kernels: - if kernel == kernel_white: - continue # Identity is not satisfied on diagonal - K_auto = kernel(X) - K_cross = kernel(X, X) - assert_almost_equal(K_auto, K_cross, 5) + K_auto = kernel(X) + K_cross = kernel(X, X) + assert_almost_equal(K_auto, K_cross, 5) -def test_kernel_diag(): +@pytest.mark.parametrize('kernel', kernels) +def test_kernel_diag(kernel): # Test that diag method of kernel returns consistent results. - for kernel in kernels: - K_call_diag = np.diag(kernel(X)) - K_diag = kernel.diag(X) - assert_almost_equal(K_call_diag, K_diag, 5) + K_call_diag = np.diag(kernel(X)) + K_diag = kernel.diag(X) + assert_almost_equal(K_call_diag, K_diag, 5) def test_kernel_operator_commutative(): @@ -173,13 +176,13 @@ def test_kernel_anisotropic(): assert_array_equal(kernel.k2.length_scale, [1.0, 4.0]) -def test_kernel_stationary(): +@pytest.mark.parametrize('kernel', + [kernel for kernel in kernels + if kernel.is_stationary()]) +def test_kernel_stationary(kernel): # Test stationarity of kernels. - for kernel in kernels: - if not kernel.is_stationary(): - continue - K = kernel(X, X + 1) - assert_almost_equal(K[0, 0], np.diag(K)) + K = kernel(X, X + 1) + assert_almost_equal(K[0, 0], np.diag(K)) def check_hyperparameters_equal(kernel1, kernel2): @@ -191,24 +194,25 @@ def check_hyperparameters_equal(kernel1, kernel2): assert_equal(attr_value1, attr_value2) -def test_kernel_clone(): +@pytest.mark.parametrize("kernel", kernels) +def test_kernel_clone(kernel): # Test that sklearn's clone works correctly on kernels. - for kernel in kernels: - kernel_cloned = clone(kernel) + kernel_cloned = clone(kernel) - # XXX: Should this be fixed? - # This differs from the sklearn's estimators equality check. - assert_equal(kernel, kernel_cloned) - assert_not_equal(id(kernel), id(kernel_cloned)) + # XXX: Should this be fixed? + # This differs from the sklearn's estimators equality check. + assert_equal(kernel, kernel_cloned) + assert_not_equal(id(kernel), id(kernel_cloned)) - # Check that all constructor parameters are equal. - assert_equal(kernel.get_params(), kernel_cloned.get_params()) + # Check that all constructor parameters are equal. + assert_equal(kernel.get_params(), kernel_cloned.get_params()) - # Check that all hyperparameters are equal. - yield check_hyperparameters_equal, kernel, kernel_cloned + # Check that all hyperparameters are equal. + check_hyperparameters_equal(kernel, kernel_cloned) -def test_kernel_clone_after_set_params(): +@pytest.mark.parametrize('kernel', kernels) +def test_kernel_clone_after_set_params(kernel): # This test is to verify that using set_params does not # break clone on kernels. # This used to break because in kernels such as the RBF, non-trivial @@ -216,27 +220,25 @@ def test_kernel_clone_after_set_params(): # See https://github.com/scikit-learn/scikit-learn/issues/6961 # for more details. bounds = (1e-5, 1e5) - for kernel in kernels: - kernel_cloned = clone(kernel) - params = kernel.get_params() - # RationalQuadratic kernel is isotropic. - isotropic_kernels = (ExpSineSquared, RationalQuadratic) - if 'length_scale' in params and not isinstance(kernel, - isotropic_kernels): - length_scale = params['length_scale'] - if np.iterable(length_scale): - params['length_scale'] = length_scale[0] - params['length_scale_bounds'] = bounds - else: - params['length_scale'] = [length_scale] * 2 - params['length_scale_bounds'] = bounds * 2 - kernel_cloned.set_params(**params) - kernel_cloned_clone = clone(kernel_cloned) - assert_equal(kernel_cloned_clone.get_params(), - kernel_cloned.get_params()) - assert_not_equal(id(kernel_cloned_clone), id(kernel_cloned)) - yield (check_hyperparameters_equal, kernel_cloned, - kernel_cloned_clone) + kernel_cloned = clone(kernel) + params = kernel.get_params() + # RationalQuadratic kernel is isotropic. + isotropic_kernels = (ExpSineSquared, RationalQuadratic) + if 'length_scale' in params and not isinstance(kernel, + isotropic_kernels): + length_scale = params['length_scale'] + if np.iterable(length_scale): + params['length_scale'] = length_scale[0] + params['length_scale_bounds'] = bounds + else: + params['length_scale'] = [length_scale] * 2 + params['length_scale_bounds'] = bounds * 2 + kernel_cloned.set_params(**params) + kernel_cloned_clone = clone(kernel_cloned) + assert_equal(kernel_cloned_clone.get_params(), + kernel_cloned.get_params()) + assert_not_equal(id(kernel_cloned_clone), id(kernel_cloned)) + check_hyperparameters_equal(kernel_cloned, kernel_cloned_clone) def test_matern_kernel(): @@ -258,63 +260,65 @@ def test_matern_kernel(): assert_array_almost_equal(K1, K2) -def test_kernel_versus_pairwise(): +@pytest.mark.parametrize("kernel", kernels) +def test_kernel_versus_pairwise(kernel): # Check that GP kernels can also be used as pairwise kernels. - for kernel in kernels: - # Test auto-kernel - if kernel != kernel_white: - # For WhiteKernel: k(X) != k(X,X). This is assumed by - # pairwise_kernels - K1 = kernel(X) - K2 = pairwise_kernels(X, metric=kernel) - assert_array_almost_equal(K1, K2) - - # Test cross-kernel - K1 = kernel(X, Y) - K2 = pairwise_kernels(X, Y, metric=kernel) + + # Test auto-kernel + if kernel != kernel_white: + # For WhiteKernel: k(X) != k(X,X). This is assumed by + # pairwise_kernels + K1 = kernel(X) + K2 = pairwise_kernels(X, metric=kernel) assert_array_almost_equal(K1, K2) + # Test cross-kernel + K1 = kernel(X, Y) + K2 = pairwise_kernels(X, Y, metric=kernel) + assert_array_almost_equal(K1, K2) -def test_set_get_params(): + +@pytest.mark.parametrize("kernel", kernels) +def test_set_get_params(kernel): # Check that set_params()/get_params() is consistent with kernel.theta. - for kernel in kernels: - # Test get_params() - index = 0 - params = kernel.get_params() - for hyperparameter in kernel.hyperparameters: - if isinstance("string", type(hyperparameter.bounds)): - if hyperparameter.bounds == "fixed": - continue - size = hyperparameter.n_elements - if size > 1: # anisotropic kernels - assert_almost_equal(np.exp(kernel.theta[index:index + size]), - params[hyperparameter.name]) - index += size - else: - assert_almost_equal(np.exp(kernel.theta[index]), - params[hyperparameter.name]) - index += 1 - # Test set_params() - index = 0 - value = 10 # arbitrary value - for hyperparameter in kernel.hyperparameters: - if isinstance("string", type(hyperparameter.bounds)): - if hyperparameter.bounds == "fixed": - continue - size = hyperparameter.n_elements - if size > 1: # anisotropic kernels - kernel.set_params(**{hyperparameter.name: [value] * size}) - assert_almost_equal(np.exp(kernel.theta[index:index + size]), - [value] * size) - index += size - else: - kernel.set_params(**{hyperparameter.name: value}) - assert_almost_equal(np.exp(kernel.theta[index]), value) - index += 1 - - -def test_repr_kernels(): + + # Test get_params() + index = 0 + params = kernel.get_params() + for hyperparameter in kernel.hyperparameters: + if isinstance("string", type(hyperparameter.bounds)): + if hyperparameter.bounds == "fixed": + continue + size = hyperparameter.n_elements + if size > 1: # anisotropic kernels + assert_almost_equal(np.exp(kernel.theta[index:index + size]), + params[hyperparameter.name]) + index += size + else: + assert_almost_equal(np.exp(kernel.theta[index]), + params[hyperparameter.name]) + index += 1 + # Test set_params() + index = 0 + value = 10 # arbitrary value + for hyperparameter in kernel.hyperparameters: + if isinstance("string", type(hyperparameter.bounds)): + if hyperparameter.bounds == "fixed": + continue + size = hyperparameter.n_elements + if size > 1: # anisotropic kernels + kernel.set_params(**{hyperparameter.name: [value] * size}) + assert_almost_equal(np.exp(kernel.theta[index:index + size]), + [value] * size) + index += size + else: + kernel.set_params(**{hyperparameter.name: value}) + assert_almost_equal(np.exp(kernel.theta[index]), value) + index += 1 + + +@pytest.mark.parametrize("kernel", kernels) +def test_repr_kernels(kernel): # Smoke-test for repr in kernels. - for kernel in kernels: - repr(kernel) + repr(kernel) From b02f1f31aade73c78c0e3d985d668744906be92e Mon Sep 17 00:00:00 2001 From: Roman Yurchak Date: Tue, 29 May 2018 15:29:46 +0200 Subject: [PATCH 3/3] Fix comment placement --- sklearn/gaussian_process/tests/test_kernels.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sklearn/gaussian_process/tests/test_kernels.py b/sklearn/gaussian_process/tests/test_kernels.py index eeb367bc93fc2..d5949f60ff6f9 100644 --- a/sklearn/gaussian_process/tests/test_kernels.py +++ b/sklearn/gaussian_process/tests/test_kernels.py @@ -71,7 +71,8 @@ def eval_kernel_for_theta(theta): @pytest.mark.parametrize( 'kernel', [kernel for kernel in kernels - if not (isinstance(kernel, KernelOperator) # skip non-basic kernels + # skip non-basic kernels + if not (isinstance(kernel, KernelOperator) or isinstance(kernel, Exponentiation))]) def test_kernel_theta(kernel): # Check that parameter vector theta of kernel is set correctly.