From 871731e9101494ffb75e0db738ab8b501162fca8 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Fri, 29 Nov 2019 16:24:51 +0100 Subject: [PATCH 01/12] maj --- test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 00000000..e69de29b From 5f4def7b9f6b877d24b7662f0f1ef54c3dc4d5eb Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Fri, 29 Nov 2019 16:29:41 +0100 Subject: [PATCH 02/12] maj --- test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test.txt diff --git a/test.txt b/test.txt deleted file mode 100644 index e69de29b..00000000 From 3d50a3740a0ee74654b32e2c752e36591dc49c26 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Tue, 10 Dec 2019 11:26:30 +0100 Subject: [PATCH 03/12] corrected PR 267 --- metric_learn/base_metric.py | 1 + test/test_pairs_classifiers.py | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index 427fcf86..2e94c828 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -215,6 +215,7 @@ def score_pairs(self, pairs): :ref:`mahalanobis_distances` : The section of the project documentation that describes Mahalanobis Distances. """ + check_is_fitted(self, ['preprocessor_']) pairs = check_input(pairs, type_of_inputs='tuples', preprocessor=self.preprocessor_, estimator=self, tuple_size=2) diff --git a/test/test_pairs_classifiers.py b/test/test_pairs_classifiers.py index 840cd151..66b034b8 100644 --- a/test/test_pairs_classifiers.py +++ b/test/test_pairs_classifiers.py @@ -66,14 +66,24 @@ def test_predict_monotonous(estimator, build_dataset, ids=ids_pairs_learners) def test_raise_not_fitted_error_if_not_fitted(estimator, build_dataset, with_preprocessor): - """Test that a NotFittedError is raised if someone tries to predict and - the metric learner has not been fitted.""" + """Test that a NotFittedError is raised if someone tries to use + score_pairs, decision_function, get_metric, transform or + get_mahalanobis_matrix on input data and the metric learner + has not been fitted.""" input_data, labels, preprocessor, _ = build_dataset(with_preprocessor) estimator = clone(estimator) estimator.set_params(preprocessor=preprocessor) set_random_state(estimator) + with pytest.raises(NotFittedError): + estimator.score_pairs(input_data) with pytest.raises(NotFittedError): estimator.decision_function(input_data) + with pytest.raises(NotFittedError): + estimator.get_metric() + with pytest.raises(NotFittedError): + estimator.transform(input_data) + with pytest.raises(NotFittedError): + estimator.get_mahalanobis_matrix() @pytest.mark.parametrize('calibration_params', @@ -138,7 +148,8 @@ def fit(self, pairs, y): def test_unset_threshold(): - # test that set_threshold indeed sets the threshold + """Tests that the "threshold is unset" error is raised when using predict + (performs binary classification on pairs) with an unset threshold.""" identity_pairs_classifier = IdentityPairsClassifier() pairs = np.array([[[0.], [1.]], [[1.], [3.]], [[2.], [5.]], [[3.], [7.]]]) y = np.array([1, 1, -1, -1]) From 397808e16d7b0011492c8d6bca8498c24a151822 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Tue, 10 Dec 2019 11:32:03 +0100 Subject: [PATCH 04/12] trailing whitespace --- test/test_pairs_classifiers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_pairs_classifiers.py b/test/test_pairs_classifiers.py index 66b034b8..57ab7e4c 100644 --- a/test/test_pairs_classifiers.py +++ b/test/test_pairs_classifiers.py @@ -66,7 +66,7 @@ def test_predict_monotonous(estimator, build_dataset, ids=ids_pairs_learners) def test_raise_not_fitted_error_if_not_fitted(estimator, build_dataset, with_preprocessor): - """Test that a NotFittedError is raised if someone tries to use + """Test that a NotFittedError is raised if someone tries to use score_pairs, decision_function, get_metric, transform or get_mahalanobis_matrix on input data and the metric learner has not been fitted.""" From 65e2e8357da8426260d85c8b994338438e6121b5 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Tue, 10 Dec 2019 13:35:11 +0100 Subject: [PATCH 05/12] test calibrate_threshold, test predict --- test/test_pairs_classifiers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test_pairs_classifiers.py b/test/test_pairs_classifiers.py index 57ab7e4c..4152c3f8 100644 --- a/test/test_pairs_classifiers.py +++ b/test/test_pairs_classifiers.py @@ -84,6 +84,12 @@ def test_raise_not_fitted_error_if_not_fitted(estimator, build_dataset, estimator.transform(input_data) with pytest.raises(NotFittedError): estimator.get_mahalanobis_matrix() + with pytest.raises(NotFittedError): + estimator.calibrate_threshold(input_data, labels) + + estimator.set_threshold(0.5) + with pytest.raises(NotFittedError): + estimator.predict(input_data) @pytest.mark.parametrize('calibration_params', From 560d3e09a4c6d1c5dd32a66aae4d5e49d080455f Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Fri, 20 Dec 2019 11:16:05 +0100 Subject: [PATCH 06/12] maj --- metric_learn/base_metric.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index 70aded8c..14c7e100 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -216,7 +216,10 @@ def score_pairs(self, pairs): :ref:`mahalanobis_distances` : The section of the project documentation that describes Mahalanobis Distances. """ - check_is_fitted(self, ['preprocessor_']) + if sys.version_info.major < 3 or sys.version_info.minor < 5: + check_is_fitted(self, ['preprocessor_']) + else: + check_is_fitted(self) pairs = check_input(pairs, type_of_inputs='tuples', preprocessor=self.preprocessor_, estimator=self, tuple_size=2) From 832d3e01678a1a6d993ed7d7f025d61f1048af3f Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Mon, 23 Dec 2019 12:19:16 +0100 Subject: [PATCH 07/12] Checks estimator is fitted before set threshold --- metric_learn/base_metric.py | 19 ++++++++++++++++++- test/test_pairs_classifiers.py | 5 +++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index 14c7e100..c264a846 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -353,8 +353,14 @@ def predict(self, pairs): y_predicted : `numpy.ndarray` of floats, shape=(n_constraints,) The predicted learned metric value between samples in every pair. """ + # TODO: remove when we stop supporting Python < 3.5 + if sys.version_info.major < 3 or sys.version_info.minor < 5: + check_is_fitted(self, 'preprocessor_') + else: + check_is_fitted(self) + if "threshold_" not in vars(self): - msg = ("A threshold for this estimator has not been set," + msg = ("A threshold for this estimator has not been set, " "call its set_threshold or calibrate_threshold method.") raise AttributeError(msg) return 2 * (- self.decision_function(pairs) <= self.threshold_) - 1 @@ -435,6 +441,12 @@ def set_threshold(self, threshold): self : `_PairsClassifier` The pairs classifier with the new threshold set. """ + # TODO: remove when we stop supporting Python < 3.5 + if sys.version_info.major < 3 or sys.version_info.minor < 5: + check_is_fitted(self, 'preprocessor_') + else: + check_is_fitted(self) + self.threshold_ = threshold return self @@ -497,6 +509,11 @@ def calibrate_threshold(self, pairs_valid, y_valid, strategy='accuracy', -------- sklearn.calibration : scikit-learn's module for calibrating classifiers """ + # TODO: remove when we stop supporting Python < 3.5 + if sys.version_info.major < 3 or sys.version_info.minor < 5: + check_is_fitted(self, 'preprocessor_') + else: + check_is_fitted(self) self._validate_calibration_params(strategy, min_rate, beta) diff --git a/test/test_pairs_classifiers.py b/test/test_pairs_classifiers.py index 4152c3f8..f30a3a2b 100644 --- a/test/test_pairs_classifiers.py +++ b/test/test_pairs_classifiers.py @@ -87,7 +87,8 @@ def test_raise_not_fitted_error_if_not_fitted(estimator, build_dataset, with pytest.raises(NotFittedError): estimator.calibrate_threshold(input_data, labels) - estimator.set_threshold(0.5) + with pytest.raises(NotFittedError): + estimator.set_threshold(0.5) with pytest.raises(NotFittedError): estimator.predict(input_data) @@ -163,7 +164,7 @@ def test_unset_threshold(): with pytest.raises(AttributeError) as e: identity_pairs_classifier.predict(pairs) - expected_msg = ("A threshold for this estimator has not been set," + expected_msg = ("A threshold for this estimator has not been set, " "call its set_threshold or calibrate_threshold method.") assert str(e.value) == expected_msg From 30106e7a3c960c8082607a2c13071221b6f183d1 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Tue, 24 Dec 2019 15:09:05 +0100 Subject: [PATCH 08/12] correct failed tests with MockBadClassifier --- test/test_pairs_classifiers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_pairs_classifiers.py b/test/test_pairs_classifiers.py index f30a3a2b..6c71abcd 100644 --- a/test/test_pairs_classifiers.py +++ b/test/test_pairs_classifiers.py @@ -380,6 +380,7 @@ class MockBadPairsClassifier(MahalanobisMixin, _PairsClassifierMixin): """ def fit(self, pairs, y, calibration_params=None): + self.preprocessor_ = 'not used' self.components_ = 'not used' self.calibrate_threshold(pairs, y, **(calibration_params if calibration_params is not None else From d52575f84048a19d43f200ede77d2008aed889fd Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Mon, 13 Jan 2020 21:51:59 +0100 Subject: [PATCH 09/12] remove checks --- metric_learn/base_metric.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index 73cf5b91..b50ab81b 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -340,11 +340,7 @@ def predict(self, pairs): y_predicted : `numpy.ndarray` of floats, shape=(n_constraints,) The predicted learned metric value between samples in every pair. """ - # TODO: remove when we stop supporting Python < 3.5 - if sys.version_info.major < 3 or sys.version_info.minor < 5: - check_is_fitted(self, 'preprocessor_') - else: - check_is_fitted(self) + check_is_fitted(self, 'preprocessor_') if "threshold_" not in vars(self): msg = ("A threshold for this estimator has not been set, " @@ -424,11 +420,7 @@ def set_threshold(self, threshold): self : `_PairsClassifier` The pairs classifier with the new threshold set. """ - # TODO: remove when we stop supporting Python < 3.5 - if sys.version_info.major < 3 or sys.version_info.minor < 5: - check_is_fitted(self, 'preprocessor_') - else: - check_is_fitted(self) + check_is_fitted(self, 'preprocessor_') self.threshold_ = threshold return self @@ -492,11 +484,7 @@ def calibrate_threshold(self, pairs_valid, y_valid, strategy='accuracy', -------- sklearn.calibration : scikit-learn's module for calibrating classifiers """ - # TODO: remove when we stop supporting Python < 3.5 - if sys.version_info.major < 3 or sys.version_info.minor < 5: - check_is_fitted(self, 'preprocessor_') - else: - check_is_fitted(self) + check_is_fitted(self, 'preprocessor_') self._validate_calibration_params(strategy, min_rate, beta) From ed609dd2c67f10f0c250fb95392076f719765af9 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Mon, 13 Jan 2020 22:00:34 +0100 Subject: [PATCH 10/12] forgot one --- metric_learn/base_metric.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index b50ab81b..6e077625 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -215,10 +215,7 @@ def score_pairs(self, pairs): :ref:`mahalanobis_distances` : The section of the project documentation that describes Mahalanobis Distances. """ - if sys.version_info.major < 3 or sys.version_info.minor < 5: - check_is_fitted(self, ['preprocessor_']) - else: - check_is_fitted(self) + check_is_fitted(self, ['preprocessor_']) pairs = check_input(pairs, type_of_inputs='tuples', preprocessor=self.preprocessor_, estimator=self, tuple_size=2) From 33fbdf6d4c1a6068780a50bb863cd9f846b0915f Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Fri, 24 Jan 2020 09:27:09 +0100 Subject: [PATCH 11/12] missed one check_is_fitted --- metric_learn/base_metric.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/metric_learn/base_metric.py b/metric_learn/base_metric.py index 6e077625..ee73c793 100644 --- a/metric_learn/base_metric.py +++ b/metric_learn/base_metric.py @@ -93,6 +93,8 @@ def _prepare_inputs(self, X, y=None, type_of_inputs='classic', The checked input labels array. """ self._check_preprocessor() + + check_is_fitted(self, ['preprocessor_']) return check_input(X, y, type_of_inputs=type_of_inputs, preprocessor=self.preprocessor_, From 79ab5ba8b6a2ecfc5b675e49420e94d03d2d0657 Mon Sep 17 00:00:00 2001 From: RobinVogel Date: Fri, 24 Jan 2020 09:49:50 +0100 Subject: [PATCH 12/12] sklearn changed the assumptions behind check_is_fitted --- test/test_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_utils.py b/test/test_utils.py index 3092e168..76be5817 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -749,6 +749,8 @@ def test_array_like_indexer_array_like_valid_classic(input_data, indices): """Checks that any array-like is valid in the 'preprocessor' argument, and in the indices, for a classic input""" class MockMetricLearner(MahalanobisMixin): + def fit(self): + pass pass mock_algo = MockMetricLearner(preprocessor=input_data) @@ -763,6 +765,8 @@ def test_array_like_indexer_array_like_valid_tuples(input_data, indices): """Checks that any array-like is valid in the 'preprocessor' argument, and in the indices, for a classic input""" class MockMetricLearner(MahalanobisMixin): + def fit(self): + pass pass mock_algo = MockMetricLearner(preprocessor=input_data)