ai-privacy-toolkit/notebooks/membership_inference_diffpriv_nursery.ipynb

454 lines
44 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Running membership inference attacks on the Nursery data and defending using differential privacy"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this tutorial we will show how to run black-box membership attacks on both a vanilla model and models trained with differential privacy. The attacks are taken from the ART library's inference module (https://github.com/Trusted-AI/adversarial-robustness-toolbox) and the differentially private model implementation is taken fron the Differential Privacy Library (https://github.com/IBM/differential-privacy-library).\n",
"\n",
"This will be demonstrated on the Nursery dataset (original dataset can be found here: https://archive.ics.uci.edu/ml/datasets/nursery). "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We have already preprocessed the dataset such that all categorical features are one-hot encoded, and the data was scaled using sklearn's StandardScaler."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Load data"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"sys.path.insert(0, os.path.abspath('..'))\n",
"\n",
"from art.utils import load_nursery\n",
"\n",
"train_size = 200\n",
"(x_train, y_train), (x_test, y_test), _, _ = load_nursery(test_set=0.5)\n",
"x_train = x_train[:train_size]\n",
"y_train = y_train[:train_size]\n",
"x_test = x_test[:train_size]\n",
"y_test = y_test[:train_size]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Train logistic regression model"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Base model accuracy: 0.91\n"
]
}
],
"source": [
"from sklearn.linear_model import LogisticRegression\n",
"from art.estimators.classification.scikitlearn import ScikitlearnLogisticRegression\n",
"\n",
"model = LogisticRegression(solver=\"lbfgs\", max_iter=1000)\n",
"model.fit(x_train, y_train)\n",
"\n",
"art_classifier = ScikitlearnLogisticRegression(model)\n",
"base_model_accuracy = model.score(x_test, y_test)\n",
"\n",
"print('Base model accuracy: ', base_model_accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Attack\n",
"### Black-box attack\n",
"The black-box attack basically trains an additional classifier (called the attack model) to predict the membership status of a sample. It can use as input to the learning process probabilities/logits or losses, depending on the type of model and provided configuration.\n",
"#### Train attack model"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from art.attacks.inference.membership_inference import MembershipInferenceBlackBox\n",
"\n",
"attack_train_ratio = 0.5\n",
"attack_train_size = int(len(x_train) * attack_train_ratio)\n",
"attack_test_size = int(len(x_test) * attack_train_ratio)\n",
"\n",
"attack = MembershipInferenceBlackBox(art_classifier, attack_model_type='rf') \n",
"\n",
"#train attack model\n",
"attack.fit(x_train[:attack_train_size], y_train[:attack_train_size],\n",
" x_test[:attack_test_size], y_test[:attack_test_size])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Infer membership and check accuracy"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"attack accuracy on training data: 0.5\n",
"attack accuracy on test data: 0.5800000000000001\n",
"overall attack accuracy: 0.54\n"
]
}
],
"source": [
"# infer attacked feature\n",
"inferred_train = attack.infer(x_train[attack_train_size:], y_train[attack_train_size:])\n",
"inferred_test = attack.infer(x_test[attack_test_size:], y_test[attack_test_size:])\n",
"\n",
"# check accuracy\n",
"train_acc = np.sum(inferred_train) / len(inferred_train)\n",
"test_acc = 1 - (np.sum(inferred_test) / len(inferred_test))\n",
"acc = (train_acc * len(inferred_train) + test_acc * len(inferred_test)) / (len(inferred_train) + len(inferred_test))\n",
"print('attack accuracy on training data: ', train_acc)\n",
"print('attack accuracy on test data: ', test_acc)\n",
"print('overall attack accuracy: ', acc)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This means that for 54% of the data, membership status is inferred correctly (a little better than a random coin flip)."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"precision and recall: (0.5434782608695652, 0.5)\n"
]
}
],
"source": [
"def calc_precision_recall(predicted, actual, positive_value=1):\n",
" score = 0 # both predicted and actual are positive\n",
" num_positive_predicted = 0 # predicted positive\n",
" num_positive_actual = 0 # actual positive\n",
" for i in range(len(predicted)):\n",
" if predicted[i] == positive_value:\n",
" num_positive_predicted += 1\n",
" if actual[i] == positive_value:\n",
" num_positive_actual += 1\n",
" if predicted[i] == actual[i]:\n",
" if predicted[i] == positive_value:\n",
" score += 1\n",
" \n",
" if num_positive_predicted == 0:\n",
" precision = 1\n",
" else:\n",
" precision = score / num_positive_predicted # the fraction of predicted “Yes” responses that are correct\n",
" if num_positive_actual == 0:\n",
" recall = 1\n",
" else:\n",
" recall = score / num_positive_actual # the fraction of “Yes” responses that are predicted correctly\n",
"\n",
" return precision, recall\n",
"\n",
"# rule-based\n",
"print('precision and recall: ', calc_precision_recall(np.concatenate((inferred_train, inferred_test)), \n",
" np.concatenate((np.ones(len(inferred_train)), np.zeros(len(inferred_test))))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Train differentially private model"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"DP model accuracy: 0.56\n"
]
}
],
"source": [
"import diffprivlib.models as dp\n",
"\n",
"dp_model = dp.LogisticRegression(epsilon=5, data_norm=5)\n",
"dp_model.fit(x_train, y_train)\n",
"# print('norm: ', np.linalg.norm(x_train) )\n",
"\n",
"dp_art_model = ScikitlearnLogisticRegression(dp_model)\n",
"print('DP model accuracy: ', dp_model.score(x_test, y_test))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Black-box attack"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"attack accuracy on training data: 0.4\n",
"attack accuracy on test data: 0.62\n",
"overall attack accuracy: 0.51\n",
"precision and recall: (0.5128205128205128, 0.4)\n"
]
}
],
"source": [
"dp_attack = MembershipInferenceBlackBox(dp_art_model, attack_model_type='rf')\n",
"\n",
"# train attack model\n",
"dp_attack.fit(x_train[:attack_train_size].astype(np.float32), y_train[:attack_train_size],\n",
" x_test[:attack_test_size].astype(np.float32), y_test[:attack_test_size])\n",
"\n",
"# infer \n",
"dp_inferred_train = dp_attack.infer(x_train.astype(np.float32)[attack_train_size:], y_train[attack_train_size:])\n",
"dp_inferred_test = dp_attack.infer(x_test.astype(np.float32)[attack_test_size:], y_test[attack_test_size:])\n",
"\n",
"# check accuracy\n",
"dp_train_acc = np.sum(dp_inferred_train) / len(dp_inferred_train)\n",
"dp_test_acc = 1 - (np.sum(dp_inferred_test) / len(dp_inferred_test))\n",
"dp_acc = (dp_train_acc * len(dp_inferred_train) + dp_test_acc * len(dp_inferred_test)) / (len(dp_inferred_train) + len(dp_inferred_test))\n",
"print('attack accuracy on training data: ', dp_train_acc)\n",
"print('attack accuracy on test data: ', dp_test_acc)\n",
"print('overall attack accuracy: ', dp_acc)\n",
"\n",
"print('precision and recall: ', calc_precision_recall(np.concatenate((dp_inferred_train, dp_inferred_test)), \n",
" np.concatenate((np.ones(len(dp_inferred_train)), np.zeros(len(dp_inferred_test))))))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The differentially private model reduces the attack accuracy, but also completely ruins the model's accuracy.\n",
"Let's see if we can find a sweet spot where both acceptable accuracy and privacy can be acheived."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.01\n",
"0.1\n",
"0.5\n",
"1.0\n",
"5.0\n",
"10.0\n",
"25.0\n",
"75.0\n",
"100.0\n",
"200.0\n"
]
}
],
"source": [
"accuracy = []\n",
"attack_accuracy = []\n",
"epsilons = [0.01, 0.1, 0.5, 1.0, 5.0, 10.0, 25.0, 75.0, 100.0, 200.0]\n",
"\n",
"for eps in epsilons:\n",
" print(eps)\n",
" dp_clf = dp.LogisticRegression(epsilon=eps, data_norm=5)\n",
" dp_clf.fit(x_train, y_train)\n",
" accuracy.append(dp_clf.score(x_test, y_test))\n",
" dp_art_classifier = ScikitlearnLogisticRegression(dp_clf)\n",
" dp_attack = MembershipInferenceBlackBox(dp_art_classifier, attack_model_type='rf')\n",
" dp_attack.fit(x_train[:attack_train_size].astype(np.float32), y_train[:attack_train_size].astype(np.float32),\n",
" x_test[:attack_test_size].astype(np.float32), y_test[:attack_test_size].astype(np.float32))\n",
" dp_inferred_train = dp_attack.infer(x_train.astype(np.float32)[attack_train_size:], y_train.astype(np.float32)[attack_train_size:])\n",
" dp_inferred_test = dp_attack.infer(x_test.astype(np.float32)[attack_train_size:], y_test.astype(np.float32)[attack_train_size:])\n",
" dp_train_acc = np.sum(dp_inferred_train) / len(dp_inferred_train)\n",
" dp_test_acc = 1 - (np.sum(dp_inferred_test) / len(dp_inferred_test))\n",
" dp_acc = (dp_train_acc * len(dp_inferred_train) + dp_test_acc * len(dp_inferred_test)) / (len(dp_inferred_train) + len(dp_inferred_test))\n",
" attack_accuracy.append(dp_acc)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"plt.plot(epsilons, accuracy)\n",
"plt.plot(epsilons, np.ones_like(epsilons) * base_model_accuracy, dashes=[2,2], label=\"base model\")\n",
"plt.title(\"Differentially private logistic regression\")\n",
"plt.xlabel(\"epsilon\")\n",
"plt.ylabel(\"Model accuracy\")\n",
"plt.ylim(0, 1)\n",
"plt.xlim(0.1, 200)\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.plot(epsilons, attack_accuracy)\n",
"plt.plot(epsilons, np.ones_like(epsilons) * acc, dashes=[2,2], label=\"base model\")\n",
"plt.title(\"Differentially private logistic regression\")\n",
"plt.xlabel(\"epsilon\")\n",
"plt.ylabel(\"Attack accuracy\")\n",
"plt.ylim(0, 1)\n",
"plt.xlim(0.1, 200)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks like epsilon=25 is a good choice."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"DP model accuracy with eps=100: 0.795\n",
"DP model attack accuracy with eps=100: 0.52\n"
]
}
],
"source": [
"dp_model = dp.LogisticRegression(epsilon=25, data_norm=5)\n",
"dp_model.fit(x_train, y_train)\n",
"\n",
"dp_art_classifier = ScikitlearnLogisticRegression(dp_model)\n",
"print('DP model accuracy with eps=100: ', dp_model.score(x_test, y_test))\n",
"\n",
"dp_attack = MembershipInferenceBlackBox(dp_art_classifier, attack_model_type='rf')\n",
"dp_attack.fit(x_train[:attack_train_size].astype(np.float32), y_train[:attack_train_size].astype(np.float32),\n",
" x_test[:attack_test_size].astype(np.float32), y_test[:attack_test_size].astype(np.float32))\n",
"dp_inferred_train = dp_attack.infer(x_train.astype(np.float32)[attack_train_size:], y_train.astype(np.float32)[attack_train_size:])\n",
"dp_inferred_test = dp_attack.infer(x_test.astype(np.float32)[attack_test_size:], y_test.astype(np.float32)[attack_test_size:])\n",
"dp_train_acc = np.sum(dp_inferred_train) / len(dp_inferred_train)\n",
"dp_test_acc = 1 - (np.sum(dp_inferred_test) / len(dp_inferred_test))\n",
"dp_acc = (dp_train_acc * len(dp_inferred_train) + dp_test_acc * len(dp_inferred_test)) / (len(dp_inferred_train) + len(dp_inferred_test))\n",
" \n",
"print('DP model attack accuracy with eps=100: ', dp_acc)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}