From 693a319a7e183de345148ebded666884993ffc2e Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Sun, 18 May 2025 19:12:47 +0100 Subject: [PATCH 1/6] ENH: implemented _fit_predict override output checks --- .../_yield_anomaly_detection_checks.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index 363db48e23..0ee1c3b9f5 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -100,3 +100,33 @@ def check_anomaly_detector_output(estimator, datatype): ), "y_pred must contain only 0s, 1s, True, or False" else: raise ValueError(f"Unknown anomaly output type: {ot}") + + +def check_anomaly_detector_fit_predict(estimator, datatype): + """Test the anomaly detector fit_predict method.""" + est1 = _clone_estimator(estimator) + est2 = _clone_estimator(estimator) + esitimator_class = type(estimator) + + # Doesn't proceed if _fit_predict is inherited + if "_fit_predict" not in esitimator_class.__dict__: + return + + fit_predict_output = est1.fit_predict( + FULL_TEST_DATA_DICT[datatype]["train"][0], + FULL_TEST_DATA_DICT[datatype]["train"][1], + ) + assert isinstance(fit_predict_output, np.ndarray) + + expected_output = est2.fit( + FULL_TEST_DATA_DICT[datatype]["train"][0], + FULL_TEST_DATA_DICT[datatype]["train"][1], + ).predict(FULL_TEST_DATA_DICT[datatype]["train"][0]) + + assert isinstance(expected_output, np.ndarray) + + # Assert outputs are same + assert len(fit_predict_output) == len(expected_output) + assert np.array_equal( + fit_predict_output, expected_output + ), "outputs of _fit_predict() does not match fit().predict()" From aeeaef35ae2a80912e837572002f67a634f71d5b Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Sun, 18 May 2025 23:18:52 +0100 Subject: [PATCH 2/6] mnt: typo fix --- .../estimator_checking/_yield_anomaly_detection_checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index 0ee1c3b9f5..d1658d0323 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -106,10 +106,10 @@ def check_anomaly_detector_fit_predict(estimator, datatype): """Test the anomaly detector fit_predict method.""" est1 = _clone_estimator(estimator) est2 = _clone_estimator(estimator) - esitimator_class = type(estimator) + estimator_class = type(estimator) # Doesn't proceed if _fit_predict is inherited - if "_fit_predict" not in esitimator_class.__dict__: + if "_fit_predict" not in estimator_class.__dict__: return fit_predict_output = est1.fit_predict( From f569cff418c541437e21afde8890dd0d0ae05649 Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Tue, 27 May 2025 11:01:56 +0100 Subject: [PATCH 3/6] refactored _fit_predict check to output function --- .../_yield_anomaly_detection_checks.py | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index d1658d0323..fefb5b802d 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -73,6 +73,8 @@ def check_anomaly_detector_learning_types(estimator, datatype): def check_anomaly_detector_output(estimator, datatype): """Test the anomaly detector output on valid data.""" estimator = _clone_estimator(estimator) + estimator2 = _clone_estimator(estimator) + estimator_class = type(estimator) estimator.fit( FULL_TEST_DATA_DICT[datatype]["train"][0], @@ -101,32 +103,17 @@ def check_anomaly_detector_output(estimator, datatype): else: raise ValueError(f"Unknown anomaly output type: {ot}") - -def check_anomaly_detector_fit_predict(estimator, datatype): - """Test the anomaly detector fit_predict method.""" - est1 = _clone_estimator(estimator) - est2 = _clone_estimator(estimator) - estimator_class = type(estimator) - - # Doesn't proceed if _fit_predict is inherited + # check _fit_predict output is same as fit().predict() if "_fit_predict" not in estimator_class.__dict__: return - fit_predict_output = est1.fit_predict( - FULL_TEST_DATA_DICT[datatype]["train"][0], - FULL_TEST_DATA_DICT[datatype]["train"][1], - ) - assert isinstance(fit_predict_output, np.ndarray) + expected_output = estimator.predict(FULL_TEST_DATA_DICT[datatype]["train"][0]) - expected_output = est2.fit( + fit_predict_output = estimator2.fit_predict( FULL_TEST_DATA_DICT[datatype]["train"][0], FULL_TEST_DATA_DICT[datatype]["train"][1], - ).predict(FULL_TEST_DATA_DICT[datatype]["train"][0]) - - assert isinstance(expected_output, np.ndarray) + ) - # Assert outputs are same - assert len(fit_predict_output) == len(expected_output) assert np.array_equal( fit_predict_output, expected_output ), "outputs of _fit_predict() does not match fit().predict()" From 3522d1dedb21cb284175de911a44e8f1dd5740b5 Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Tue, 27 May 2025 16:38:05 +0100 Subject: [PATCH 4/6] added random state to clone function --- .../estimator_checking/_yield_anomaly_detection_checks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index fefb5b802d..c2b30439a4 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -72,8 +72,8 @@ def check_anomaly_detector_learning_types(estimator, datatype): def check_anomaly_detector_output(estimator, datatype): """Test the anomaly detector output on valid data.""" - estimator = _clone_estimator(estimator) - estimator2 = _clone_estimator(estimator) + estimator = _clone_estimator(estimator, random_state=42) + estimator2 = _clone_estimator(estimator, random_state=42) estimator_class = type(estimator) estimator.fit( From c32be8f623fc294ce0f8c4e5754ea5dacddbbd42 Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Wed, 28 May 2025 10:43:18 +0100 Subject: [PATCH 5/6] renamed estimator to estimator1 --- .../_yield_anomaly_detection_checks.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index c2b30439a4..038dbcf646 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -72,20 +72,20 @@ def check_anomaly_detector_learning_types(estimator, datatype): def check_anomaly_detector_output(estimator, datatype): """Test the anomaly detector output on valid data.""" - estimator = _clone_estimator(estimator, random_state=42) + estimator1 = _clone_estimator(estimator, random_state=42) estimator2 = _clone_estimator(estimator, random_state=42) estimator_class = type(estimator) - estimator.fit( + estimator1.fit( FULL_TEST_DATA_DICT[datatype]["train"][0], FULL_TEST_DATA_DICT[datatype]["train"][1], ) - y_pred = estimator.predict(FULL_TEST_DATA_DICT[datatype]["test"][0]) + y_pred = estimator1.predict(FULL_TEST_DATA_DICT[datatype]["test"][0]) assert isinstance(y_pred, np.ndarray) assert len(y_pred) == FULL_TEST_DATA_DICT[datatype]["test"][0].shape[1] - ot = estimator.get_tag("anomaly_output_type") + ot = estimator1.get_tag("anomaly_output_type") if ot == "anomaly_scores": assert np.issubdtype(y_pred.dtype, np.floating) or np.issubdtype( y_pred.dtype, np.integer @@ -107,7 +107,7 @@ def check_anomaly_detector_output(estimator, datatype): if "_fit_predict" not in estimator_class.__dict__: return - expected_output = estimator.predict(FULL_TEST_DATA_DICT[datatype]["train"][0]) + expected_output = estimator1.predict(FULL_TEST_DATA_DICT[datatype]["train"][0]) fit_predict_output = estimator2.fit_predict( FULL_TEST_DATA_DICT[datatype]["train"][0], From b00e7b30c65d284da51e78da56ef32b82613dd0c Mon Sep 17 00:00:00 2001 From: Aryan Ramani Date: Wed, 28 May 2025 13:17:51 +0100 Subject: [PATCH 6/6] using np.allclose instead of np.array_equal --- .../estimator_checking/_yield_anomaly_detection_checks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py index 038dbcf646..d1f80e8a55 100644 --- a/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py +++ b/aeon/testing/estimator_checking/_yield_anomaly_detection_checks.py @@ -114,6 +114,6 @@ def check_anomaly_detector_output(estimator, datatype): FULL_TEST_DATA_DICT[datatype]["train"][1], ) - assert np.array_equal( + assert np.allclose( fit_predict_output, expected_output ), "outputs of _fit_predict() does not match fit().predict()"