diff --git a/concrete-ml/linearSVR.ipynb b/concrete-ml/linearSVR.ipynb new file mode 100644 index 0000000..9948165 --- /dev/null +++ b/concrete-ml/linearSVR.ipynb @@ -0,0 +1,768 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1087af6d", + "metadata": {}, + "source": [ + "# Linear Regression using LinearSVR" + ] + }, + { + "cell_type": "markdown", + "id": "b0f118fd", + "metadata": {}, + "source": [ + "In this notebook, we show how to create, train and evaluate a linearSVR regression model using Concrete-ML library, our open-source privacy-preserving machine learning framework based on fully homomorphic encryption (FHE).\n", + "\n", + "For the sake of simplicity, we will only consider a single explanatory variable, making it easy to plot its relationship with the target variable. \n", + "\n", + "In order to identify the best set of hyperparameters for the linearSVR, we perform a grid search on the following : \n", + "\n", + "* $C$: (inverse) strength of the l2 penalization\n", + "* $\\epsilon$: margin for the support vectors\n", + "\n", + "Please refer to Scikit-Learn documentation on [linearSVR](https://scikit-learn.org/stable/modules/generated/sklearn.svm.LinearSVR.html) for more details" + ] + }, + { + "cell_type": "markdown", + "id": "244d272c", + "metadata": {}, + "source": [ + "## Import librairies" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "9ea25662", + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "import numpy as np\n", + "\n", + "from sklearn.datasets import make_regression\n", + "from sklearn.svm import LinearSVR as SklearnLinearSVR\n", + "from sklearn.metrics import r2_score\n", + "from sklearn.model_selection import GridSearchCV, train_test_split\n", + "from sklearn.metrics import make_scorer, mean_squared_error\n", + "\n", + "from concrete.ml.sklearn.svm import LinearSVR as ConcreteLinearSVR" + ] + }, + { + "cell_type": "markdown", + "id": "728a5450", + "metadata": {}, + "source": [ + "And some helpers for visualization." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "ba20b4ed", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "from IPython.display import display\n", + "\n", + "train_plot_config = {\"c\": \"black\", \"marker\": \"D\", \"s\": 15, \"label\": \"Train data\"}\n", + "test_plot_config = {\"c\": \"red\", \"marker\": \"x\", \"s\": 15, \"label\": \"Test data\"}\n", + "\n", + "def get_sklearn_plot_config(r2_score=None):\n", + " label = \"scikit-learn\"\n", + " if r2_score is not None:\n", + " label += f\", {'$R^2$'}={r2_score:.4f}\"\n", + " return {\"c\": \"blue\", \"linewidth\": 2.5, \"label\": label}\n", + "\n", + "def get_concrete_plot_config(r2_score=None):\n", + " label = \"Concrete-ML\"\n", + " if r2_score is not None:\n", + " label += f\", {'$R^2$'}={r2_score:.4f}\"\n", + " return {\"c\": \"orange\", \"linewidth\": 2.5, \"label\": label}\n" + ] + }, + { + "cell_type": "markdown", + "id": "6a8e092d", + "metadata": {}, + "source": [ + "## Generate a dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9b2dc4be", + "metadata": {}, + "outputs": [], + "source": [ + "# pylint: disable=unbalanced-tuple-unpacking\n", + "X, y = make_regression(\n", + " n_samples=200, n_features=1, n_targets=1, bias=5.0, noise=30.0, random_state=42\n", + ")\n", + "# pylint: enable=unbalanced-tuple-unpacking\n", + "\n", + "# We split the dataset into a training and a testing set\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)\n", + "\n", + "# We sort the test set for a better visualization\n", + "sorted_indexes = np.argsort(np.squeeze(X_test))\n", + "X_test = X_test[sorted_indexes, :]\n", + "y_test = y_test[sorted_indexes]" + ] + }, + { + "cell_type": "markdown", + "id": "ef0975f5", + "metadata": {}, + "source": [ + "We display the dataset to visualize the data distribution." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ae52a4e4", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0oAAAGsCAYAAADjWFdbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAABYV0lEQVR4nO3dfXxcZZ3///fMlN5QmtSWMiE2LQ2w3CjKXYGmKOUhSys3BmcQFDZyZxPZlp8R2EIAAR/uUiygEUFJcGk1i3KXNOMiyrKVqJtUqEjktviloWSgJrQBElqgNzPn98fpTGamM8ncnzMzr+fjMY/hnDkz5zon4+68e13X53IYhmEIAAAAABDmtLoBAAAAAGA3BCUAAAAAiEFQAgAAAIAYBCUAAAAAiEFQAgAAAIAYBCUAAAAAiEFQAgAAAIAYE6xuQD4Eg0Ft2bJF06ZNk8PhsLo5AAAAACxiGIY++OADVVZWyulM3G9UEkFpy5YtqqqqsroZAAAAAGzC7/dr9uzZCV8viaA0bdo0SebNKCsrs7g1AAAAAKwyMjKiqqqqcEZIpCSCUmi4XVlZGUEJAAAAwLhTcijmAAAAAAAxCEoAAAAAEIOgBAAAAAAxSmKOUjKCwaB27dpldTOQJfvtt59cLpfVzQAAAECBIihJ2rVrl9544w0Fg0Grm4Ismj59uioqKlg7CwAAACkr+aBkGIb+8Y9/yOVyqaqqasxFp1AYDMPQhx9+qHfeeUeSdPDBB1vcIgAAABSakg9Ke/bs0YcffqjKykrtv//+VjcHWTJlyhRJ0jvvvKODDjqIYXgAAABIScl3nwQCAUnSxIkTLW4Jsi0UfHfv3m1xSwAAAFBoSj4ohTCPpfjwNwUAAEC6CEoAAAAAEIOgBAAAAAAxCEoIO+SQQ9Tc3FwwnwsAAADkCkGpADkcjjEft956a1qfu2HDBtXX12e3sWlYs2aNpk+fbnUzAAAAkjc0JHm9kt9vbvv95vbQkLXtQtoISlnk8/lUUVEhn8+X0/P84x//CD+am5tVVlYWte/aa68NH2sYhvbs2ZPU586aNYsS6QAAAOmor5c6OqRFi6SeHvO5o8Pcj4JEUMoSn88nr9erwcFBeb3enIalioqK8KO8vFwOhyO8vXHjRk2bNk2//e1vdcIJJ2jSpEn6v//7P23atEm1tbVyu9064IADNH/+fP3v//5v1OfGDpFzOBz62c9+pi9/+cvaf//9dfjhh+vXv/71mG175513dO6552rKlCmaN2+eHnzwwX2O+cEPfqBjjjlGU6dOVVVVlf71X/9V27dvlyR1dXXpsssu0/Dw8D49ZG1tbTrxxBM1bdo0VVRU6KKLLgovKgsAAGCp5mapulrq65MWLjSfq6vN/ShIBKUsCIWkYDAoSQoGgzkPS+O5/vrrdfvtt+vVV1/VZz7zGW3fvl1nnXWW1q1bp+eff15LlizRueeeq/7+/jE/57vf/a4uuOACvfDCCzrrrLN08cUX69133014/KWXXiq/36+nn35ajz32mH7yk5/sE2acTqfuvvtuvfzyy/r5z3+u3//+91qxYoUkqaamZp9eslAP2e7du/W9731Pf/vb39TZ2anNmzfr0ksvzexGAQAAZENVldTWFr2vrc3cj8JklIDh4WFDkjE8PLzPax999JHxyiuvGB999FFan93Z2Wm4XC7D4XAYksIPh8NhuFwuo7OzM9Pmj2n16tVGeXl5ePvpp582JCV13k996lPGj3/84/D23LlzjR/+8IfhbUnGTTfdFN7evn27Icn47W9/G/fzXnvtNUOS8eyzz4b3vfrqq4akqM+N9eijjxozZ85MeE2JbNiwwZBkfPDBB3Ffz/RvCwAAkLT+fsOorjYMafRRXW3uh62MlQ0i0aOUoYaGBgUCARmGEbXfMAwFAgE1NDRY0q4TTzwxanv79u269tprddRRR2n69Ok64IAD9Oqrr47bo/SZz3wm/N9Tp05VWVlZwuFur776qiZMmKATTjghvO/II4/cpzDD//7v/+oLX/iCPvnJT2ratGmqq6vT0NCQPvzwwzHb8txzz+ncc8/VnDlzNG3aNJ122mmSNO41AAAA5Fxj4+hwu+7u0WF4jY1WtwxpIihlqKWlRS6XSw6HI2q/w+GQy+VSS0uLJe2aOnVq1Pa1116rtWvX6rbbbtOf/vQn9fb26phjjtGuXbvG/Jz99tsvatvhcISHGKZj8+bNOuecc/SZz3xG7e3teu6553TvvfdK0pht2bFjhxYvXqyysjI9+OCD2rBhg9auXTvu+wAAAPKitVXyeKSuLqmmxnz2eMz9KEgTrG5AoautrVV7e3t4jpJhGHI4HHI6nWpvb1dtba3VTZQkdXd369JLL9WXv/xlSWYP0+bNm7N6jiOPPFJ79uzRc889p/nz50uSXnvtNb3//vvhY5577jkFg0HdddddcjrNnP7II49Efc7EiRMVCASi9m3cuFFDQ0O6/fbbVbV3rO9f/vKXrLYfAAAgbTNnSu3to9tVVdHbKDj0KGVBKCyFfvjbLSRJ0uGHH66Ojg719vbqb3/7my666KKMeobiOeKII7RkyRI1NDTomWee0XPPPadvfOMbmjJlSviYww47TLt379aPf/xj9fX1qa2tTffdd1/U5xxyyCHavn271q1bp23btunDDz/UnDlzNHHixPD7fv3rX+t73/teVtsPAAAAhBCUsiQUltxut+1CkmSW5P7EJz6hmpoanXvuuVq8eLGOP/74rJ9n9erVqqys1GmnnSaPx6P6+noddNBB4dc/+9nP6gc/+IG+//3v69Of/rQefPBBrVy5Muozampq9M1vflMXXnihZs2apVWrVmnWrFlas2aNHn30UR199NG6/fbbdeedd2a9/QAAAIAkOYzYKgRFaGRkROXl5RoeHlZZWVnUax9//LHeeOMNzZs3T5MnT7aohcgF/rYAABS4oSFzwdbmZnMom99vFkdobTWHugFpGCsbRKJHCQAAAPZUXy91dEiLFkk9PeZzR4e5H/Y3NCR5vWbAlcxnr9fcXwAo5gAAAAB7am6WenvNMtsLF5r7qqvN/bC/UNDt7TUX362rM/+WUkEUuqBHCQAAAPZUVWX+wI7U1mbuh/01N4+uJ7Vw4eg6UwUSdAlKAAAAsCe/3+yFiFRXNzqUC/ZW4EGXoAQAAAB7amwc7YXo7h7tnWhstLplSEaBB12CEgAAAOyptVXyeKSuLqmmxnz2eMz9sL8CD7oUcwAAAIA9zZwZPem/qqogigBgr1CgDZV37+oaLe9eAAhKAAAAALKvwIMuQ++QFZs3b5bD4VBvb6/VTQEAAAAyRlAqQA6HY8zHrbfemtFnd3Z2Zq2tY7n00kt13nnn5eVcAAAAQCoYeleA/vGPf4T/++GHH9bNN9+s1157LbzvgAMOsKJZAAAAQNGgR6kAVVRUhB/l5eVyOBxR+x566CEdddRRmjx5so488kj95Cc/Cb93165dWr58uQ4++GBNnjxZc+fO1cqVKyVJhxxyiCTpy1/+shwOR3g7nmeffVbHHXecJk+erBNPPFHPP/981OuBQEBXXHGF5s2bpylTpuiII47Qj370o/Drt956q37+85/L5/OFe8K6urokSdddd53+6Z/+Sfvvv7+qq6v1ne98R7t3787OzQMAAACSQI9SNgwNSfX1oxU9/P7Rih4zZ+a1KQ8++KBuvvlm3XPPPTruuOP0/PPPa+nSpZo6daouueQS3X333fr1r3+tRx55RHPmzJHf75d/by37DRs26KCDDtLq1au1ZMkSuVyuuOfYvn27zjnnHP3zP/+z/uu//ktvvPGGvvWtb0UdEwwGNXv2bD366KOaOXOmenp6VF9fr4MPPlgXXHCBrr32Wr366qsaGRnR6tWrJUkzZsyQJE2bNk1r1qxRZWWlXnzxRS1dulTTpk3TihUrcnjnAAAAgFEEpWyor5c6OqTeXnO14bo6s0a8lPfKHrfccovuuusueTweSdK8efP0yiuvqKWlRZdccon6+/t1+OGH69RTT5XD4dDcuXPD7501a5Ykafr06aqoqEh4jl/+8pcKBoP6z//8T02ePFmf+tSn9NZbb+nKK68MH7Pffvvpu9/9bnh73rx5Wr9+vR555BFdcMEFOuCAAzRlyhTt3Llzn3PddNNN4f8+5JBDdO211+qhhx4iKAEAACBvCErZ0NxshqS+PmnhQnNfdbW5P4927NihTZs26YorrtDSpUvD+/fs2aPy8nJJZgGFf/7nf9YRRxyhJUuW6JxzztGZZ56Z0nleffVVfeYzn9HkyZPD+xYsWLDPcffee68eeOAB9ff366OPPtKuXbt07LHHjvv5Dz/8sO6++25t2rRJ27dv1549e1RWVpZSGwEAAIBMMEcpG6qqzJ6kSG1t5v482r59uyTp/vvvV29vb/jx0ksv6c9//rMk6fjjj9cbb7yh733ve/roo490wQUX6Pzzz896Wx566CFde+21uuKKK/Q///M/6u3t1WWXXaZdu3aN+b7169fr4osv1llnnaXHH39czz//vG688cZx3wcAAABkEz1K2eD3m8PtItXVmasP5zEsud1uVVZWqq+vTxdffHHC48rKynThhRfqwgsv1Pnnn68lS5bo3Xff1YwZM7TffvspEAiMeZ6jjjpKbW1t+vjjj8O9SqEgFtLd3a2amhr967/+a3jfpk2boo6ZOHHiPufq6enR3LlzdeONN4b3vfnmm2NfOAAAAJBl9ChlQ2OjOeyuulrq7jaf+/rM/Xn23e9+VytXrtTdd9+tv//973rxxRe1evVq/eAHP5Ak/eAHP9CvfvUrbdy4UX//+9/16KOPqqKiQtOnT5dkzglat26dBgYG9N5778U9x0UXXSSHw6GlS5fqlVde0RNPPKE777wz6pjDDz9cf/nLX/Tkk0/q73//u77zne9ow4YNUccccsgheuGFF/Taa69p27Zt2r17tw4//HD19/froYce0qZNm3T33Xdr7dq12b9RAAAAwBgIStnQ2ip5PGYPUk2N+ezxmPvz7Bvf+IZ+9rOfafXq1TrmmGN02mmnac2aNZo3b54ks6LcqlWrdOKJJ2r+/PnavHmznnjiCTmd5lfhrrvu0lNPPaWqqiodd9xxcc9xwAEH6L//+7/14osv6rjjjtONN96o73//+1HHNDQ0yOPx6MILL9TJJ5+soaGhqN4lSVq6dKmOOOIInXjiiZo1a5a6u7v1pS99Sd/+9re1fPlyHXvsserp6dF3vvOdHNwpAAAAIDGHYRiG1Y3ItZGREZWXl2t4eHifogAff/yx3njjDc2bNy+qOAEKH39bAAAAxBorG0SiRwkAAAAAYhCUAAAAACAGQQkAAAAAYhCUAAAAACAGQQkAAAAoUj6fTxUVFfL5fFY3peAQlPYqgeJ/JScYDFrdBAAAAMv4fD55vV4NDg7K6/USllI0weoGWG2//faTw+HQ1q1bNWvWLDkcDqubhAwZhqFdu3Zp69atcjqdmjhxotVNAgAAyKtQSAr9w3EwGJTX61V7e7tqa2stbl1hyOk6SitXrlRHR4c2btyoKVOmqKamRt///vd1xBFHhI/5+OOPdc011+ihhx7Szp07tXjxYv3kJz+R2+0OH9Pf368rr7xSTz/9tA444ABdcsklWrlypSZMSC7njVcrffv27XrrrbfoVSoy+++/vw4++GCCEgAAKCmRISny963D4ZDT6Sz5sJTsOko5DUpLlizRV7/6Vc2fP1979uzRDTfcoJdeekmvvPKKpk6dKkm68sor9Zvf/EZr1qxReXm5li9fLqfTqe7ubklSIBDQscceq4qKCt1xxx36xz/+oa9//etaunSpbrvttqTakczNCAQC2r17d3YuHJZzuVyaMGECPYQAAKDkVFRUaHBwMOHrbrdbAwMDeWyRvdgiKMXaunWrDjroIP3hD3/Q5z//eQ0PD2vWrFn65S9/qfPPP1+StHHjRh111FFav369TjnlFP32t7/VOeecoy1btoR7me677z5dd9112rp1a9zegp07d2rnzp3h7ZGREVVVVY17MwAAAIBCR4/S2JINSnkt5jA8PCxJmjFjhiTpueee0+7du3XGGWeEjznyyCM1Z84crV+/XpK0fv16HXPMMVFD8RYvXqyRkRG9/PLLcc+zcuVKlZeXhx9VVVW5uiQAAADAVmpra9Xe3i6n0xkeXUNISl3eglIwGFRjY6MWLlyoT3/605KkgYEBTZw4UdOnT486NrI7cGBgICokhV4PvRZPU1OThoeHww+/35/lqwEAAADsKzIsSSIkpSFvQWnZsmV66aWX9NBDD+X8XJMmTVJZWVnUAwAAACglobDkdrsJSWnIS1Bavny5Hn/8cT399NOaPXt2eH9FRYV27dql999/P+r4wcFBVVRUhI+JnYwW2g4dAwAAAGBftbW1GhgYICSlIadByTAMLV++XGvXrtXvf/97zZs3L+r1E044Qfvtt5/WrVsX3vfaa6+pv79fCxYskCQtWLBAL774ot55553wMU899ZTKysp09NFH57L5AAAAAEpUThecXbZsmX75y1/K5/Np2rRp4TlF5eXlmjJlisrLy3XFFVfo6quv1owZM1RWVqarrrpKCxYs0CmnnCJJOvPMM3X00Uerrq5Oq1at0sDAgG666SYtW7ZMkyZNymXzAQAAAJSonJYHT7SGzerVq3XppZdKGl1w9le/+lXUgrORw+refPNNXXnllerq6tLUqVN1ySWX6Pbbb8/agrMAAAAASoMt11GyCkEJAAAAgGTTdZQAAAAAoBAQlAAAAAAgBkEJAAAAAGIQlAAAAAAgBkEJAAAAAGIQlAAAAErB0JDk9Up+v7nt95vbQ0PWtguwqZwuOAsAAACbqK+XOjqk3l6prU2qq5P6+szX2tstbRpgRwQlAACAUtDcbIakvj5p4UJzX3W1uR/APhh6BwAAUAqqqsyepEhtbeZ+APsgKAEAAJQCv98cbheprm50zhKAKAQlAACAUtDYaA67q66WurvN574+cz+AfRCUAAAASkFrq+TxSF1dUk2N+ezxmPsLhM/nU0VFhXw+n9VNQQlwGIZhWN2IXBsZGVF5ebmGh4dVVlZmdXMAAACQIp/PJ6/Xq0AgIJfLpfb2dtXW1lrdLBSgZLMBPUoAAACwtVBICgaDkqRgMCiv10vPEnKKoAQAAADbigxJoYFQhmEQlpBzBCUAAIBSMjQkeb2j1e78fnN7aMjadiXQ0NCgQCCg2NkihmEoEAiooaHBopah2BGUAAAAbChnhQvq66WODmnRIqmnx3zu6DD321BLS4tcLpccDkfUfofDIZfLpZaWFotahmJHMQcAAACbyWnhAr/fDEd9faP7qqvNKng2XXw2dvidw+GQ0+mkoAPSQjEHAACAApTzwgVVVVJbW/S+tjbbhiRJqq2tVXt7u5xO86crIQn5QFACAACwibwULvD7pbq66H11daNzlmwqFJbcbjchCXnB0DsAAACbqKio0ODgYMLX3W63BgYGMjuJ12vOSaquNnuS6urMYXgej9TentlnAwWAoXcAAAAFJi+FC1pbzVDU1SXV1JjPHo+5H0AYPUoAAAA2QuECILfoUQIAAChAFC4A7IGgBAAAYDMULgCsR1ACAACwodraWg0MDOQ1JOVskVugABGUAAAAEJ4bNTg4mN11m4ACRVACAAAocTlf5BYoQAQlAACAIpTsMLq8LHILFCDKgwMAABSZUPgJBAJyuVxjFoTIyyK3gI1QHhwAAKAEpTqMLi+L3AIFiKAEAABQJNIZRldbW6sVK1aEF7eVxCK3gBh6BwAAUDTSGUYXOUwvZLzhekAhY+gdAABAiUl1GF3sML2QFStWEJJQ8ghKAAAAiQwNSV6v5Peb236/uT00ZG27EqitrVV7e7ucTue4w+jiDdMLHb9q1Sqq3aHkEZQAAAASqa+XOjqkRYuknh7zuaPD3G9TkWFJUsK5Rg0NDQoEAoqdhWEYhgKBgBoaGvLWZsCOCEoAAACJNDdL1dVSX5+0cKH5XF1t7rexUFhyu90J5xpR7Q4YG8UcAAAAxtLTY4akkO5uqabGuvZkUezwO6rdoRRQzAEAACBTfr9UVxe9r65udM5SgUt2mB5QighKAACgKPh8PlVUVGS3CEFj4+hwu+7u0WF4jY3ZO4fFkhmmB5QighIAACh4oSFkg4ODCRdWTUtrq+TxSF1d5nC7ri5zu7U1O5+fA+kExtraWg0MDBCSgAjMUQIAAAWNeTajIhePZdFYID7mKAEAgKIXby0gwzAUDAaz27NUAGIXjy3FewBkE0EJAADkRS7mELEWkMnn88nj8UTdi2IIjPt8ZwpsAWAUNoISAADIuVzNIWItINMll1wS7kmKVMiBMe53pgAXAEbhIigBAICcyuWQsMjy1qGwVGpzlHw+nz744IO4rxVqYEz0nXnyi18syAWAUZgISgAAIGfyMYeolNcCCt3fRLW5HA5H/Hth4yFsY31nzv7mN/XH2N6jtjapqsqClqLYUfUOAADkTEVFhQYHBxO+7na7NTAwkJVz+Xw+NTQ0qKWlpSRCkjT+/Z0+fbree++9fV/wes0ha9XVZtCoqzN7Zzweqb09hy0e31jXNFvSn1wuHRIIjO6srjbLthOWkCSq3gEAAMslM4coW0UeSnEtoET3VzJ71tasWRP/jc3Nth3CNtZ35keSGZKKeAFg2AdBCQAA5Ey8OUQzJT1mGPrNffdJkr7l8ejewUEt9XgKtjqbVRLN0XK5XOro6EgcGquqzJ6kSDYZwjbWvLPJv/hFwS0AjMJFUAIAADkVO4eoVZJH0qk33aQ7PR6tCwbllfTTAi9lnY5s9KalNUfL7zeH20Wqqxuds2SxRNd0Vl2dOTQwFOiqqsztmTMtbC2KFUEJAADkXOiHr9vt1tT779cOt1tTBwf1p2BQh0raJKlRpbVIajZLpkfe36QKWTQ2jg63s+kQtpSvCcgyijkAAIDEhobMNWqam81/vff7zR/Tra0Z/Sv+OTNm6PGIIgM1ktZHvJ7NIg92FFvZLe8lzXP0dwUKAcUcAABA5nKxwKffr5/H/Dttm8yKZoW67k8q8lEyfVwzZzKEDRgHQQkAAITtM2cmB9XRtlxwgWa+/742yexJ2iTpUEnNMgPDihUrinqYVUNDgwKBwD5rHxmGoUAgoIaGBotaBiASQQkAAEhKMGcmB9XRvrBpk9olLZI53G6RpHZJoT6qBx54IO3PLgTJlEwHYD2CEgAAiBoOJo0WVXjyZz/LenW02++/Xxe6XHp7b1B4S9L5kt6Vxg0K2VpzyUpjlb+maAFgHwQlAABK3FhzZnYsXZr16mhjrf0zVlDIZpU4q6VV0htAXhGUAAAocWPNmVkq6fFJk7K+wGeqQSFRj1cxhCXKXwP2RFACAKDEjTVnZtjlUuDhh3NSHS3ZoGCLKnE5Ultbq4GBAUISYEOsowQAAKxf12cMFRUVGhwcTPh6sa+5FMvn86mhoUEtLS2W/22AQsQ6SgAAIGl2njNDlbhRxTRPC7A7ghIAAJBk3zkzVIkzFeM8LcDOGHoHAAAKQigoBAKBcSvkFZt487Sk0gyMQKYYegcAAIqKpT1eQ0OS1zu6fpTfb24PDeXl9GNVJgwEAmpoaMhLO4BSktOg9Mc//lHnnnuuKisr5XA41NnZGfW6YRi6+eabdfDBB2vKlCk644wz9P/+3/+LOubdd9/VxRdfrLKyMk2fPl1XXHGFtm/fnstmAwAAm7KsSlx9vdTRIS1aJPX0mM8dHeb+PGCeFpB/OQ1KO3bs0Gc/+1nde++9cV9ftWqV7r77bt1333165plnNHXqVC1evFgff/xx+JiLL75YL7/8sp566ik9/vjj+uMf/6j6PP0fJQAAAElSc/PoYrsLF44uwtvcnJfTM08LyL+8zVFyOBxau3atzjvvPElmb1JlZaWuueYaXXvttZKk4eFhud1urVmzRl/96lf16quv6uijj9aGDRt04oknSpJ+97vf6ayzztJbb72lysrKpM7NHCUAAJCxnh4zJIV0d5uL8OZRKc/TArLF9nOU3njjDQ0MDOiMM84I7ysvL9fJJ5+s9evXS5LWr1+v6dOnh0OSJJ1xxhlyOp165plnEn72zp07NTIyEvUAAAAWsniOT8b8fqmuLnpfXd3o9eSJXSsTAsXIsqAUWhjO7XZH7Y9cNG5gYEAHHXRQ1OsTJkzQjBkzxlxYbuXKlSovLw8/qkKriQMAgPwbGpI+85nROT5r10pHHZXXOT4Za2wcHW7X3T06DK+xMe9NsWyeFlBiirLqXVNTk4aHh8MPf57/tQcAAESor5e2bJEmTDDDhccj7dghTZ2atzk+GWttNdvd1WUOt+vqMrdbW61uGYAcmWDViSsqKiRJg4ODOvjgg8P7BwcHdeyxx4aPeeedd6Let2fPHr377rvh98czadIkTZo0KfuNBgAAqWtulnp7zZAUqa1NKpRRHzNnSu3to9tVVdHbAIqOZT1K8+bNU0VFhdatWxfeNzIyomeeeUYLFiyQJC1YsEDvv/++nnvuufAxv//97xUMBnXyySfnvc0AACANVVXSnXfuu//aa/M+xwcAkpXToLR9+3b19vaqt7dXklnAobe3V/39/XI4HGpsbNS///u/69e//rVefPFFff3rX1dlZWW4Mt5RRx2lJUuWaOnSpXr22WfV3d2t5cuX66tf/WrSFe8AAIDF/H7pX/4lel9oGF6cOT4+n08VFRXy+Xz5aR8AxJHToPSXv/xFxx13nI477jhJ0tVXX63jjjtON998syRpxYoVuuqqq1RfX6/58+dr+/bt+t3vfqfJkyeHP+PBBx/UkUceqS984Qs666yzdOqpp6qV8cAAABSOxkbpww+l/fc3CzhUV0t79kiVlfvM8QmVvx4cHJTX6yUsAbBM3tZRshLrKAEAYKGhIbOgQ3OzOQzP7zfDU2urOfdnr1BICgaDMgyDBVUB5ESy2YCgBAAALBcbkkIISwCyjaAUgaAEAIC9VVRUaHBwMOHrkessAkAmks0GRbmOEgAAKCwtLS1yuVxyOBxR+x0Oh1wul1paWixqGYBSRVACAACWq62tVXt7u5xOZzgsMewOgJUISgAAwBYiw5IkQhIASxGUAABATsVdF2loSPJ6Rxec9fslr1e1p56q9vZ2ud3urIQk1mQCkC6CEgAAJcKK0JBwXaT6enNNpUWLpJ4e87mjQ6qvV21trQYGBrISkliTCUC6qHoHAEAJCIWGQCAgl8uVlyFtY66LdPzxZjjq6xt9Q3W11NVlrrWUy3MzlA8oaVS9AwCUFIZYJRYZGiQpGAxmvYcl9v7HWxfJMIzRc//1r1JbW/SHtLXlJCTtc26+IwCSQI8SAKDgWdFbUijysZBrvPvf0NAw5rpIxx14oP5aVpaTHiXWZAIwFnqUAAAlIR+9JYXA5/PpqIMO0pYFC6IKJLguvFDlgYBi/13UMAwFAgE1NDRkfN549//yyy8fc12kxw87zAxJ1dVSd7f53NcnNTZm1B6JNZkAZAdBCQBQsBhiZQrdh3/fulWVf/6zdsyfHy6QcM7OnbpfykloGOv+r1q1SitWrEi4LlLlL34hVVZKv/ylVFNjPldWSrffnnZ7QuKtyTRT0mOGod/cd5/Zg7a3yp6GhjI+H4DiRFACABSshoYGBXLYW1IIIsNKo6RNkqYODkoLF4Z7bKbef39OFnId7/4/8MADiddFuv56acsW6aKLzFB30UXm9vXXp92eSLFrMrVK8khavHLlPlX2ACAeghIAoGDZYYiVlUUkYnt03pJUF3tQW5sWf+MbKS/kmsx1JXP/Q4Fln3WRmptHh9tFhDo1N6d8HxKJPPfU++/P+fkAFBmjBAwPDxuSjOHhYaubAgDIss7OTsPlchkOh8OQZDgcDsPlchmdnZ15O7ekvJ0zktvtNiSFH7Ml43XJMCIf1dWG0d8fbq/b7R63nalcV0b3v7s7uq3d3Sldf8ryfT4AtpRsNqBHCQBQ0GKHWOVrrZzxikjko6cptkenWdKhMofffc7p1A63O6pAQjILuaZaHCPt++/3S3Ux/V91daOFKLIt3+cDUPjyFNwsRY8SABS/ZHtLsnWuyF4UScYMyXhMMuY6nUZTU5Mx1+k0HpOMWU5nVtqU6Poi2xLZhs7OTrMnyeMxjG3b0r4uJdlLlPL993hGe7y6u81nydyfC/k+HwDbSjYbEJQAAEhR7JA37Q0oxt6hbwsihsA9FjF8baywM1bIGG8oXLaGAMa7rsiH2+1O63Pj2rbNDCl7hwWmGupsfz4AtpVsNmDBWQAAUhSvLPZsSV0yh76FbJK0SNLbDkd4eFwwGBxdFPfUU7XlnHNU8+yzejMY1FynUz0nnaTKxx+XZs6Me65EFet8Pp8aGhrCBRSydV1SdhenzbVs3AcAxS3ZbEBQAgAgDfECzCmGoZ6IY2okrY/z3lDw6D3sMH36tde0SWa1ujaZQWvLKaeocv16S4JLssHMjkJtDwQCo2HU5m0GkH/JZgOKOQAAkIbYIgZzHA799/TpUce0yexpimXsXZT1i3tD0qGSejRaiKHm2WfDPSP5XifKquIYmUq1CAUAjIegBABAmiLX6ek56STNfP997XC79TmnMxyAmhO810iw7lGdpDeDwfDwMSvWiUq49pFNxet5C4VRwhKAdBGUAADIQKjkduXjj0sej6Zu2KBrOzr0BadT7ZK+uXfoWrywM1tmr1OkNklznc6oxVoj37/PULihIcnrHS1z7feb20NDWbkuu4ckSZb0vAEofgQlAACyYeZMqb1dqqpSbW2tftTRoWVut362dq06Ojrihp3fHnHE6HC7vc+HSuo56aRwQBl3KFx9vdTRIS1aJPX0mM8dHeZ+i+RjDalIVvW8AShuFHMAACAP4hYaSKLqXeT741Zz8/vNcNTXN7qvulrq6pKqqvJybZGsKqhQyEUoAOQXxRwAAMiHJIe+xZ33M3OmKtev1486OuR2u/Wjjg5Vrl+/T0gKvT/uULiqKqktZgBfW5ulIcmKggqFWoQCgH3RowQAQCa8XnOoW3W1GVDq6szeHY9Ham/P/bo+NulRsssaTKyjBGA8rKMUgaAEAMiZMYKK769/zf0wtHGCWr5UVFRocHAw4etut1sDAwN5aw8AJMLQOwAA8iHB0LdQSMr5MLTWVjMUdXVJNTXms8dj7s8jCioAKDYEJQAAkhS3mpvfb/biRNjh8ehbHs/46/qE5je98IL5/Mwz0dt75zmNWUUuotqeJPO5vT3uPKdcSqqUeRZlVFkvRyXVARQZowQMDw8bkozh4WGrmwIAKFCdnZ2Gy+UyJBkul8vo7Ow0X/B4DEMyjOpqw+juNp8l4zHJUIKH2+2Ofu/++5vPEyaYz1Onms8eT+Lz2lQ+2pvxORL8zQyPJ+ttBWA/yWYDepQAAHmR77V1smnMam5xhr5tOeUUXRnRszJD0mOSqiS5XC79/N//3ezBuOUWc27Rhx+aJ9qzx3zesUOqrtaTX/yiZVXk0hW3ul8WjfW3SPo71txs3ve+PmnhQvO5utrcDwAheQpulqJHCQCsVWi9IpFCbXc4HFG9Qg6HY8xriXzfY5JhSMbrkvHTurroHozubvO/Yx5/uP32lM/b2dlpuN3ugrq/qRjrb+F0Og2n05n8dyz2vnd35+ciAFgu2WxA1TsAQE4V+kKgmVRzC137wYGAuiQdGvninDnSI49IF1wg9ffv897NLpc+FwjorSTPa9VCr/k03t8iZNzvmE1KqgOwBlXvAACWi7e2jhGvqIGFxhuulUk1t9raWq1YsUJvSfp6zGsfbd8uXXdddEiaMMF8njpVhwQC+tHe84x3XisXes2nRH+LWON+xxobR4fbdXePDsNrbMxJuwEUqJz3bdkAQ+8AwBputzthQQNFFjXItW3bzGFu/f3mdn+/YXg8xm9+8YukhgTGDvkab9hd7Puq9g67izfEzpAM45OfNIwvftEw/vxns51/+1tU+8Y6b7pDAwtVoutN6TuW4PtgbNuW34sBYIlkswFBCQCQM7b5EZ+gyln73rYk06Z05lmFgmLkHKUFkuGPDUp758fEm2M03nnHC6NOp7Now1Lo+pxOp/XfMQAFg6AUgaAEANZJtzcmq/r7RwsoRISWqphQkUxYSqVYQujaZ+4NS7P3PjbHBqW5c42B44835u4tRjDX6TTePuWUcA/HWOdNpoelGAND5D2xxXcMQMGgmEMEijkAgLVsUWigp8csBb1XjaT1CQ4dq0BDqmLnaT0myStph9utqR0d5mK1e4sKbJJUJ6lNZuGHLaecosr1iVqZ+BwhDoejIAtopMMW3zEABYFiDgAA28j12jrj8vvNQBKhTea6RpESFUrIZP2n0LU7neb/y73S6dSWU07R1A0bpJoaPdnUpN9KekNmOOrZ+7xJUs2zzyZ13thzhK7FsGkBjVyw/DsGoPjkumvLDhh6BwDZUbDr9KQ5Rymb6z8lmn8UWvtnQcxwvAVpFLyI/LxEj7wU0KBYAgAbY45SBIISAGSukBeNTabqnSSjqakp/JZcz3uJvJ+z41TFe33vXKVUz5eLAhopB+QEwdTweFI+NwBkG3OUIjBHCQAyU+iLxo7lhhtu0MqVKyUpPLdFUsI5P9m47kTzltKdozTe52fS7rTm/rCgKwAbSzYbEJQAAGMaq1BAoYelRIHigAMO0PDwcML3ZVLsId79nCGpVVKjpLckzXU61XPSSap8/HFp5syMzpNJcYOMAldM8Qx1d0s1NWlcCQBkF8UcAABZ0dDQoEAgoNh/VzMMQ4FAQA0NDRa1zJRusYV4gcXYW/Tggw8+kNPplMPhiHpPvGIPqYp3P9+VdL7MkOR0OvWjjg6zJynNkCRlXtxgrPszblGIOMUzVFdn7geAAkFQAgCMqaWlRS6XSzMlPSZp9t79VZLaJT1wxx2WtS30Y35wcDDqx3sy4WmsABgMBlVWVhYVlrLVgxa6n4lCWEdHR9Z66GprazUwMJDW52UUkBsbzWF31dVmT1J1tbnd2JhyOwDAKgQlAMCYQj0TrTLn0XTJXIPoaUkeSWd1dua2AUNDktc72hvh90ter55oawv3eEgK93TccMMNccNTrPECy5o1a6JKbmdrmGFkKe/YEPbr1atV+4tf7HOtGhrK6JzpGO/+jNmr1toqeTzmnKSaGvPZ4zH3A0ChyHYVCTui6h0AZO5399+/T2U2o7p6tJJcriRR2jv2kWylumQq2+WqJHrcKoI2qxaX68p/AGAFyoNHICgBQHb84fbbo4NSd3dmH5jMejv9/aOBYe/jDZfLmD3GWkGxoSmZsBQVWJKUaYja5/1xrjUvYXScNhZsWXgAiIOgFIGgBACpy8uP+GR7ULq7o877h9tvj7tW0FiPsRZaTSfw5CxAxFxrxmE0Cwp2oWEAiIOgFIGgBABji/0hnLdhYcmErwTH/O7++xMurJpKj1I6cjYkzYY9SgBQbJLNBhRzAIASF1s5LlQMIbZIwhPnnZf9CfpVVVJbW/S+trboRUkTVFBb/NvfRhVbcLlcampqykmlukgZlc2O81lR1fmoFgcA9pGX2GYxepQAIL54PSNKY55P2pLpQRlnHlNSvWHZsLcdxx14oCHJmC0Zj0nGjBSG+EWK285k5mwBADLC0LsIBCUAtmKTH8OxISmZR3l5eXbnq+SoyltO5tTsbet2t9s41ekMVwB8LE6YHO/8VJMDAOsQlCIQlADYik1KQLvd7qQDUmTPktPpzF5vTZKhMWvBJ975zj7bMM45Z/zgGqf36/W9PUuh+zJ9+nSjqalpzB6tRAGVsAQA+UFQikBQAmArNpmwP9YP9mRDUz7WHMrqULpEITXZ4BpTke7UvaHR6XSGA2TkPYx3j8YLqMkO3StoNulVBVCaCEoRCEoAbMcmJaATDQFramqK+uGfTFjKxdygrA9RixdS58wxH+MF1zjv3e52G0dPmzbmvYptMz1Khm16VQGUJoJSBIISAFuxSY9SSKKAM3369JTmLsUrCtHU1JRxu7IeKOKF1GSCa4If9+1J9sJF9hSV/Bwlm/1vAEBpoTw4ANiVzUpA19bWqr29XW63O6qM9po1a+RyucKltuMJld/+4IMP9imXLUkrV67UDTfckFa7GhoaFAgEwp8VYhiGAoGAGhoaUv9Qv1+qq4ve97WvmY9IdXXmsRGeOO88PT5pkp5sagqXR3980iQtlfZpYyyn06mWlpbwduieh0qbZ7uEue0lUxYeAKyW+8xmPXqUANhKAc3PGKsyXqgXJJmep3R6SnLSo5TmHKVEvW7JVg50Op1x25uT6nyFgB4lABZi6F0EghKAUpStH+GRISGyaEHs3KSxwkK6wSbrQ9TSqHo3XhuSuX4rh9bZMowxRwmAhQhKEQhKAEpNtgsrRP7YjvfDu7OzM6U5OlZeSzrnHq9XK7KNubgHmbbfins3pgLqVQVQfAhKEQhKAEqJVYUCmpqaxgwJmRZ2sKJXJJVS3p2dncb06dONAx0O4zGZ6ytp7/NjkjErwfC7XCn5ghEAkADFHACgBPl8Pnm93n0KKwSDQXm9Xvl8vpyd+7bbblNTU1PC11etWpX2+WtrazUwMJD3YgctLS1xC1qEilh8/PHH4Wuqra3Ve++9p7+dfLK8krokLdj77JX05vTpqj3+ePMD/H7J65WGhnLSbiu/BwBQLAhKAFBEkqkU5/P5VFFRkZMfy2OFJbv8SE/l+iOr04XCksPhCP/38PDwPtdU+cgj2uF261BJPZIOlbRn0iRNefddadEiqafHfO7okOrrs359Uo4qBgJAiSEoAUARCP34v/zyyxP2gLhcLl1++eXyer0aHBzMWWh54IEH4u63w4/0UE9LKtcfW8o7dG9DIWSfAFhVpakdHVGfMeFXvxotA79w4Wh5+Obm7F1chLF6wlwuV1SpcgBAfAUTlO69914dcsghmjx5sk4++WQ9++yzVjcJAGwh8sf/qlWrtGLFin16QJxOp1asWKFVq1YpGAxKyl0Pj11/pEcOR5NSu/5QWJo+fbokMyQlHNIWb62ma6+V7rwzel8O1w1K1BNWcus1AUAmcjdNKnseeughY+LEicYDDzxgvPzyy8bSpUuN6dOnG4ODg0m9n2IOAApJKoULEk3Yb2pqiqp2FtrO6ppEabTLqkIC2VqTKaniDolKX0+dmvd1g2xb9Q4ALFRUVe9OOukkY9myZeHtQCBgVFZWGitXrkzq/QQlAIUilR+24/34b2pqCgeuVKq3WXEtuZat608qcMUrfV1Zadm6QbZcRwkALFQ0QWnnzp2Gy+Uy1q5dG7X/61//uvGlL30p7ns+/vhjY3h4OPzw+/0EJQC2l2ovTKqlq/PZoxR53lz+SE/287N5/Wn1lrFuEADYRtEEpbffftuQZPT09ETt/7d/+zfjpJNOivueW265Je6PBoISALtK54d8qu+x23C4VMWGolR7rLJ5/XbqLQMApKak11FqamrS8PBw+OH3+61uEgCMKZ1yzqlO2I+t3pbsxP50y4lnswx5bLW6G264IeXCDLHXf6DDof7589Na2yj0WW63uyiKI+SyZDwAFKy8xLYMpDP0LhZzlADYXSZDw9LpWUm1WESyn53p+8b6rHj3JtV7Ffo8t9ttvH3KKZbNG7ITescAlJqiGXpnGGYxh+XLl4e3A4GA8clPfpJiDgCKSiZDw3IxFyjd9uRiiFtsKBrrkXRhiv7+0XCUx0p0ycpHEYZCH44JAOkoqqD00EMPGZMmTTLWrFljvPLKK0Z9fb0xffp0Y2BgIKn3E5QAFAq7/Ot+uj1c2S4aMV7BiozP0d0dHZS6u1NqX67k43tgVYEPALBastnAYRgxA+Jt6p577tEdd9yhgYEBHXvssbr77rt18sknJ/XekZERlZeXa3h4WGVlZTluKQBkxufzqaGhQS0tLZbNfamoqNDg4GDC191utwYGBrL2vkQiF4mN9/+uHA6HDMNIbzFVv19atEjq6xvdV10tdXXlbCHYZMRec64Wis323woACkWy2aBgijksX75cb775pnbu3Klnnnkm6ZAEAIWmtrZWAwMDlhYIaGlpkcvlCheJCHE4HHK5XGppacnq+xJJVLDC5XKpqakp5cIUURobzZBUXS11d5vPfX3mfovEC4aGYSRVrCJV2f5bAUCxKZigBADIn1Qr6iX7PkkpV1dLVK3vtttuy6zyXGur5PGYPUg1Neazx2Puz5WhIbOyXqgaa0ylvXSqH6Yr3b8xAJSM3I4AtAfmKAFAerJZ9S7TeTf5KG6Qcx7PmJX2rJg3ZJd5cQCQL0U3RykTzFECgPSlO2cq8n2S8jLvxvaSmBeVrzlKkewwLw4A8iXZbEBQAgAkb2hIqq+XmpvNH/Z+vzmnp7VVmjkz7lsSFWQo2bDU0yMtXDi63d1tDv2LELpngUBALper9O4RAORQ0RVzAADYQH291NFh9or09JjPHR3m/gTyOe/G9vx+qa4uel9d3eicpb1C84fSnn8FAMgYQQkAkLzm5tHqcAsXjlaNa25O+Baqq0VIodKeHaofAkApIygBgJ2NUyUt76qqpLa2ffeFxGlfbHW1GZIekzTH4TB7S44/3tpryicrKu0BANIyweoGAADGEBrq1ttrBpS6utFCAHvLbedVvKFjf/iDdOqp0q9+lbB9obDk9XrVGgjIK2nJrFmaOmtWdHEDK64pn2bOjL7Gqqriv2YAKFAUcwAAO0uiSlpeeb1mcKuuNoPb174m9fdHHzNG+3w+n777jW/oTy6Xpg4OJvUeAACyiWIOAFAM4g11a2tLOVD4fL6UF3qNK3bo2P/9n3TaaUm3r7a2Vn/dulVTOzqSfg8AAFYgKAGAnSVZJW0fEXObfD6fvuXx6N7BQS31eDILS6GhY7HzklJpX7rXhDFlLQwDACQRlADA3lKokhZl79ymHfPn606PR+uCQXkl/TQYlNfrzd6P6XTaN857+MGfutC6S4ODg9n9+wJACSMoAYCdpVslrblZO9xuTR0c1J+CQR0qaZOkRknBbIaldNo3xnvi/uC3SeU/uwa4yAV9pSz/fQGghFHMAQCK1DkzZujx994Lb9dIWh/xutvt1sDAQN7blUjkD37DMORwOOR0OtU/f74q//zn0QISocp6Hk/eKsaF2hYIBORyuWyzCGzsPQsJ3Tu7tBMA7IRiDgCKhl3/JT/rMug52ece+f16eOLEqGPaJM1WHhZ6TeM64v3gNwxDwWBQNc8+qx1ud0qL3GaTnXtsGhoaFAgEFPtvnoZhKBAIqKGhwaKWAUARMErA8PCwIckYHh62uikAUtTZ2Wm4XC5DkuFyuYzOzk6rm5Q7Ho9hSIZRXW0Y3d3ms2TuH0Pce7T3s7a73capTqfxumQYkvFYPu5jGtfhdrsNSQkfZ3/iE+ZnhB7d3blrf4TQvXU4HFHtcTgctvg+2r19AGBHyWYDghIA24r9EVj0P/76+0dDRehRXW3uTyDRPfrNL35hvHjEEcYch8Pwer3GXKfTeEwyZjmdub1/27YZxpIlhjFnTvR1HHJIStcR+YN/rtNpbHe7U7ov2TJegHO73Tlvw3hK7n8nAJChZLMBQ+8A2NJYQ7HsMuwp61JcM2mse3TOJZfomNdeU79hqL29XSd++cta5nbr/o6O3M5Zqa+Xfvc7ac+e6P1z5465TlJtba3a29vldDrlcDgkjc6z6TnpJHNx2lQr/2VBS0uLXC5XuE0hOR++mILIeyeJuUkAkC15CG2Wo0cJKDx2+Zf8zs5Ow+125+df51PsURrvHsU+mpqa8nMNsb1JkrkviR6guMMIt20zh+2F3t/fb25v25bji4luk917bPL6XQWAAsbQuwgEJaDw2GHuRd7nR40xtyfej+BE98jysHTaadEhqbIyqblWIXb8wV9Sc+UAoMglmw0oDw7AthKVi87HsCJLzj00ZA5da242h6n5/VJjo5447zx96bLL4pamTlQeOhGn06lAIJCb9ktmmz/3OenNN0f3zZkjfepT5jDCmTNzd+4c8/l8amhoUEtLC8PaAKCAUR4cQMGzau6FZfOjZs401wUKzeWpqpLv61/Xly67LGFp6th7FDuXJtZ1112Xm7aHNDaaISlyPlF/vzRlSkGHJMm81wMDA4QkACgRBCUAthYKAm63O/2QlOK6PnZZmybZwBZ5j9auXaumpqa4n9fU1KTbbrstt41ubTUXgu3qkmpqzGePx9wPAEABISgBsL2M/yW/vl7q6JAWLZJ6esznjg5zfxx2qXSWTGALLTQrKXyPbrvttn3CUl5CkhS3V0zt7fbpTcpgUV8AQGkhKAEoDmP9AG5uHi0pvXCh+Vxdbe6PY6xS1fksuzxeYLv88svl9Xo1ODi4z5DAUFhyOp35C0mFIBSaP/c5MzCfeqq5/S//QmACAEShmAOA4uD1mj94q6vNogF1dWYg8njMHo2eHjMkhXR3m0PDxhAa+haviMK4EhRmUGtrSr0riYpKrFixQqtWrbKk0EVB8/vNgNTXN7qvslKaMMGcSxX6vgAAihbFHACUlrF6jfx+MzhFqqsb7X1KIKP5USkO9xuvDZEFLWJDkpRZsYnQ8L1iWcR3zOuJt6jvli1mSBqjlxEAUIJyUZvcblhHCbCfnKyV090dvX5Pd7e5f4z1iXImxcVjxxN5v7K5GG+xrQ807vXE+7vEfl8AAEWNBWcjEJQAe8nJj/Oxgsm2bWYoCoWU/n5ze9u2zM87lkTBLUPZWow39nPyuZhvLiR1PaHQPGfO6EK4WQiyAIDCkWw2YOgdgLyKnHMj7bsuUNoaG0eH24XW7+nrM/dbUYktzeF+ychGsYlcrxWVr+F8ofPccMMNyV1PqHz5pz5lDrmbM0c67TTpkENGvy8AAEgMvQOQP9nqCYnLql6jRCKH+z3xhGHsv//ocL8stS2TnrlsDt/LZrvSPc94j32ux27fFwBA3jD0LgJBCbCHXP44T0VO5kfFivwhHgpNU6eaoSmLc6TSvZZchdZ8DeeLd55436lCH04IAMg+glIEghKQe8n8YM9pj1IK7Uy1tyPjYJWtwg5Z7gXJdqjJ1993rPMQkgAA4yEoRSAoAbmVSviwsoBAOudOOVglCjNPPJF5YYccVO/L5jC5fPUYjnee0IOQBACIh6AUgaAE5E5ewkcO2plMr0NaoS5RmJk6NfMepSyXHI+8zmwMRbRDj5LL5TKamppyP7QSAFCwCEoRCEpAbmTywzgv84QipNrbkfa1xQszoUIO2egJiik5fvYnPmGrQGDlHCV6kAAAyUg2GzgMY28d1SI2MjKi8vJyDQ8Pq6yszOrmAEWjoqJCg4ODCV93u90aGBjIY4sSi1cOW0pcVjuja+vpkRYuHN1+4gnpZz+TmpvN0uR+v1mGurU1tRLlfr+0aJFZxnqvTZK+4HTqRx0dSZUFz4fQvQ4EAnK5XEmXLLfreQAAxSXZbMA6SgDS1tLSIpfLFV7LJ8ThcMjlcqmlpcWilu0r1bWH0r62eOsnLV8+GpKk9Ndx2rtW1A63W59zOrVJ0qGS7srWWlRZErrXbrc7p+ElX+cBAJQmepQAZCS2pybVhU/zLZVeiLSuzeuVOjrMBW/b2szQ1NdnLnLa3p5Z44eGtOWcc1Tz7LPqNwx90jDULKle0ns2v+8AANhFstmAoAQgY4U2BMrn86mhoUEtLS3jtjPlaxsakurrMx9ml0AhDXcEAMCOCEoRCEpA7qUSPgqNna4t1blWAAAgGkEpAkEJQDEptOGOAADYCcUcAMAKQ0PmPCW/39z2+83toaGsnSKyMIUkQhIAADlAUAJQcnw+nyoqKnJTJa6+3izmsGiRWSZ80SJzu74+q6eh4hsAALnF0DsAJSXnhSfirHWk6mqpq2u0PDgAALAMQ+8AFLYcDGGLnNsjScEE6w9l1ONUVWWWBY/U1kZIAgCgwBCUANhTloewxasWZxjGPmEpdNzg4GB6i7jGW3C2rm408AEAgIJAUAJgT83N5pC1vj5p4ULzubra3J+GhoYGBQIBxY42NgxDgUBADQ0N+/Q4BQIBeTye1MJSY+NoW7u7R6+hsTGtdqcjp3OwAAAoEQQlAPaU5SFsLS0tcrlccjgcUfsdDodcLpcuv/zyuOsTBYPB1MJSa6vk8ZhzkmpqzGePx9yfBxn3iAEAAEkEJQDZku05RX6/dng80fsyGMIWWVI7FJYi1x964IEH4vY4SWZYuvTSS5M70cyZUnv7aKCrqjK3Z85Mq92pSHYOFgAAGB9BCUB2ZHlO0ZYLLtDUwUFtkvQ5p1M73O6Mh7CNtf5QS0tLeH+sGZL+8/339eTPfmbuyMHaSJlKdg4WAABIDkEJwD7SmuOSxTlFPp9Pxz77rNolLZLUbRj61Nat2nLKKRkPYUu0/lBtba2mTZsW9z2tkjySDlu6VH/8/vdztjZSJpKZgwUAAJLHOkoAomS0zlBPjxmSQrq7zXk6aZw/dq5Q5DC5XC2u6vP55PF4wkPXQqokPS3p0MidNlsbycr7BgBAIWEdJQApy2iOS5bKYlvZM1JbW6uOjo6oIXgOh0N+STFXpsXvvCPfX/+as7akarw5WIQkAABSQ1ACICkLc1yyVBZ7vOp0LS0tKX1eqkJhyeVySTLvwWxJMfX39JPt2/X/ffnLtpr7M9YcLAAAkBqCEgBJWejJyVJZbDv0jMQGjmaZw+42SarZ+3yopB8Yhu0KJSSagwUAAFLDHCUAkuw3xyWjuVJZbsP0QEAtkholvSVptszwVC/pPYa3AQBQUJijBCAlmfTkpFUlL8n2WNkzEmrD+y6XzpcZkrT3+XxJ74qqcgAAFCt6lABESbUnxw49P7mWqBqeRMEEAAAKDT1KANKSSk9ORlXyCkiowEN5eTlV5QAAKBEEJQD7qK2t1cDAQNIhKa0qedkyNCR5vaNlyP1+c3toKKunqa2t1fvvvx9VPpyQBABA8SIoAUiLlesdRamvlzo6pEWLzAVvFy0yt+vrc3K6TOZO5WIuFwAAyA3mKAFIi22q5Pn9Zjjq6xvdV11tlievqsr9+ZNUCnO5AAAoBMxRApBTtaeeqv758zXH4ZDD4dBsSY9JOtDhyG8IqKqS2mKWg21rs2VIKva5XAAAFBOCEoD01Ner8s9/1suzZmmhw6EuSV5JvSedlN+eEr9fqquL3ldXNzpnyWK2mcsFAABSQlACikWeihqENTdL1dWaOjioPwWDOlTSDrdblY88kpvzJdLYaA67q66WurvN574+c78N2GYuFwAASEnOgtJ//Md/qKamRvvvv7+mT58e95j+/n6dffbZ2n///XXQQQfp3/7t37Rnz56oY7q6unT88cdr0qRJOuyww7RmzZpcNRkobHkuahBvyNvUjo78D3lrbZU8HnNOUk2N+ezxmPttoKWlRS6XK1xSPMThcMjlcqmlpcWilgEAgLHkLCjt2rVLX/nKV3TllVfGfT0QCOjss8/Wrl271NPTo5///Odas2aNbr755vAxb7zxhs4++2ydfvrp6u3tVWNjo77xjW/oySefzFWzgcK1t4dHfX3SwoWjvSzNzbk5n12GvM2cKbW3jwa0qipze+bM/LYjgVCVPNZfAgCgsOQsKH33u9/Vt7/9bR1zzDFxX/+f//kfvfLKK/qv//ovHXvssfriF7+o733ve7r33nu1a9cuSdJ9992nefPm6a677tJRRx2l5cuX6/zzz9cPf/jDXDUbKFz5Lmpg8yFv6cpFCe/IsCSx/hIAAIXAsjlK69ev1zHHHCO32x3et3jxYo2MjOjll18OH3PGGWdEvW/x4sVav379mJ+9c+dOjYyMRD2AopfvHh6bD3lLR6jwwuDgYNYLLWSy/hIAAMg/y4LSwMBAVEiSFN4eGBgY85iRkRF99NFHCT975cqVKi8vDz+qbFQmGNnD4p0x8t3DY/Mhb6nKRwnv2tpaDQwMEJIAACgAKQWl66+/Xo69a6YkemzcuDFXbU1aU1OThoeHww+/TcoEI3ty+S//BasIe3jyhRLeAAAgVkpB6ZprrtGrr7465qO6ujqpz6qoqNDg4GDUvtB2RUXFmMeUlZVpypQpCT970qRJKisri3qgeLB4ZwJZ7uEppR47SngDAIBYKQWlWbNm6cgjjxzzMXHixKQ+a8GCBXrxxRf1zjvvhPc99dRTKisr09FHHx0+Zt26dVHve+qpp7RgwYJUmo0iwr/850ep9dhRwhsAAMTK2Ryl/v5+9fb2qr+/X4FAQL29vert7dX27dslSWeeeaaOPvpo1dXV6W9/+5uefPJJ3XTTTVq2bJkmTZokSfrmN7+pvr4+rVixQhs3btRPfvITPfLII/r2t7+dq2bD5viX/xSlsQhtrnrs7NxDRQlvAACwDyNHLrnkEkPSPo+nn346fMzmzZuNL37xi8aUKVOMAw880LjmmmuM3bt3R33O008/bRx77LHGxIkTjerqamP16tUpt2V4eNiQZAwPD2d4VbBaZ2en4XK5DIfDEfW9cjgchsvlMjo7O61uor14PIYhGUZ1tWF0d5vPkrk/jlzd39DnSrL136lQ2gkAANKXbDbIWVCyE4JScYn9MZ+3kLRtmxkw+vvN7f5+c3vbttyeNxP9/aPhKPSorh69hhhutzvuP3CEHm63O7nzRtyrzs5OY67TaTwmGTNsGGo7OzsNt9sdbk/sNgAAKC7JZgOHYcSMYSpCIyMjKi8v1/DwMIUdikRoeFggEJDL5crP8CivV+roMMtut7WZaxT19ZmV5drbc3vuTPT0SAsXjm53d5tV8eKINwdMSmMY2t57tcPt1pKtW7UmGNShktolnZ/O5+WIJd8jAABgqWSzAUEJBcvn86mhoUEtLS35+XHr90uLFpnhKKS62izDbde1utJoc2xYSivUxDnvJkmLJL0VcZjb7Q6vm5ZvWblOAABQcJLNBpYtOAtkKu+Ld1ZVmT1Jkdra7BuSpLQWoY0sbCApvfAQ517VaTQkWV1NLmvVE9MolgEAAAoDQQlIlt9vDreLVFc3+iPZjuIsQrvllFN01J/+NGYYCIUlt9udXg9LnHvVJmm2sjvsLt1Kelmrnlhfbw7HXLTIHOK4aJG5XV+fUnsAAID9EJSAZKXRO2O5mEVofX/9q+Zs2KCNW7eO23OSUY9dzL3a4XbrUEnNSrOHKo5M1nrK2rpJzc2j34OFC0evubk5+QsBAAC2RFACkhWnd0Yej7m/AORqfaS4Yu7V1A0btOWUU3TTrFlZDUnpXkvW1k0qxOGYAAAgKRRzAEpA1qrZ2UA2ryXjqneFWOADAIASRzEHAGFZm5OTqSwUP8jmtWQ8F6sQh2MCAICkEJSAEpC1OTmZykLxg2xfS0ZzsQp8OCYAAEiMoXdAibDFukFZGqpmi2sBAAAFiaF3AKJkZX2kTGWp+IEtrgUAABQ1ghJQQjKek5OpLK5FZfm1AACAosbQOwD54/Wac5Kqq82epLo6cxiex2Ou9wQAAJBjDL0DilEWqsZZyi7FDwr9PgIAgJwjKKHo+Xw+VVRU5GZh1XzLQtU4S82cafYcheYkVVWZ2zNn5rcdhX4fAQBAzjH0DkUt4wVF7YYFTrOD+wgAQMli6B1KXmQJaUkKBoPyer2F3bMUr2rcPfeYC5wyjCx5Waq+BwAAihdBCUUpdp0dSTIMo/DDUryqceefzzCyVGWx+h4AAChOBCUUpYaGBgUCAcWOLDUMQ4FAQA0NDRa1LEONjeZwsepqqbvbfP7wQ2nqVHP/woWjrzc3W91a+4p3H/v6zP0AAAAiKKFItbS0yOVyyeFwRO13OBxyuVxqaWmxqGUZSlQ17tFHo4+LM4ysqIpaZMou1fcAAIBtEZRQlEKLkTqdznBYcjgccjqd2S3okO8y0/GqxjU3S8uXRx8XM4wsNBRxcHAwP0MP7V5+2y7V9wAAgG0RlFC0IsOSpOyHJMkeZabHGUZmSVELO9wXAACADFAeHEXP5/OpoaFBLS0t2S8Nbocy00NDZgBpbjbP6febIam1Vb7/+799ilpIOepdi2SH+wIAABBHstmAoARkqqfHLKIQ0t1tznvJkkyCXkVFhQYHBxO+7na7NTAwkGkT48vxfQEAAEgH6ygB+ZDjMtOZzi1qaWnRLKdTj0mavXffbEmPSZrldOauqAXltwEAQIEjKAGZyGGZ6WzMLaqtrVXvSSfJK6lL0oK9z15JvSedlJthdxLltwEAQMEjKAGZyFGZ6WwumFv5yCPa4XbrUEk9kg6VtMPtVuUjj2TUxjFRfhsAABQ45igBNpT1uUXMFwIAAJDEHCWgoGV1wVzmCwEAAKSMoATYUFYXzC2g+UI+n08VFRW5XxAXAABgHAQlwKaytmBugcwXyrTCHwAAQDYRlFD4hoYkr3d0KJnfb24PDVnbriwIhSW3253+4rAzZ0rt7aMLvVZVmdszZ2a3sRnIRoU/AACAbKKYAwqf1yt1dJhDytrazPk3fX1mr0l7u9WtwzjiVfiTMhhqCAAAMAaKOaB0NDePzrtZuHB0Pk5zs9UtG18R94Ylq6GhQYFAQLH/ZmMYhgKBgBoaGixqGQAAKGUEJRS+qiqzJylSW9voUDM7q683e8MWLTJLeC9aZG7X11vdsrzJaoU/AACALCEoofAVcvnrQu4Ny5KsVvgDAADIEoISCl8Blb/eRyH3hmVR1ir8AQAAZAlBCYWvQMpfx1XIvWFZlpUKfwAAAFlC1TvASlTsAwAAyKtks8GEPLYJQKxQr1dzszncrqvLHDJYCL1hAAAARYweJQAAAAAlg3WUAAAAACBNBCUAAAAAiEFQQlHz+XyqqKiQz+ezuikAAAAoIAQlFC2fzyev16vBwUF5vV7CEgAAAJJGUEJRCoWkYDAoSQoGg4QlAAAAJI2ghKITGZJCRR0NwyAsAQAAIGmUB0fRqaio0ODgYMLX3W63BgYG8tgiAAAA2AXlwVGyWlpa5HK55HA4ovY7HA65XC61tLRY1DIAAAAUCoISik5tba3a29vldDrDYcnhcMjpdKq9vV21tbUWtxAAAAB2R1BCUYoMS5IISQAAAEgJQQlFKxSW3G43IQkAAAApoZgDAAAAgJJBMQcAAAAASBNBCQAAAABiEJQAAAAAIAZBCQAAAABiEJQAAAAAIAZBCQAAAABiEJQAAAAAIAZBCQAAAABiEJQAAAAAIAZBCQAAAABiEJQAAAAAIAZBCQAAAABiEJQAAAAAIEbOgtLmzZt1xRVXaN68eZoyZYoOPfRQ3XLLLdq1a1fUcS+88II+97nPafLkyaqqqtKqVav2+axHH31URx55pCZPnqxjjjlGTzzxRK6aDQAAAAC5C0obN25UMBhUS0uLXn75Zf3whz/UfffdpxtuuCF8zMjIiM4880zNnTtXzz33nO644w7deuutam1tDR/T09Ojr33ta7riiiv0/PPP67zzztN5552nl156KVdNBwAAAFDiHIZhGPk62R133KGf/vSn6uvrkyT99Kc/1Y033qiBgQFNnDhRknT99ders7NTGzdulCRdeOGF2rFjhx5//PHw55xyyik69thjdd999yV13pGREZWXl2t4eFhlZWVZvioAAAAAhSLZbJDXOUrDw8OaMWNGeHv9+vX6/Oc/Hw5JkrR48WK99tpreu+998LHnHHGGVGfs3jxYq1fvz7heXbu3KmRkZGoBwAAAAAkK29B6fXXX9ePf/xjNTQ0hPcNDAzI7XZHHRfaHhgYGPOY0OvxrFy5UuXl5eFHVVVVti4DAAAAQAlIOShdf/31cjgcYz5Cw+ZC3n77bS1ZskRf+cpXtHTp0qw1PpGmpiYNDw+HH36/P+fnHNfQkOT1SqG2+P3m9tCQte0CAAAAsI8Jqb7hmmuu0aWXXjrmMdXV1eH/3rJli04//XTV1NREFWmQpIqKCg0ODkbtC21XVFSMeUzo9XgmTZqkSZMmjXsteVVfL3V0SL29UlubVFcn7Z2rpfZ2S5sGAAAAIFrKQWnWrFmaNWtWUse+/fbbOv3003XCCSdo9erVcjqjO7AWLFigG2+8Ubt379Z+++0nSXrqqad0xBFH6BOf+ET4mHXr1qmxsTH8vqeeekoLFixItenWam42Q1Jfn7RwobmvutrcDwAAAMBWcjZH6e2339aiRYs0Z84c3Xnnndq6dasGBgai5hZddNFFmjhxoq644gq9/PLLevjhh/WjH/1IV199dfiYb33rW/rd736nu+66Sxs3btStt96qv/zlL1q+fHmump4bVVVmT1KktjZzPwAAAABbyVl58DVr1uiyyy6L+1rkKV944QUtW7ZMGzZs0IEHHqirrrpK1113XdTxjz76qG666SZt3rxZhx9+uFatWqWzzjor6bbYojy43y8tWjQ63E4ye5S6ughLAAAAQJ4kmw3yuo6SVWwRlLxec45SdXX0HCWPhzlKAAAAQJ4kmw1SnqOENIUKWTQ3mz1IXV1SY+PofgAAAAC2QY8SAAAAgJKRbDbI24KzAAAAAFAoCEoAAAAAEIOgBAAAAAAxCEoAAAAAEIOgBAAAAAAxCEoAAAAAEIOgBAAAAAAxCEoAAAAAEIOgBAAAAAAxCEoAAAAAEIOgBAAAAAAxJljdgHwwDEOSNDIyYnFLAAAAAFgplAlCGSGRkghKH3zwgSSpqqrK4pYAAAAAsIMPPvhA5eXlCV93GONFqSIQDAa1ZcsWTZs2TQ6Hw+rmIAtGRkZUVVUlv9+vsrIyq5sDi/F9QCS+D4jE9wEhfBcQYhiGPvjgA1VWVsrpTDwTqSR6lJxOp2bPnm11M5ADZWVl/B87hPF9QCS+D4jE9wEhfBcgacyepBCKOQAAAABADIISAAAAAMQgKKEgTZo0SbfccosmTZpkdVNgA3wfEInvAyLxfUAI3wWkqiSKOQAAAABAKuhRAgAAAIAYBCUAAAAAiEFQAgAAAIAYBCUAAAAAiEFQAgAAAIAYBCUUtM2bN+uKK67QvHnzNGXKFB166KG65ZZbtGvXLqubBov8x3/8h2pqarT//vtr+vTpVjcHeXbvvffqkEMO0eTJk3XyySfr2WeftbpJsMgf//hHnXvuuaqsrJTD4VBnZ6fVTYJFVq5cqfnz52vatGk66KCDdN555+m1116zulkoAAQlFLSNGzcqGAyqpaVFL7/8sn74wx/qvvvu0w033GB102CRXbt26Stf+YquvPJKq5uCPHv44Yd19dVX65ZbbtFf//pXffazn9XixYv1zjvvWN00WGDHjh367Gc/q3vvvdfqpsBif/jDH7Rs2TL9+c9/1lNPPaXdu3frzDPP1I4dO6xuGmyOdZRQdO644w799Kc/VV9fn9VNgYXWrFmjxsZGvf/++1Y3BXly8skna/78+brnnnskScFgUFVVVbrqqqt0/fXXW9w6WMnhcGjt2rU677zzrG4KbGDr1q066KCD9Ic//EGf//znrW4ObIweJRSd4eFhzZgxw+pmAMijXbt26bnnntMZZ5wR3ud0OnXGGWdo/fr1FrYMgN0MDw9LEr8VMC6CEorK66+/rh//+MdqaGiwuikA8mjbtm0KBAJyu91R+91utwYGBixqFQC7CQaDamxs1MKFC/XpT3/a6ubA5ghKsKXrr79eDodjzMfGjRuj3vP2229ryZIl+spXvqKlS5da1HLkQjrfBwAAYi1btkwvvfSSHnroIaubggIwweoGAPFcc801uvTSS8c8prq6OvzfW7Zs0emnn66amhq1trbmuHXIt1S/Dyg9Bx54oFwulwYHB6P2Dw4OqqKiwqJWAbCT5cuX6/HHH9cf//hHzZ492+rmoAAQlGBLs2bN0qxZs5I69u2339bpp5+uE044QatXr5bTSUdpsUnl+4DSNHHiRJ1wwglat25deMJ+MBjUunXrtHz5cmsbB8BShmHoqquu0tq1a9XV1aV58+ZZ3SQUCIISCtrbb7+tRYsWae7cubrzzju1devW8Gv8K3Jp6u/v17vvvqv+/n4FAgH19vZKkg477DAdcMAB1jYOOXX11Vfrkksu0YknnqiTTjpJzc3N2rFjhy677DKrmwYLbN++Xa+//np4+4033lBvb69mzJihOXPmWNgy5NuyZcv0y1/+Uj6fT9OmTQvPWywvL9eUKVMsbh3sjPLgKGhr1qxJ+COIr3ZpuvTSS/Xzn/98n/1PP/20Fi1alP8GIa/uuece3XHHHRoYGNCxxx6ru+++WyeffLLVzYIFurq6dPrpp++z/5JLLtGaNWvy3yBYxuFwxN2/evXqcYd1o7QRlAAAAAAgBpM5AAAAACAGQQkAAAAAYhCUAAAAACAGQQkAAAAAYhCUAAAAACAGQQkAAAAAYhCUAAAAACAGQQkAAAAAYhCUAAAAACAGQQkAAAAAYhCUAAAAACDG/w9bxR73RUeUMwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.ioff()\n", + "\n", + "plt.clf()\n", + "fig, ax = plt.subplots(1, figsize=(10, 5))\n", + "fig.patch.set_facecolor(\"white\")\n", + "ax.scatter(X_train, y_train, **train_plot_config)\n", + "ax.scatter(X_test, y_test, **test_plot_config)\n", + "ax.legend()\n", + "display(fig)" + ] + }, + { + "cell_type": "markdown", + "id": "931bce92", + "metadata": {}, + "source": [ + "## Identify best set of hyperparameters" + ] + }, + { + "cell_type": "markdown", + "id": "acbf941b", + "metadata": {}, + "source": [ + "### Sklearn LinearSVR" + ] + }, + { + "cell_type": "markdown", + "id": "4860fd50", + "metadata": {}, + "source": [ + "Create scorer with the [Mean Squared Error](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_squared_error.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "11bb680b", + "metadata": {}, + "outputs": [], + "source": [ + "grid_scorer = make_scorer(mean_squared_error, greater_is_better=False)" + ] + }, + { + "cell_type": "markdown", + "id": "f864d02e", + "metadata": {}, + "source": [ + "We train the scikit-learn LinearSVR model on clear data.\n", + "\n", + "We use a parameter grid with several values for $\\epsilon$ and $C$. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "449e78b4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fitting 5 folds for each of 9 candidates, totalling 45 fits\n" + ] + } + ], + "source": [ + "param_grid = {\n", + " \"epsilon\": [0.0, 1.0, 10.0],\n", + " \"C\": [0.1, 1.0, 10.0],\n", + "}\n", + "\n", + "sklearn_rgs = SklearnLinearSVR()\n", + "\n", + "gs_sklearn = GridSearchCV(\n", + " sklearn_rgs,\n", + " param_grid,\n", + " cv=5,\n", + " scoring=grid_scorer,\n", + " verbose=1,\n", + ").fit(X_train, y_train)" + ] + }, + { + "cell_type": "markdown", + "id": "5e3e7c24", + "metadata": {}, + "source": [ + "### Concrete-ML quantized linearSVR" + ] + }, + { + "cell_type": "markdown", + "id": "f82a8c7d", + "metadata": {}, + "source": [ + "The typical development flow of a Concrete-ML model is the following:\n", + "\n", + "* The model is trained on clear (plaintext) data as only FHE inference is currently supported\n", + "* The resulting trained model is quantized using a `n_bits` parameter set by the user (see documentation [here](https://docs.zama.ai/concrete-ml/developer-guide/api/concrete.ml.sklearn.svm#class-linearsvr)). This parameter can either be:\n", + " 1. a dictionary composed of `op_inputs` and `op_weights` keys. These parameters are given as integers representing the number of bits over which the associated data should be quantized.\n", + " 2. an integer, representing the number of bits over which each input and weight should be quantized. Default is 8. We will use 6 bits for educational purposes. \n", + "* The quantized model is compiled to a FHE equivalent following 3 steps:\n", + " 1. create an executable operation graph\n", + " 2. check that the op-graph is FHE compatible by checking the maximum bit-width needed to execute the model\n", + " 3. determine cryptographic parameters that will help to generate the secret keys and evaluation keys. If no parameters can be found, the compilation process can't be completed and an error is thrown. The user then can either lower the value(s) chosen for `n_bits` or decrease the number of features found in the data set (using techniques such as [PCA](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)) and run the development flow once again.\n", + "* Inference can then be done on encrypted data (using `execute_in_fhe=True` when calling `.predict()` method. See bellow)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "2f6c5f40", + "metadata": {}, + "source": [ + "We use the same grid of parameter values. We set the number of bits to 6 (see explanation in following sections). " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e6126ebb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fitting 5 folds for each of 9 candidates, totalling 45 fits\n" + ] + } + ], + "source": [ + "param_grid = {\n", + " \"n_bits\": [6],\n", + " \"epsilon\": [0.0, 1.0, 10.0],\n", + " \"C\": [0.1, 1.0, 10.0],\n", + "}\n", + "\n", + "concrete_rgs = ConcreteLinearSVR()\n", + "\n", + "gs_concrete = GridSearchCV(\n", + " concrete_rgs,\n", + " param_grid,\n", + " cv=5,\n", + " scoring=grid_scorer,\n", + " verbose=1,\n", + ").fit(X_train, y_train)" + ] + }, + { + "cell_type": "markdown", + "id": "991386ee", + "metadata": {}, + "source": [ + "### Compare Sklearn and Concrete-ML Quantized best models" + ] + }, + { + "cell_type": "markdown", + "id": "512f94e0", + "metadata": {}, + "source": [ + "#### Performance" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e884473f", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mean time fit sklearn: 0.001s, std time fit sklearn: 0.000s\n", + "Mean time fit concrete: 0.162s,std time fit concrete: 0.048s\n", + "Best MSE score sklearn: 943.87\n", + "Best MSE score concrete: 936.11\n" + ] + } + ], + "source": [ + "# Print mean time fit and std time fit for both models\n", + "print(\n", + " f\"Mean time fit sklearn: {np.mean(gs_sklearn.cv_results_['mean_fit_time']):.3f}s,\"\n", + " f\" std time fit sklearn: {np.std(gs_sklearn.cv_results_['mean_fit_time']):.3f}s\"\n", + ")\n", + "print(\n", + " f\"Mean time fit concrete: {np.mean(gs_concrete.cv_results_['mean_fit_time']):.3f}s,\"\n", + " f\"std time fit concrete: {np.std(gs_concrete.cv_results_['mean_fit_time']):.3f}s\"\n", + ")\n", + "\n", + "# Print best score for both models\n", + "print(f\"Best MSE score sklearn: {-gs_sklearn.best_score_:.2f}\")\n", + "print(f\"Best MSE score concrete: {-gs_concrete.best_score_:.2f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "03f0143f", + "metadata": {}, + "source": [ + "#### Hyperparameters" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "7d5027bb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Best parameters for Concrete: {'C': 10.0, 'epsilon': 1.0, 'n_bits': 6}\n", + "Best parameters for Sklearn: {'C': 10.0, 'epsilon': 1.0}\n" + ] + } + ], + "source": [ + "# Get best hyper parameters out of gs_concrete\n", + "best_params_concrete = gs_concrete.best_params_\n", + "print(f\"Best parameters for Concrete: {best_params_concrete}\")\n", + "best_params_sklearn = gs_sklearn.best_params_\n", + "print(f\"Best parameters for Sklearn: {best_params_sklearn}\")" + ] + }, + { + "cell_type": "markdown", + "id": "326ef351", + "metadata": {}, + "source": [ + "### Train with best hyperparameter set on the complete training dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "23d61559", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
LinearSVR(C=10.0, epsilon=1.0)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "LinearSVR(C=10.0, epsilon=1.0)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Train concrete and sklearn LinearSVR with best hyper parameters\n", + "concrete_rgs = ConcreteLinearSVR(**best_params_concrete)\n", + "sklearn_rgs = SklearnLinearSVR(**best_params_sklearn)\n", + "\n", + "concrete_rgs.fit(X_train, y_train)\n", + "sklearn_rgs.fit(X_train, y_train)" + ] + }, + { + "cell_type": "markdown", + "id": "d9251a9d", + "metadata": {}, + "source": [ + "## Concrete-ML Quantized linearSVR with FHE" + ] + }, + { + "cell_type": "markdown", + "id": "64dcbfc0", + "metadata": {}, + "source": [ + "### Prerequisite" + ] + }, + { + "cell_type": "markdown", + "id": "8eba8bb8", + "metadata": {}, + "source": [ + "Some prerequisites should be reviewed before deep diving !\n", + "\n", + "Quantization is a technique that converts continuous data (floating point, e.g., in 32-bits) to discrete numbers within a fixed range (e.g. integer in 8-bits). This means that some information is lost during the process. However, the larger is the integers' range, the smaller the error becomes, making it acceptable to some cases.\n", + "\n", + "To learn more about quantization, please refer to this [page](https://docs.zama.ai/concrete-ml/advanced-topics/quantization).\n", + "\n", + "Regarding FHE, the input data type must be represented exclusively as integers, making the use of quantization necessary. Therefore, a linear model trained on floats is quantized into an equivalent integer model using *Post-Training Quantization*. This operation can lead to a loss of accuracy compared to the standard floating point models working on clear data.\n", + "\n", + "In practice however, this loss is usually very limited with linear FHE models as they can consider very large integers, with up to 50 bits in some cases. This means these models can quantize their inputs and weights over large number of bits (e.g. 16) while still considering data sets containing many features (e.g. 1000). We therefore often observe almost identical performance scores between float, quantized and FHE models.\n", + "\n", + "To learn more about the relation between the maximum bit-width reached within a model, the bits of quantization used and the dataset's number of features, please refer to this [page](https://docs.zama.ai/concrete-ml/advanced-topics/pruning)." + ] + }, + { + "cell_type": "markdown", + "id": "80e835f8", + "metadata": {}, + "source": [ + "### Compilation" + ] + }, + { + "cell_type": "markdown", + "id": "0ea0e874", + "metadata": {}, + "source": [ + "To perform homomorphic inference, we take the above trained quantized model and we compile it to get a FHE model.\n", + "\n", + "The compiler requires an exhaustive set of data to evaluate the maximum integer bit-width within the graph, which is needed during the FHE computations before running any predictions.\n", + "\n", + "The user can either provide the entire train dataset or a smaller but representative subset of it." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c9590403", + "metadata": {}, + "outputs": [], + "source": [ + "# Compile the model using the training data\n", + "circuit = concrete_rgs.compile(X_train)" + ] + }, + { + "cell_type": "markdown", + "id": "b33827f6", + "metadata": {}, + "source": [ + "### Generate the key" + ] + }, + { + "cell_type": "markdown", + "id": "b00a9172", + "metadata": {}, + "source": [ + "The compiler returns a circuit, which can then be used for key generation and predictions. More precisely, it generates:\n", + "\n", + "* a Secret Key, used for the encryption and decryption processes. This key should remain accessible only to the user.\n", + "* an Evaluation Key, used to evaluate the circuit on encrypted data. Anyone could access this key without breaching the model's security.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "53cc3b51", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generating a key for an 6-bit circuit\n" + ] + } + ], + "source": [ + "# Generate the key\n", + "print(f\"Generating a key for an {circuit.graph.maximum_integer_bit_width()}-bit circuit\")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3212b1b0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Key generation time: 120.03 seconds\n" + ] + } + ], + "source": [ + "time_begin = time.time()\n", + "circuit.client.keygen(force=False)\n", + "print(f\"Key generation time: {time.time() - time_begin:.2f} seconds\")" + ] + }, + { + "cell_type": "markdown", + "id": "752452bc", + "metadata": {}, + "source": [ + "### Now let's predict using the FHE model on encrypted data" + ] + }, + { + "cell_type": "markdown", + "id": "9b71e63e", + "metadata": {}, + "source": [ + "Please, notice the `execute_in_fhe=True` that makes the job under the hood: before the data is sent to be applied to the model, it is encrypted with the client secret key generated above. \n", + "\n", + "As for future comparison bellow, we also predict on the very same data on both:\n", + "* the Sklearn model,\n", + "* the Concrete-ML quantized model without FHE. " + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "ccc0edcc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Execution time: 10.8313 seconds per sample\n", + "Execution time: 0.0001 seconds per sample\n", + "Execution time: 0.0003 seconds per sample\n" + ] + } + ], + "source": [ + "# Now predict using the FHE-quantized model on the testing set\n", + "time_begin = time.time()\n", + "y_pred_fhe = concrete_rgs.predict(X_test, execute_in_fhe=True)\n", + "print(f\"Execution time: {(time.time() - time_begin) / len(X_test):.4f} seconds per sample\")\n", + "\n", + "# Now predict using the Sklearn model on the testing set\n", + "time_begin = time.time()\n", + "y_pred_sklearn = sklearn_rgs.predict(X_test)\n", + "print(f\"Execution time: {(time.time() - time_begin) / len(X_test):.4f} seconds per sample\")\n", + "\n", + "# Now predict using clear quantized Concrete-ML model on testing set\n", + "time_begin = time.time()\n", + "y_preds_quantized = concrete_rgs.predict(X_test)\n", + "print(f\"Execution time: {(time.time() - time_begin) / len(X_test):.4f} seconds per sample\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "d7e99e85", + "metadata": {}, + "source": [ + "## Compare" + ] + }, + { + "cell_type": "markdown", + "id": "d8d8c76d", + "metadata": {}, + "source": [ + "### Display performance spreads" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5dbc0d68", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Clear FP32 sklearn model MSE: 940.179\n", + "Clear quantized model MSE: 992.409\n", + "FHE model MSE: 992.409\n", + "\n", + "Relative difference between Concrete-ml (quantized clear) and Concrete-ml (FHE) scores: 0.00%\n", + "Relative difference between scikit-learn (clear) and Concrete-ml (FHE) scores: 5.56%\n" + ] + } + ], + "source": [ + "# Print all MSE a string to explain\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "mse_sklearn = mean_squared_error(y_test, y_pred_sklearn)\n", + "mse_clear = mean_squared_error(y_test, y_preds_quantized)\n", + "mse_fhe = mean_squared_error(y_test, y_pred_fhe)\n", + "\n", + "print(\n", + " f\"Clear FP32 sklearn model MSE: {mse_sklearn:.3f}\\n\"\n", + " f\"Clear quantized model MSE: {mse_clear:.3f}\\n\"\n", + " f\"FHE model MSE: {mse_fhe:.3f}\"\n", + ")\n", + "\n", + "# Measure the error of the FHE quantized model with respect to quantized clear Concrete-ML model\n", + "concrete_score_difference = abs(mse_fhe - mse_clear) * 100 / mse_clear\n", + "print(\n", + " \"\\nRelative difference between Concrete-ml (quantized clear) and Concrete-ml (FHE) scores:\",\n", + " f\"{concrete_score_difference:.2f}%\",\n", + ")\n", + "\n", + "\n", + "# Measure the error of the FHE quantized model with respect to the sklearn float model\n", + "score_difference = abs(mse_fhe - mse_sklearn) * 100 / mse_sklearn\n", + "print(\n", + " \"Relative difference between scikit-learn (clear) and Concrete-ml (FHE) scores:\",\n", + " f\"{score_difference:.2f}%\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "18786764", + "metadata": {}, + "source": [ + "We can observe that scikit-learn and Concrete-ML (quantized clear) models output very close scores. This demonstrate how the quantization process has a very limited impact on performances.\n", + "\n", + "As for the spread in performance between Concrete-ml (FHE) and scikit-learn, there are also close to one another. \n", + "* On the below graph, we see that test dataset has points for which `X` values are outside the range of train dataset. Since, when we compiled the quantized model we used `X_train`, those `X` values in the test dataset were not seen by the compilation process, then the decision rule poorly generalizes on those values outside the boundaries observed on `X_tain`\n", + "* Moreover, keep in mind that the current notebook has been voluntarily performed with `n_bits = 6` whereas the default value is 8. Running the current notebook with a `n_bits > 6` will lead to a significant performance increase and will close the performance gap with scikit-learn. " + ] + }, + { + "cell_type": "markdown", + "id": "87023b7e", + "metadata": {}, + "source": [ + "### Visualize decision rule" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "205ae5c4", + "metadata": {}, + "outputs": [], + "source": [ + "# We densify the space representation of the original X,\n", + "# to better visualize the resulting step function in the following figure\n", + "x_space = np.linspace(X_test.min(), X_test.max(), num=300)\n", + "x_space = x_space[:, np.newaxis]\n", + "y_pred_q_space = concrete_rgs.predict(x_space)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "1825a31e", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+UAAAKTCAYAAAB/z6niAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/av/WaAAAACXBIWXMAAA9hAAAPYQGoP6dpAAC6kklEQVR4nOzdeVzU1f7H8dcwiitupOCCC2apueaWYje7WlpmFLTd2yWXUipbyJ9Ztui9LVq2XCotQUtLs+2K0mZmFppoapplaZaiiSmomCguoDPf3x9fGRjWAQdmBt7Px2Me+D3f73znzGD3+p5zzudYDMMwEBEREREREZFK5+fpDoiIiIiIiIhUVwrlIiIiIiIiIh6iUC4iIiIiIiLiIQrlIiIiIiIiIh6iUC4iIiIiIiLiIQrlIiIiIiIiIh6iUC4iIiIiIiLiITU83YHKYLfb2b9/PwEBAVgsFk93R0RERERERKo4wzA4fvw4LVq0wM+v+PHwahHK9+/fT0hIiKe7ISIiIiIiItVMamoqrVq1KvZ8tQjlAQEBgPlhNGjQwMO9ERERERERkaru2LFjhISEOPJocapFKM+dst6gQQOFchEREREREak0pS2hVqE3EREREREREQ9RKBcRERERERHxEIVyEREREREREQ+pFmvKXWG328nJyfF0N0SkjGrWrInVavV0N0REREREykWhHMjJyWH37t3Y7XZPd0VEyqFRo0YEBweXWkRDRERERMTbVPtQbhgGBw4cwGq1EhISUuKm7iLiXQzD4OTJkxw8eBCA5s2be7hHIiIiIiJlU+1D+dmzZzl58iQtWrSgbt26nu6OiJRRnTp1ADh48CDNmjXTVHYRERER8SnVfljYZrMB4O/v7+GeiEh55X6hdubMGQ/3RERERESkbKp9KM+ltagivkv//YqIiIiIr1IoFxEREREREfEQhXJxaNu2LbGxsT5zXxEREREREV+nUO6DLBZLiY9///vf5brvxo0bGTdunHs7Ww7z58+nUaNGnu6GiIiIiIhIhav21dd90YEDBxx//uCDD5gyZQo7duxwtNWvX9/xZ8MwsNls1KhR+q+6adOm7u2oiIiIiIiIlEgj5W6UmJhIcHAwiYmJFfo6wcHBjkfDhg2xWCyO419//ZWAgACWLVtGr169qFWrFmvWrGHXrl2Eh4cTFBRE/fr16dOnD1999ZXTfQtOM7dYLMydO5cbb7yRunXr0qFDBz7++OMS+3bw4EFGjBhBnTp1aNeuHe+++26ha15++WW6du1KvXr1CAkJ4d577yUrKwuApKQkRo8eTWZmZqGR/wULFtC7d28CAgIIDg7mn//8p2N/ahEREREREV+kUO4miYmJREZGkp6eTmRkZIUH89I8+uijPPfcc2zfvp1u3bqRlZXFtddey8qVK/nhhx8YNmwYI0aMYO/evSXe5z//+Q+33HILP/30E9deey233347R44cKfb6UaNGkZqayjfffMP//vc/Xn/99ULB2c/Pj1dffZVffvmFt99+m6+//ppJkyYBMGDAAGJjY2nQoAEHDhzgwIEDTJw4ETC3u3r66af58ccfWbp0KXv27GHUqFHn90GJiIiIiIh4kKavu0FuILfb7QDY7XYiIyNZvHgx4eHhHunTU089xVVXXeU4btKkCd27d3ccP/300yxZsoSPP/6Y++67r9j7jBo1in/84x8ATJs2jVdffZUNGzYwbNiwQtf+9ttvLFu2jA0bNtCnTx8A3nzzTTp16uR0XUxMjOPPbdu25ZlnnuHuu+/m9ddfx9/f32n0P78xY8Y4/hwaGsqrr75Knz59yMrKcpqyLyIiIiIi4is0Un6e8gdywzAAcx13bjD31Ih57969nY6zsrKYOHEinTp1olGjRtSvX5/t27eXOlLerVs3x5/r1atHgwYNip0yvn37dmrUqEGvXr0cbR07dixUtO2rr75i8ODBtGzZkoCAAKKiosjIyODkyZMl9mXTpk2MGDGC1q1bExAQwBVXXAFQ6nsQERERERHxVgrl5yk6OhqbzeYI5LlyC6xFR0d7pF/16tVzOp44cSJLlixh2rRpfPvtt2zZsoWuXbuSk5NT4n1q1qzpdGyxWBwzAspjz549XHfddXTr1o3FixezadMmZs2aBVBiX06cOMHQoUNp0KAB7777Lhs3bmTJkiWlPk9ERERERMSbKZSfp7i4OKxWKxaLxandYrFgtVqJi4vzUM+cJScnM2rUKG688Ua6du1KcHAwe/bscetrdOzYkbNnz7Jp0yZH244dOzh69KjjeNOmTdjtdl566SUuu+wyLrroIvbv3+90H39/f2w2m1Pbr7/+SkZGBs899xyXX345HTt2VJE3ERERERHxeQrl5yk8PJzFixfj5+fnCOYWiwU/Pz+Prikv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6MDevXt5//332bVrF6+++ipLlixx/wclIiIiIt4nt1bToEGwdq35MyHBbBepohTK3SE+HiIiICkJBgwwf0ZEmO2V7K677mLu3LnMmzePrl27csUVVzB//nzHSHlAQAAzZsygd+/e9OnThz179vD555/j52f+VXjppZdYsWIFISEh9OzZs8jXqF+/Pp988glbt26lZ8+ePP744zz//PNO10RHRxMREcGtt95Kv379yMjI4N5773W6ZuzYsVx88cX07t2bpk2bkpyczPXXX89DDz3EfffdR48ePVi7di1PPvlkBXxSIiIiIuJ1YmPzBrjCwvIGviq5VpN4oXyzKM6eBWNv1ZlFYTEMw/B0JyrasWPHaNiwIZmZmYUKhp0+fZrdu3fTrl07p8JlIuI79N+xiIhIFbJ2bV7xZDBnog4Y4Ln+iHeIjISEBDa1vJ676r7Lg0efYtShF8zB0Ere8cpVJeXQ/DRSLiIiIiIi3sFLajWJ9zk5/RUebhhP3z8T2PJ7fSYcepT01n2qxCwKhXIREREREfEOXlSrSbzHihXQZVgrXswcix0rAH/RhMe6fVLpO15VBIVyERERERHxDl5Uq0k8LyMDRo2Cq6+G3budz93CBzz70/VVYhaFQrmIiIiIiHiHwEBzfXDu6GdIiHkcGOjZfkmlMgx4/33o1Aneftv5XEvrARKf284HoY8RvHdDlZhFoVAuIiIiIiIiXmHvXhgxAv7xDzh0yPncvaHL2PaTjesf6VSlZlHU8HQHREREREREpHqz2eD11+GxxyAry/lcp04wZw6EhV2T15g7i6IKUCgXERERERERj/nlF7jrLvjuO+f2mjXNkD55MtSq5Zm+VQaFchEREREREal02dkwbRpMnw5nzjif69/fHB2/5BLP9K0yKZSLiIiIiIhIpUpONkfHf/3Vub1+fXjuObjnHvCrJhXQqsnbFBEREREREU87dgzuvRcGDiwcyK+7DrZtg/Hjq08gB42Ui4iIiIiISCX4+GMzkP/5p3N7s2bw6qtwyy1gsXimb55Ujb5/EHGP1NRUBg0aROfOnenWrRsfffSRp7skIiIiIuK10tLMwB0eXjiQjx4N27fDrbdWz0AOGikXKbMaNWoQGxtLjx49SEtLo1evXlx77bXUq1fP010TEREREfEahgHz5sH//R8cPep8LjQU4uJgyBCPdM2raKS8Gho0aBAxMTHFHpd2/fm8VlXQvHlzevToAUBwcDAXXHABR44c8WynRERERES8yM6dMHgw3HmncyD384OHH4atWxXIcymUV0MJCQk8/fTT5b6+Kgbt/K644gosFgsWiwV/f386derEokWLirx206ZN2Gw2QkJCyv16x48fJyYmhjZt2lCnTh0GDBjAxo0bi7z2ueeew2KxFPn5z5o1i7Zt21K7dm369evHhg0bSnzd1atXM2LECFq0aIHFYmHp0qWFrmnbtq3js8j/GD9+fJn6P336dPr06UNAQADNmjXjhhtuYMeOHaV/OCIiIiLiU86cgeefh65d4ZtvnM/17AkbN8KMGVC3rmf6540UyquhJk2aEBAQUGHXV6acnBy33s8wDH744QdefPFFDhw4wI4dOxg2bBh33HEHu3fvdrr2yJEj3HHHHcTHx5/Xa951112sWLGCBQsWsHXrVq6++mqGDBnCnwUW3GzcuJG4uDi6detW6B4ffPABEyZMYOrUqWzevJnu3bszdOhQDh48WOzrnjhxgu7duzNr1qxir9m4cSMHDhxwPFasWAHAzTffXKb+r1q1ivHjx/Pdd9+xYsUKzpw5w9VXX82JEydc/pxERERExLtt2gR9+8Kjj8Lp03nttWubQXzDBrj0Us/1z2sZ1UBmZqYBGJmZmYXOnTp1yti2bZtx6tQpD/Ts/Hz00UdGly5djNq1axtNmjQxBg8ebGRlZRmGYRg2m814/vnnjfbt2xv+/v5GSEiI8cwzzxiGYRhXXHGF8eCDDzruU/D4008/NRo0aGAsXLiw0PmRI0cagNNj9+7dxfYx/3NtNpsxbdo0o23btkbt2rWNbt26GR999JHT9cuWLTPCwsKMhg0bGk2aNDGGDx9u7Ny50+l+48ePNx588EEjMDDQGDRokKP9/vvvNx5++GGjcePGRlBQkDF16tQyf6Y7duwwAOPnn392tG3dutUAjGXLljnaTp8+bVx++eXGO++8U+bXyO/kyZOG1Wo1Pv30U6f2Sy+91Hj88ccdx8ePHzc6dOhgrFixotDvyzAMo2/fvsb48eMdxzabzWjRooUxffp0l/oBGEuWLCn1ugcffNBo3769Ybfby9T/gg4ePGgAxqpVq1zqX2l8+b9jEREREV934oRhTJxoGH5+hmGuJM97/P3vhvH7757uoWeUlEPzU6G3AjIzzfUNntK1KzRsWPp1Bw4c4B//+AczZszgxhtv5Pjx43z77bcYhgHA5MmTmTNnDv/9738ZOHAgBw4c4NeCGwEWYdGiRdx9990sWrSI6667rtD5V155hd9++40uXbrw1FNPAdC0aVOX3tv06dNZuHAhs2fPpkOHDqxevZp//etfNG3alCuuuAIwR28nTJhAt27dyMrKYsqUKdx4441s2bIFv3ObFb799tvcc889JCcnO93/7bffZsKECaxfv55169YxatQowsLCuOqqq1zqH5jT0Rs3bkznzp0B2LdvH48//ji1atVyjFAbhsGoUaP4+9//TlRUVKF7TJs2jWnTppX4Otu2baN169acPXsWm81G7dq1nc7XqVOHNWvWOI7Hjx/P8OHDGTJkCM8884zTtTk5OWzatInJkyc72vz8/BgyZAjr1q1z+b2XJicnh4ULFzJhwgQs50pjutr/gjIzMwFzFoaIiIiI+K4VKyA6GgpMKqVxY3jpJRg1qvpWVXeVQnkBW7fC5Zd77vW//RYGDiz9ugMHDnD27FkiIiJo06YNAF27dgXMNb6vvPIKM2fOZOTIkQC0b9+egaXceNasWTz++ON88sknjpBcUMOGDfH396du3boEBwe7/L6ys7OZNm0aX331Ff379wcgNDSUNWvWEBcX53i9yMhIp+e99dZbNG3alG3bttGlSxcAOnTowIwZMwq9Rrdu3Zg6darjmpkzZ7Jy5coyhfLNmzeTmZlJQEAANpuN06dPU6dOHWbPnk2LFi0ASE5O5oMPPqBbt26OddgLFixwfP533303t9xyS4mvk3uvgIAA+vfvz9NPP02nTp0ICgrivffeY926dVx44YUAvP/++2zevLnYdeaHDx/GZrMRFBTk1B4UFOTSFzGuWrp0KUePHmXUqFGONlf6X5DdbicmJoawsDDH71REREREfEtGhllV/e23C5+79VZ45RUo8M9TKYZCuY/q3r07gwcPpmvXrgwdOpSrr76am266icaNG7N9+3ays7MZPHiwy/f73//+x8GDB0lOTqZPnz5l7s+7775LdHS043jZsmVcnu/bjZ07d3Ly5MlCATknJ4eePXs6jn///XemTJnC+vXrOXz4MHa7HYC9e/c6AlyvXr2K7EPBtdbNmzcvcU11UTZv3sz48eN54IEHOHr0KBMnTiQsLMwpiA4cONDRr6I0adKkTCPA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xpNPPkm7du2oU6cO7du35+mnn3b6P4C2bds6PtP8j/Hjx7vcRxEREZGqJH1tvOPPp3JqM2/VaDJPNqJW/UbMmd+IRf9rRKt2jcD/3MNiKe5WRYqLi8NqtWIp8DyLxYLVaiUuLu7834QUq1LXlGdmZgLQpEkTwAwpZ86cYciQIY5rOnbsSOvWrVm3bh0A69ato2vXrgTl20xv6NChHDt2jF9++aXI18nOzubYsWNOj6poz5499OrVi6+//poXXniBrVu38sUXX3DllVd6NMB46suSkJAQ3n//fU6dOuVoO336NIsWLaJ169Zufz3DMPjhhx948cUXOXDgADt27GDYsGHccccd7N692+naI0eOcMcddxAfH1/M3Vxz1113sWLFChYsWMDWrVu5+uqrGTJkCH/++adL58G1GSzF2bhxI3FxcXTr1q3QuQ8++IAJEyYwdepUNm/eTPfu3Rk6dCgHDx50XPP888/zxhtvMHPmTLZv387zzz/PjBkzeO2115xe48CBA47HihUrALj55pvL/bmJiIiI+KIDB+CeO/bS9MwXjraP1t/M0ZONGTMGtm+Hm28ucwYvJDw8nMWLF+Pn5+cI5haLBT8/PxV7qwxGJbHZbMbw4cONsLAwR9u7775r+Pv7F7q2T58+xqRJkwzDMIyxY8caV199tdP5EydOGIDx+eefF/laU6dONYBCj8zMzELXnjp1yti2bZtx6tSp83l7HnHNNdcYLVu2NLKysgqd++uvvwzDMIzTp08b999/v9G0aVOjVq1aRlhYmLFhwwana6+44grj/vvvNx5++GGjcePGRlBQkDF16lTHeZvNZjz//PNG+/btDX9/fyMkJMR45plnnJ4/fvx448EHHzQCAwONQYMGOZ43bdo0o23btkbt2rWNbt26GR999JFhGIYxcuTIQr+f3bt3l/q84owcOdIIDw83unTpYixcuNDR/u677xrdunUzwsPDjZEjRxa6/nzs2LHDAIyff/7Z0bZ161YDMJYtW+ZoO336tHH55Zcb77zzznm93smTJw2r1Wp8+umnTu2XXnqp8fjjj5d6vjgHDx40AGPVqlUlvv7x48eNDh06GCtWrDCuuOIK48EHH3Q637dvX2P8+PGOY5vNZrRo0cKYPn26o2348OHGmDFjnJ4XERFh3H777cW+7oMPPmi0b9/esNvtxV7jy/8di4iI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VmQdOnSgTp06rFy5krvuusvlt9G5c2dq1arF3r17i51y7u/vj81mK/PzAgICSnztYcOGkZOTg8ViYejQoS73uSxSUlI4evSo05Tvzp070759exYtWsRjjz3m0n3KMn09v3r16lGvXj3++usvli9f7rR0oLTzpc1gKWjw4MFs3epcZ2H06NF07NiRRx55BKvVitVqpVevXqxcudKx1ZzdbmflypWOL0gATp48iZ+f86YPVqu1yNkE8+bNo1mzZgwfPrzE/omIiIj4HNtpzvy+gNxhsXW/X8aS7yMAaNwY/vtfuOOO86+qLr6hwqevl6Z27drMmjWrxBHNNm3a8Pnnn7uza8Xzb+jSmm5vMGvWLMLCwujbty9PPfUU3bp14+zZs6xYsYI33niD7du3c8899/Dwww/TpEkTWrduzYwZMzh58iR33nmnS69Ru3ZtHnnkESZNmoS/vz9hYWEcOnSIX375pcR7BAQEMHHiRB566CHsdjsDBw4kMzOT5ORkGjRowMiRI2nbti3r169nz5491K9fnyZNmrj0vNJYrVbH9Hyr1VrsdZmZmWzZssWpLTAw0KWigJs2baJmzZpcdNFFTu2DBw9myZIlLofysk5fX758OYZhcPHFF7Nz504efvhhOnbsyOjRo106D6XPYAGYOXMmS5YsYeXKlQQEBBRab16vXj0CAwOd2idMmMDIkSPp3bs3ffv2JTY2lhMnTji99ogRI3j22Wdp3bo1l1xyCT/88AMvv/wyY8aMcbq/3W5n3rx5jBw5kho19I2wiIiIVB0ZGfDRC4u5u9tfjrY535jT0m+7DWJjoUCZHqni9K9dHxYaGsrmzZt59tln+b//+z8OHDhA06ZN6dWrl2OWwnPPPYfdbicqKorjx4/Tu3dvli9fTuPGjV1+nSeffJIaNWowZcoU9u/fT/Pmzbn77rtLfd7TTz9N06ZNmT59OikpKTRq1IhLL73UEVgnTpzIyJEj6dy5M6dOnWL37t20bdu21Oe5okGDBqVek5SUVGh9+5133sncuXOZP38+o0ePLvaLpc2bN9OhQwf8/f2d2ocMGcLs2bPZt29fiVPCyyszM5PJkyezb98+mjRpQmRkJM8++6xj+UFp58G1GSyHDx9m165dZerbrbfeyqFDh5gyZQppaWn06NGDL774wqn422uvvcaTTz7Jvffey8GDB2nRogXR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SQjlAAAAAACYhFAOAAAAAIBJCOUAAAAAAJiEUA7UYtu2bRozZoy6deumZs2aqXv37poyZYoOHz5sdmmIA48//rjS0tLUvHlztWnTxuxyEKNeeuklnX766WratKn69OmjL774wuySEOM++eQTDRkyRJ06dZLFYtGbb75pdkmIA08++aQuvvhitWrVSh07dtTQoUO1ceNGs8sCfAjlQC02bNggt9stu92utWvXasaMGZo1a5YefPBBs0tDHDh8+LCGDRum22+/3exSEKMWLlyoe++9V1OmTNHXX3+tXr16afDgwfrhhx/MLg0xbN++ferVq5deeukls0tBHPn44481YcIEff7551q0aJGOHDmiQYMGad++fWaXBkhin3KgTqZNm6aZM2dqy5YtZpeCODF//nzl5OSovLzc7FIQY/r06aOLL75YL774oiTJ7XYrJSVFd955pyZPnmxydYgHFotFb7zxhoYOHWp2KYgzpaWl6tixoz7++GNdfvnlZpcDMFIO1EVFRYVOOeUUs8sAgAY5fPiwli9froEDB/rOWa1WDRw4UMuWLTOxMgAIvYqKCkni/+kQMQjlQIA2bdqkF154QdnZ2WaXAgAN8uOPP8rlcikpKcnvfFJSkpxOp0lVAUDoud1u5eTkqH///jrvvPPMLgeQRChHHJo8ebIsFssJHxs2bPD7neLiYl111VUaNmyYxo0bZ1LliHb1+ewBAIDgmTBhgtasWaPXXnvN7FIAn0ZmFwCE26RJkzRq1KgT3pOamur7886dOzVgwAClpaUpLy8vxNUhltX1sweESvv27WWz2VRSUuJ3vqSkRMnJySZVBQChNXHiRL399tv65JNP1LlzZ7PLAXwI5Yg7HTp0UIcOHQK6t7i4WAMGDFDv3r01b948Wa1MLkH91eWzB4RSkyZN1Lt3by1evNjXZMvtdmvx4sWaOHGiucUBQJB5PB7deeedeuONN1RYWKhu3bqZXRLgh1AO1KK4uFjp6enq2rWrpk+frtLSUt81RpIQatu3b9euXbu0fft2uVwurVy5UpLUo0cPtWzZ0tziEBPuvfdejRw5UhdddJEuueQS5ebmat++fbr11lvNLg0xbO/evdq0aZPveOvWrVq5cqVOOeUUdenSxcTKEMsmTJig//u//5PD4VCrVq18vTMSExPVrFkzk6sD2BINqNX8+fNr/Z9T/rNBqI0aNUqvvvrqcec/+ugjpaenh78gxKQXX3xR06ZNk9Pp1Pnnn6/nn39effr0MbssxLDCwkINGDDguPMjR47U/Pnzw18Q4oLFYqnx/Lx58066rAwIB0I5AAAAAAAmYYEsAAAAAAAmIZQDAAAAAGASQjkAAAAAACYhlAMAAAAAYBJCOQAAAAAAJiGUAwAAAABgEkI5AAAAAAAmIZQDAAAAAGASQjkAAAAAACYhlAMAAAAAYBJCOQAAAAAAJvl/EOzbtbg8WMcAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.ioff()\n", + "\n", + "plt.clf()\n", + "fig, ax = plt.subplots(1, figsize=(12, 8))\n", + "fig.patch.set_facecolor(\"white\")\n", + "ax.scatter(X_train, y_train, **train_plot_config)\n", + "ax.scatter(X_test, y_test, **test_plot_config)\n", + "ax.plot(X_test, y_pred_sklearn, **get_sklearn_plot_config(mse_sklearn))\n", + "ax.plot(x_space, y_pred_q_space, **get_concrete_plot_config(mse_clear))\n", + "ax.legend()\n", + "display(fig)" + ] + }, + { + "cell_type": "markdown", + "id": "141bc829", + "metadata": {}, + "source": [ + "## Conclusion" + ] + }, + { + "cell_type": "markdown", + "id": "c44fff29", + "metadata": {}, + "source": [ + "In this tutorial, we have shown how easy it is to train and execute a linearSVR regression model in FHE using Concrete-ML.\n", + "\n", + "We have also discussed the development flow of a FHE model: training, quantization, compilation and inference.\n", + "\n", + "The slight decrease in prediction quality is due to the quantization of the model's weights and input data, which makes the model poorly generalize outside of its training domain. However, this decrease remains negligible as both floating point (scikit-learn) and FHE (Concrete-ML) models give almost identical MSE scores." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}