From 4c8b275d22e90886537c8ec92ead30d3117fadf5 Mon Sep 17 00:00:00 2001 From: ivana Date: Mon, 23 Mar 2026 17:14:12 +0100 Subject: [PATCH 1/2] Filter the group-wise samples only for the control attack; Align the prediction indices with the input indices in KNNInferencePredictor::predict. --- src/anonymeter/evaluators/inference_evaluator.py | 2 +- src/anonymeter/neighbors/mixed_types_kneighbors.py | 5 ++++- tests/test_mixed_types_kneigbors.py | 13 ++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/anonymeter/evaluators/inference_evaluator.py b/src/anonymeter/evaluators/inference_evaluator.py index 51682ea..af716e2 100644 --- a/src/anonymeter/evaluators/inference_evaluator.py +++ b/src/anonymeter/evaluators/inference_evaluator.py @@ -324,7 +324,7 @@ def risk_for_groups(self, confidence_level: float = 0.95) -> dict[str, Evaluatio # Count the number of success control attacks n_control = evaluate_inference_guesses( guesses=self._guesses_control.loc[common_indices], - secrets=data_control[self._secret], + secrets=data_control[self._secret].loc[common_indices], regression=self._regression, ).sum() else: diff --git a/src/anonymeter/neighbors/mixed_types_kneighbors.py b/src/anonymeter/neighbors/mixed_types_kneighbors.py index 318628a..75d941b 100644 --- a/src/anonymeter/neighbors/mixed_types_kneighbors.py +++ b/src/anonymeter/neighbors/mixed_types_kneighbors.py @@ -277,4 +277,7 @@ def predict(self, x: pd.DataFrame) -> pd.Series: guesses_idx = self._nn.kneighbors(queries=x[self._columns]) if isinstance(guesses_idx, tuple): raise RuntimeError("guesses_idx cannot be a tuple") - return self._target_series.iloc[guesses_idx.flatten()] + + guesses = self._target_series.iloc[guesses_idx.flatten()].copy() + guesses.index = x.index + return guesses diff --git a/tests/test_mixed_types_kneigbors.py b/tests/test_mixed_types_kneigbors.py index 21e0b26..ad39342 100644 --- a/tests/test_mixed_types_kneigbors.py +++ b/tests/test_mixed_types_kneigbors.py @@ -5,7 +5,7 @@ import pandas as pd import pytest -from anonymeter.neighbors.mixed_types_kneighbors import MixedTypeKNeighbors, gower_distance +from anonymeter.neighbors.mixed_types_kneighbors import KNNInferencePredictor, MixedTypeKNeighbors, gower_distance from tests.fixtures import get_adult @@ -79,3 +79,14 @@ def test_gower_distance_numerical(): r0, r1 = rng.random(size=10), rng.random(size=10) dist = gower_distance(r0=r0, r1=r1, cat_cols_index=10) np.testing.assert_almost_equal(dist, np.sum(np.abs(r0 - r1))) + + +def test_knn_inference_predictor_prediction_index_alignment(): + df = get_adult("ori", n_samples=10) + aux_cols = ["age", "education", "sex"] + predictor = KNNInferencePredictor(data=df, columns=aux_cols, target_col="income", n_jobs=1) + queries = df[aux_cols] + + guesses = predictor.predict(queries) + + assert list(guesses.index) == list(queries.index) From 62590e0893137b96979198aa2eae5346df95f2e2 Mon Sep 17 00:00:00 2001 From: ivana Date: Fri, 27 Mar 2026 11:21:59 +0100 Subject: [PATCH 2/2] Remove df copy; Use pd.testing.assert_index_equal instead of list comparison. --- src/anonymeter/neighbors/mixed_types_kneighbors.py | 2 +- tests/test_mixed_types_kneigbors.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/anonymeter/neighbors/mixed_types_kneighbors.py b/src/anonymeter/neighbors/mixed_types_kneighbors.py index 75d941b..be7c402 100644 --- a/src/anonymeter/neighbors/mixed_types_kneighbors.py +++ b/src/anonymeter/neighbors/mixed_types_kneighbors.py @@ -278,6 +278,6 @@ def predict(self, x: pd.DataFrame) -> pd.Series: if isinstance(guesses_idx, tuple): raise RuntimeError("guesses_idx cannot be a tuple") - guesses = self._target_series.iloc[guesses_idx.flatten()].copy() + guesses = self._target_series.iloc[guesses_idx.flatten()] guesses.index = x.index return guesses diff --git a/tests/test_mixed_types_kneigbors.py b/tests/test_mixed_types_kneigbors.py index ad39342..a7315b7 100644 --- a/tests/test_mixed_types_kneigbors.py +++ b/tests/test_mixed_types_kneigbors.py @@ -89,4 +89,4 @@ def test_knn_inference_predictor_prediction_index_alignment(): guesses = predictor.predict(queries) - assert list(guesses.index) == list(queries.index) + pd.testing.assert_index_equal(guesses.index, queries.index)