{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# 2A.ml - Machine Learning et donn\u00e9es crypt\u00e9es - correction\n", "\n", "Comment faire du machine learning avec des donn\u00e9es crypt\u00e9es ? Ce notebook propose d'en montrer un principe expos\u00e9s [CryptoNets: Applying Neural Networks to Encrypted Data with High Throughput and Accuracy](http://proceedings.mlr.press/v48/gilad-bachrach16.pdf). Correction."]}, {"cell_type": "code", "execution_count": 1, "metadata": {"collapsed": true}, "outputs": [], "source": ["%matplotlib inline"]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 3, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Principe**\n", "\n", "Voir l'\u00e9nonc\u00e9."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Exercice 1 : \u00e9crire deux fonctions de cryptage, d\u00e9cryptage\n", "\n", "Il faut bien choisir $n$, $a$ pour impl\u00e9menter la fonction de cryptage :\n", "$\\varepsilon:\\mathbb{N} \\rightarrow \\mathbb{Z}/n\\mathbb{Z}$ et $\\varepsilon(x) = (x * a) \\mod n$. On v\u00e9rifie ensuite qu'elle conserve l'addition au module $n$ pr\u00e8s."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"data": {"text/plain": ["(2885, 3462)"]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["def compose(x, a, n):\n", " return (a * x) % n\n", "\n", "def crypt(x):\n", " return compose(x, 577, 10000)\n", "\n", "crypt(5), crypt(6)"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"text/plain": ["(6347, 6347)"]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["crypt(5+6), (crypt(5) + crypt(6)) % 10000"]}, {"cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [{"data": {"text/plain": ["(577, 577)"]}, "execution_count": 6, "metadata": {}, "output_type": "execute_result"}], "source": ["crypt(6-5), (crypt(6) - crypt(5)) % 10000"]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [{"data": {"text/plain": ["(9423, 9423)"]}, "execution_count": 7, "metadata": {}, "output_type": "execute_result"}], "source": ["crypt(5-6), (crypt(5) - crypt(6)) % 10000"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Si $a=47$, on cherche $a',k$ tel que $aa' - nk=1$."]}, {"cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [{"data": {"text/plain": ["2513"]}, "execution_count": 8, "metadata": {}, "output_type": "execute_result"}], "source": ["n = 10000\n", "for k in range(2, n):\n", " if (577*k) % n == 1:\n", " ap = k\n", " break\n", "ap"]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [{"data": {"text/plain": ["(5, 6)"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["def decrypt(x):\n", " return compose(x, 2513, 10000)\n", "\n", "decrypt(crypt(5)), decrypt(crypt(6))"]}, {"cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [{"data": {"text/plain": ["(335, 335)"]}, "execution_count": 10, "metadata": {}, "output_type": "execute_result"}], "source": ["decrypt(crypt(5)*67), decrypt(crypt(5*67))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Notes sur l'inverse de a\n", "\n", "Si $n$ est premier alors $\\mathbb{Z}/n\\mathbb{Z}$ est un corps. Cela implique que tout nombre $a \\neq 0$ a un inverse dans $\\mathbb{Z}/n\\mathbb{Z}$. Donc, $\\forall a \\neq 0, \\exists a'$ tel que $aa'=1$. On va d'abord montrer que $\\forall a \\neq 0, \\forall k \\in \\mathbb{N^*}, a^k \\neq 0$. On proc\u00e8de par l'absurde en supposant que $\\exists k > 0$ tel quel $a^k=0$. Cela signifie qu'il existe $v$ tel quel $a^k = vn$. Comme $n$ est premier, $a$ divise $v$ et on peut \u00e9crire que $a^k = wan \\Rightarrow a(a^{k-1} - wn)=0$. Par r\u00e9currence, on peut montrer qu'il existe $z$ tel que $a = zn$ donc $a$ est un multiple de $n$ et c'est impossible car $a$ et $n$ sont premiers entre eux.\n", "\n", "L'ensemble $A=\\{a, a^2, a^3, ...\\}$ est \u00e0 valeur dans $\\mathbb{Z}/n\\mathbb{Z}$ et est fini donc il existe n\u00e9cessairement $i$ tel que $a^i \\in A$. Il existe alors $k > 0$ tel que $a^i \\equiv a^k \\mod n$ et $u$ tel que $a^i = a^k + un$. On suppose d'abord que $i > k$, alors $a^k(a^{i-k} -1) = un$. Comme $n$ est premier, $a^{i-k} -1$ divise $n$ donc il existe $v$ tel que $a^{i-k}=un + 1$ donc $a^{i-k} \\equiv 1 \\mod n$. On note $a^{i-k-1} = a^{-1}$ l'inverse de $a$ dans $\\mathbb{Z}/n\\mathbb{Z}$. Si $k > i$, la m\u00eame chose est vraie pour $a^{k-i}$. Si $i^*=\\arg\\min\\{i \\, | \\, a^i \\in A\\}$, $i^* \\leqslant n-1$ car l'ensemble $A$ contient au plus $n-1$ \u00e9l\u00e9ments et $i^*-k < n-1$. On note maintenant $j^* = \\arg \\min \\{j \\, | \\, a^j \\equiv 1 \\mod n\\}$. Donc ce cas, on peut montrer que $A = \\{1, a, ..., a^{j^*-1}\\}$. $j^*$ est l'[ordre](https://fr.wikipedia.org/wiki/Ordre_(th%C3%A9orie_des_groupes) du sous-groupe engendr\u00e9 par $a$.\n", "Le [th\u00e9or\u00e8me de Lagrange](https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_de_Lagrange_sur_les_groupes) nous dit que cet ordre divise $n-1$ qui est l'ordre du groupe multiplicatif $\\mathbb{Z}/n\\mathbb{Z} \\backslash \\{0\\}$. On peut donc \u00e9crire $n-1=kj^*$ avec $k \\in \\mathbb{N}$. Par cons\u00e9quent, $a^{n-1} \\equiv 1 \\mod n$. Ce th\u00e9or\u00e8me en consid\u00e9rant les classes d'\u00e9quivalence qui forment une partition de l'ensemble du groupe de d\u00e9part."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Exercice 2 : Entra\u00eener une r\u00e9gression lin\u00e9aire"]}, {"cell_type": "code", "execution_count": 10, "metadata": {"collapsed": true}, "outputs": [], "source": ["from sklearn.datasets import load_diabetes\n", "data = load_diabetes()"]}, {"cell_type": "code", "execution_count": 11, "metadata": {"collapsed": true}, "outputs": [], "source": ["X = data.data\n", "Y = data.target"]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [{"data": {"text/plain": ["LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)"]}, "execution_count": 13, "metadata": {}, "output_type": "execute_result"}], "source": ["from sklearn.linear_model import LinearRegression\n", "clr = LinearRegression()\n", "clr.fit(X, Y)"]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"data": {"text/plain": ["(array([ 206.11706979]), 151.0)"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["clr.predict(X[:1]), Y[0]"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.51774942541329338"]}, "execution_count": 15, "metadata": {}, "output_type": "execute_result"}], "source": ["from sklearn.metrics import r2_score\n", "r2_score(Y, clr.predict(X))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["On consid\u00e8re seulement la fonction de d\u00e9cision brute car c'est une fonction qui peut-\u00eatre calcul\u00e9e \u00e0 partir d'additions et de multiplications. Pour la suite, nous aurons besoin d'un mod\u00e8le qui fonctionne sur des variables normalis\u00e9es avec [MinMaxScaler](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html). On supprime \u00e9galement le biais pour le remplacer par une colonne constante."]}, {"cell_type": "code", "execution_count": 15, "metadata": {"collapsed": true}, "outputs": [], "source": ["from sklearn.preprocessing import MinMaxScaler\n", "import numpy\n", "X_norm = numpy.hstack([MinMaxScaler((0, 100)).fit_transform(X), \n", " numpy.ones((X.shape[0], 1))])\n", "Y_norm = MinMaxScaler((0, 100)).fit_transform(Y.reshape(len(Y), 1)).ravel()"]}, {"cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0.0, 100.0)"]}, "execution_count": 17, "metadata": {}, "output_type": "execute_result"}], "source": ["Y_norm.min(), Y_norm.max()"]}, {"cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [{"data": {"text/plain": ["LinearRegression(copy_X=True, fit_intercept=False, n_jobs=1, normalize=False)"]}, "execution_count": 18, "metadata": {}, "output_type": "execute_result"}], "source": ["clr_norm = LinearRegression(fit_intercept=False)\n", "clr_norm.fit(X_norm, Y_norm)"]}, {"cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [{"data": {"text/plain": ["(array([ 56.42276317]), 39.252336448598129)"]}, "execution_count": 19, "metadata": {}, "output_type": "execute_result"}], "source": ["clr_norm.predict(X_norm[:1]), Y_norm[0]"]}, {"cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.51774942541329338"]}, "execution_count": 20, "metadata": {}, "output_type": "execute_result"}], "source": ["from sklearn.metrics import r2_score\n", "r2_score(Y_norm, clr_norm.predict(X_norm))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Exercice 3 : r\u00e9\u00e9crire la fonction de pr\u00e9diction pour une r\u00e9gression lin\u00e9aire\n", "\n", "La fonction est un produit scalaire."]}, {"cell_type": "code", "execution_count": 20, "metadata": {"collapsed": true}, "outputs": [], "source": ["def decision_linreg(xs, coef, bias):\n", " s = bias\n", " xs = xs.copy().ravel()\n", " coef = coef.copy().ravel()\n", " if xs.shape != coef.shape:\n", " raise ValueError(\"Not the same dimension {0}!={1}\".format(xs.shape, coef.shape))\n", " for x, c in zip(xs, coef):\n", " s += c * x\n", " return s"]}, {"cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [{"data": {"text/plain": ["[0.038075906433424102,\n", " 0.050680118739818703,\n", " 0.061696206518688498,\n", " 0.021872354994955798,\n", " -0.044223498424446402]"]}, "execution_count": 22, "metadata": {}, "output_type": "execute_result"}], "source": ["list(X[0])[:5]"]}, {"cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [{"data": {"text/plain": ["(array([ 206.11706979]), 206.1170697870923)"]}, "execution_count": 23, "metadata": {}, "output_type": "execute_result"}], "source": ["clr.predict(X[:1]), decision_linreg(X[:1], clr.coef_, clr.intercept_)"]}, {"cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [{"data": {"text/plain": ["(array([ 56.42276317]), 56.422763173548944)"]}, "execution_count": 24, "metadata": {}, "output_type": "execute_result"}], "source": ["clr_norm.predict(X_norm[:1]), decision_linreg(X_norm[:1], clr_norm.coef_, clr_norm.intercept_)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Exercice 4 : assembler le tout\n", "\n", "Prendre une observation, crypter, pr\u00e9dire, d\u00e9crypter, comparer avec la version non crypt\u00e9e. Il faudra sans doute un peu ruser car la fonction de cryptage s'applique \u00e0 des entiers et le mod\u00e8le de pr\u00e9diction \u00e0 des r\u00e9els. On multiplie par 10000 les variables. Comme le cryptage que nous avons choisi ne conserve que l'addition, nous garderons les mod\u00e8les en clair."]}, {"cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [{"data": {"text/plain": ["[0, -7, 42, 24, -69, 46, 8, 14, 60, 5, -843]"]}, "execution_count": 25, "metadata": {}, "output_type": "execute_result"}], "source": ["coef_int = [int(i) for i in clr_norm.coef_ * 100]\n", "coef_int"]}, {"cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [{"data": {"text/plain": ["0"]}, "execution_count": 26, "metadata": {}, "output_type": "execute_result"}], "source": ["inter_int = int(clr_norm.intercept_ * 10000)\n", "inter_int"]}, {"cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [{"data": {"text/plain": ["(56.422763173548944, 54.65)"]}, "execution_count": 27, "metadata": {}, "output_type": "execute_result"}], "source": ["import numpy\n", "\n", "\n", "def decision_linreg_int(xs, coef):\n", " s = 0\n", " for x, c in zip(xs, coef):\n", " s += c * x\n", " return s % 10000\n", "\n", "def decision_crypt_decrypt_linreg(xs, coef_int):\n", " # On crypte les entr\u00e9es\n", " int_xs = [int(x) for x in xs.ravel()]\n", " crypt_xs = [crypt(i) for i in int_xs]\n", " # On applique la pr\u00e9diction.\n", " pred = decision_linreg_int(crypt_xs, coef_int)\n", " # On d\u00e9crypte.\n", " dec = decrypt(pred % 10000)\n", " return dec / 100\n", "\n", "(decision_linreg(X_norm[:1], clr_norm.coef_, clr_norm.intercept_), \n", " decision_crypt_decrypt_linreg(X_norm[0], coef_int))"]}, {"cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["0 56.4227631735 54.65\n", "1 13.4181768255 11.59\n", "2 47.3159066512 45.73\n", "3 44.2112042336 42.02\n", "4 32.2304805013 30.26\n"]}, {"data": {"text/plain": ["[]"]}, "execution_count": 28, "metadata": {}, "output_type": "execute_result"}, {"data": {"image/png": "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\nrkJggg==\n", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["p1s = []\n", "p2s = []\n", "for i in range(0, X_norm.shape[0]):\n", " p1 = decision_linreg(X_norm[i:i+1], clr_norm.coef_, clr_norm.intercept_)\n", " p2 = decision_crypt_decrypt_linreg(X_norm[i], coef_int)\n", " if i < 5:\n", " print(i, p1, p2)\n", " p1s.append(p1)\n", " p2s.append(p2)\n", "\n", "import matplotlib.pyplot as plt\n", "plt.plot(p1s, p2s, '.')"]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Notes**\n", "\n", "Les coefficients sont en clair mais les donn\u00e9es sont crypt\u00e9es. Pour crypter les coefficients du mod\u00e8le, il faudrait pouvoir s'assurer que l'addition et la multiplication sont stables apr\u00e8s le cryptage. Cela n\u00e9cessite un cryptage diff\u00e9rent comme [Fully Homomorphic Encryption over the Integers](https://eprint.iacr.org/2009/616.pdf). Les entiers crypt\u00e9s sont dans l'intervalle [0, 10000], cela veut dire qu'il est pr\u00e9f\u00e9rable de crypter des entiers dans un intervalle \u00e9quivalent sous peine de ne pouvoir d\u00e9crypter avec certitude. Ceci implique que l'algorithme fasse des calculs qui restent dans cet intervalle. C'est pourquoi les entr\u00e9es et les sorties prennent leur valeur dans l'intervalle [0, 100] afin que le produit *coefficient x entr\u00e9e* reste dans l'intervalle consid\u00e9r\u00e9. Pour \u00e9viter ce probl\u00e8me, il faudrait d\u00e9composer chaque entier en une s\u00e9quence d'entiers entre 0 et 100 et r\u00e9\u00e9crire les op\u00e9rations addition et multiplication en fonction."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Questions\n", "\n", "Le cryptage choisi est moins efficace qu'un cryptage [RSA](https://fr.wikipedia.org/wiki/Chiffrement_RSA) qui conserve la multiplication. Il faudrait transformer l'\u00e9criture du mod\u00e8le pour utiliser des multiplications plut\u00f4t que des additions. Si je vous disais qu'une des variables est l'\u00e2ge d'une population, vous pourriez la retrouver. Il en est de m\u00eame pour un chiffrage RSA qui change un entier en un autre. On peut crypter des \u00e9l\u00e9ments de ces entiers et les recomposer dans le monde crypt\u00e9. C'est ce que propose d'autres type de cryptage. **On peut aussi alt\u00e9rer les donn\u00e9es en ajoutant un bruit al\u00e9atoire qui change peu la pr\u00e9diction mais qui change la valeur crypt\u00e9e. Dans ce cas, la distribution de chaque variable para\u00eetra uniforme.**\n", "\n", "On peut entra\u00eener un mod\u00e8le sur des donn\u00e9es crypt\u00e9es si on peut reproduire l'addition et la multiplication avec les nombres crypt\u00e9s. Une option est le cryptage : [Fully Homomorphic Encryption over the Integers](https://eprint.iacr.org/2009/616.pdf). Cela implique qu'on peut approcher toute fonction par un polyn\u00f4me (voir [d\u00e9veloppement limit\u00e9](https://fr.wikipedia.org/wiki/D%C3%A9veloppement_limit%C3%A9)). Le gradient d'un polyn\u00f4me est un polyn\u00f4me \u00e9galement. Il est possible de calculer la norme du gradient crypt\u00e9 mais pas de la comparer \u00e0 une autre valeur crypt\u00e9es.\n", "\n", "De ce fait les arbres de d\u00e9cision se pr\u00eatent mal \u00e0 ce type d'apprentissage puisque chaque noeud de l'arbre consiste \u00e0 comparer deux valeurs. Cependant, on peut s'en sortir en imposant \u00e0 l'algorithme d'apprentissage d'un arbre de d\u00e9cision de ne s'appuyer sur des \u00e9galit\u00e9s. Cela n\u00e9cessite plus de coefficients et la discr\u00e9tisation des variables continues. Il reste une derni\u00e8re chose \u00e0 v\u00e9rifier. Chaque noeud d'un arbre de d\u00e9cision est d\u00e9termin\u00e9 en maximisant une quantit\u00e9. Comment trouver le maximum dans un ensemble de donn\u00e9es crypt\u00e9es qu'on ne peut comparer ? On utilise une propri\u00e9t\u00e9 des normes :\n", "\n", "$$\\lim_{d \\rightarrow \\infty} (x^d + y^d)^{1/d} = \\max(x, y)$$\n", "\n", "Il existe d'autres options : [Machine Learning Classification over Encrypted Data](https://eprint.iacr.org/2014/331.pdf)."]}, {"cell_type": "markdown", "metadata": {"collapsed": true}, "source": ["## Ajouter du bruit sur une colonne\n", "\n", "Les donn\u00e9es peuvent \u00eatre crypt\u00e9es mais la distribution est inchang\u00e9e \u00e0 une permutation pr\u00e8s. Pour \u00e9viter cela, on ajoute un peu de bruit, nous allons voir comment faire cela. On suppose que nous avons une colonne qui des entiers distribu\u00e9s selon une loi de Poisson."]}, {"cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [{"data": {"text/plain": ["(0, 8)"]}, "execution_count": 29, "metadata": {}, "output_type": "execute_result"}], "source": ["from numpy.random import poisson\n", "X = poisson(size=10000)\n", "mx = X.max()+1\n", "X.min(), mx"]}, {"cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [{"data": {"image/png": "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\n", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["from matplotlib import pyplot as plt\n", "plt.hist(X, bins=mx, rwidth=0.9);"]}, {"cell_type": "code", "execution_count": 30, "metadata": {"collapsed": true}, "outputs": [], "source": ["def crypt(x):\n", " return compose(x, 5794, 10000)"]}, {"cell_type": "code", "execution_count": 31, "metadata": {"collapsed": true}, "outputs": [], "source": ["import numpy\n", "Xcrypt = numpy.array([crypt(x) for x in X])"]}, {"cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([ 0, 5794, 5794, 5794, 5794, 0, 7382, 7382, 0, 1588])"]}, "execution_count": 33, "metadata": {}, "output_type": "execute_result"}], "source": ["Xcrypt[:10]"]}, {"cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD8CAYAAAB+UHOxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAE7NJREFUeJzt3X+snuV93/H3p+ZH0iSrTTkg13Zm\np/W6kkk1yDPeMk0ZZGBgmqkUJKMpeIzK3QZTslXbTPsHTTIkOrVhQkqpaHFjqjSEkbRYiTvmEaoq\nf/DDpI6DcahPgMGJPXw6A0kWjQ7y3R/PZfKAj88vH58D53q/pEfPfX/v636e67p9n/Px/eN5TqoK\nSVJ/fmKhOyBJWhgGgCR1ygCQpE4ZAJLUKQNAkjplAEhSpwwASeqUASBJnTIAJKlTZyx0ByZz7rnn\n1urVqxe6G5L0jvLEE0/8VVWNTNXubR0Aq1evZu/evQvdDUl6R0nyP6fTzlNAktQpA0CSOmUASFKn\nDABJ6pQBIEmdMgAkqVMGgCR1ygCQpE4ZAJLUqbf1J4Elzd7q7V9d6C684bnbrlroLmgCHgFIUqcM\nAEnq1KI+BfR2OQT28FfS25FHAJLUKQNAkjplAEhSp6YMgCTvSvJYkm8mOZDkk63+uSTPJtnXHuta\nPUnuSDKaZH+Si4Zea2uSQ+2x9fQNS5I0lelcBH4VuKSqfpDkTODrSf60Lfv3VXX/W9pfAaxtj4uB\nO4GLk5wD3AKsBwp4IsmuqnppLgYiSZqZKY8AauAHbfbM9qhJVtkM3NPWewRYmmQ5cDmwp6qOtV/6\ne4BNp9Z9SdJsTesaQJIlSfYBRxn8En+0Lbq1nea5PcnZrbYCeGFo9bFWO1ldkrQAphUAVfV6Va0D\nVgIbkvwd4GbgbwN/FzgH+I+teSZ6iUnqb5JkW5K9SfaOj49Pp3uSpFmY0V1AVfUy8GfApqo60k7z\nvAr8AbChNRsDVg2tthI4PEn9re9xV1Wtr6r1IyMjM+meJGkGpnMX0EiSpW363cBHgG+38/okCXA1\n8GRbZRdwXbsbaCPwSlUdAR4ELkuyLMky4LJWkyQtgOncBbQc2JlkCYPAuK+qvpLka0lGGJza2Qf8\ny9Z+N3AlMAr8ELgeoKqOJfk08Hhr96mqOjZ3Q5EkzcSUAVBV+4ELJ6hfcpL2Bdx4kmU7gB0z7KMk\n6TTwk8CS1CkDQJI6ZQBIUqcMAEnqlAEgSZ0yACSpUwaAJHXKAJCkThkAktQpA0CSOmUASFKnDABJ\n6pQBIEmdMgAkqVMGgCR1ygCQpE4ZAJLUKQNAkjplAEhSp6YMgCTvSvJYkm8mOZDkk62+JsmjSQ4l\n+WKSs1r97DY/2pavHnqtm1v96SSXn65BSZKmNp0jgFeBS6rqF4F1wKYkG4HfBG6vqrXAS8ANrf0N\nwEtV9XPA7a0dSS4AtgAfBDYBv5NkyVwORpI0fVMGQA38oM2e2R4FXALc3+o7gavb9OY2T1t+aZK0\n+r1V9WpVPQuMAhvmZBSSpBmb1jWAJEuS7AOOAnuA7wAvV9VrrckYsKJNrwBeAGjLXwF+erg+wTqS\npHk2rQCoqterah2wksH/2n9hombtOSdZdrL6myTZlmRvkr3j4+PT6Z4kaRZmdBdQVb0M/BmwEVia\n5Iy2aCVwuE2PAasA2vKfAo4N1ydYZ/g97qqq9VW1fmRkZCbdkyTNwHTuAhpJsrRNvxv4CHAQeBj4\naGu2FXigTe9q87TlX6uqavUt7S6hNcBa4LG5GogkaWbOmLoJy4Gd7Y6dnwDuq6qvJHkKuDfJfwL+\nAri7tb8b+MMkowz+578FoKoOJLkPeAp4Dbixql6f2+FIkqZrygCoqv3AhRPUn2GCu3iq6v8C15zk\ntW4Fbp15NyVJc81PAktSpwwASeqUASBJnTIAJKlTBoAkdcoAkKROGQCS1CkDQJI6ZQBIUqcMAEnq\nlAEgSZ0yACSpUwaAJHXKAJCkThkAktQpA0CSOmUASFKnDABJ6pQBIEmdmjIAkqxK8nCSg0kOJPl4\nq/9Gku8m2dceVw6tc3OS0SRPJ7l8qL6p1UaTbD89Q5IkTceUfxQeeA341ar6RpL3AU8k2dOW3V5V\nvzXcOMkFwBbgg8DPAP8jyd9qiz8L/GNgDHg8ya6qemouBiJJmpkpA6CqjgBH2vT3kxwEVkyyymbg\n3qp6FXg2ySiwoS0brapnAJLc29oaAJK0AGZ0DSDJauBC4NFWuinJ/iQ7kixrtRXAC0OrjbXayeqS\npAUw7QBI8l7gS8Anqup7wJ3AzwLrGBwh/PbxphOsXpPU3/o+25LsTbJ3fHx8ut2TJM3QtAIgyZkM\nfvl/vqq+DFBVL1bV61X1I+D3+PFpnjFg1dDqK4HDk9TfpKruqqr1VbV+ZGRkpuORJE3TdO4CCnA3\ncLCqPjNUXz7U7JeAJ9v0LmBLkrOTrAHWAo8BjwNrk6xJchaDC8W75mYYkqSZms5dQB8CPgZ8K8m+\nVvs14Nok6xicxnkO+BWAqjqQ5D4GF3dfA26sqtcBktwEPAgsAXZU1YE5HIskaQamcxfQ15n4/P3u\nSda5Fbh1gvruydaTJM0fPwksSZ0yACSpUwaAJHXKAJCkThkAktQpA0CSOmUASFKnDABJ6pQBIEmd\nMgAkqVMGgCR1ygCQpE4ZAJLUKQNAkjplAEhSpwwASeqUASBJnTIAJKlTBoAkdWrKAEiyKsnDSQ4m\nOZDk461+TpI9SQ6152WtniR3JBlNsj/JRUOvtbW1P5Rk6+kbliRpKtM5AngN+NWq+gVgI3BjkguA\n7cBDVbUWeKjNA1wBrG2PbcCdMAgM4BbgYmADcMvx0JAkzb8pA6CqjlTVN9r094GDwApgM7CzNdsJ\nXN2mNwP31MAjwNIky4HLgT1VdayqXgL2AJvmdDSSpGmb0TWAJKuBC4FHgfOr6ggMQgI4rzVbAbww\ntNpYq52sLklaANMOgCTvBb4EfKKqvjdZ0wlqNUn9re+zLcneJHvHx8en2z1J0gxNKwCSnMngl//n\nq+rLrfxiO7VDez7a6mPAqqHVVwKHJ6m/SVXdVVXrq2r9yMjITMYiSZqB6dwFFOBu4GBVfWZo0S7g\n+J08W4EHhurXtbuBNgKvtFNEDwKXJVnWLv5e1mqSpAVwxjTafAj4GPCtJPta7deA24D7ktwAPA9c\n05btBq4ERoEfAtcDVNWxJJ8GHm/tPlVVx+ZkFJKkGZsyAKrq60x8/h7g0gnaF3DjSV5rB7BjJh2U\nJJ0efhJYkjplAEhSpwwASeqUASBJnTIAJKlT07kNVHNs9favLnQX3vDcbVctdBckLRCPACSpUwaA\nJHXKAJCkThkAktQpA0CSOmUASFKnDABJ6pQBIEmdMgAkqVMGgCR1ygCQpE4ZAJLUKQNAkjo1ZQAk\n2ZHkaJInh2q/keS7Sfa1x5VDy25OMprk6SSXD9U3tdpoku1zPxRJ0kxM5wjgc8CmCeq3V9W69tgN\nkOQCYAvwwbbO7yRZkmQJ8FngCuAC4NrWVpK0QKb8ewBV9edJVk/z9TYD91bVq8CzSUaBDW3ZaFU9\nA5Dk3tb2qRn3WJI0J07lGsBNSfa3U0TLWm0F8MJQm7FWO1ldkrRAZhsAdwI/C6wDjgC/3eqZoG1N\nUj9Bkm1J9ibZOz4+PsvuSZKmMqsAqKoXq+r1qvoR8Hv8+DTPGLBqqOlK4PAk9Yle+66qWl9V60dG\nRmbTPUnSNMwqAJIsH5r9JeD4HUK7gC1Jzk6yBlgLPAY8DqxNsibJWQwuFO+afbclSadqyovASb4A\nfBg4N8kYcAvw4STrGJzGeQ74FYCqOpDkPgYXd18Dbqyq19vr3AQ8CCwBdlTVgTkfjSRp2qZzF9C1\nE5TvnqT9rcCtE9R3A7tn1DtJ0mnjJ4ElqVMGgCR1ygCQpE4ZAJLUKQNAkjplAEhSpwwASeqUASBJ\nnTIAJKlTBoAkdcoAkKROGQCS1CkDQJI6ZQBIUqcMAEnqlAEgSZ0yACSpUwaAJHXKAJCkTk0ZAEl2\nJDma5Mmh2jlJ9iQ51J6XtXqS3JFkNMn+JBcNrbO1tT+UZOvpGY4kabqmcwTwOWDTW2rbgYeqai3w\nUJsHuAJY2x7bgDthEBjALcDFwAbgluOhIUlaGFMGQFX9OXDsLeXNwM42vRO4eqh+Tw08AixNshy4\nHNhTVceq6iVgDyeGiiRpHs32GsD5VXUEoD2f1+orgBeG2o212snqkqQFMtcXgTNBrSapn/gCybYk\ne5PsHR8fn9POSZJ+bLYB8GI7tUN7PtrqY8CqoXYrgcOT1E9QVXdV1fqqWj8yMjLL7kmSpjLbANgF\nHL+TZyvwwFD9unY30EbglXaK6EHgsiTL2sXfy1pNkrRAzpiqQZIvAB8Gzk0yxuBuntuA+5LcADwP\nXNOa7wauBEaBHwLXA1TVsSSfBh5v7T5VVW+9sCxJmkdTBkBVXXuSRZdO0LaAG0/yOjuAHTPqnSTp\ntPGTwJLUKQNAkjplAEhSpwwASeqUASBJnTIAJKlTBoAkdcoAkKROGQCS1CkDQJI6ZQBIUqcMAEnq\nlAEgSZ0yACSpUwaAJHVqyr8HIElzbfX2ry50F97w3G1XLXQXFoxHAJLUKQNAkjplAEhSp04pAJI8\nl+RbSfYl2dtq5yTZk+RQe17W6klyR5LRJPuTXDQXA5Akzc5cHAH8o6paV1Xr2/x24KGqWgs81OYB\nrgDWtsc24M45eG9J0iydjlNAm4GdbXoncPVQ/Z4aeARYmmT5aXh/SdI0nGoAFPDfkzyRZFurnV9V\nRwDa83mtvgJ4YWjdsVaTJC2AU/0cwIeq6nCS84A9Sb49SdtMUKsTGg2CZBvA+9///lPsniTpZE7p\nCKCqDrfno8AfAxuAF4+f2mnPR1vzMWDV0OorgcMTvOZdVbW+qtaPjIycSvckSZOYdQAkeU+S9x2f\nBi4DngR2AVtbs63AA216F3BduxtoI/DK8VNFkqT5dyqngM4H/jjJ8df5o6r6b0keB+5LcgPwPHBN\na78buBIYBX4IXH8K7y1JOkWzDoCqegb4xQnq/xu4dIJ6ATfO9v0kSXPLTwJLUqcMAEnqlAEgSZ0y\nACSpUwaAJHXKAJCkThkAktQpA0CSOmUASFKnDABJ6pQBIEmdMgAkqVMGgCR16lT/IpgWmdXbv7rQ\nXQDguduuWuguSIueRwCS1CkDQJI6ZQBIUqcMAEnqlAEgSZ2a9wBIsinJ00lGk2yf7/eXJA3MawAk\nWQJ8FrgCuAC4NskF89kHSdLAfH8OYAMwWlXPACS5F9gMPDXP/ZCkE7xdPgcD8/NZmPkOgBXAC0Pz\nY8DF89wHaU69XX5p+OE5zVSqav7eLLkGuLyqfrnNfwzYUFX/ZqjNNmBbm/154OlZvNW5wF+dYncX\nE7fHidwmJ3KbnOiduk3+ZlWNTNVovo8AxoBVQ/MrgcPDDarqLuCuU3mTJHurav2pvMZi4vY4kdvk\nRG6TEy32bTLfdwE9DqxNsibJWcAWYNc890GSxDwfAVTVa0luAh4ElgA7qurAfPZBkjQw798GWlW7\ngd2n+W1O6RTSIuT2OJHb5ERukxMt6m0yrxeBJUlvH34VhCR1alEFQE9fM5FkVZKHkxxMciDJx1v9\nnCR7khxqz8taPUnuaNtmf5KLhl5ra2t/KMnWhRrTXEiyJMlfJPlKm1+T5NE2ti+2mw9IcnabH23L\nVw+9xs2t/nSSyxdmJHMjydIk9yf5dttX/p77SP5t+5l5MskXkryr2/2kqhbFg8FF5e8AHwDOAr4J\nXLDQ/TqN410OXNSm3wf8JYOv1/jPwPZW3w78Zpu+EvhTIMBG4NFWPwd4pj0va9PLFnp8p7Bd/h3w\nR8BX2vx9wJY2/bvAv2rT/xr43Ta9Bfhim76g7TtnA2vaPrVkocd1CttjJ/DLbfosYGnP+wiDD6M+\nC7x7aP/4573uJ4vpCOCNr5moqr8Gjn/NxKJUVUeq6htt+vvAQQY792YGP/S056vb9Gbgnhp4BFia\nZDlwObCnqo5V1UvAHmDTPA5lziRZCVwF/H6bD3AJcH9r8tbtcXw73Q9c2tpvBu6tqler6llglMG+\n9Y6T5G8A/xC4G6Cq/rqqXqbjfaQ5A3h3kjOAnwSO0Ol+spgCYKKvmVixQH2ZV+2w9ELgUeD8qjoC\ng5AAzmvNTrZ9FtN2+y/AfwB+1OZ/Gni5ql5r88Nje2Pcbfkrrf1i2h4fAMaBP2inxX4/yXvoeB+p\nqu8CvwU8z+AX/yvAE3S6nyymAMgEtUV/i1OS9wJfAj5RVd+brOkEtZqk/o6S5J8AR6vqieHyBE1r\nimWLYns0ZwAXAXdW1YXA/2FwyudkFv02adc7NjM4bfMzwHsYfDvxW3WxnyymAJjyayYWmyRnMvjl\n//mq+nIrv9gO22nPR1v9ZNtnsWy3DwH/NMlzDE7/XcLgiGBpO9SHN4/tjXG35T8FHGPxbA8YjGWs\nqh5t8/czCIRe9xGAjwDPVtV4Vf0/4MvA36fT/WQxBUBXXzPRzkPeDRysqs8MLdoFHL9LYyvwwFD9\nunanx0bglXb4/yBwWZJl7X9Hl7XaO0pV3VxVK6tqNYN/+69V1T8DHgY+2pq9dXsc304fbe2r1be0\nuz/WAGuBx+ZpGHOqqv4X8EKSn2+lSxl89XqX+0jzPLAxyU+2n6Hj26TP/WShr0LP5YPBXQx/yeCK\n/K8vdH9O81j/AYNDzv3Avva4ksH5yYeAQ+35nNY+DP4Yz3eAbwHrh17rXzC4iDUKXL/QY5uDbfNh\nfnwX0AcY/GCOAv8VOLvV39XmR9vyDwyt/+ttOz0NXLHQ4znFbbEO2Nv2kz9hcBdP1/sI8Eng28CT\nwB8yuJOny/3ETwJLUqcW0ykgSdIMGACS1CkDQJI6ZQBIUqcMAEnqlAEgSZ0yACSpUwaAJHXq/wPm\nMhx4smiMxQAAAABJRU5ErkJggg==\n", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["plt.hist(Xcrypt, bins=mx, rwidth=0.9);"]}, {"cell_type": "markdown", "metadata": {}, "source": ["M\u00eame distribution dans un ordre diff\u00e9rent. Pour changer cette distribution, on ajoute un petit bruit peu important pour la variable num\u00e9rique consid\u00e9r\u00e9e mais qui sera crypt\u00e9e de mani\u00e8re totalement diff\u00e9rente."]}, {"cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([ 90, 145, 120, 172, 131, 76, 343, 398, 17, 288])"]}, "execution_count": 35, "metadata": {}, "output_type": "execute_result"}], "source": ["import random\n", "Xbruit = numpy.array([100*x + random.randint(0,100) for x in X])\n", "Xbruit[:10]"]}, {"cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAs8AAAD8CAYAAACIA0mdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAHE5JREFUeJzt3X+s5XV95/Hnqwxo648CeiGz/Ohg\nd5aVJiuQG8SwMRYEQRuxiSZDGp1uaKZZsdFoUodusvbHusHNVrsmlnYs1OnGihR1mQirziLGuGmB\nAUdkHOmMyMrIlJmKaNvN2oLv/eN8bj1c7o/v/XHO+d57n4/k5Hy/7/P5nu/73DN8fPs97+/3m6pC\nkiRJ0uJ+atIJSJIkSWuFxbMkSZLUkcWzJEmS1JHFsyRJktSRxbMkSZLUkcWzJEmS1JHFsyRJktSR\nxbMkbXBJzk2yf+jxwyTvSnJqkr1JDrXnUyadqyRNWrxJiiRpRpITgO8CrwSuA56sqhuS7AROqar3\nTjRBSZqwXhfPL33pS2vLli2TTkOSluX+++//26qamnQeS5HkCuB9VXVJkoeB11TV0SSbgS9V1bkL\nbe+8LWmt6jpnbxpHMsu1ZcsW9u3bN+k0JGlZkvyfSeewDNuAT7Tl06vqKEAroE+ba4MkO4AdAGef\nfbbztqQ1qeucbc+zJAmAJCcBbwT+YinbVdWuqpququmpqTV1oF2SlsziWZI04yrggap6oq0/0do1\naM/HJpaZJPWExbMkacY1/KRlA2APsL0tbwduH3tGktQzFs+SJJL8DHA58Omh8A3A5UkOtddumERu\nktQnvT5hUJI0HlX1f4GXzIp9D7hsMhlJUj955FmSJEnqyOJZkiRJ6sjiWZIkSerI4lmSJEnqyBMG\nR2zLzjsmuv9Hb3jDRPcvSZK0nnjkWZIkSerI4lmSJEnqyOJZkiRJ6mhd9jzbZyxJkqRR8MizJEmS\n1JHFsyRJktSRxbMkSZLUkcWzJEmS1JHFsyRJktSRxbMkSZLUkcWzJEmS1JHFsyRJktTRosVzkucn\nuTfJ15IcSPI7LX5OknuSHEryySQntfjz2vrh9vqWofe6vsUfTvK6UX0oSZIkaRS6HHn+EXBpVb0C\nOB+4MsnFwAeAD1XVVuD7wLVt/LXA96vqXwIfauNIch6wDfgF4ErgD5OcsJofRpIkSRqlRYvnGvj7\ntnpiexRwKXBbi+8G3tSWr27rtNcvS5IWv6WqflRV3wYOAxetyqeQJEmSxqBTz3OSE5LsB44Be4Fv\nAU9V1dNtyBHgjLZ8BvAYQHv9B8BLhuNzbCNJkiT1XqfiuaqeqarzgTMZHC1++VzD2nPmeW2++LMk\n2ZFkX5J9x48f75KeJEmSNBZLutpGVT0FfAm4GDg5yab20pnA4235CHAWQHv9Z4Enh+NzbDO8j11V\nNV1V01NTU0tJT5K0TElOTnJbkm8mOZjkVUlOTbK3nRi+N8kpk85Tkiaty9U2ppKc3JZ/GngtcBC4\nG3hzG7YduL0t72nrtNe/WFXV4tva1TjOAbYC967WB5Ekrch/Az5XVf8aeAWDeX4ncFc7Mfyuti5J\nG9qmxYewGdjdrozxU8CtVfXZJN8Abknyn4CvAje18TcB/z3JYQZHnLcBVNWBJLcC3wCeBq6rqmdW\n9+NIkpYqyYuBVwO/ClBV/wj8Y5Krgde0YbsZ/PL43vFnKEn9sWjxXFUPAhfMEX+EOa6WUVX/D3jL\nPO/1fuD9S09TkjRCLwOOA3+a5BXA/cA7gdOr6ihAVR1NctpcGyfZAewAOPvss8eTsSRNiHcYlCRt\nAi4EbqyqC4B/YAktGp6rImkjsXiWJB0BjlTVPW39NgbF9BNJNgO052MTyk+SesPiWZI2uKr6G+Cx\nJOe20GUMzk8ZPgF8+MRwSdqwupwwKEla/34D+HiSk4BHgH9HO0k8ybXAd5jnfBZJ2kgsniVJVNV+\nYHqOly4bdy6S1Ge2bUiSJEkdWTxLkiRJHVk8S5IkSR1ZPEuSJEkdWTxLkiRJHVk8S5IkSR1ZPEuS\nJEkdWTxLkiRJHVk8S5IkSR1ZPEuSJEkdWTxLkiRJHVk8S5IkSR1ZPEuSJEkdWTxLkjasLTvvmHQK\nktYYi2dJkiSpI4tnSZIkqSOLZ0mS5mFbh6TZLJ4lSZKkjhYtnpOcleTuJAeTHEjyzhb/7STfTbK/\nPV4/tM31SQ4neTjJ64biV7bY4SQ7R/ORJEmSpNHY1GHM08B7quqBJC8C7k+yt732oar6r8ODk5wH\nbAN+AfgXwP9K8q/ayx8BLgeOAPcl2VNV31iNDyJJkiSN2qLFc1UdBY625b9LchA4Y4FNrgZuqaof\nAd9Ochi4qL12uKoeAUhySxtr8SxJkqQ1YUk9z0m2ABcA97TQO5I8mOTmJKe02BnAY0ObHWmx+eKS\n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\n", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["fix, ax = plt.subplots(1, 2, figsize=(12,4))\n", "ax[0].hist(Xbruit, bins=mx, rwidth=0.9)\n", "ax[1].hist(Xbruit, bins=mx*100);"]}, {"cell_type": "code", "execution_count": 36, "metadata": {"collapsed": true}, "outputs": [], "source": ["Xbruitcrypt = numpy.array([crypt(x) for x in Xbruit])"]}, {"cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [{"data": {"image/png": "iVBORw0KGgoAAAANSUhEUgAAAs8AAAD8CAYAAACIA0mdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4wLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvpW3flQAAGudJREFUeJzt3W2sZVWd5/HvrynBx7YAL6S6Cqcg\nXaFlOqPgDQ3txDiUD6BGeAEzEKM1dpmaTNOONp1oMb4wPTOd6ExHadMOdo2g5YTmYVAHQtPalRJi\nOmnRQmlES6wSaaimpK7yoKPpVvQ/L84qOdy6l9p1763z+P0kJ2fvtdc+57/uOrX4s/fae6eqkCRJ\nknR4vzbsACRJkqRxYfIsSZIkdWTyLEmSJHVk8ixJkiR1ZPIsSZIkdWTyLEmSJHVk8ixJkiR1ZPIs\nSZIkdWTyLEmSJHW0atgBPJuXvOQltX79+mGHIUlLcvfdd/+gqmaGHccgOW5LGlddx+yRTp7Xr1/P\nrl27hh2GJC1Jkn8YdgyD5rgtaVx1HbOdtiFJkiR1ZPIsSZIkdWTyLEmSJHVk8ixJkiR1ZPIsSZIk\ndWTyLEmSJHVk8ixJkiR1ZPIsSZIkdWTyLEmSJHU00k8YXKr1W/9qqN//4AffNNTvlyRJ0tExkcnz\nKDGRlyRJmhwmz5IW5P/4SZJ0KOc8S5IkSR155HmKeCRRkiRpeTzyLEmSJHVk8ixJkiR15LQNTb1R\nms4ySrFIkqRDeeRZkiRJ6sjkWZIkSerI5FmSJEnq6LDJc5JrkxxIcl9f2f9I8u0k9yb5XJLVfduu\nTLI3yf1J3tBXfn4r25tk68o3RZIkSTq6uhx5/hRw/ryyHcBvV9W/Ar4DXAmQ5AzgUuBftn3+Z5Jj\nkhwDfAy4ADgDuKzVlSQNWZLTk9zT9/pRkvckOSHJjiR72vvxw45VkobtsMlzVX0JeGxe2d9U1VNt\n9cvAurZ8IXBDVf1zVX0P2Auc3V57q+qBqvoZcEOrK0kasqq6v6peUVWvAF4J/BT4HLAV2FlVG4Cd\nbV2SptpK3Kru94Ab2/Jaesn0QftaGcDD88p/Z6EPS7IF2ALw0pe+dAXCkzTuvIXfQG0EvltV/5Dk\nQuA1rXw7cCfwviHFJUkjYVkXDCZ5P/AUcN3BogWq1bOUH1pYta2qZqtqdmZmZjnhSZKO3KXA9W35\n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\n", "text/plain": [""]}, "metadata": {}, "output_type": "display_data"}], "source": ["fix, ax = plt.subplots(1, 2, figsize=(12,4))\n", "ax[0].hist(Xbruitcrypt, bins=mx, rwidth=0.9)\n", "ax[1].hist(Xbruitcrypt, bins=mx*100);"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Le bruit ajout\u00e9 ne change rien, la nouvelle variable permet de discriminer aussi bien mais il multiplie le nombre de valeurs distinctes. Si chaque valeur est presque unique, l'histogramme de la variable crypt\u00e9e est quasi-uniforme."]}, {"cell_type": "code", "execution_count": 38, "metadata": {"collapsed": true}, "outputs": [], "source": []}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.1"}}, "nbformat": 4, "nbformat_minor": 2}