{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# Algo - les k premiers \u00e9l\u00e9ments\n", "\n", "Rechercher les k premiers \u00e9l\u00e9ments est un exercice classique d'algorithmie, souvent appel\u00e9 *top-k*et qu'on peut r\u00e9soudre \u00e0 l'aide d'un [algorithme de s\u00e9lection](https://fr.wikipedia.org/wiki/Algorithme_de_s%C3%A9lection). C'est tr\u00e8s utile en machine learning pour retourner les 3, 4, ou 5 premiers r\u00e9sultats d'un mod\u00e8le pr\u00e9dictif."]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["
run previous cell, wait for 2 seconds
\n", ""], "text/plain": [""]}, "execution_count": 2, "metadata": {}, "output_type": "execute_result"}], "source": ["from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()"]}, {"cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": ["%matplotlib inline"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Enonc\u00e9\n", "\n", "On part d'une liste toute simple, une permutation al\u00e9atoire des premiers entiers. On conna\u00eet donc les *k* plus petits \u00e9l\u00e9ments qu'il faut obtenir."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([17, 11, 18, 15, 3, 19, 8, 14, 4, 2, 16, 5, 9, 7, 1, 6, 10,\n", " 0, 13, 12])"]}, "execution_count": 4, "metadata": {}, "output_type": "execute_result"}], "source": ["import numpy\n", "perm = numpy.random.permutation(numpy.arange(20))\n", "perm"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : on trie tout et on prend les k plus petit\n", "\n", "C'est la m\u00e9thode la plus simple mais pas la plus efficace."]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": ["def topk_sortall(ensemble, k):\n", " # \u00e0 vous\n", " # ...\n", " pass\n", "\n", "topk_sortall(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : version plus rapide au choix\n", "\n", "A vois de choisir entre l'une et l'autre voire les deux si vous allez vite.\n", "\n", "**Id\u00e9e 1**\n", "\n", "On garde un tableau de *k* \u00e9l\u00e9ments tri\u00e9s *T*, on parcourt tous les \u00e9l\u00e9ments du tableau initial. Si l'\u00e9l\u00e9ment est plus petit que le plus grand des \u00e9l\u00e9ments dans le tableau *T*, on l'ajoute \u00e0 ce tableau de fa\u00e7on \u00e0 le garder trier. On continue jusqu'\u00e0 la fin et le tableau *T* est l'ensemble des *k* plus petits \u00e9l\u00e9ments.\n", "\n", "**Id\u00e9e 2**\n", "\n", "On d\u00e9coupe le tableau en $\\left[\\frac{n}{k}\\right]$ tableaux de taille *k* qu'on trie. On fusionne ensuite ces $\\left[\\frac{n}{k}\\right]$ pour garder ensuite les *k* plus petits \u00e9l\u00e9ments."]}, {"cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": ["def topk_idee1ou2(ensemble, k):\n", " pass"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Vous avez aussi le droit de tricher pour une troisi\u00e8me id\u00e9e [Heap / Tas](http://www.xavierdupre.fr/app/ensae_teaching_cs/helpsphinx/notebooks/nbheap.html) mais il faudra vous d\u00e9brouiller tout seul."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : algorithme de s\u00e9lection\n", "\n", "L'id\u00e9e est assez simple : on prend un \u00e9l\u00e9ment du tableau au hasard - le pivot - , on range \u00e0 droite tous les \u00e9l\u00e9ments sup\u00e9rieurs, \u00e0 gauche tous les \u00e9l\u00e9ments inf\u00e9rieurs. Si ce pivot se trouve \u00e0 la position *k* alors on a trouv\u00e9 les *k* plus petits \u00e9l\u00e9ments. Sinon, on sait o\u00f9 chercher."]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 4 : utiliser la fonction perf_counter pour comparer les vitessses de chaque solution\n", "\n", "Et bien s\u00fbr, il faudra expliquer pourquoi l'algorithme le plus rapide est bien le plus rapide. Faire varier la taille du tableau initial."]}, {"cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": ["from time import perf_counter"]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## R\u00e9ponses"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : on trie tout et on prend les k plus petit\n", "\n", "Tr\u00e8s simple mais le co\u00fbt est en $O(n \\ln n)$ puisqu'il faut trier tous les \u00e9l\u00e9ments."]}, {"cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0, 1, 2, 3])"]}, "execution_count": 10, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_sortall(ensemble, k):\n", " ensemble = ensemble.copy()\n", " ensemble.sort()\n", " return ensemble[:k]\n", "\n", "topk_sortall(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Or trier tous les \u00e9l\u00e9ments n'est pas n\u00e9cessaire. On n'a pas besoin de trier tous les \u00e9l\u00e9ments apr\u00e8s la position *k*. Il est donc a priori envisageable de fairre mieux en ne faisant que les calculs n\u00e9cessaires."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : version plus rapide au choix\n", "\n", "La premi\u00e8re id\u00e9e n'est pas une de celles propos\u00e9es mais elle est tr\u00e8s simple. Parmi les tris d\u00e9crits sur cette [interstices/tri](https://interstices.info/les-algorithmes-de-tri/), le tri par s\u00e9lection est int\u00e9ressant car il suffit d'effectuer les *k* premi\u00e8res it\u00e9rations pour retrouver les *k* plus petits \u00e9l\u00e9ments aux *k* premi\u00e8res positions."]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0, 1, 2, 3])"]}, "execution_count": 11, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_tri_selection(ensemble, k):\n", " ensemble = ensemble.copy()\n", " for i in range(0, min(k, len(ensemble))):\n", " for j in range(i + 1, len(ensemble)):\n", " if ensemble[i] > ensemble[j]:\n", " ensemble[i], ensemble[j] = ensemble[j], ensemble[i]\n", " return ensemble[:k]\n", "\n", "topk_tri_selection(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Le co\u00fbt de l'algorithme est en $O(kn)$.\n", "\n", "**id\u00e9e 1**"]}, {"cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [{"data": {"text/plain": ["[0, 1, 2, 3]"]}, "execution_count": 12, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_insertion(ensemble, k):\n", " \n", " def position(sub, value):\n", " a, b = 0, len(sub) - 1\n", " m = (a + b) // 2\n", " while a < b:\n", " if value == sub[m]:\n", " return m\n", " if value < sub[m]:\n", " b = m - 1\n", " else:\n", " a = m + 1\n", " m = (a + b) // 2\n", " return m if sub[m] >= value else m + 1\n", " \n", " res = [ensemble[0]]\n", " for i in range(1, len(ensemble)):\n", " if ensemble[i] < res[-1]:\n", " # on ins\u00e8re selon un m\u00e9thode dichotomique\n", " p = position(res, ensemble[i])\n", " res.insert(p, ensemble[i])\n", " if len(res) > k:\n", " res.pop()\n", " \n", " return res\n", "\n", "\n", "topk_insertion(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Le co\u00fbt de l'algorithme est dans le pire des cas $O(n * (\\ln k + k))$ :\n", "\n", "* *n* car il y *n* it\u00e9rations\n", "* $\\ln k$ car on recherche un \u00e9l\u00e9ment de fa\u00e7on dichotomique dans un tableau tri\u00e9\n", "* *k* car on ins\u00e8re un \u00e9l\u00e9ment dans un tableau en d\u00e9pla\u00e7ant tous les \u00e9l\u00e9ments plus grands\n", "\n", "Dans les faits, c'est un peu plus compliqu\u00e9 car le fait qu'on ait trouv\u00e9 un \u00e9l\u00e9ment plus petit \u00e0 la position $i$ que le plus grand d\u00e9j\u00e0 trouv\u00e9 n'est pas un \u00e9v\u00e9nement fr\u00e9quent si on suppose que le tableau est dans un ordre al\u00e9atoire. On pourrait m\u00eame dire que la probabilit\u00e9 de trouver un \u00e9l\u00e9ment faisant partie des *k* plus petits \u00e9l\u00e9ments est de plus en plus faible. On pourrait soit en rester l\u00e0, soit se dire qu'on souhaite un algorithme plus rapide encore m\u00eame dans le pire des cas qui serait pour cette version-ci un tableau tri\u00e9 dans le sens d\u00e9croissant. Dans ce cas, on sait que le prochain \u00e9l\u00e9ment fait toujours partie des $k$ plus petits \u00e9l\u00e9ments connus jusqu'\u00e0 pr\u00e9sent.\n", "\n", "On pourrait r\u00e9pondre \u00e0 cette question si on suppose que les \u00e9l\u00e9ments sont ind\u00e9pendants et tir\u00e9s selon la m\u00eame loi al\u00e9atoire."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**id\u00e9e 2**\n", "\n", "L'id\u00e9e est un peu plus compliqu\u00e9e."]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [{"data": {"text/plain": ["[0, 1, 2, 3]"]}, "execution_count": 13, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_fusion(ensemble, k):\n", " n = len(ensemble) // (len(ensemble) // k)\n", " res = []\n", " last = 0\n", " while last < len(ensemble):\n", " res.append(last)\n", " last += n\n", " res.append(len(ensemble))\n", " \n", " subs = []\n", " for i in range(1, len(res)):\n", " sub = ensemble[res[i-1] : res[i]]\n", " sub.sort()\n", " subs.append(sub)\n", " \n", " indices = [0 for sub in subs]\n", " topk = []\n", " while len(topk) < k:\n", " arg = None\n", " for i, sub in enumerate(subs):\n", " if indices[i] < len(sub) and (arg is None or sub[indices[i]] < subs[arg][indices[arg]]):\n", " arg = i\n", " topk.append(subs[arg][indices[arg]])\n", " indices[arg] += 1\n", " \n", " return topk\n", " \n", "\n", "topk_fusion(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : algorithme de s\u00e9lection\n", "\n", "Premi\u00e8re version par r\u00e9currence."]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"data": {"text/plain": ["[3, 2, 1, 0]"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_select_recursive(ensemble, k):\n", " if len(ensemble) <= k:\n", " return ensemble\n", " p = ensemble[k]\n", " inf, sup = [], []\n", " for e in ensemble:\n", " if e > p:\n", " sup.append(e)\n", " else:\n", " inf.append(e)\n", " if len(inf) == k:\n", " return inf\n", " if len(sup) == 0:\n", " # potentiellement une boucle infinie, on change\n", " # le pivot de c\u00f4t\u00e9\n", " sup.append(p)\n", " del inf[inf.index(p)]\n", " if len(inf) >= k:\n", " return topk_select_recursive(inf, k)\n", " return inf + topk_select_recursive(sup, k - len(inf))\n", "\n", "\n", "topk_select_recursive(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Une seconde version sans r\u00e9currence."]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0, 1, 2, 3])"]}, "execution_count": 15, "metadata": {}, "output_type": "execute_result"}], "source": ["def topk_select(ensemble, k):\n", " ensemble = ensemble.copy()\n", " \n", " def loop(a, b, pivot):\n", " pivot_index = None\n", " while a < b:\n", " while a < len(ensemble) and ensemble[a] < pivot:\n", " a += 1\n", " while b >= 0 and ensemble[b] >= pivot:\n", " if ensemble[b] == pivot:\n", " pivot_index = b\n", " b -= 1\n", " if a < b:\n", " ensemble[a], ensemble[b] = ensemble[b], ensemble[a]\n", " return min(a, len(ensemble) - 1), pivot_index\n", " \n", "\n", " a = 0\n", " b = len(ensemble) - 1\n", " m = k\n", " while True:\n", " pivot = ensemble[m]\n", " m, pi = loop(a, b, pivot)\n", " if m == k:\n", " return ensemble[:m]\n", " # Les cas particuliers interviennent lorsque pivot choisi est\n", " # identique au pr\u00e9c\u00e9dent.\n", " if m > k:\n", " if b == m - 1:\n", " ensemble[b], ensemble[pi] = ensemble[pi], ensemble[b]\n", " b -= 1\n", " else:\n", " b = m - 1\n", " else:\n", " if a == m:\n", " ensemble[a], ensemble[pi] = ensemble[pi], ensemble[a]\n", " a += 1\n", " else:\n", " a = m\n", " m = k\n", "\n", " \n", "topk_select(perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 4 : utiliser la fonction perf_counter pour comparer les vitessses de chaque solution"]}, {"cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.0033986000000005845"]}, "execution_count": 16, "metadata": {}, "output_type": "execute_result"}], "source": ["from time import perf_counter\n", "\n", "def measure_time(fct, perm, k, repeat=1000):\n", " t1 = perf_counter()\n", " for r in range(repeat):\n", " fct(perm, k)\n", " return perf_counter() - t1\n", "\n", "measure_time(topk_sortall, perm, 4)"]}, {"cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.09221089999999954"]}, "execution_count": 17, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_tri_selection, perm, 4)"]}, {"cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.01921359999999961"]}, "execution_count": 18, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_insertion, perm, 4)"]}, {"cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.04859970000000047"]}, "execution_count": 19, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_fusion, perm, 4)"]}, {"cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.016174200000000027"]}, "execution_count": 20, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_select_recursive, perm, 4)"]}, {"cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.0986205"]}, "execution_count": 21, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_select, perm, 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["La premi\u00e8re fonction est plus rapide surtout parce que le tri est impl\u00e9ment\u00e9 par une fonction du langage particuli\u00e8rement optimis\u00e9e (en C). Il faudrait impl\u00e9menter un tri en python pour pouvoir comparer."]}, {"cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": ["perm10000 = numpy.random.permutation(numpy.arange(10000))"]}, {"cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.0050952000000004105"]}, "execution_count": 23, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_sortall, perm10000, 40, repeat=10)"]}, {"cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [{"data": {"text/plain": ["1.6007581999999996"]}, "execution_count": 24, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_tri_selection, perm10000, 40, repeat=10)"]}, {"cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.10587389999999974"]}, "execution_count": 25, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_insertion, perm10000, 40, repeat=10)"]}, {"cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.1086203999999995"]}, "execution_count": 26, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_fusion, perm10000, 40, repeat=10)"]}, {"cell_type": "code", "execution_count": 26, "metadata": {"scrolled": false}, "outputs": [{"data": {"text/plain": ["0.03971849999999222"]}, "execution_count": 27, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_select_recursive, perm10000, 40, repeat=10)"]}, {"cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [{"data": {"text/plain": ["0.09422410000001946"]}, "execution_count": 28, "metadata": {}, "output_type": "execute_result"}], "source": ["measure_time(topk_select, perm10000, 40, repeat=10)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Il faut faire tourner la fonction un grand nombre de fois sur diff\u00e9rentes tailles de *n* pour voir l'\u00e9volution."]}, {"cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 9/9 [00:09<00:00, 1.10s/it]\n"]}, {"data": {"text/html": ["
"]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["import matplotlib.pyplot as plt\n", "fig, ax = plt.subplots(1, 2, figsize=(14, 4))\n", "df.set_index('k').drop([\"n\", \"topk_tri_selection\"], axis=1).plot(\n", " logy=True, logx=True, title=\"Co\u00fbt en fonction de k\", ax=ax[0])\n", "df.set_index('k')[[\"topk_tri_selection\"]].plot(\n", " logy=True, logx=True, title=\"Co\u00fbt en fonction de k\", ax=ax[1]);"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pas \u00e9vident, le langage est trop haut niveau et le co\u00fbt de l'interpr\u00e9teur gomme les aspects algorithmique. Il faudrait augmenter la taille du tableau \u00e0 trier ou affiner la mesure."]}, {"cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 5/5 [00:05<00:00, 1.19s/it]\n"]}, {"data": {"text/html": ["
\n", "\n", "
\n", " \n", "
\n", "
\n", "
k
\n", "
n
\n", "
topk_sortall
\n", "
topk_tri_selection
\n", "
topk_insertion
\n", "
topk_fusion
\n", "
topk_select_recursive
\n", "
topk_select
\n", "
\n", " \n", " \n", "
\n", "
0
\n", "
10
\n", "
20
\n", "
0.000464
\n", "
0.001552
\n", "
0.000253
\n", "
0.000390
\n", "
0.000560
\n", "
0.001252
\n", "
\n", "
\n", "
1
\n", "
10
\n", "
100
\n", "
0.000301
\n", "
0.007772
\n", "
0.001735
\n", "
0.002594
\n", "
0.001299
\n", "
0.004708
\n", "
\n", "
\n", "
2
\n", "
10
\n", "
1000
\n", "
0.000406
\n", "
0.052845
\n", "
0.003583
\n", "
0.007324
\n", "
0.002064
\n", "
0.006233
\n", "
\n", "
\n", "
3
\n", "
10
\n", "
10000
\n", "
0.005089
\n", "
0.372522
\n", "
0.026215
\n", "
0.066013
\n", "
0.026855
\n", "
0.060124
\n", "
\n", "
\n", "
4
\n", "
10
\n", "
100000
\n", "
0.063857
\n", "
3.491449
\n", "
0.245375
\n", "
0.699281
\n", "
0.221890
\n", "
0.565102
\n", "
\n", " \n", "
\n", "
"], "text/plain": [" k n topk_sortall topk_tri_selection topk_insertion topk_fusion \\\n", "0 10 20 0.000464 0.001552 0.000253 0.000390 \n", "1 10 100 0.000301 0.007772 0.001735 0.002594 \n", "2 10 1000 0.000406 0.052845 0.003583 0.007324 \n", "3 10 10000 0.005089 0.372522 0.026215 0.066013 \n", "4 10 100000 0.063857 3.491449 0.245375 0.699281 \n", "\n", " topk_select_recursive topk_select \n", "0 0.000560 0.001252 \n", "1 0.001299 0.004708 \n", "2 0.002064 0.006233 \n", "3 0.026855 0.060124 \n", "4 0.221890 0.565102 "]}, "execution_count": 31, "metadata": {}, "output_type": "execute_result"}], "source": ["res = []\n", "k = 10\n", "for n in tqdm([20, 100, 1000, 10000, 100000]):\n", " permn = numpy.random.permutation(numpy.arange(n))\n", " obs = dict(k=k, n=permn.shape[0])\n", " for fct in [topk_sortall, topk_tri_selection, topk_insertion,\n", " topk_fusion, topk_select_recursive, topk_select]:\n", " obs[fct.__name__] = measure_time(fct, permn, k, repeat=10)\n", " res.append(obs)\n", "\n", "df = DataFrame(res)\n", "df.head()"]}, {"cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [{"data": {"image/png": "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\n", "text/plain": [""]}, "metadata": {"needs_background": "light"}, "output_type": "display_data"}], "source": ["df.set_index('n').drop([\"k\"], axis=1).plot(\n", " logy=True, logx=True, title=\"Co\u00fbt en fonction de n\");"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Les co\u00fbts paraissent lin\u00e9aires en *n*. Il faudrait cependant augmenter la taille encore car on sait que l'un d'entre eux ne l'est pas. Le co\u00fbt de l'interpr\u00e9teur python est l\u00e0-encore non n\u00e9gligeable. Il faudrait prendre des langages plus rapide ou plus bas niveau ou augmenter les tailles pour voir quelque chose d'int\u00e9ressant."]}, {"cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": []}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}}, "nbformat": 4, "nbformat_minor": 2}