diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..2574780 Binary files /dev/null and b/.DS_Store differ diff --git a/Regit/FHE_Regression.ipynb b/Regit/FHE_Regression.ipynb new file mode 100644 index 0000000..d008274 --- /dev/null +++ b/Regit/FHE_Regression.ipynb @@ -0,0 +1,833 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "FHE_Regression.ipynb", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "code", + "metadata": { + "id": "g10qn096oe1b" + }, + "source": [ + "#Team: Regit\n", + "#Project: Privacy Preserving Credit Card Fraud Analysis\n", + "#Members: Jatan Loya, Tejas Bana, Siddhant Kulkarni" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "TImP-23w4sqx" + }, + "source": [ + "#Install TenSeal (Wrapper for SEAL)\n", + "!pip3 install tenseal" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zVC8AU9R4bQH" + }, + "source": [ + "#Importing dependencies: PyTorch, pandas, numpy, matplotlib\n", + "import torch\n", + "import tenseal as ts\n", + "import pandas as pd\n", + "import random\n", + "from time import time\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "q2ISbd-f5ZWH", + "outputId": "7825be0f-bacc-4690-9b38-ba563dc3bca7" + }, + "source": [ + "#Downloading dataset from GDrive\n", + "!gdown --id 18Z6ZrdDtZJU-YFTLJILLkwi_-4OneoJm" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + " 8%|▊ | 5.00M/66.0M [00:00<00:02, 29.4MB/s]" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Downloading creditcardfraud.zip to ./creditcardfraud\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "100%|██████████| 66.0M/66.0M [00:00<00:00, 71.1MB/s]\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vm4-5zWW519w", + "outputId": "60b377a4-cf65-45ce-b41a-e2b80c7e92ac" + }, + "source": [ + "#Reading the dataset\n", + "dataset = pd.read_csv(\"./creditcard.csv\")\n", + "print(\"Few Entries: \")\n", + "print(dataset.head())\n", + "print(\"Dataset Shape: \", dataset.shape)\n", + "print(\"Maximum Transaction Value: \", np.max(dataset.Amount))\n", + "print(\"Minimum Transaction Value: \", np.min(dataset.Amount))" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Few Entries: \n", + " Time V1 V2 V3 ... V27 V28 Amount Class\n", + "0 0.0 -1.359807 -0.072781 2.536347 ... 0.133558 -0.021053 149.62 0\n", + "1 0.0 1.191857 0.266151 0.166480 ... -0.008983 0.014724 2.69 0\n", + "2 1.0 -1.358354 -1.340163 1.773209 ... -0.055353 -0.059752 378.66 0\n", + "3 1.0 -0.966272 -0.185226 1.792993 ... 0.062723 0.061458 123.50 0\n", + "4 2.0 -1.158233 0.877737 1.548718 ... 0.219422 0.215153 69.99 0\n", + "\n", + "[5 rows x 31 columns]\n", + "Dataset Shape: (284807, 31)\n", + "Maximum Transaction Value: 25691.16\n", + "Minimum Transaction Value: 0.0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 265 + }, + "id": "X51IG5Me7bF8", + "outputId": "6654edab-897c-4afa-aa7f-4801d1b7cdbe" + }, + "source": [ + "#Plotting a scatterplot for the dataset\n", + "color = {1:'blue',0:'yellow'}\n", + "fraudlist = dataset[dataset.Class == 1]\n", + "notfraudlist = dataset[dataset.Class == 0]\n", + "fig,axes = plt.subplots(1,2)\n", + "axes[0].scatter(list(range(1,fraudlist.shape[0]+1)),fraudlist.Amount,color='blue')\n", + "axes[1].scatter(list(range(1,notfraudlist.shape[0]+1)),notfraudlist.Amount,color='yellow')\n", + "plt.show()\n" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9EE1mi8v6Ixz", + "outputId": "afa4cf33-e314-4333-903f-fce33fa53719" + }, + "source": [ + "#Returns the number of unique class values\n", + "values = np.array(df[\"Class\"].values)\n", + "np.unique(values, return_counts=True)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(array([0, 1]), array([284315, 492]))" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 24 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "TQmcswww5N7j", + "outputId": "62607bff-0597-4302-f1fb-25b1e00a4600" + }, + "source": [ + "torch.random.manual_seed(73)\n", + "random.seed(73)\n", + "\n", + "\n", + "def split_train_test(x, y, test_ratio=0.3):\n", + " idxs = [i for i in range(len(x))]\n", + " random.shuffle(idxs)\n", + " # delimiter between test and train data\n", + " delim = int(len(x) * test_ratio)\n", + " test_idxs, train_idxs = idxs[:delim], idxs[delim:]\n", + " return x[train_idxs], y[train_idxs], x[test_idxs], y[test_idxs]\n", + "\n", + "\n", + "def credit_card_data():\n", + " data = pd.read_csv(\"./creditcard.csv\")\n", + " # drop rows with missing values\n", + " data = data.dropna()\n", + " # drop some features\n", + " data = data.drop(columns=[\"Time\"])\n", + " # balance data\n", + " grouped = data.groupby('Class')\n", + " data = grouped.apply(lambda x: x.sample(grouped.size().min(), random_state=73).reset_index(drop=True))\n", + " # extract labels\n", + " y = torch.tensor(data[\"Class\"].values).float().unsqueeze(1)\n", + " data = data.drop(\"Class\", 'columns')\n", + " # standardize data\n", + " data = (data - data.mean()) / data.std()\n", + " x = torch.tensor(data.values).float()\n", + " return split_train_test(x, y)\n", + "\n", + "\n", + "def random_data(m=1024, n=2):\n", + " # data separable by the line `y = x`\n", + " x_train = torch.randn(m, n)\n", + " x_test = torch.randn(m // 2, n)\n", + " y_train = (x_train[:, 0] >= x_train[:, 1]).float().unsqueeze(0).t()\n", + " y_test = (x_test[:, 0] >= x_test[:, 1]).float().unsqueeze(0).t()\n", + " return x_train, y_train, x_test, y_test\n", + "\n", + "x_train, y_train, x_test, y_test = credit_card_data()\n", + "\n", + "print(\"############# Data summary #############\")\n", + "print(f\"x_train has shape: {x_train.shape}\")\n", + "print(f\"y_train has shape: {y_train.shape}\")\n", + "print(f\"x_test has shape: {x_test.shape}\")\n", + "print(f\"y_test has shape: {y_test.shape}\")\n", + "print(\"#######################################\")" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "############# Data summary #############\n", + "x_train has shape: torch.Size([689, 29])\n", + "y_train has shape: torch.Size([689, 1])\n", + "x_test has shape: torch.Size([295, 29])\n", + "y_test has shape: torch.Size([295, 1])\n", + "#######################################\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "YwlEsLRF9J8h" + }, + "source": [ + "#Defining the class of linear regression model\n", + "class LR(torch.nn.Module):\n", + "\n", + " def __init__(self, n_features):\n", + " super(LR, self).__init__()\n", + " self.lr = torch.nn.Linear(n_features, 1)\n", + " \n", + " def forward(self, x):\n", + " out = torch.sigmoid(self.lr(x))\n", + " return out" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "wQKWae7x9Ur2" + }, + "source": [ + "#We have used SGD optimiser and Binary Cross entropy as Loss\n", + "n_features = x_train.shape[1]\n", + "model = LR(n_features)\n", + "optim = torch.optim.SGD(model.parameters(), lr=1)\n", + "criterion = torch.nn.BCELoss()\n" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "v4LEUvqn9XJq", + "outputId": "3a708903-08e9-4efc-bf70-ad11cfb2d95c" + }, + "source": [ + "#Number of epochs for training and the training function\n", + "EPOCHS = 15\n", + "\n", + "def train(model, optim, criterion, x, y, epochs=EPOCHS):\n", + " for e in range(1, epochs + 1):\n", + " optim.zero_grad()\n", + " out = model(x)\n", + " loss = criterion(out, y)\n", + " loss.backward()\n", + " optim.step()\n", + " print(f\"Loss at epoch {e}: {loss.data}\")\n", + " return model\n", + "\n", + "model = train(model, optim, criterion, x_train, y_train)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Loss at epoch 1: 0.26793885231018066\n", + "Loss at epoch 2: 0.2589355409145355\n", + "Loss at epoch 3: 0.25133609771728516\n", + "Loss at epoch 4: 0.2448013871908188\n", + "Loss at epoch 5: 0.2390972077846527\n", + "Loss at epoch 6: 0.2340555638074875\n", + "Loss at epoch 7: 0.2295524626970291\n", + "Loss at epoch 8: 0.22549419105052948\n", + "Loss at epoch 9: 0.22180868685245514\n", + "Loss at epoch 10: 0.21843957901000977\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "UxhjnEkS9X0R", + "outputId": "aa27441e-437f-4ad4-c7c6-27e59a599d77" + }, + "source": [ + "#Accuracy of model on plaintext test_set\n", + "def accuracy(model, x, y):\n", + " out = model(x)\n", + " correct = torch.abs(y - out) < 0.5\n", + " return correct.float().mean()\n", + "\n", + "plain_accuracy = accuracy(model, x_test, y_test)\n", + "print(f\"Accuracy on plain test_set: {plain_accuracy}\")" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Accuracy on plain test_set: 0.9152542352676392\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "CIBldnpZ9eU6" + }, + "source": [ + "#Defining class of encrypted Linear Regression Model\n", + "class EncryptedLR:\n", + " \n", + " def __init__(self, torch_lr):\n", + " self.weight = torch_lr.lr.weight.data.tolist()[0]\n", + " self.bias = torch_lr.lr.bias.data.tolist()\n", + " \n", + " def forward(self, enc_x):\n", + "\n", + " enc_out = enc_x.dot(self.weight) + self.bias\n", + " return enc_out\n", + " \n", + " def __call__(self, *args, **kwargs):\n", + " return self.forward(*args, **kwargs)\n", + " \n", + "\n", + "#Functions for encrypting and decrypting data\n", + " \n", + " def encrypt(self, context):\n", + " self.weight = ts.ckks_vector(context, self.weight)\n", + " self.bias = ts.ckks_vector(context, self.bias)\n", + " \n", + " def decrypt(self, context):\n", + " self.weight = self.weight.decrypt()\n", + " self.bias = self.bias.decrypt()\n", + " \n", + "\n", + "eelr = EncryptedLR(model)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "WXHKbc5M9rSE" + }, + "source": [ + "#Setting the parameters for FHE is very important since it has direct impact on\n", + "#Speed and accuracy of the model\n", + "\n", + "poly_mod_degree = 4096\n", + "coeff_mod_bit_sizes = [40, 20, 40]\n", + "#Creating TenSEALContext\n", + "ctx_eval = ts.context(ts.SCHEME_TYPE.CKKS, poly_mod_degree, -1, coeff_mod_bit_sizes)\n", + "#Setting Global scale for ciphertext\n", + "ctx_eval.global_scale = 2 ** 20\n", + "#Generating Galois keys for dot product operations\n", + "ctx_eval.generate_galois_keys()\n", + "\n" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "t1WDGHFx9uU_", + "outputId": "3b3f778e-b714-4c09-ea09-a253f21ca510" + }, + "source": [ + "#Encrypting the Test dataset\n", + "t_start = time()\n", + "enc_x_test = [ts.ckks_vector(ctx_eval, x.tolist()) for x in x_test]\n", + "t_end = time()\n", + "print(f\"Encryption of the test-set took {int(t_end - t_start)} seconds\")" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Encryption of the test-set took 0 seconds\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DlzRLONo9wQ0", + "outputId": "188d917b-ec7e-4d2d-a728-f6de7b553048" + }, + "source": [ + "#Written function for encrypted evaluation of the model\n", + "def encrypted_evaluation(model, enc_x_test, y_test):\n", + " t_start = time()\n", + " \n", + " correct = 0\n", + " for enc_x, y in zip(enc_x_test, y_test):\n", + " # encrypted evaluation\n", + " enc_out = model(enc_x)\n", + " # plain comparaison\n", + " out = enc_out.decrypt()\n", + " out = torch.tensor(out)\n", + " out = torch.sigmoid(out)\n", + " if torch.abs(out - y) < 0.5:\n", + " correct += 1\n", + " \n", + " t_end = time()\n", + " print(f\"Evaluated test_set of {len(x_test)} entries in {int(t_end - t_start)} seconds\")\n", + " print(f\"Accuracy: {correct}/{len(x_test)} = {correct / len(x_test)}\")\n", + " return correct / len(x_test)\n", + " \n", + "\n", + "encrypted_accuracy = encrypted_evaluation(eelr, enc_x_test, y_test)\n", + "diff_accuracy = plain_accuracy - encrypted_accuracy\n", + "print(f\"Difference between plain and encrypted accuracies: {diff_accuracy}\")\n", + "if diff_accuracy < 0:\n", + " print(\"Oh! We got a better accuracy on the encrypted test-set! The noise was on our side...\")\n", + "\n", + "#Our accuracy is better on the encrypted model as compared to plaintext eval" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Evaluated test_set of 295 entries in 2 seconds\n", + "Accuracy: 273/295 = 0.9254237288135593\n", + "Difference between plain and encrypted accuracies: -0.010169506072998047\n", + "Oh! We got a better accuracy on the encrypted test-set! The noise was on our side...\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "lXp2M8Nn90D_" + }, + "source": [ + "class EncryptedLR:\n", + " \n", + " def __init__(self, torch_lr):\n", + " self.weight = torch_lr.lr.weight.data.tolist()[0]\n", + " self.bias = torch_lr.lr.bias.data.tolist()\n", + " # we accumulate gradients and counts the number of iterations\n", + " self._delta_w = 0\n", + " self._delta_b = 0\n", + " self._count = 0\n", + " \n", + " def forward(self, enc_x):\n", + " enc_out = enc_x.dot(self.weight) + self.bias\n", + " enc_out = EncryptedLR.sigmoid(enc_out)\n", + " return enc_out\n", + " \n", + " def backward(self, enc_x, enc_out, enc_y):\n", + " out_minus_y = (enc_out - enc_y)\n", + " self._delta_w += enc_x * out_minus_y\n", + " self._delta_b += out_minus_y\n", + " self._count += 1\n", + " \n", + " def update_parameters(self):\n", + " if self._count == 0:\n", + " raise RuntimeError(\"You should at least run one forward iteration\")\n", + " \n", + " self.weight -= self._delta_w * (1 / 2*self._count) + self.weight * 0.05\n", + " self.bias -= self._delta_b * (1 / 2*self._count)\n", + " self._delta_w = 0\n", + " self._delta_b = 0\n", + " self._count = 0\n", + " \n", + " @staticmethod\n", + " def sigmoid(enc_x):\n", + " #Using approximation of sigmoid function\n", + " return enc_x.polyval([0.5, 0.197, 0, -0.004])\n", + " \n", + " def plain_accuracy(self, x_test, y_test):\n", + "\n", + " w = torch.tensor(self.weight)\n", + " b = torch.tensor(self.bias)\n", + " out = torch.sigmoid(x_test.matmul(w) + b).reshape(-1, 1)\n", + " correct = torch.abs(y_test - out) < 0.5\n", + " return correct.float().mean() \n", + " \n", + " def encrypt(self, context):\n", + " self.weight = ts.ckks_vector(context, self.weight)\n", + " self.bias = ts.ckks_vector(context, self.bias)\n", + " \n", + " def decrypt(self):\n", + " self.weight = self.weight.decrypt()\n", + " self.bias = self.bias.decrypt()\n", + " \n", + " def __call__(self, *args, **kwargs):\n", + " return self.forward(*args, **kwargs)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "cwfAqRol99ug" + }, + "source": [ + "#Again setting the parameters for FHE operations\n", + "poly_mod_degree = 8192\n", + "coeff_mod_bit_sizes = [40, 21, 21, 21, 21, 21, 21, 40]\n", + "# Creating TenSEALContext\n", + "ctx_training = ts.context(ts.SCHEME_TYPE.CKKS, poly_mod_degree, -1, coeff_mod_bit_sizes)\n", + "ctx_training.global_scale = 2 ** 21\n", + "ctx_training.generate_galois_keys()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "fr6GKbG6LNEg" + }, + "source": [ + "import tenseal as ts\n", + "\n", + "bits_scale = 40\n", + "\n", + "# Create TenSEAL context\n", + "context = ts.context(\n", + " ts.SCHEME_TYPE.CKKS,\n", + " poly_modulus_degree=16384+16384,\n", + " coeff_mod_bit_sizes=[40, bits_scale, bits_scale, bits_scale, bits_scale, bits_scale, bits_scale, 40]\n", + ")\n", + "\n", + "#Setting Global scale\n", + "context.global_scale = pow(2, bits_scale)\n", + "\n", + "#Galois keys for ciphertext rotations\n", + "context.generate_galois_keys()\n", + "context.generate_relin_keys()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "BAwjtT9b9_eJ", + "outputId": "830ca517-609d-47f3-c493-31ca2c9408fe" + }, + "source": [ + "#Encrypting training dataset\n", + "t_start = time()\n", + "enc_x_train = [ts.ckks_vector(ctx_training, x.tolist()) for x in x_train]\n", + "enc_y_train = [ts.ckks_vector(ctx_training, y.tolist()) for y in y_train]\n", + "t_end = time()\n", + "print(f\"Encryption of the training_set took {int(t_end - t_start)} seconds\")" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Encryption of the training_set took 17 seconds\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 550 + }, + "id": "IRh0vHSN-Bb9", + "outputId": "fca8339a-e2e2-4892-db5b-a79cb0f97c9c" + }, + "source": [ + "#Plotting distribution of plaintext and encrypted data\n", + "normal_dist = lambda x, mean, var: np.exp(- np.square(x - mean) / (2 * var)) / np.sqrt(2 * np.pi * var)\n", + "\n", + "def plot_normal_dist(mean, var, rmin=-10, rmax=10):\n", + " x = np.arange(rmin, rmax, 0.01)\n", + " y = normal_dist(x, mean, var)\n", + " fig = plt.plot(x, y)\n", + " \n", + "# Plaintext distribution\n", + "lr = LR(n_features)\n", + "data = lr.lr(x_test)\n", + "mean, var = map(float, [data.mean(), data.std() ** 2])\n", + "plot_normal_dist(mean, var)\n", + "print(\"Distribution on plain data:\")\n", + "plt.show()\n", + "\n", + "# Encrypted distribution\n", + "def encrypted_out_distribution(eelr, enc_x_test):\n", + " w = eelr.weight\n", + " b = eelr.bias\n", + " data = []\n", + " for enc_x in enc_x_test:\n", + " enc_out = enc_x.dot(w) + b\n", + " data.append(enc_out.decrypt())\n", + " data = torch.tensor(data)\n", + " mean, var = map(float, [data.mean(), data.std() ** 2])\n", + " plot_normal_dist(mean, var)\n", + " print(\"Distribution on encrypted data:\")\n", + " plt.show()\n", + "\n", + "eelr = EncryptedLR(lr)\n", + "eelr.encrypt(ctx_training)\n", + "encrypted_out_distribution(eelr, enc_x_train)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Distribution on plain data:\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + }, + { + "output_type": "stream", + "text": [ + "Distribution on encrypted data:\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [], + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mKxoA2Js-HEY", + "outputId": "724d8db2-5241-4863-f84f-147a4cedd092" + }, + "source": [ + "#Training the model on encrypted data\n", + "#Training for fewer epochs since FHE is very compute intensive\n", + "eelr = EncryptedLR(LR(n_features))\n", + "accuracy = eelr.plain_accuracy(x_test, y_test)\n", + "print(f\"Accuracy at epoch #0 is {accuracy}\")\n", + "\n", + "times = []\n", + "for epoch in range(1):\n", + " eelr.encrypt(ctx_training)\n", + " \n", + " t_start = time()\n", + " for enc_x, enc_y in zip(enc_x_train, enc_y_train):\n", + " enc_out = eelr.forward(enc_x)\n", + " eelr.backward(enc_x, enc_out, enc_y)\n", + " eelr.update_parameters()\n", + " t_end = time()\n", + " times.append(t_end - t_start)\n", + " \n", + " eelr.decrypt()\n", + " accuracy = eelr.plain_accuracy(x_test, y_test)\n", + " print(f\"Accuracy at epoch #{epoch + 1} is {accuracy}\")\n", + "\n", + "\n", + "print(f\"\\nAverage time per epoch: {int(sum(times) / len(times))} seconds\")\n", + "print(f\"Final accuracy is {accuracy}\")\n", + "\n", + "diff_accuracy = plain_accuracy - accuracy\n", + "print(f\"Difference between plain and encrypted accuracies: {diff_accuracy}\")\n", + "if diff_accuracy < 0:\n", + " print(\"Oh! We got a better accuracy when training on encrypted data! The noise was on our side...\")" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Accuracy at epoch #0 is 0.7423728704452515\n", + "Accuracy at epoch #1 is 0.8711864352226257\n", + "\n", + "Average time per epoch: 148 seconds\n", + "Final accuracy is 0.8711864352226257\n", + "Difference between plain and encrypted accuracies: 0.04406780004501343\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "01TXwJaKCPP1" + }, + "source": [ + "#There is difference of 4% in accuracy between plaintext model and model trained\n", + "#on encrypted data which is very close given less time for parameters tweaking" + ], + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Regit/Regit.md b/Regit/Regit.md new file mode 100644 index 0000000..d4dbf4b --- /dev/null +++ b/Regit/Regit.md @@ -0,0 +1,30 @@ +# Privacy Preserving Credit Card Fraud Detection +## Team Regit + +We aim to develop a privacy preserving credit card fraud detection system using Fully Homomorphic Encryption (FHE) and Differential Privacy (DP). + +## Proposed Features + +- Training and evaluating a regression model on encrypted data +- Neural network trained on differentially private data and evaluated on encrypted data. + + +## Tech + +We use a number of open source projects to work: + +- [TenSeal] - A python wrapper for SEAL +- [Opacus] - Framework for differential privacy +- [Pytorch] - Open source ML framework + +##Results + +We have been able to implement an encrypted Regression model which performs very well, just shaving off 4% acc vs the plaintext model. + +Colab Link: https://colab.research.google.com/drive/1DzqSIne3s0p5mXZha8wLoqVE7FchCdyN?usp=sharing +## Team + +- Jatan Loya +- Tejas Bana +- Siddhant Kulkarni + diff --git a/Regit/Regit.pptx b/Regit/Regit.pptx new file mode 100644 index 0000000..04d662b Binary files /dev/null and b/Regit/Regit.pptx differ