### Install Development Dependencies Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Installs all necessary dependencies for development, including build tools and testing frameworks. ```bash pip install ".[dev]" ``` -------------------------------- ### Install Anonymeter with Notebook Dependencies Source: https://github.com/statice/anonymeter/blob/main/README.md Use this command to install anonymeter along with necessary libraries for running notebooks if installing from PyPI. ```shell pip install anonymeter[notebooks] ``` -------------------------------- ### Local Installation of Anonymeter Source: https://github.com/statice/anonymeter/blob/main/README.md Install Anonymeter locally after cloning the repository. Use the appropriate pip command based on your needs: basic dependencies, notebook support, or full development setup. ```shell cd anonymeter # if you are not there already pip install . # Basic dependencies pip install ".[notebooks]" # Dependencies to run example notebooks pip install -e ".[notebooks,dev]" # Development setup ``` -------------------------------- ### Install Package from Test PyPI Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Creates a new virtual environment and installs the anonymeter package from Test PyPI with a specific version. ```bash mkdir ~/test-anonymeter # create some test directory cd ~/test-anonymeter python -m venv .venv # create new virtual env source .venv/bin/activate asdf reshim python # in case you use asdf pip install --upgrade pip pip install --index-url https://test.pypi.org/simple anonymeter==NEW_VERSION ``` -------------------------------- ### Install Anonymeter from Local Source with Notebook Dependencies Source: https://github.com/statice/anonymeter/blob/main/README.md Use this command to install anonymeter with notebook dependencies when installing from a local source. ```shell pip install ".[notebooks]" ``` -------------------------------- ### Install Anonymeter from PyPI Source: https://github.com/statice/anonymeter/blob/main/README.md Use this command to install the Anonymeter package from the Python Package Index. This is the simplest method for general use. ```shell pip install anonymeter ``` -------------------------------- ### Execute Evaluation and Get Risk Estimate Source: https://github.com/statice/anonymeter/blob/main/README.md Execute the evaluation pipeline by calling the evaluate method and access the estimated risk using the risk method. ```python evaluator.evaluate() risk = evaluator.risk() ``` -------------------------------- ### Clone Anonymeter Repository Source: https://github.com/statice/anonymeter/blob/main/README.md Clone the Anonymeter repository from GitHub to install it locally. This is useful for development or if you need to modify the source code. ```shell git clone git@github.com:statice/anonymeter.git ``` -------------------------------- ### Get High-Level Privacy Risk Estimation Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Use the `risk()` method to obtain a high-level estimation of privacy risk and its confidence interval. Specify the desired confidence level. ```python evaluator.risk(confidence_level=0.95) ``` -------------------------------- ### Get Detailed Attack Success Rates Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Use the `results()` method to retrieve detailed success rates for the main, baseline, and control attacks. This provides insight into the components of the Anonymeter risk calculation. ```python res = evaluator.results() print("Successs rate of main attack:", res.attack_rate) print("Successs rate of baseline attack:", res.baseline_rate) print("Successs rate of control attack:", res.control_rate) ``` -------------------------------- ### Get Linkability Risk Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Retrieve the calculated linkability risk from the evaluator. The `risk()` method can also take `n_neighbors` as an argument to re-evaluate risk with different indirect link tolerances. ```python evaluator.risk() ``` -------------------------------- ### Plot Overall Risk Scores per Secret Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Generate a bar chart to visualize the overall privacy risk scores for each secret column evaluated in the end-to-end example. This provides a comparative overview of the inference risk across different attributes. ```python fig, ax = plt.subplots() risks = [res[1].risk().value for res in results] columns = [res[0] for res in results] ax.bar(x=columns, height=risks, alpha=0.5, ecolor='black', capsize=10) plt.xticks(rotation=45, ha='right') plt.title("Risk scores per secret") ax.set_ylabel("Measured inference risk") _ = ax.set_xlabel("Secret column") ``` -------------------------------- ### Get InferenceEvaluator Results Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Retrieve the evaluation results from the InferenceEvaluator. The .results() method returns an object containing various metrics, including the overall privacy risk. ```python result = evaluator.results() print(f"Privacy risk for secret=[{secret}]: {result.risk()}") ``` -------------------------------- ### Build Package Distributions Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Cleans the build directory and creates source and wheel distributions for the package. ```bash rm -rf ./dist # clean the build directory if necessary python -m build ``` -------------------------------- ### Configure Twine for PyPI Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Sets up the .pypirc file to authenticate with the official PyPI repository using an API token. ```toml [pypi] username = "__token__" password = "YOUR_TOKEN_HERE" ``` -------------------------------- ### Configure Twine for Test PyPI Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Sets up the .pypirc file to authenticate with Test PyPI using an API token. ```toml [testpypi] username = "__token__" password = "YOUR_TOKEN_HERE" ``` -------------------------------- ### Run Tests with Pytest Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Sets up a symbolic link to the tests directory and runs the package tests using pytest. ```bash ln -s ~/code/anonymeter/tests ~/test-anonymeter/tests pip install pytest python -m pytest ``` -------------------------------- ### Display first few rows of the original dataset Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Shows the initial rows of the original dataset to understand its structure and content. ```python ori.head() ``` -------------------------------- ### Upload to PyPI Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Uploads the built package artifacts to the official PyPI repository. ```bash twine upload dist/* ``` -------------------------------- ### Prepare data and train a custom Decision Tree model for inference Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Sets up a preprocessing pipeline with OneHotEncoder for categorical features and passthrough for numerical features. Then, it trains a DecisionTreeClassifier on the original data to predict the 'income' column using other attributes as input. ```python # Choose a target (the secret) column for the inference model secret = "income" # Select the input colums - aux_cols to train the inference model on aux_cols = [col for col in ori.columns if col != secret] # Data Preprocessing requirements categorical_cols = ori[aux_cols].select_dtypes(include=["object"]).columns numeric_cols = ori[aux_cols].select_dtypes(include=["number"]).columns preprocess = ColumnTransformer( transformers=[ ("cat", OneHotEncoder(handle_unknown="ignore"), categorical_cols), ("num", "passthrough", numeric_cols) ] ) # The inference model tree = DecisionTreeClassifier( criterion="gini", max_depth=5, min_samples_split=10, min_samples_leaf=5, max_features="sqrt", random_state=42, ) # Build the pipeline out of the preprocessing step and inference model model = Pipeline(steps=[ ("preprocess", preprocess), ("tree", tree) ]) # Fit the model model.fit(ori[aux_cols], ori[secret]) # Wrap the model in an InferencePredictor (anonymeter.evaluators.inference_predictor::InferencePredictor) ``` -------------------------------- ### Configure Anonymeter to Log to a File Source: https://github.com/statice/anonymeter/blob/main/README.md Set up a file handler to direct anonymeter logs to a file named 'anonymeter.log' with DEBUG level. ```python import logging # create a file handler file_handler = logging.FileHandler("anonymeter.log") # set the logging level for the file handler file_handler.setLevel(logging.DEBUG) # add the file handler to the logger logger = logging.getLogger("anonymeter") logger.addHandler(file_handler) logger.setLevel(logging.DEBUG) ``` -------------------------------- ### Initialize and Evaluate LinkabilityEvaluator Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Configure and run the LinkabilityEvaluator with specified auxiliary columns and attack parameters. The `n_jobs` parameter follows joblib conventions. ```python aux_cols = [ ['type_employer', 'education', 'hr_per_week', 'capital_loss', 'capital_gain'], [ 'race', 'sex', 'fnlwgt', 'age', 'country'] ] evaluator = LinkabilityEvaluator(ori=ori, syn=syn, control=control, n_attacks=2000, aux_cols=aux_cols, n_neighbors=10) evaluator.evaluate(n_jobs=-2) # n_jobs follow joblib convention. -1 = all cores, -2 = all execept one ``` -------------------------------- ### Load datasets Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Loads the original, synthetic, and control datasets using pandas. Ensure the 'datasets' directory exists and contains the specified CSV files. ```python dataset_dir = "./datasets/" ori = pd.read_csv(os.path.join(dataset_dir, "adults_train.csv")) syn = pd.read_csv(os.path.join(dataset_dir, "adults_syn_ctgan.csv")) control = pd.read_csv(os.path.join(dataset_dir, "adults_control.csv")) ``` -------------------------------- ### Upload to Test PyPI Source: https://github.com/statice/anonymeter/blob/main/CONTRIBUTING.md Uploads the built package artifacts to the Test PyPI repository for testing. ```bash twine upload --repository testpypi dist/* ``` -------------------------------- ### Initialize SinglingOutEvaluator Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Initializes the SinglingOutEvaluator with loaded datasets and specifies parameters for the number of attacks and columns. ```python evaluator = SinglingOutEvaluator(ori=ori, syn=syn, control=control, n_attacks=2000, n_cols=12) ``` -------------------------------- ### Initialize and Evaluate InferenceEvaluator Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Initialize the InferenceEvaluator with original, synthetic, and control data, along with auxiliary columns, a secret column, and a pre-trained inference model. Evaluate the privacy risk using the .evaluate() method. ```python evaluator = InferenceEvaluator(ori=ori, syn=syn, control=control, aux_cols=aux_cols, secret=secret, n_attacks=ori.shape[0], # the min value of n_attacks and ori.shape[0] is considered regression = False, inference_model=inference_model) # We pass the inference_model here # Evaluate evaluator.evaluate(n_jobs=-2) ``` -------------------------------- ### Retrieve Singling Out Queries Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Retrieves and displays the first three singling out queries generated by the attacker. This helps understand which attributes are being used for singling out. ```python evaluator.queries()[:3] ``` -------------------------------- ### Import necessary libraries Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Imports all required libraries for data manipulation, evaluation, and plotting. ```python import pandas as pd import os from pathlib import Path from datetime import datetime from anonymeter.evaluators import SinglingOutEvaluator from matplotlib import pyplot as plt import time import seaborn as sns from collections import defaultdict ``` -------------------------------- ### Print timing results (n_cols=12) Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Prints the average and standard deviation of the execution time measured by %%timeit for constructing and running queries. ```python print(f"mean : {_.average:.2f} s") print(f"std : {_.stdev:.2f} s") ``` -------------------------------- ### Initialize and Evaluate InferenceEvaluator Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Set up and run the InferenceEvaluator to measure the risk of inferring secret attributes. Auxiliary columns are defined to model an attacker's knowledge, and a specific 'secret' column is targeted. ```python columns = ori.columns results = [] for secret in columns: aux_cols = [col for col in columns if col != secret] evaluator = InferenceEvaluator(ori=ori, syn=syn, control=control, aux_cols=aux_cols, secret=secret, n_attacks=1000) evaluator.evaluate(n_jobs=-2) results.append((secret, evaluator.results())) ``` -------------------------------- ### Instantiate Anonymeter Evaluator Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Instantiate an Anonymeter evaluator by providing the original, synthetic, and control datasets, along with the number of attacks to perform. The number of attacks influences the statistical uncertainty and computation time. ```python evaluator = *Evaluator(ori: pd.DataFrame, syn: pd.DataFrame, control: pd.DataFrame, n_attacks: int) ``` -------------------------------- ### Combine original and control datasets Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Concatenates the original training data and the control dataset for use in splitting. ```python adult_combined = pd.concat([ori, control], axis=0) ``` -------------------------------- ### Split data into train, release, and control sets Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Calls the defined function to split the combined dataset into the respective sets. ```python df_train, df_release, df_control = split_train_control_release() ``` -------------------------------- ### Import Anonymeter Evaluators and Utilities Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Import necessary libraries including pandas for data manipulation, matplotlib and seaborn for plotting, and the specific evaluator classes from Anonymeter. Ensure these are available in your environment. ```python import os import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from anonymeter.evaluators import SinglingOutEvaluator from anonymeter.evaluators import LinkabilityEvaluator from anonymeter.evaluators import InferenceEvaluator ``` -------------------------------- ### Instantiate Privacy Risk Evaluator Source: https://github.com/statice/anonymeter/blob/main/README.md Instantiate a privacy risk evaluator by providing the original dataset, synthetic dataset, control dataset, and the number of target records to attack. ```python evaluator = *Evaluator(ori: pd.DataFrame, syn: pd.DataFrame, control: pd.DataFrame, n_attacks: int) ``` -------------------------------- ### Nearest-neighbor search for mixed-type data with MixedTypeKNeighbors Source: https://context7.com/statice/anonymeter/llms.txt Uses a Gower-inspired distance for numeric and categorical columns. JIT-compiled via Numba and parallelized with joblib. Requires pandas DataFrames for candidates and queries. ```python import pandas as pd from anonymeter.neighbors.mixed_types_kneighbors import MixedTypeKNeighbors candidates = pd.DataFrame({ "age": [25, 35, 45, 55], "income": [30000, 50000, 70000, 90000], "gender": ["M", "F", "F", "M"], }) queries = pd.DataFrame({ "age": [30, 50], "income": [45000, 80000], "gender": ["F", "M"], }) nn = MixedTypeKNeighbors(n_neighbors=2, n_jobs=-2) nn.fit(candidates) # Returns indices of the 2 nearest candidates for each query row idx = nn.kneighbors(queries, return_distance=False) print(idx) # Example output: # [[1 0] # [3 2]] # With distances distances, idx = nn.kneighbors(queries, return_distance=True) print(distances) ``` -------------------------------- ### Import necessary libraries Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Imports the required libraries for data manipulation and anonymeter evaluation, including pandas and specific components from anonymeter. ```python import os import pandas as pd from anonymeter.evaluators import SinglingOutEvaluator from anonymeter.evaluators.singling_out_evaluator import _evaluate_queries, _generate_singling_out_queries ``` -------------------------------- ### Re-evaluate Linkability Risk with Different Neighbors Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Check the measured linkability risk for different values of `n_neighbor` without re-running the entire evaluation. This allows for quick analysis of how indirect links affect the risk. ```python print(evaluator.risk(n_neighbors=7)) ``` -------------------------------- ### Evaluate Singling Out Risk Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Initializes and runs the SinglingOutEvaluator for univariate attacks. Handles potential RuntimeErrors by suggesting increased n_attacks for more stable results. ```python evaluator = SinglingOutEvaluator(ori=ori, syn=syn, control=control, n_attacks=500) try: evaluator.evaluate(mode='univariate') risk = evaluator.risk() print(risk) except RuntimeError as ex: print(f"Singling out evaluation failed with {ex}. Please re-run this cell." "For more stable results increase `n_attacks`. Note that this will " "make the evaluation slower.") ``` -------------------------------- ### Re-initialize SinglingOutEvaluator with n_cols=3 Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Re-initializes the SinglingOutEvaluator, this time setting n_cols to 3 to observe the performance impact. It also increases max_attempts. ```python evaluator = SinglingOutEvaluator(ori=ori, syn=syn, control=control, n_attacks=2000, max_attempts=100_000, n_cols=3) ``` -------------------------------- ### Perform multivariate singling out evaluation Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Runs the multivariate singling out attack for different numbers of auxiliary columns and calculates the average time taken for each configuration. The risk is stored. ```python for n in n_cols_to_try: start_time = time.time() for i in range(n_iters): evaluator = SinglingOutEvaluator( ori=ori, syn=syn, control=control, n_attacks=500, n_cols=n, max_attempts=max_attempts, ) evaluator.evaluate(mode="multivariate") risk = evaluator.risk() risks[n].append(risk) print(f"Average time: {(time.time() - start_time) / n_iters:.2f} seconds") ``` -------------------------------- ### Visualize Inference Risk Results Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Generate a bar chart to visualize the measured inference risk for each secret column. This helps identify attributes with high privacy exposure. ```python fig, ax = plt.subplots() risks = [res[1].risk().value for res in results] columns = [res[0] for res in results] ax.bar(x=columns, height=risks, alpha=0.5, ecolor='black', capsize=10) plt.xticks(rotation=45, ha='right') ax.set_ylabel("Measured inference risk") _ = ax.set_xlabel("Secret column") ``` -------------------------------- ### Evaluate Multivariate Singling Out Attack Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb Configure and run the `SinglingOutEvaluator` for multivariate attacks by setting the `mode` to 'multivariate' and specifying `n_cols` for the number of attributes in attacker queries. Includes error handling for unstable results. ```python evaluator = SinglingOutEvaluator(ori=ori, syn=syn, control=control, n_attacks=100, # this attack takes longer n_cols=4) try: evaluator.evaluate(mode='multivariate') risk = evaluator.risk() print(risk) except RuntimeError as ex: print(f"Singling out evaluation failed with {ex}. Please re-run this cell." "For more stable results increase `n_attacks`. Note that this will " "make the evaluation slower.") ``` -------------------------------- ### Visualize singling out risk Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Creates a stripplot to visualize the singling out risk across different numbers of auxiliary columns. Requires seaborn and matplotlib. ```python df = pd.DataFrame( [(k, r.value) for k, lst in risks.items() for r in lst], columns=["aux_cols", "risk"] ) sns.set(style="darkgrid") plt.figure(figsize=(4, 3)) ax = sns.stripplot(data=df, x="aux_cols", y="risk", jitter=0.2) ax.set_xlabel("Number of auxiliary columns") ax.set_ylabel("Risk") plt.ylim(bottom=0.0) plt.title(f"Singling out risk ({n_iters} runs)") plt.show() ``` -------------------------------- ### Configure Anonymeter logging Source: https://context7.com/statice/anonymeter/llms.txt Configures Python's standard logging module for the 'anonymeter' logger. Set to DEBUG for verbose output or attach a file handler for persistent logs. ```python import logging # Print debug information to stdout logging.getLogger("anonymeter").setLevel(logging.DEBUG) # Log to a file instead file_handler = logging.FileHandler("anonymeter.log") file_handler.setLevel(logging.DEBUG) logger = logging.getLogger("anonymeter") logger.addHandler(file_handler) logger.setLevel(logging.DEBUG) ``` -------------------------------- ### Set attack mode Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Defines the mode for generating singling out queries. 'multivariate' is used here. ```python mode = "multivariate" ``` -------------------------------- ### Import necessary libraries for Anonymeter Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Imports essential libraries including pandas, scikit-learn components, and Anonymeter modules for data manipulation, model building, and privacy evaluation. ```python import os import matplotlib.pyplot as plt import pandas as pd from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.preprocessing import OneHotEncoder from sklearn.tree import DecisionTreeClassifier from anonymeter.evaluators import InferenceEvaluator from anonymeter.evaluators.sklearn_inference_predictor import SklearnInferencePredictor ``` -------------------------------- ### Evaluate Linkability Risk with LinkabilityEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Use LinkabilityEvaluator to assess the risk of linking records using synthetic data via nearest-neighbor matching. Define auxiliary columns for partial record views. Configure the number of attacks and neighbors. Evaluate using multiple CPU cores and retrieve results, including attack and control rates at different neighbor thresholds. ```python import pandas as pd from anonymeter.evaluators import LinkabilityEvaluator ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") # Define the two column groups available to the attacker cols = ori.columns.tolist() mid = len(cols) // 2 aux_cols = (cols[:mid], cols[mid:]) evaluator = LinkabilityEvaluator( ori=ori, syn=syn, control=control, aux_cols=aux_cols, n_attacks=500, n_neighbors=1, # attack succeeds only if both halves share the exact same nearest neighbor ) evaluator.evaluate(n_jobs=-2) # use all-but-one CPU cores results = evaluator.results(confidence_level=0.95) print(f"Attack rate: {results.attack_rate}") print(f"Control rate: {results.control_rate}") risk = evaluator.risk() print(f"Linkability risk: {risk.value:.3f} CI: {risk.ci}") # Example output: # Linkability risk: 0.015 CI: (0.005, 0.025) # Retrieve raw link counts at a broader neighbor threshold results_k3 = evaluator.results(n_neighbors=3) print(f"Attack rate at k=3: {results_k3.attack_rate}") ``` -------------------------------- ### Use Custom Sklearn Model with InferenceEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Integrate any scikit-learn classifier or regressor as the attacker model by using `SklearnInferencePredictor`. This is useful for large datasets where the default kNN is too slow. The sklearn model must be pre-fitted and include its own preprocessing. ```python import pandas as pd from sklearn.pipeline import Pipeline from sklearn.preprocessing import OrdinalEncoder from sklearn.tree import DecisionTreeClassifier from sklearn.compose import ColumnTransformer from anonymeter.evaluators import InferenceEvaluator from anonymeter.evaluators.sklearn_inference_predictor import SklearnInferencePredictor ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") secret = "income" aux_cols = [c for c in syn.columns if c != secret] # Build and fit a preprocessing + classifier pipeline on the synthetic data cat_cols = syn[aux_cols].select_dtypes(include="object").columns.tolist() num_cols = syn[aux_cols].select_dtypes(exclude="object").columns.tolist() preprocessor = ColumnTransformer([ ("cat", OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1), cat_cols), ("num", "passthrough", num_cols), ]) clf = Pipeline([("prep", preprocessor), ("clf", DecisionTreeClassifier(max_depth=5))]) clf.fit(syn[aux_cols], syn[secret]) # Wrap the fitted model and pass it to the evaluator inference_model = SklearnInferencePredictor(model=clf) evaluator = InferenceEvaluator( ori=ori, syn=syn, control=control, aux_cols=aux_cols, secret=secret, regression=False, n_attacks=500, inference_model=inference_model, ) evaluator.evaluate() risk = evaluator.risk() print(f"Inference risk (DecisionTree): {risk.value:.3f} CI: {risk.ci}") ``` -------------------------------- ### Perform univariate singling out evaluation Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Runs the univariate singling out attack multiple times and calculates the average time taken. The risk is stored for later analysis. ```python risks = defaultdict(list) start_time = time.time() for i in range(n_iters): evaluator = SinglingOutEvaluator( ori=ori, syn=syn, control=control, n_attacks=500 ) evaluator.evaluate(mode="univariate") risk = evaluator.risk() risks[1].append(risk) print(f"Average time: {(time.time() - start_time) / n_iters:.2f} seconds") ``` -------------------------------- ### Visualize Singling Out Risk with Stripplot Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Generates a stripplot to visualize the singling out risk across different numbers of auxiliary columns. A horizontal red line indicates the leak fraction. ```python df = pd.DataFrame( [(k, r.value) for k, lst in risks_leaky.items() for r in lst], columns=["aux_cols", "risk"] ) plt.figure(figsize=(4, 3)) ax = sns.stripplot(data=df, x="aux_cols", y="risk", jitter=0.2) ax.set_xlabel("Number of auxiliary columns") ax.set_ylabel("Risk") plt.axhline(y=leak_fraction, color='red', linestyle='--') plt.ylim(bottom=0.0) plt.title(f"Singling out risk ({n_iters} runs)") plt.show() ``` -------------------------------- ### Set evaluation parameters Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Defines parameters for the evaluation, including the maximum number of attempts for an attack and the number of iterations for averaging results. ```python max_attempts = 1_000_000 n_iters = 5 n_cols_to_try = [3, 12] # for the multivariate attack ``` -------------------------------- ### Time query generation and evaluation (n_cols=12) Source: https://github.com/statice/anonymeter/blob/main/notebooks/measure_time_singling_out.ipynb Measures the time taken to generate singling out queries and evaluate them using the initialized evaluator. This snippet uses the default n_cols=12. ```python %%timeit -n 1 -r 3 -o queries = _generate_singling_out_queries( df=evaluator._syn, n_attacks=evaluator._n_attacks, n_cols=evaluator._n_cols, mode=mode, max_attempts=evaluator._max_attempts, rng=evaluator._rng ) _queries = _evaluate_queries(df=evaluator._ori, queries=queries) ``` -------------------------------- ### Perform univariate evaluation with leaky data Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Runs the univariate singling out attack using the synthesized leaky dataset and calculates the average time. Stores the risk. ```python risks_leaky = defaultdict(list) start_time = time.time() for i in range(n_iters): evaluator = SinglingOutEvaluator( ori=df_train, syn=df_syn, control=df_control, n_attacks=500 ) evaluator.evaluate(mode="univariate") risk = evaluator.risk() risks_leaky[1].append(risk) print(f"Average time: {(time.time() - start_time) / n_iters:.2f} seconds") ``` -------------------------------- ### End-to-End Evaluation Loop Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Iterate through a list of secret columns, preprocess data, train a DecisionTreeClassifier as a custom inference model, and evaluate privacy risks (both overall and group-wise) for each column. ```python columns = ["education", "education_num", "type_employer", "age"] # Example with 4 columns results_for_groups = {} results = [] for secret in columns: aux_cols = [col for col in columns if col != secret] # Data Preprocessing requirements categorical_cols = ori[aux_cols].select_dtypes(include=["object"]).columns numeric_cols = ori[aux_cols].select_dtypes(include=["number"]).columns preprocess = ColumnTransformer( transformers=[ ("cat", OneHotEncoder(handle_unknown="ignore"), categorical_cols), ("num", "passthrough", numeric_cols) ] ) # The inference model tree = DecisionTreeClassifier( criterion="gini", max_depth=5, min_samples_split=10, min_samples_leaf=5, max_features="sqrt", random_state=42, ) # Build the pipeline out of the preprocessing step and inference model model = Pipeline(steps=[ ("preprocess", preprocess), ("tree", tree) ]) # Fit the model model.fit(ori[aux_cols], ori[secret]) # Wrap the model in an InferencePredictor (anonymeter.evaluators.inference_predictor::InferencePredictor) # In this case we use our implemented SklearnInferencePredictor inference_model = SklearnInferencePredictor(model) # Init the InferenceEvaluator evaluator = InferenceEvaluator(ori=ori, syn=syn, control=control, aux_cols=aux_cols, secret=secret, n_attacks=ori.shape[0], # the min value of n_attacks and ori.shape[0] is considered inference_model=inference_model) # Evaluate evaluator.evaluate(n_jobs=-2) # Gather the results for the current group results_for_groups[secret] = evaluator.risk_for_groups() results.append((secret, evaluator.results())) ``` -------------------------------- ### Synthesize a leaky dataset Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Calls the synthesize_leaky function with a specified leak fraction to create a synthetic dataset. ```python leak_fraction = 0.2 df_syn = synthesize_leaky(df_train, df_release, leak_fraction=leak_fraction) ``` -------------------------------- ### Define data splitting function Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Defines a function to split a combined dataset into training, release, and control sets. Ensures the dataset size is divisible by 3. ```python def split_train_control_release(): # Random shuffle and split df = adult_combined.sample(frac=1, random_state=42) if len(df) % 3 != 0: df = df[: -(len(df) % 3)] df_train = df[: len(df) // 3] df_control = df[len(df) // 3 : 2 * len(df) // 3] df_release = df[2 * len(df) // 3 :] return df_train, df_release, df_control ``` -------------------------------- ### Derive Privacy Risk from Attack Results Source: https://github.com/statice/anonymeter/blob/main/notebooks/anonymeter_example.ipynb You can calculate the `PrivacyRisk` object directly from the detailed attack results obtained via the `results()` method. ```python res.risk() ``` -------------------------------- ### Inspect Raw Attack Statistics with EvaluationResults Source: https://context7.com/statice/anonymeter/llms.txt Use `EvaluationResults` to directly construct or inspect raw attack statistics, including Wilson-score success rates for main, baseline, and control attacks. It provides a `.risk()` method to compute the final residual privacy risk. ```python from anonymeter.stats.confidence import EvaluationResults, PrivacyRisk # Construct directly (useful for testing or custom attack pipelines) results = EvaluationResults( n_attacks=500, n_success=80, # main attack successes n_baseline=25, # random-guess successes n_control=30, # control-set successes confidence_level=0.95, ) print(f"Attack rate: {results.attack_rate.value:.3f} ± {results.attack_rate.error:.3f}") print(f"Baseline rate: {results.baseline_rate.value:.3f} ± {results.baseline_rate.error:.3f}") print(f"Control rate: {results.control_rate.value:.3f} ± {results.control_rate.error:.3f}") risk: PrivacyRisk = results.risk() print(f"Residual risk: {risk.value:.3f} CI: {risk.ci}") # PrivacyRisk is a NamedTuple: .value (float), .ci (tuple[float, float]) # Without a control set, risk equals the raw attack rate results_no_ctrl = EvaluationResults(n_attacks=500, n_success=80, n_baseline=25) print(results_no_ctrl.risk()) ``` -------------------------------- ### Plot Group-wise Inference Risk Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Visualize the computed group-wise inference risks using a bar chart. This helps in identifying which specific values within a secret column pose a higher privacy risk. ```python fig, ax = plt.subplots() risks = [res.risk().value for _, res in risk_for_groups.items()] cols = [key for key,_ in risk_for_groups.items()] ax.bar(x=cols, height=risks, alpha=0.5, ecolor='black', capsize=10) plt.xticks(rotation=45, ha='right') plt.title(secret) ax.set_ylabel("Measured inference risk") _ = ax.set_xlabel("Secret column value") ``` -------------------------------- ### Plot Group-wise Risk Scores for Secrets Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Iterates through secrets and plots the measured inference risk for each group of a secret column. Requires matplotlib and pre-computed results. ```python for secret in columns: curr_res = results_for_groups[secret] fig, ax = plt.subplots() risks = [res.risk().value for _, res in curr_res.items()] cols = [key for key,_ in curr_res.items()] ax.bar(x=cols, height=risks, alpha=0.5, ecolor='black', capsize=10) plt.xticks(rotation=45, ha='right') plt.title(secret) ax.set_ylabel("Measured inference risk") _ = ax.set_xlabel("Secret column groups") ``` -------------------------------- ### Set Anonymeter Logging Level to DEBUG Source: https://github.com/statice/anonymeter/blob/main/README.md Configure the anonymeter logger to output messages with DEBUG level and above. ```python import logging # set the logging level to DEBUG logging.getLogger("anonymeter").setLevel(logging.DEBUG) ``` -------------------------------- ### Define function to synthesize leaky data Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Creates a synthetic dataset by combining a specified fraction of the original training data with samples from the release dataset. Includes input validation and shuffling. ```python def synthesize_leaky( df_train: pd.DataFrame, df_release: pd.DataFrame, leak_fraction: float ) -> pd.DataFrame: """ Generate a synthetic dataset that contains a fraction of training data and release data. Assumes df_train and df_release have the same size and samples without replacement. Parameters: ---------- df_train : pandas.DataFrame Original training dataset to leak from df_release : pandas.DataFrame Release dataset to sample from leak_fraction : float Fraction of training data to include (between 0 and 1) Returns: -------- pandas.DataFrame Synthetic dataset containing leaked training data and release data samples """ # Validate inputs if not 0 <= leak_fraction <= 1: raise ValueError("leak_fraction must be between 0 and 1") # Calculate number of samples to take from each dataset n_samples = len(df_train) n_leak = int(n_samples * leak_fraction) n_release = n_samples - n_leak # Randomly sample from training data leaked_samples = df_train.sample(n=n_leak, replace=False) # Randomly sample from release data without replacement release_samples = df_release.sample(n=n_release, replace=False) # Combine the samples X_leaky_syn = pd.concat([leaked_samples, release_samples]) # Shuffle the combined dataset X_leaky_syn = X_leaky_syn.sample(frac=1).reset_index(drop=True) return X_leaky_syn ``` -------------------------------- ### Perform multivariate evaluation with leaky data Source: https://github.com/statice/anonymeter/blob/main/notebooks/singling_out.ipynb Runs the multivariate singling out attack using the synthesized leaky dataset for different numbers of auxiliary columns. Stores the risk. ```python for n in n_cols_to_try: start_time = time.time() for i in range(n_iters): evaluator = SinglingOutEvaluator( ori=df_train, syn=df_syn, control=df_control, n_attacks=500, n_cols=n, max_attempts=max_attempts, ) evaluator.evaluate(mode="multivariate") risk = evaluator.risk() ``` -------------------------------- ### Evaluate Singling-Out Risk with SinglingOutEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Use SinglingOutEvaluator to measure the risk of an attacker uniquely identifying individuals using synthetic data. Supply original, synthetic, and control datasets. Configure the number of attacks and columns for multivariate mode. Access results and risk estimates, and inspect successful queries. ```python import pandas as pd from anonymeter.evaluators import SinglingOutEvaluator # Load datasets ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") # Instantiate and run the evaluator evaluator = SinglingOutEvaluator( ori=ori, syn=syn, control=control, n_attacks=500, # number of singling-out queries to attempt n_cols=3, # columns combined per query (multivariate mode) seed=42, ) evaluator.evaluate(mode="multivariate") # or mode="univariate" # Access results results = evaluator.results(confidence_level=0.95) print(f"Attack rate: {results.attack_rate}") # SuccessRate(value=..., error=...) print(f"Control rate: {results.control_rate}") print(f"Baseline rate: {results.baseline_rate}") risk = evaluator.risk() print(f"Singling-out risk: {risk.value:.3f} CI: {risk.ci}") # Example output: # Singling-out risk: 0.032 CI: (0.018, 0.046) # Inspect the successful singling-out queries queries = evaluator.queries(baseline=False) print(f"Successful singling-out queries: {len(queries)}") ``` -------------------------------- ### Filter warnings Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Suppresses warnings to keep the output clean during execution. ```python import warnings warnings.filterwarnings('ignore') ``` -------------------------------- ### LinkabilityEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Measures whether an attacker with two partial views of a record can use the synthetic data to link those partial views back to the same individual via nearest-neighbor matching. ```APIDOC ## LinkabilityEvaluator ### Description Measures whether an attacker with two partial views of a record (auxiliary columns) can use the synthetic data to link those partial views back to the same individual via nearest-neighbor matching. The original dataset is vertically split into two subsets defined by `aux_cols`; records are re-linked if they share the same closest synthetic neighbor. ### Usage ```python import pandas as pd from anonymeter.evaluators import LinkabilityEvaluator ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") # Define the two column groups available to the attacker cols = ori.columns.tolist() mid = len(cols) // 2 aux_cols = (cols[:mid], cols[mid:]) evaluator = LinkabilityEvaluator( ori=ori, syn=syn, control=control, aux_cols=aux_cols, n_attacks=500, n_neighbors=1, # attack succeeds only if both halves share the exact same nearest neighbor ) evaluator.evaluate(n_jobs=-2) # use all-but-one CPU cores results = evaluator.results(confidence_level=0.95) print(f"Attack rate: {results.attack_rate}") print(f"Control rate: {results.control_rate}") risk = evaluator.risk() print(f"Linkability risk: {risk.value:.3f} CI: {risk.ci}") # Retrieve raw link counts at a broader neighbor threshold results_k3 = evaluator.results(n_neighbors=3) print(f"Attack rate at k=3: {results_k3.attack_rate}") ``` ### Parameters - **ori** (pd.DataFrame) - Original dataset. - **syn** (pd.DataFrame) - Synthetic dataset. - **control** (pd.DataFrame) - Control dataset. - **aux_cols** (tuple[list[str], list[str]]) - A tuple containing two lists of column names, representing the two partial views of a record available to the attacker. - **n_attacks** (int) - Number of attacks to perform. - **n_neighbors** (int) - The number of nearest neighbors to consider for linking. - **n_jobs** (int, optional) - Number of CPU cores to use for parallel processing. Defaults to -1 (all cores). ### Methods - **evaluate(n_jobs: int = -1)**: Runs the linkability attack evaluation. `n_jobs` specifies the number of parallel jobs. - **results(confidence_level: float = 0.95, n_neighbors: int = 1)**: Returns the attack rate and control rate with confidence intervals for a given number of neighbors. - **risk()**: Calculates and returns the linkability risk score. ``` -------------------------------- ### Evaluate Inference Risk with InferenceEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Use InferenceEvaluator to assess the risk of inferring a secret attribute from synthetic data. Requires original, synthetic, and control datasets, along with auxiliary and secret columns. The `regression` flag determines scoring for categorical or continuous secrets. ```python import pandas as pd from anonymeter.evaluators import InferenceEvaluator ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") secret = "income" aux_cols = [c for c in ori.columns if c != secret] evaluator = InferenceEvaluator( ori=ori, syn=syn, control=control, aux_cols=aux_cols, secret=secret, regression=False, # categorical secret → exact-match scoring n_attacks=500, ) evaluator.evaluate(n_jobs=-2) risk = evaluator.risk() print(f"Inference risk: {risk.value:.3f} CI: {risk.ci}") # Example output: # Inference risk: 0.041 CI: (0.024, 0.058) # Group-wise risk: per-value breakdown of the secret column group_results = evaluator.risk_for_groups(confidence_level=0.95) for group, res in group_results.items(): grisk = res.risk() print(f" Group '{group}': risk={grisk.value:.3f} CI={grisk.ci}") # Example output: # Group '<=50K': risk=0.028 CI=(0.012, 0.044) # Group '>50K': risk=0.071 CI=(0.041, 0.101) ``` -------------------------------- ### Compute Group-wise Inference Risk Source: https://github.com/statice/anonymeter/blob/main/notebooks/attribute_inference_custom_model_and_group_wise_risk.ipynb Calculate the group-wise inference risk using the .risk_for_groups() method of the InferenceEvaluator. This is useful for understanding how privacy risk varies across different subgroups of the data. ```python risk_for_groups = evaluator.risk_for_groups() ``` -------------------------------- ### SinglingOutEvaluator Source: https://context7.com/statice/anonymeter/llms.txt Evaluates whether an attacker can use the synthetic data to construct queries that uniquely identify a single individual in the original dataset. Supports both univariate and multivariate attack modes. ```APIDOC ## SinglingOutEvaluator ### Description Evaluates whether an attacker can use the synthetic data to construct queries that uniquely identify a single individual in the original dataset. Supports both `univariate` (single-column) and `multivariate` (multi-column) attack modes. A `control` dataset (original records not used for synthesis) should be supplied for a reliable residual-risk estimate. ### Usage ```python import pandas as pd from anonymeter.evaluators import SinglingOutEvaluator # Load datasets ori = pd.read_csv("notebooks/datasets/adults_train.csv") syn = pd.read_csv("notebooks/datasets/adults_syn_ctgan.csv") control = pd.read_csv("notebooks/datasets/adults_control.csv") # Instantiate and run the evaluator evaluator = SinglingOutEvaluator( ori=ori, syn=syn, control=control, n_attacks=500, # number of singling-out queries to attempt n_cols=3, # columns combined per query (multivariate mode) seed=42, ) evaluator.evaluate(mode="multivariate") # or mode="univariate" # Access results results = evaluator.results(confidence_level=0.95) print(f"Attack rate: {results.attack_rate}") # SuccessRate(value=..., error=...) print(f"Control rate: {results.control_rate}") print(f"Baseline rate: {results.baseline_rate}") risk = evaluator.risk() print(f"Singling-out risk: {risk.value:.3f} CI: {risk.ci}") # Inspect the successful singling-out queries queries = evaluator.queries(baseline=False) print(f"Successful singling-out queries: {len(queries)}") ``` ### Parameters - **ori** (pd.DataFrame) - Original dataset. - **syn** (pd.DataFrame) - Synthetic dataset. - **control** (pd.DataFrame) - Control dataset (original records not used for synthesis). - **n_attacks** (int) - Number of singling-out queries to attempt. - **n_cols** (int) - Number of columns to combine per query (for multivariate mode). - **seed** (int, optional) - Random seed for reproducibility. ### Methods - **evaluate(mode: str)**: Runs the singling-out attack evaluation. `mode` can be 'univariate' or 'multivariate'. - **results(confidence_level: float = 0.95)**: Returns the attack rate, control rate, and baseline rate with confidence intervals. - **risk()**: Calculates and returns the singling-out risk score. - **queries(baseline: bool = True)**: Returns the successful singling-out queries. `baseline` determines whether to include baseline queries. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.