mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-09 03:55:04 -05:00
Starting from sklearn tutorial on PoissonRegression, quantize the regressor and compile to FHE Closes #979, #599, #1132
535 lines
97 KiB
Plaintext
535 lines
97 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b760a0f6",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Generalized Linear Model : Poisson Regression\n",
|
|
"\n",
|
|
"Currently, **Concrete** only supports unsigned integers up to 7-bits, for both parameters, inputs and intermediate values such as accumulators. Nevertheless, we want to evaluate a linear regression model with it. Luckily, we can make use of **quantization** to overcome this limitation!"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "253288cf",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Let's start by importing some libraries to develop our linear regression model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "6200ab62",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from copy import deepcopy\n",
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"from sklearn.linear_model import PoissonRegressor\n",
|
|
"from sklearn.datasets import fetch_openml\n",
|
|
"from sklearn.model_selection import train_test_split\n",
|
|
"from sklearn.decomposition import PCA\n",
|
|
"from tqdm import tqdm\n",
|
|
"\n",
|
|
"from concrete.quantization import QuantizedLinear, QuantizedArray, QuantizedModule\n",
|
|
"from concrete.quantization.quantized_activations import QuantizedActivation\n",
|
|
"\n",
|
|
"import concrete.numpy as hnp"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f43e2387",
|
|
"metadata": {},
|
|
"source": [
|
|
"### And some helpers for visualization"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "d104c8df",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from IPython.display import display"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "53e676b8",
|
|
"metadata": {},
|
|
"source": [
|
|
"### We need an inputset, get one from OpenML for insurance claims"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "d451e829",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df = fetch_openml(data_id=41214, as_frame=True, cache=True, data_home=\"~/.cache/sklearn\").frame\n",
|
|
"df = df.head(50000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4690cc15",
|
|
"metadata": {},
|
|
"source": [
|
|
"### We want to predict the frequency of insurance claims. Our example will only use a single predictor feature so we can easily visualize results\n",
|
|
"### First, compute the target value from the input dataset\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "5e163891",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df[\"Frequency\"] = df[\"ClaimNb\"] / df[\"Exposure\"]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "75f4fdb7",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Let's visualize our inputset to get a grasp of it. The target variable, \"Frequency\" has a poisson distribution"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "2a124a62",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 1080x504 with 2 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"plt.ioff()\n",
|
|
"fig, ax = plt.subplots(1,2,figsize=(15,7))\n",
|
|
"fig.patch.set_facecolor('xkcd:mint green')\n",
|
|
"ax[0].set_title(\"Frequency of claims vs. Driver Age\")\n",
|
|
"ax[0].set_xlabel(\"Driver Age\")\n",
|
|
"ax[0].set_ylabel(\"Frequency of claims\")\n",
|
|
"ax[0].scatter(df[\"DrivAge\"], df[\"Frequency\"], marker=\"o\", color=\"red\")\n",
|
|
"ax[1].set_title(\"Histogram of Frequency of claims\")\n",
|
|
"ax[1].set_xlabel(\"Frequency of claims\")\n",
|
|
"ax[1].set_ylabel(\"Count\")\n",
|
|
"df[\"Frequency\"].hist(bins=30, log=True, ax=ax[1])\n",
|
|
"display(fig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5c8310ab",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Now, we need a model so let's define it\n",
|
|
"\n",
|
|
"### First let's split the data, keeping a part of the data to be used for calibration. The calibration set is not used in training nor for testing the model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "d81db277",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df_train, df_test = train_test_split(df, test_size=0.2, random_state=0)\n",
|
|
"df_calib, df_test = train_test_split(df_test, test_size=100, random_state=0)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "faa5247c",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Train the scikit-learn PoissonRegressor model "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "682fb2d8",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"PoissonRegressor(alpha=1e-12, max_iter=300)"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"reg = PoissonRegressor(alpha=1e-12, max_iter=300)\n",
|
|
"reg.fit(df_train[\"DrivAge\"].values.reshape(-1,1), df_train[\"Frequency\"])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "084fb296",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Time to make some predictions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "4953b03e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"test_data = np.sort(df_test[\"DrivAge\"].values).reshape(-1,1)\n",
|
|
"predictions = reg.predict(test_data)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f28155cf",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Let's visualize our predictions to see how our model performs. Note that the graph is on a Y log scale so the regression line looks linear"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "111574ed",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"plt.clf()\n",
|
|
"fig, ax = plt.subplots(1)\n",
|
|
"fig.patch.set_facecolor('xkcd:mint green')\n",
|
|
"ax.set_yscale(\"log\")\n",
|
|
"ax.plot(test_data, predictions, color=\"blue\")\n",
|
|
"ax.scatter(df_test[\"DrivAge\"], df_test[\"Frequency\"], marker=\"o\", color=\"red\")\n",
|
|
"ax.set_xlabel(\"Driver Age\")\n",
|
|
"ax.set_title(\"Regression with sklearn\")\n",
|
|
"ax.set_ylabel(\"Frequency of claims\")\n",
|
|
"display(fig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2d959640",
|
|
"metadata": {},
|
|
"source": [
|
|
"### FHE models need to be quantized, so let's define a **Quantized Poisson Regressor** (Generalized Linear Model with exponential link)\n",
|
|
"\n",
|
|
"We use the quantization primitives available in the Concrete library: QuantizedArray, QuantizedFunction and QuantizedLinear"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "9f5acbfe",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class QuantizedExp(QuantizedActivation):\n",
|
|
" \"\"\"Quantized exponential function.\"\"\"\n",
|
|
"\n",
|
|
" def calibrate(self, x: np.ndarray):\n",
|
|
" self.q_out = QuantizedArray(self.n_bits, np.exp(x))\n",
|
|
"\n",
|
|
" def __call__(self, q_input: QuantizedArray) -> QuantizedArray:\n",
|
|
" quant_exp = np.exp(self.dequant_input(q_input))\n",
|
|
" q_out = self.quant_output(quant_exp)\n",
|
|
" return q_out\n",
|
|
" \n",
|
|
"class QuantizedGLM(QuantizedModule):\n",
|
|
" def __init__(self, n_bits, sklearn_model, calibration_data) -> None:\n",
|
|
" # Create a QuantizedLinear layer\n",
|
|
" self.n_bits = n_bits\n",
|
|
"\n",
|
|
" self.q_calibration_data = QuantizedArray(n_bits, calibration_data)\n",
|
|
"\n",
|
|
" q_weights = QuantizedArray(1, np.expand_dims(sklearn_model.coef_,1))\n",
|
|
" q_bias = QuantizedArray(1, sklearn_model.intercept_)\n",
|
|
" q_layer = QuantizedLinear(6, q_weights, q_bias)\n",
|
|
" quant_layers_dict = {}\n",
|
|
" # Calibrate and get new calibration_data for next layer/activation\n",
|
|
" calibration_data = self._calibrate_and_store_layers_activation(\n",
|
|
" \"linear\", q_layer, calibration_data, quant_layers_dict\n",
|
|
" )\n",
|
|
"\n",
|
|
" # Create a new quantized layer (based on type(layer))\n",
|
|
" q_exp = QuantizedExp(n_bits=7)\n",
|
|
" calibration_data = self._calibrate_and_store_layers_activation(\n",
|
|
" \"invlink\", q_exp, calibration_data, quant_layers_dict\n",
|
|
" )\n",
|
|
"\n",
|
|
" super().__init__(quant_layers_dict)\n",
|
|
"\n",
|
|
"\n",
|
|
" def _calibrate_and_store_layers_activation(self, name, q_function, calibration_data, quant_layers_dict):\n",
|
|
" # Calibrate the output of the layer\n",
|
|
" q_function.calibrate(calibration_data)\n",
|
|
" # Store the learned quantized layer\n",
|
|
" quant_layers_dict[name] = q_function\n",
|
|
" # Create new calibration data (output of the previous layer)\n",
|
|
" q_calibration_data = QuantizedArray(self.n_bits, calibration_data)\n",
|
|
" # Dequantize to have the value in clear and ready for next calibration\n",
|
|
" return q_function(q_calibration_data).dequant()\n",
|
|
"\n",
|
|
"\n",
|
|
" def quantize_input(self, x):\n",
|
|
" q_input_arr = deepcopy(self.q_calibration_data)\n",
|
|
" q_input_arr.update_values(x)\n",
|
|
" return q_input_arr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ab82ae87",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Let's quantize our model parameters\n",
|
|
"\n",
|
|
"First we get the calibration data, we then run it through the non quantized model to determine all possible intermediate values. After each operation these values are quantized and the quantized version of the operations are stored in the QuantizedGLM module"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "09d12194",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"calib_data = np.expand_dims(df_calib[\"DrivAge\"].values, 1)\n",
|
|
"n_bits = 5\n",
|
|
"q_glm = QuantizedGLM(n_bits, reg, calib_data)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e2528092",
|
|
"metadata": {},
|
|
"source": [
|
|
"### And quantize our inputs and perform quantized inference "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "f0f0699a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"q_test_data = q_glm.quantize_input(test_data)\n",
|
|
"y_pred = q_glm.forward_and_dequant(q_test_data)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a5a50eb8",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Visualize the results"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"id": "5fb15eb4",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"plt.clf()\n",
|
|
"fig, ax = plt.subplots(1)\n",
|
|
"fig.patch.set_facecolor('xkcd:mint green')\n",
|
|
"ax.set_yscale(\"log\")\n",
|
|
"ax.plot(test_data, y_pred, color=\"blue\")\n",
|
|
"ax.scatter(df_test[\"DrivAge\"], df_test[\"Frequency\"], marker=\"o\", color=\"red\")\n",
|
|
"ax.set_xlabel(\"Driver Age\")\n",
|
|
"ax.set_ylabel(\"Frequency of claims\")\n",
|
|
"ax.set_title(\"Quantized regression with {} bits\".format(6))\n",
|
|
"display(fig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "af6bc89e",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Now it's time to make the inference homomorphic"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "fe9935bd",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"BENCHMARK_CONFIGURATION = hnp.CompilationConfiguration(\n",
|
|
" dump_artifacts_on_unexpected_failures=True,\n",
|
|
" enable_topological_optimizations=True,\n",
|
|
" check_every_input_in_inputset=True,\n",
|
|
" treat_warnings_as_errors=True,\n",
|
|
")\n",
|
|
"\n",
|
|
"engine = q_glm.compile(\n",
|
|
" q_test_data,\n",
|
|
" BENCHMARK_CONFIGURATION,\n",
|
|
" show_mlir=False,\n",
|
|
")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "01d67c28",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Let's compile our quantized inference function to it's homomorphic equivalent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"id": "c1fc0f48",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from PIL import Image\n",
|
|
"file = Image.open(engine.draw())\n",
|
|
"file.show()\n",
|
|
"file.close()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "46753da7",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Finally, let's make homomorphic inference"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"id": "ca928b78",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"100%|██████████| 100/100 [01:54<00:00, 1.15s/it]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"y_pred_fhe = np.zeros((test_data.shape[0],), np.float32)\n",
|
|
"for i, test_sample in enumerate(tqdm(q_test_data.qvalues)):\n",
|
|
" q_sample = np.expand_dims(test_sample, 1).transpose([1,0]).astype(np.uint8)\n",
|
|
" q_pred_fhe = engine.run(q_sample)\n",
|
|
" y_pred_fhe[i] = q_glm.dequantize_output(q_pred_fhe)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "68f67b3f",
|
|
"metadata": {},
|
|
"source": [
|
|
"### And visualize it"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"id": "92c7f2f5",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEGCAYAAACKB4k+AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAkAUlEQVR4nO3deVhU9f4H8PewbzKAgCLbuG+oqIBlpdYvtSxSc8voaqmR1k1N69qNay5XzFuWLaZGi5riVlku3by3LCu9pqKgIrmFyOKCbMMyrDPz++PEYRE4AzLLYd6v5+GZmTMLn8HxvOd8t6NYo9+oBxEREQAbcxdARESWg6FAREQihgIREYkYCkREJGIoEBGRyM7cBdyJFd4vQ6VSmbsMIiJZOZ92AStyPmjwPlmHgkqlQkJCgrnLICKSlcCwzo3ex+YjIiISMRSIiEjEUCAiIhFDgYiIRAwFIiISyTIUkvclYWf0JqjVanOXQtYkPh5QqQAbG+EyPt7cFRG1OlmGQkhkKKbEPQ2lUmnuUshaxMcD0dHA1auAXi9cRkczGKjNkWUoEJlcTAyg0dTdptEI24naEIYCkSHS05u3nUimGApEhggKat52IpliKBAZIjYWcHGpu83FRdhO1IYwFIgMERUFxMUBwcGAQiFcxsUJ24naEFkviEdkUlFRDAFq83ikQEREIoYCERGJZNl8lLwvCef2JXFGMxFRK5PlkQJnNBMRGYcsQ4GIiIyDoUBERCKGAhERiRgKREQkYigQEZGIoUBERCKGAhERiRgKREQkYigQEZGIoUBERCKGAhERibggHhERiWR5pMAF8YiIjEOWoUBERMbBUCAiIhFDgYiIRAwFIiISMRSIiEjEUCAiIhFDgYiIRAwFIiISMRSIiEjEUCAiIhFDgYiIRAwFIiISMRSIiEjEUCAiIhFDgYiIRAwFIiISMRSIiEjEUCAiIpFFnaP57DenkPLtaZQVlmLIzGHoNSrE3CUREVkVo4fC9hmfImX/abj5umNR8gpx++8HzuLredug1+owZNYwPPjqI+g3bhD6jRsETX4J9r68k6FARGRiRm8+inj6XkQfWFBnm06rw1cvbEH0dy9hUUosErcfw42ULPH+71fswz0vPGDs0oiIqB6jh0LXYT3h6uVWZ1v68VR4d/OFdxdf2DnYYeATEUjekwi9Xo99i3ah18P9EDhIZezSiIioHrP0KRRk5cMj0Eu8rQzwQvqxP/DrBz/g4g8pKFWXIudyNu6Zff9tz/1f3CEcjfsZAGBzS2eymomIrIFFdTQPmzsSw+aObPIxQ6NHYGj0CADA1rC1JqiKiMh6mGVIqoe/Jwoy8sTb6sw8KP09zVEKERHVYpZQCAzvjFuXspF75RaqKqqQuOM4+j420ODnJ+9Lws7oTVCr1UaskojI+hi9+ejzqRtw+dB5lOQUY2nAAjy0bBzumjkME9ZG4aPRb0On1WHIjPvg19ff4NcMiQxFSGQom4+IiFqZ0UNh2vbZDW7vM2YA+owZYOxfT0REzcBlLoiISNSsIwVNfgkKMvLQqX+gseoxSPK+JJzbl8Q+BSKiViZ5pLB2xCqUFZaiJK8Ybw9aip3PbsI3C7aboLTGhUSGYkrc01AqlWatg4iorZEMhTJ1KZzcnXF290mETRuKl44txsUfUkxRGxERmZhkKOiqtFBfL0DirhPo+yg7homI2jLJUBj1+lh8NPpt+HTzRVB4F+SkZsOnewdT1EZERCYm2dEcOikcoZPCxdveXXzxzFd/NWpRUtjRTERkHJKhkHvlFn794AfkpeVAV1WzAN2svfOMWlhTOHmNiMg4JEPhs3EfYMjM+9A3MhQKG4UpaiIiIjORDAU7J3vJlUuJiKhtkAyFYfMexIFl36DXqBDYOtY8nCfBISJqeyRD4frZTCRsOYrLP56vaT5SAC/8uMjYtTWKHc1ERMYhGQqnv0jAP1LfhJ2D5ZyPhx3NRETGITlPoWOIP0oLNKaohYiIzEzy639pgQarer2GwHAV7Bztxe3mHJJKRGYUHw/ExADp6UBQEBAbC0RFmbsqaiWSofDQsnEmKIOIZCE+HoiOBjR/th5cvSrcBhgMbYRkKHQb3ssUdRCRHMTE1ARCNY1G2M5QaBMaDYX3712JuYdfw6vt5gC156zpASiAVYXrjV9dIzj6iMhM0tObt51kR7FGv1Fv7iJaamvYWiQkJJi7DCLroVIJTUb1BQcDaWmmroZaKDCsMxYmLGnwPoNPx1mUXYj89Fzxh4isUGws4OJSd5uLi7Cd2gTJPoXkvYnYs3AHCq8VwM3XHflXc+Hb2w+vnuOHgMjqVPcbcPRRmyV5pPDd4q8x/7fF8OnREYuvvIU5B1+B6q6upqiNiCxRVJTQVKTTCZcMhDZFMhRs7G3h2t4Nep0eOp0O3e/vjYyENBOURkREpibZfOTs4YLy4jJ0GdYDW6Pi4ObbDg6uDqaojYiITEwyFGbumQt7J3uMWzMVJ+OPokxditGvjzVFbY3ikFQiIuOQDAVHV0fxesT0e41ajKG4IB4RkXE0GgripLU/J6uJLGDyGhERGUejobCqiDt9IiJrIzn6KO23P1BWVCreLisqxdVjfxi1KCIiMg/JUPhyzudwdHMSbzu4OuKLOZ8btSgiIjIPyVDQ6/VQKGo6FWxsbKCr0hm1KCIiMg/JUGjfxQe/vP89tJVV0FZW4ef3/ov2XXxMURsREZmY5JDUSRum4+u58fh+xT5AoUCP/+uNyXFPm6A0IiIyNclQaOfrjmk75piiFiIiMjPJULBEnNFMRGQcBp9PwZKERIZiStzTUCqV5i6FiKhNaTQUfn7vvwCA1COXTFYMERGZV6OhcHzjYQDA7he3mqwYIiIyr0b7FDr07oTY7otQeK0Ab/ZfXHOHXg8oFPjbmX+aoj4iIjKhRkNh2vbZKLyhxkej38bMvXNNWRMREZlJk6OP3Dsq8crp5aiqqMKtizcAAL49O8LWXpaDloiISILk3v3yz+exbdon8FJ5Q6/XoyAjD09unoWuw3qaoj4iIjIhyVDYs2AHZv93IXx7+gEAsi/ewJapG7Dw5FJj10ZERCYmOU9BW6kVAwEAfHt0hLZSa9SiiIjIPCSPFALDVNgx6zOEPTUUAHAy/igCw1TGrouIiMxA8khh0vpp6NjHH7+8/z1+ef97dOjTCZPWTzNFbWRs8fGASgXY2AiX8fHmroiIzEzySMHO0R4jFozGiAWjTVEPmUp8PBAdDWg0wu2rV4XbABAVZb66iMisZLn2EbWCmJiaQKim0QjbichqyXLCAVdJbQXp6c3bTkRWQfJI4drZDFPU0SxcJbUVBAU1bzsRWQXJUPjy+S1YE7Ech9f9iFK1RurhJBexsYCLS91tLi7CdiKyWpKhMPfX1/BUfDQKMnLxzuBl2PLkBlz4/pwpaiNjiooC4uKA4GBAoRAu4+LYyUxk5QzqU/Dp3hFjVkxAYFhnfD03HpmJ6YBej0dWTkD/x8OMXSMZS1QUQ4CI6pAMhWtnMnBs42H8/u1p9BjZFzP3zUPgIBXU1/Lx3t2xDAUiojZEMhR2vxiPIbOG4ZGVE+Dg7CBuV3byxMMrHjdqcUREZFqSofDst/Nh7+wAG1uh+0Gn06GqrBIOLo4I/8tQoxdIRESmI9nRvP7Bt1BZWiHertRUYP2Dbxm1KCIiMg/JUKgsq4Sjm5N429HNCRWaiiaeQUREciUZCg6ujsg4lSbezjiZBvtafQtERNR2SPYpjH93KjZPWgf3Th6AHii6oca0nXNMUBoREZmaZCgEhXfB38+vRPYFnqOZiKitM2jvnn7iCvLScqCr0iHz1FUAQPi0e4xaGBERmZ5kKGz9Sxxy/8iGf2gQFH8OS1UoFAwFIqI2SDIUMhLS8GpKLBQKhSnqISIiM5IcfeQX4o/CGzxvARGRNZA8UijJKca/+sQgKKIz7Bztxe2z9s4zamFERGR6kqEweulYU9RBREQWQDIUug3vhbyrObh16SZ6PtgXFZpy6LQ6U9RGREQmJtmncPTjn7Fp4of44rnNAAB1Vj4+G/dBqxeSk5qNHTM/w8aJH7b6axMRkWEkQ+Hwhwcx90gMnNydAQgn3CnOLjToxbfP+BSLfefiXyH/qLP99wNnsbLn3xHbbRF+WPUtAMC7iy+e+HRGc+snIqJWJBkKdo72sHOoaWXSVmmF0zcaIOLpexF9YEGdbTqtDl+9sAXR372ERSmxSNx+DDdSsppZNhERGYNkn0LX4T3x/cr9qCytwIXvz+HIuh/RNzLUoBfvOqwn8tJy6mxLP54K726+8O7iCwAY+EQEkvckomMff4Ne839xh3A07mcAgM0t9m0QEbUmySOFR1dNhJtPO/j1C8D/PjqE3mP6Y8wdnHGtICsfHoFe4m1lgBfUWfkoyS3GrtmbkZV4FT+8sb/R5w+NHoGFCUuwMGEJfHx8WlwHERHdTvJIwcbGBnc/Oxx3PzvcqIW4tnfD5A3Tjfo7iIioaZKh8M/OrzTYh7A49c0W/UIPf08UZOSJt9WZeVD6ezbrNZL3JeHcviSo1ZxpTUTUmiRDYUHCEvF6ZVklTn9xApq8khb/wsDwzrh1KRu5V25B6e+JxB3H8dS255r1GiGRoQiJDMXWsLUtroMsRHw8EBMDpKcDQUFAbCwQFWXuqoislmSfgmt7N/HHw98Tw+ePQsq3pw168c+nbsC7d69A9oUbWBqwAL99+gts7WwxYW0UPhr9Nlb1fg2hk8Ph19ewTmZqY+Ljgeho4OpVQK8XLqOjhe1EZBbSq6TWOhWnXqdHRkIadFWGjfqZtn12g9v7jBmAPmMGGFYhtV0xMYBGU3ebRiNs59ECkVlIhsLehTvF6zZ2NvBSeWP6LvOejpN9Cm1EenrzthOR0UmGwgs/LTJFHc3CPoU2IihIaDJqaDsRmYVkKBx65z9N3j9iwehWK4asTGys0IdQuwnJxUXYTkRmIdnRnJFwBUfW/wh1Vj7UWfn434afkHkqDWVFpSgrKjVFjW1TfDygUgE2NsKlNXauRkUBcXFAcLAw7Dk4WLjN/gQis5E8UijIzMfCU0vh1E5YEG/00rH4+JF38dTW5g0jpVqqR91Uf0OuHnUDWN8OMSrK+t4zkQWTPFIoullYZ0E8Owc7FN00bJVUY0nel4Sd0Zvk29Hc1KgbIiIzkjxSCJ82FGsi/ol+4wcBAM5+cwrh0+8xemFNkX1HM0fdEJGFkgyFkTGR6PVwP6T+ehEAMHXjTAQMDDZ6YW0aR90QkYWSbD4CgEpNBZzcnTF83ih4BHgi98otY9fVtsXGCqNsauOoGyKyAJKhcGDZNzj4r3/j4BvCGdK0lVpsfSrO6IW1aRx1Q0QWSjIUzn59CrP2zoODqyMAQNnJE+VFZUYvrCmy72gGhABISwN0OuGSgUBEFkD6dJwOdlAoFMCfq2eXl5QbuyZJIZGhmBL3NJRKpblLISJqUyQ7mkMnh2PXc5tQWlCKox//jGOf/Yq7jHzCHSIiMo8mQ0Gv1yN0SgSyz9+Ak7szsi9cx8PLx6PnyL6mqo+IiEyoyVBQKBT4eMwa/O3sCgYBEZEVkOxT8B8UjPQTqaaoxTS45hARUaMk+xTSj6Xi3a1H4aXyFkYg6fWAQoG/nfmnKeprUIvPp8A1h4iImqRYo9+ob+iO/PRceAa1R97VnAaf6BXsbdTCDLE1bC0SEhIMf4JK1fBM4uBgYVgoEZEVCAzrjIUJSxq8r9Hmo0/HvQ9A2PnvWbADXsHedX5kiWsOERE1qfE+hVrHD7mpbWRZi8bWFuKaQ0REAJoKBUUj1+WMaw4RETWp0Y7ma6cz8Kr7HEAPVJZWCNcB4QhCAawqXG+iEltRdWdyTIzQZBQUJAQCO5mJiAA0EQrvaD8zZR2mwzN9ERE1SnJIqiVq8ZBUIiJqkkHnU7A0XBCPiMg4ZBkKRERkHAwFIiISMRSIiEjEUCAiIhFDgYiIRLIckkpEZA10OqCoCMjPBwoKhMvq68OGAd26tf7vZCgQERlRZSWgVtfs0BvawTd2vaBACIaGbNrEUCAiMiu9XtjBZ2UB167V/GRnN76DLy5u+jUdHABPT+HHwwPw9QV69hSu195e/3qHDsZ5j7IMBc5oJqI7pdcL59uq3nlXfzOvfT0vD7h+vW4AlJbe/lpubnV32l26NL4zr3/dyQlQWNCio7IMhZDIUIREhmJr2Fpzl0JkPPHxXLxRQkVFwztzQ64XFAhNO01xdQX8/IBOnYCICOGy9o+/v3B//cWX5UyWoUDU5lnxqWMrKoRv5BkZQGZmzWVmZt1mmoKCmj9PY+zt63479/ICunYVrld/W2/sulIpPN/aMBSILFFMzO17PI1G2C6jUCgtFfIsLa3mMj0dKCur+7iqKiEIMjOBmzeFpp3a3N2BgAChHb1Xr6Z35rWvW1rTjBwwFIgskUxOHVtcXLOzr73jr77Mzq77eHt7Yefu6lp3u42N0AwzYAAQGCg8pvoyIEAIBTINhgKRJQoKEvasDW1vZfn5QGKi8HPqlHCZkyP9vMpKoQmnNkdHoUSVChg7FggOFq6rVMJ1Pz/A1rbV3wK1IoYCkSWKja3bpwCIp47V64Fbt4TmluvXa0bH1L+8cUO6I7W+gABg0CBg+HDpZhdbW6GjtXqHr1IJzTs2XCdB1hgKRGZSXg4UFjZy56goYLUjsHIlSjLzkeQzEglD5yJhSwgS5gG5ubc/xcurZqRMz55Ax45Cm7oUNzeh2WbgQMDH547eErUBDAWiO1RUdHvHaUOys4Hjx4WfEyeA06eFDtbGTfzzB8AtwHY/EBICjBsH9O8vfEvv1EkIAkMDgEgKQ4GoEXr97bNR9Xrg8mXgt9+AY8eEy4sXm/e67u5AeDjw8svCjl2qmcbeHujXDwgNBZydm/e7iJqLoUBWpaJCGPaYlXV7e7tGA5w/D5w7B6SkCD9NLVHQoQNw113AtGnCEEgp1WHQowfb3clyMRRItjQaYYBO/QXDioqECU/VP+npNddv3JB+3Y4dgT59gGeeEYZF1t+B+/sLYRAc3AbHwHMWtdVjKJBZFRYCycnCiBkplZVCU82ZM8DZs8ClS7dPcqrP1VXYtwUGCu3w1dcDAoThk7XZ2wvf4tu3b/n7kTUrnkVNNRgKdMeKioSd9OnTTYymqaW4WAiC06eBK1ea97sUCmGZgv79galThZ14/aUInJ1rdv4eHm3w27yxtJFZ1HRnZBkKXCXVuPR6oZnlypWan4aWHrh5E0hKEjpem8PGRtiZh4cDM2cKwyGDgqR33jY2wlj4+rNhqZXIZBY1GZcsQ4GrpDZfXp4wW7V+m3p1AKSl1QRAWtrtQyw9PG6fierhIYyImT5duBwwAPD2lq7Fzs46FxqzeCacRU2WS5ahQIKKCmEH/scfwpe5+mPe1WohCE6eFB7XFE9PoHNnoYP1kUeE65071yxR0JaWBqZGNDGLmqwHQ8HMysuFtvUTJ4RJTZcvS3ee6nRCx2xGhvRju3QRmmlmzxaWL1Cpbm+m8fERlgkmK1fdb8DRR1aNodBKCguFHfuxY8LO3ZChj2Vlwlj46vHyHToI39TtDPhX6d5d2OF37Sr8BAffPprGyQlo167574WsWFQUQ8DKMRQaoNUKO/XqE3vUPsnHjRvC/bXl5gqTnqq/tffo0fA38vrs7ICHHhK+yUdECMMkOVKGiMzJKkNh61Zg27a626pPyJ2ZKawwWX/H7+Qk7LT9/IQTbdfWvbswPHLIEGEH7+lp3PqJiIzFKkNBo2l4vXg3N+D+++ue3KP6upcXv8WbFWfaEpmEVYZCdHTNRE2SAc60JTIZLstFlq+pmbYtER8vdPpUz4aLj7/TConaDIYCWb7WnGlbfdRx9arQkVR91MFgMB+GtEVhKJDla2xGbUtm2rb2UQfdGYa0xWEokOWLjb19SnVLZ9pyfR/LwpC2OAwFsnxRUUBcXM0JDIKDhdst6WRuzaMOunMMaYvDUCB5iIoSFnDS6YTLlo46as2jDrpzDGmLw1Ag69KaRx105xjSFscq5ymQleP6PpaDi/BZHIYCEZkXQ9qisPmIiIhEDAUiIhJZTCiUl5QjfvrH2PnsRpyMP2rucqg1GDJT9fnnhTXEFQrh8vnnTV1lw6x1lq0h79ta/jaW+j6NXJdR+xS2z/gUKftPw83XHYuSV4jbfz9wFl/P2wa9Vochs4bhwVcfwZndJzFgYjhCIkOxeco6DI6625ilkbEZsojd888D69fXPEerrbm9bp3paq3PWhfgM+R9W8vfxlLfpwnqMuqRQsTT9yL6wII623RaHb56YQuiv3sJi1Jikbj9GG6kZEGdmQfPQC+hKFuLOYChljJkpmpcXMPPbWy7qVjrLFtD3re1/G0s9X2aoC6jHil0HdYTeWl1T1yQfjwV3t184d3FFwAw8IkIJO9JhDLACwWZefAPDYJe1/iJh/8XdwhH434GANjc0hmveLozhsxUrX8mI6ntpmKts2wNed/W8rex1PdpgrpM/pW8ICsfHn8eEQCAMsAL6qx89H98MM58dRJfzPkcfSNDG33+0OgRWJiwBAsTlsDHx8cEFVOLGDJT1da24cc0tt1UrHWWrSHv21r+Npb6Pk1Ql8W00zi6OmLqxpmYtH4a+xPaAkNmqjZ2piNznwHJWmfZGvK+reVvY6nv0wR1mTwUPPw9UZCRJ95WZ+ZB6d+8kxon70vCzuhNUKvVrV0etRZDlpNYtw6YM6fmyMDWVrhtzk5mwHqXwjDkfVvL38ZS36cJ6lKs0W9svAG/FeSl5eDjR98VRx9pq7RY2ePveP7gK1D6e2JN+HI8te05+PX1b/Zrbw1bi4SEhNYumYioTQsM64yFCUsavM+oHc2fT92Ay4fOoySnGEsDFuChZeNw18xhmLA2Ch+Nfhs6rQ5DZtzXokAgIqLWZ9RQmLZ9doPb+4wZgD5jBhjzVxMRUQvIckG85H1JOLcviX0KREStzGJGHzVHSGQopsQ9DaVSae5SiIjaFFmGAhERGYcsm4+qnU+7gMCwzi16bsmtIrj6tGvlikxHzvXLuXZA3vXLuXaA9beW/HorTdRm9CGplurtsGWNDsmSAznXL+faAXnXL+faAdZvCmw+IiIiEUOBiIhEVhsKd0cPN3cJd0TO9cu5dkDe9cu5doD1m4LV9ikQEdHtrPZIgYiIbsdQICIikaznKRgqPyMX26Z9gqKbhYBCaNcbPm8USvKK8fmU9chLy4GXyhvTdz0PF09Xc5dbR2VZJdYOewNV5VXQVmkxYGIYHl42HrlXbuHzJzZAk1uMgMHBiNoSDTsHy/3n1Gl1eCdsGZT+nnh2/3zZ1L9c9TKc2jlBYWsDGztbLExYIovPTbXSAg12zNqIG8mZgEKBqZ/NgE/PjrKoP/vCdWyeUnMO79zUW3h4+XiETRsqi/oPrfkPfvvkFygUCvj1C8DUjTNReL3A4j/3VtGnoL5egMLrBQgcpEJZUSneGbwMM755Ecc3HYGLlysefPUR/LDqW5TmlyDyX5PNXW4der0eFSXlcHRzgrayCu/f+wbGv/ckDr3zH/R/fDAGPTEEu2Zvhv+AQNwz5wFzl9uoQ+/8BxkJV1BWWIZn98/HpsnrZFH/ctXLWJCwBG7eNROO9v5tl8V/bqrFT/8YXe/rgbtmDUdVRRUqNRX4fuV+2dRfTafVYan/S5h/bDEOf/ijxddfkJWPD+5diUUpsXBwdsCmyevQZ0x/pPz7jMV/7q2i+Ujp54HAQSoAgFM7Z3To7Qd1VgGS9yQifPo9AIDw6ffg7DeJZqyyYQqFAo5uTgAAbaUW2soqKBTA5R9/x4CJYQCAiOn34Ow3p8xZZpMKMvOQ8u1p3DVrGAAh6ORUf31y+NwAQKlag9RfLmLITOHvbudgB2cPF9nUX9vFgylo39UXXsHesqlfV6VFZWkFtFVaVGoq4O6nlMXn3rKOW0wgLy0HmYnpCB7SBUU31VD6eQAA3DsqUXTTMldd1Wl1eHvwUuRczsa9LzyA9l194ezhAls74YxlygBPqLMKzFtkE76evx2Rb05GeVEZAKAkt1g29SsUCmwYtRoKhQJ3PzcCQ6NHyOZzk3clB24+7bD9mU9x7XQGAgYHY/x7UbKpv7bEHccwaOoQAJBF/R7+nhjx8kNYHvQy7J3t0XNUCAIGq2TxubeqUCgvLsPGCWsx/t2pcHJ3rnOfQqGAQqEwU2VNs7G1wStJy1FaoMFn4z9A9vnr5i7JYOf2J6GdbzsEDlbh8qHz5i6n2V48/Bo8/D1RlF2IDSNXo0Mvvzr3W/LnRlulReapq3j8gygED+mK3fPicXDVt3UeY8n1V6uqqMK5vUl49I2Jt91nqfVr8kuQvCcRi6+8CWcPF2yatA7nD5w1d1kGsZpQ0FZWYeOEtRgcdTf6Py4cvrXroIT6egGUfh5QXy+Am6+7matsmrOHC7rd3wtpR/9AaYEG2iotbO1soc7Mh9Lfw9zlNejKkUtI3puElH+fQVVZJcoKy/D1vG2yqd/jz/OHt/N1R7/xg5B+PFU2nxuPAC8oAzwRPKQrAGDAxHAcXPWtbOqv9vt3Z+A/KBjtOghL5cuh/os/pKB9Zx+4+Qi19X98MK4cuSyLz71V9Cno9XrsmLkRHXp3wogFo8XtIY+F4sTmIwCAE5uPIGTsQHOV2KjiW4UoLdAAACpKK3Dh+3Po0NsP3e7vhdNfCuenPr75CELGDjJnmY169I1JWJr5Dl5PW41pO+ag+wO98Zf452RRf3lJOcqKSsXrF/6bjI4hAbL43ABC04pHoBeyLwhHlpcOpqBjn06yqb9a4vaapiNAHv9vPYO8kPbbH6jQlEOv1+PiwRR06NNJFp97qxh9lHr4Ij647w349QuAwkY41Hxk5QQED+mKzZPXIT89F57B3pi+aw5cvdzMXG1d185kYNv0T6DT6qDX6RE6ORyjXx+LnNRsbHliAzR5JfAfGISntkbDztHe3OU26fKh8/hp9QE8u3++LOrPSc3GxvFrAQhNMYOfvAsjYyJRklts8Z+ballJ6dgxayO0FVVo38UHUzfOhF6nl0395SXlWB60EP9IfRPOShcAkM3f/7slXyNp53HY2NnCf2AQnvjkGRRk5Vv8594qQoGIiAxjFc1HRERkGIYCERGJGApERCRiKBARkYihQEREIoYCWZ0FtjPwVujrWNU3Bm8NeB0/vX0AOp2uwceqr+Vj48QPjVbL2W9O4SXFM7gpo1nq1LZZzYxmomr2zg54JWk5AKAouxBbnvwIZYWleHjZ+DqP01ZpoezkiWe+fOGOf2f1LNb6Tm3/DZ3v7Y5T23+77fcTmQNDgaxaO193TI6bjjXhy/HQ0nE4sfkIzuw+ifLiMui1ejy5eRY+fvRdLEpegXfv+iemfDoDfn39AQBrR6zCY6unoEPvTtj94lbcSM6CtlKL0UvHot/YQTi+6XCd1/rrz6/W+d3lxWW4cvgSnv9pET6JfE8MBZ1Oh91/3YpLP/4Oj0Av2NrbImLGfQidGI6Mk2nYs2AHyovL4OrthqmbZomLwxG1BoYCWT3vLr7QaXUozi4EAGSeuopXziyHq5cb8tJyxMeFTolA0q7j8Fs2/s9zdKgRFNYZ3772Jbo/0BtTP5uJ0gIN1kQsR48H+972WvUl70lEr4f6wbdHR7i2d0XGyTQEDlbhzO6TyEvLwaKUWBRnF2FV79cQMeM+aCursPvFrZi5Zy7cfNyRuPMY/h3zFaZ+NtM0fyiyCgwFonp6juzb4E48dHIENoxajYeXjUfSruPiuvjn/3sOyXuT8NPqAwCEs+UVpOc2+VoAcGr7MQybNxIAMPCJITi1/TcEDlbhyuFLGDApHDY2NnDvqES3+3sBALIv3MD15CysH7kaAKDX6tCORwnUyhgKZPVyUrNhY2sjrrbp4OrQ4OM8/D3h2t4N185kIGnncUzaMF24Q6/HM1+9AN+edZfVvnostdHXKskrxqUff8f1s5mAQtjBQ6HAY29NabROvV6Pjn39Mf/oP1rwLokMw9FHZNWKbxXii9mf496//p9B6/IPnBKBH9/8N0rVpejUPxAA0Gt0CH794Afo9cIyYpmJVyVf5/SXCQj7y914/epqvJ62Gksy3kH7zj5I/fUiOt/THWe+OgmdToeim2r8cegCAMC3px9KbhUh7ehlAMJy8NfPZbX0rRM1iEcKZHUqSyvwVujr0FYKI4LC/nI3htdaUr0pAyaG4et52zBycaS4beTix/DN/G14q/9i6HR6tO/sg2f3z2/ydRK3H8MDi8bU2dZ/wmCc2n4MEz58ChcPpuBffWLgEegF/0HBcFa6wM7BDk9/+QJ2z41HmboU2ioths8fJXZ8E7UGrpJKZIHKi8vg6OaEktxirIlYjrlHYuDeUWnussgK8EiByAJ9/Oi7wlm6KrQYtfgxBgKZDI8UiIhIxI5mIiISMRSIiEjEUCAiIhFDgYiIRAwFIiIS/T/08JyCgv7eggAAAABJRU5ErkJggg==",
|
|
"text/plain": [
|
|
"<Figure size 432x288 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"plt.clf()\n",
|
|
"fig, ax = plt.subplots(1)\n",
|
|
"fig.patch.set_facecolor('xkcd:mint green')\n",
|
|
"ax.set_yscale(\"log\")\n",
|
|
"ax.plot(test_data, y_pred_fhe, color=\"blue\")\n",
|
|
"ax.scatter(df_test[\"DrivAge\"], df_test[\"Frequency\"], marker=\"o\", color=\"red\")\n",
|
|
"ax.set_xlabel(\"Driver Age\")\n",
|
|
"ax.set_ylabel(\"Frequency of claims\")\n",
|
|
"display(fig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c18dbdd1",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Enjoy!"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"execution": {
|
|
"timeout": 10800
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|