{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["# 2A.ml - Interpr\u00e9tabilit\u00e9 et corr\u00e9lations des variables\n", "\n", "Plus un mod\u00e8le de machine learning contient de coefficients, moins sa d\u00e9cision peut \u00eatre interpr\u00e9t\u00e9e. Comment contourner cet obstacle et comprendre ce que le mod\u00e8le a appris ? Notion de [feature importance](http://scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances.html)."]}, {"cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [{"data": {"text/html": ["
\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": ["# R\u00e9pare une incompatibilit\u00e9 entre scipy 1.0 et statsmodels 0.8.\n", "from pymyinstall.fix import fix_scipy10_for_statsmodels08\n", "fix_scipy10_for_statsmodels08()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Mod\u00e8les lin\u00e9aires\n", "\n", "Les mod\u00e8les lin\u00e9aires sont les mod\u00e8les les plus simples \u00e0 interpr\u00e9ter. A performance \u00e9quivalente, il faut toujours choisir le mod\u00e8le le plus simple. Le module [scikit-learn](http://scikit-learn.org/) ne propose pas les outils standards d'analyse des mod\u00e8les lin\u00e9aires (test de nullit\u00e9, valeur propre). Il faut choisir [statsmodels](http://statsmodels.sourceforge.net/) pour obtenir ces informations."]}, {"cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["C:\\Python395_x64\\lib\\site-packages\\statsmodels\\tsa\\base\\tsa_model.py:7: FutureWarning: pandas.Int64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.\n", " from pandas import (to_datetime, Int64Index, DatetimeIndex, Period,\n", "C:\\Python395_x64\\lib\\site-packages\\statsmodels\\tsa\\base\\tsa_model.py:7: FutureWarning: pandas.Float64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.\n", " from pandas import (to_datetime, Int64Index, DatetimeIndex, Period,\n"]}], "source": ["import numpy\n", "import statsmodels.api as smapi\n", "nsample = 100\n", "x = numpy.linspace(0, 10, 100)\n", "X = numpy.column_stack((x, x**2 - x))\n", "beta = numpy.array([1, 0.1, 10])\n", "e = numpy.random.normal(size=nsample)\n", "X = smapi.add_constant(X)\n", "y = X @ beta + e"]}, {"cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [{"data": {"text/html": ["\n", "OLS Regression Results\n", "\n", " Dep. Variable: | y | R-squared: | 1.000 | \n", "
\n", "\n", " Model: | OLS | Adj. R-squared: | 1.000 | \n", "
\n", "\n", " Method: | Least Squares | F-statistic: | 3.222e+06 | \n", "
\n", "\n", " Date: | Sat, 12 Feb 2022 | Prob (F-statistic): | 1.30e-234 | \n", "
\n", "\n", " Time: | 18:53:30 | Log-Likelihood: | -147.79 | \n", "
\n", "\n", " No. Observations: | 100 | AIC: | 301.6 | \n", "
\n", "\n", " Df Residuals: | 97 | BIC: | 309.4 | \n", "
\n", "\n", " Df Model: | 2 | | | \n", "
\n", "\n", " Covariance Type: | nonrobust | | | \n", "
\n", "
\n", "\n", "\n", " | coef | std err | t | P>|t| | [0.025 | 0.975] | \n", "
\n", "\n", " const | 1.2570 | 0.317 | 3.969 | 0.000 | 0.628 | 1.886 | \n", "
\n", "\n", " x1 | 0.0134 | 0.133 | 0.101 | 0.920 | -0.250 | 0.277 | \n", "
\n", "\n", " x2 | 10.0052 | 0.014 | 706.336 | 0.000 | 9.977 | 10.033 | \n", "
\n", "
\n", "\n", "\n", " Omnibus: | 4.968 | Durbin-Watson: | 1.920 | \n", "
\n", "\n", " Prob(Omnibus): | 0.083 | Jarque-Bera (JB): | 2.455 | \n", "
\n", "\n", " Skew: | -0.037 | Prob(JB): | 0.293 | \n", "
\n", "\n", " Kurtosis: | 2.236 | Cond. No. | 125. | \n", "
\n", "
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified."], "text/plain": ["\n", "\"\"\"\n", " OLS Regression Results \n", "==============================================================================\n", "Dep. Variable: y R-squared: 1.000\n", "Model: OLS Adj. R-squared: 1.000\n", "Method: Least Squares F-statistic: 3.222e+06\n", "Date: Sat, 12 Feb 2022 Prob (F-statistic): 1.30e-234\n", "Time: 18:53:30 Log-Likelihood: -147.79\n", "No. Observations: 100 AIC: 301.6\n", "Df Residuals: 97 BIC: 309.4\n", "Df Model: 2 \n", "Covariance Type: nonrobust \n", "==============================================================================\n", " coef std err t P>|t| [0.025 0.975]\n", "------------------------------------------------------------------------------\n", "const 1.2570 0.317 3.969 0.000 0.628 1.886\n", "x1 0.0134 0.133 0.101 0.920 -0.250 0.277\n", "x2 10.0052 0.014 706.336 0.000 9.977 10.033\n", "==============================================================================\n", "Omnibus: 4.968 Durbin-Watson: 1.920\n", "Prob(Omnibus): 0.083 Jarque-Bera (JB): 2.455\n", "Skew: -0.037 Prob(JB): 0.293\n", "Kurtosis: 2.236 Cond. No. 125.\n", "==============================================================================\n", "\n", "Notes:\n", "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n", "\"\"\""]}, "execution_count": 5, "metadata": {}, "output_type": "execute_result"}], "source": ["model = smapi.OLS(y, X)\n", "results = model.fit()\n", "results.summary()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Arbres (tree)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Lectures\n", "\n", "* [treeinterpreter](https://github.com/andosa/treeinterpreter)\n", "* [Making Tree Ensembles Interpretable](https://arxiv.org/pdf/1606.05390v1.pdf) : l'article propose de simplifier une random forest en approximant sa sortie par une somme pond\u00e9r\u00e9e d'arbre plus simples.\n", "* [Understanding variable importances in forests of randomized trees](http://papers.nips.cc/paper/4928-understanding-variable-importances-in-forests-of-randomized-trees.pdf) : cet article explique plus formellement le calcul des termes ``feature_importances_`` calcul\u00e9s par scikit-learn pour chaque arbre et for\u00eats d'arbres (voir aussi [Random Forests, Leo Breiman and Adele Cutler](http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Module treeinterpreter"]}, {"cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": ["from sklearn.datasets import load_iris\n", "iris = load_iris()\n", "X = iris.data\n", "Y = iris.target"]}, {"cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": ["from sklearn.tree import DecisionTreeClassifier\n", "clf2 = DecisionTreeClassifier(max_depth=3)\n", "clf2.fit(X, Y)\n", "Yp2 = clf2.predict(X)"]}, {"cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": ["from sklearn.tree import export_graphviz\n", "export_graphviz(clf2, out_file=\"arbre.dot\")"]}, {"cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [{"data": {"text/plain": ["0"]}, "execution_count": 9, "metadata": {}, "output_type": "execute_result"}], "source": ["import os\n", "cwd = os.getcwd()\n", "from pyquickhelper.helpgen import find_graphviz_dot\n", "dot = find_graphviz_dot()\n", "os.system (\"\\\"{1}\\\" -Tpng {0}\\\\arbre.dot -o {0}\\\\arbre.png\".format(cwd, dot))"]}, {"cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [{"data": {"image/png": "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7dovfelLekRdCI455pgnn3wyEAg8/PDDRscCAJAyJBYQn/ZrGWkXbdyzZ89dd931s5/9bO7cuZkFW2jOPffcu+66y263v/HGG0bHAgCQGsyxKF7qcyzUZ1RIt6RXtPHQoUMXXHCBIAivvPLKpEmT0nsLBWxsbOziiy8+cODAwMDA5MmTjQ4HAEArjFiAMe6+++4//elPTz75JLKKuEpKSp544om9e/dqnK0CAGASSCwgZWINJYbdoMgmWMgkOsIrr7zyq1/96v77758xY0bWw81bp59++ooVK5xOZyAQMDoWAACtkFhAcmxhTFa0MRaLye4LTbVo4yeffPLDH/7wkksuaWlpyW7c+e/6669fsGDBdddd949//MPoWAAANEFiAck1NTURUXV1tcVimTp1KluNQlRbW8tuA5k2bZrFYrFYLHV1dRzHNTc3xz3aj370o48++uixxx5TX7gEmK6uLovF0traanQgAACaYPJm8dI+eZOIvF5vT08Pz/Mul6ulpUXZxuv1bt26lZWycLlc3/ve98rKypQvumHDhu9///t9fX0LFizQ+w0VrBdffPGyyy4r2uXZACC/ILGA3Hn//ffPPvvsq6666tFHHzU6ljyzZMmSNWvWBIPBU0891ehYAADUILGA3LFarW+++WYwGPzyl79sdCx55vPPP587d+5xxx23devWiRMnGh0OAEBCmGMBOeJyuZ599tk1a9Ygq0jDlClTenp6BgcHlbXP8d0AAEwFiQXkwttvv22322+//faamhqjY8lXs2bNuueee+6+++5XX31V3Lhnz56LLrros88+MzAwAAApXAqBrBsfH//Od77z8ccfv/rqqygimQlBEK666qo///nPu3btOuaYYx566KGlS5cePHhw06ZNl112mdHRAQAQEZUYHQAUvnvuuWfHjh1//OMfkVVkyGKxrF69evbs2f/v//2/SCSyefPm8fHxyZMnb9y4EYkFAJgERiwguwYHB6urq++9994lS5YYHUuBaG9v/9WvfiUIwqFDh9iWU0899Z133jE2KgAABokFZNGBAwfOPffcr3zlK1u2bJkwARN6MvXZZ5/dfvvtv/nNbywWy/j4uPSpvXv3fv3rXzcqMAAAET7rIYtuu+22d999t7u7G1lF5nbu3HnWWWd1dXUJgiDLKkpKSjZt2mRUYAAAUvi4h2x58cUXH3ro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rFixcuXKl156yehYACA1GLEAyDN/+tOfzjnnnLvvvvuOO+4wOpbsWrBgwWuvvfb6668fd9xxRscCAFohsQDIJ4cOHaqurp48efLLL79s/iW7MvT++++fddZZ11xzTVdXl9GxAIBWuBQCkE/uvvvuPXv2rF27tuCzCiL693//90ceecTlcm3cuNHoWABAK4xYAOSN/v7+iy66aOXKlW1tbUbHkjuLFi3avn37G2+8cfzxxxsdCwAkh8QCID98+umnVVVVp5xyyvPPP2+xWIwOJ3c+/PDDs8466/LLL1+zZo3RsQBAcrgUApAfbrvtttHR0UcffbSosgoiOuGEE1wu12OPPfbUU08ZHQsAJIcRC4A8sHnz5u9+97tPPPFEU1OT0bEY47rrrtu4ceObb75ZVlZmdCwAoAaJBYDZxWKx2bNnn3POOcX8lT0Wi5199tkXXHCBx+MxOhYAUINLIQBmd9NNNx04cKDIb7ksLS397W9/u27dur6+PqNjAQA1GLEAMLWnn376P/7jP3w+39VXX210LMZrbW39/e9//+abb06bNs3oWAAgPiQWAObFKkR973vfc7lcRsdiCp988klFRcWsWbM2bNhgdCwAEB8SCwDz+s///M/BwUHUtJbatm1bTU3N2rVrf/CDHxgdCwDEgTkWACb16KOPPv3002vWrEFWIXXhhRfedNNNN99887vvvmt0LAAQB0YsAMxo3759FRUVra2tv/71r42OxXSKtlYYQF5AYgFgOuPj43V1dZFI5LXXXjv66KONDseMWHXzRx555L//+7+NjgUAvgCXQgBMZ8WKFdu2bVu7di2yikSqq6t//OMfL168+C9/+YvRsQDAF2DEAsBc9uzZc84559x5553t7e1Gx2Jqn3/++be//e2ysrLNmzfjggiAeSCxADCRsbGx888/f3x8vL+/f9KkSUaHY3a7du0677zzHnjggZtuusnoWADgf+FSCICJLF++/I033li7di2yCi2qqqpuv/32n/zkJ3/+85+NjgUA/hdGLADMYnBwcN68eU6n80c/+pHRseSNsbGxefPmTZky5Q9/+MPEiRONDgcAMGIBYJA33nhD+uOBAweuvfbaiy666JZbbjEqpHxUUlLy6KOP7ty5c8WKFdLtBw8e3L17t1FRARQzJBYABnjrrbfmzJnzi1/8YmxsjG2544473nvvvTVr1mAeYqoqKip+9rOf/fSnPxUziVAoVFVVdeeddxobGEBxwqUQAAOsXLly8eLFRDR79myPx/P+++9/5zvf+e1vf3vdddcZHVpeGhsbu+CCC8bGxrZt23b//fcvW7ZsfHz86KOPjkajJSUlRkcHUFyQWAAY4Morr3zhhRcOHz5cUlJisVhOPfXUb33rW08//bTRceWxPXv2zJkz5+STT963b9/hw4fZxoGBgfPOO8/YwACKDS6FAOTa2NjY1q1b2clvbGzs0KFDf/nLX9577z3UekqbIAgvv/zy+Ph4OBwWs4rJkydv3rzZ2MAAihASC4Bce+WVVz799FPplvHx8ddff3327NlYHj0N77zzzkUXXdTW1nbw4EFxzgoRHTp06PnnnzcwMIDihMQCINdefPHFyZMnyzYeOnTos88+u/HGG61W64cffmhIYPlozZo1M2fOfPXVV8fHx2VPCYIwMDAgy+EAINuQWADk2nPPPXfw4EHldovFYrFYZs+eXVpamvuo8tTFF1985plnJnr20KFD27Zty2U8AIDEAiCnotFoMBhUbp80adLUqVM3btzY0dGBGxm0+/rXv/7HP/5x6dKlFotlwgT5B9rkyZMDgYAhgQEULSQWADnl9/uVt2JNmDDhwgsv3L1792WXXWZIVHlt0qRJ995779NPP33sscfKSqEfPHjwueeeMyowgOKExAIgp1588UXpgERJScnEiRPb29s3b9584oknGhhYvrNarW+++eacOXNkhb3ffPPNDz74wKioAIoQEguAnHr22WcPHTrEHk+aNKmsrOzll19etmyZchgfUvW1r31t27ZtP/3pT2WXRV566SXjggIoOvgsA8idvXv3vvfee+yxxWK5+uqrd+/eXV1dbWxUhaSkpOTnP//5Cy+8cPzxx7PLIiUlJX6/3+i4AIoIEguA3GH1mkpKSo466qjVq1c/9dRTU6dONTqoAnTJJZeEQqHzzjtv4sSJhw4dwjQLgFxCYgGQO5s2bSKib3zjG4ODg9dff73R4RSyk08++aWXXrrrrrssFsvIyEg4HDY6IoBigbVCIAkstlkMFixY0NfXl+FB6uvr169fr0s8YGY4a4A63C4PyS1evBjzADK3f//+/fv3z5071+hA5B544AG9DjVv3rwlS5bodTS9xGKxwcHB+fPnGx1I3uvv71+xYoXRUYDZIbGA5Kqr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azGZ0Os45pf73pKDzkYa3lFvb++iRYtw1gB1mGMBkI6BgQHxu3U+Hh9yKcO/JjoD5BckFgD/R/vyENu3b29pacleJJkcX/u7gEzkrLdktbOht4DukFgApGPp0qV5fXzIpQz/mugMkF9KjA4AwBQK6bJxIb0Xcyqk33AhvRcwCYxYAAAAgG6QWAAAAIBukFgAAACAbpBYAAAAgG4weROS6+/vT3WXw4cPT5w4MRvBgO7ee++9r371q3odSlwABUwujX/SND4KoAih8iYkgXvci8GCBQt0qbzJFt+CwoazBqjDpRBIItUq8WvXrj3mmGPmzp07PDysR9V5A/z2t7895phjjI4ip3Spw93X12f0+8ipL33pS2vWrDE6ijS98847F1544VFHHbVixYrx8fGU9s28q0BhQ2IBunn//fetVuv1119/8803b9u27Rvf+IbREaVp0qRJhw4dMjoKMLtDhw5NmjTJ6CjSdOqpp27ZsmXZsmW33Xbb5Zdf/re//c3oiKBwILEAfbz44ouVlZWvv/56IBC499578/cDl44kFvhmBioEQRgbG8vrfl5SUnL77be//PLLb7/9dmVl5TPPPGN0RFAgkFhApg4cOHDHHXdcfvnlF1xwwa5duy6++GKjI8rU5MmTBUE4fPiw0YGAeY2NjQmCMHnyZKMDydR555332muvff/737darTfeeOOnn35qdESQ95BYQEZ27949b968VatWPfbYY729vccff7zREemAfQ09ePCg0YGAebHukdcjFqIvf/nLjzzyyLp169avX//tb397165dRkcE+Q2JBaRJEASXyzV37tyjjz56cHCwubnZ6Ih0w76GYpoFqGDdowBGLET19fW7du0qKyurrq6+7777xsfHjY4I8hUSC0hHJBK5+uqrb7rppttuu23btm1f//rXjY5ITxixgKQKacRCVF5eHggE7rvvvp/97Gff/e539+/fb3REkJeQWEDKnn766bPOOmvPnj0vvfTSsmXLCq8QFkYsIKnCG7FgJkyYcOutt27btu3dd98966yzvF6v0RFB/kFiASn47LPPbr311muuueaKK654/fXXL7jgAqMjygqMWEBSBTliITr33HODweC1117b2Nh47bXX/utf/zI6IsgnSCxAq507d1ZVVa1du7anp+fxxx8/9thjjY4oW9jZAiMWoIJ1j0JNLIjo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\n", "text/plain": [""]}, "execution_count": 10, "metadata": {}, "output_type": "execute_result"}], "source": ["from IPython.display import Image\n", "Image(\"arbre.png\")"]}, {"cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": ["from treeinterpreter import treeinterpreter\n", "pred, bias, contrib = treeinterpreter.predict(clf2, X[106:107,:])"]}, {"cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[4.9, 2.5, 4.5, 1.7]])"]}, "execution_count": 12, "metadata": {}, "output_type": "execute_result"}], "source": ["X[106:107,:]"]}, {"cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[0. , 0.97916667, 0.02083333]])"]}, "execution_count": 13, "metadata": {}, "output_type": "execute_result"}], "source": ["pred"]}, {"cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[0.33333333, 0.33333333, 0.33333333]])"]}, "execution_count": 14, "metadata": {}, "output_type": "execute_result"}], "source": ["bias"]}, {"cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([[[ 0. , 0. , 0. ],\n", " [ 0. , 0. , 0. ],\n", " [ 0. , 0.07175926, -0.07175926],\n", " [-0.33333333, 0.57407407, -0.24074074]]])"]}, "execution_count": 15, "metadata": {}, "output_type": "execute_result"}], "source": ["contrib"]}, {"cell_type": "markdown", "metadata": {}, "source": ["``pred`` est identique \u00e0 ce que retourne la m\u00e9thode ``predict`` de scikit-learn. ``bias`` est la proportion de chaque classe. ``contrib`` est la somme des contributions de chaque variable \u00e0 chaque classe. On note $X=(x_1, ..., x_n)$ une observation.\n", "\n", "$$P(X \\in classe(i)) = \\sum_i contrib(x_k,i)$$\n", "\n", "Le [code](https://github.com/andosa/treeinterpreter/blob/master/treeinterpreter/treeinterpreter.py) est assez facile \u00e0 lire et permet de comprendre ce que vaut la fonction $contrib$."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 1 : d\u00e9crire la fonction contrib\n", "\n", "La lecture de [Understanding variable importances\n", "in forests of randomized trees](http://papers.nips.cc/paper/4928-understanding-variable-importances-in-forests-of-randomized-trees.pdf) devrait vous y aider."]}, {"cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0. , 0. , 0.05393633, 0.94606367])"]}, "execution_count": 16, "metadata": {}, "output_type": "execute_result"}], "source": ["clf2.feature_importances_"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 2 : impl\u00e9menter l'algorithme\n", "\n", "D\u00e9crit dans [Making Tree Ensembles Interpretable](https://arxiv.org/pdf/1606.05390v1.pdf)"]}, {"cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## Interpr\u00e9tation et corr\u00e9lation"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Mod\u00e8les lin\u00e9aires\n", "\n", "Les mod\u00e8les lin\u00e9aires n'aiment pas les variables corr\u00e9l\u00e9es. Dans l'exemple qui suit, les variables $X_2, X_3$ sont identiques. La r\u00e9gression ne peut retrouver les coefficients du mod\u00e8le initial (2 et 8)."]}, {"cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": ["import numpy\n", "import statsmodels.api as smapi\n", "nsample = 100\n", "x = numpy.linspace(0, 10, 100)\n", "X = numpy.column_stack((x, (x-5)**2, (x-5)**2)) # ajout de la m\u00eame variable\n", "beta = numpy.array([1, 0.1, 2, 8])\n", "e = numpy.random.normal(size=nsample)\n", "X = smapi.add_constant(X)\n", "y = X @ beta + e"]}, {"cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [{"name": "stderr", "output_type": "stream", "text": ["C:\\Python395_x64\\lib\\site-packages\\numpy\\lib\\function_base.py:2691: RuntimeWarning: invalid value encountered in true_divide\n", " c /= stddev[:, None]\n", "C:\\Python395_x64\\lib\\site-packages\\numpy\\lib\\function_base.py:2692: RuntimeWarning: invalid value encountered in true_divide\n", " c /= stddev[None, :]\n"]}, {"data": {"text/html": ["\n", "\n", "
\n", " \n", " \n", " | \n", " 0 | \n", " 1 | \n", " 2 | \n", " 3 | \n", "
\n", " \n", " \n", " \n", " 0 | \n", " NaN | \n", " NaN | \n", " NaN | \n", " NaN | \n", "
\n", " \n", " 1 | \n", " NaN | \n", " 1.000000e+00 | \n", " 8.513703e-17 | \n", " 8.513703e-17 | \n", "
\n", " \n", " 2 | \n", " NaN | \n", " 8.513703e-17 | \n", " 1.000000e+00 | \n", " 1.000000e+00 | \n", "
\n", " \n", " 3 | \n", " NaN | \n", " 8.513703e-17 | \n", " 1.000000e+00 | \n", " 1.000000e+00 | \n", "
\n", " \n", "
\n", "
"], "text/plain": [" 0 1 2 3\n", "0 NaN NaN NaN NaN\n", "1 NaN 1.000000e+00 8.513703e-17 8.513703e-17\n", "2 NaN 8.513703e-17 1.000000e+00 1.000000e+00\n", "3 NaN 8.513703e-17 1.000000e+00 1.000000e+00"]}, "execution_count": 19, "metadata": {}, "output_type": "execute_result"}], "source": ["import pandas\n", "pandas.DataFrame(numpy.corrcoef(X.T))"]}, {"cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [{"data": {"text/html": ["\n", "OLS Regression Results\n", "\n", " Dep. Variable: | y | R-squared: | 1.000 | \n", "
\n", "\n", " Model: | OLS | Adj. R-squared: | 1.000 | \n", "
\n", "\n", " Method: | Least Squares | F-statistic: | 3.806e+05 | \n", "
\n", "\n", " Date: | Sat, 12 Feb 2022 | Prob (F-statistic): | 1.27e-189 | \n", "
\n", "\n", " Time: | 18:53:59 | Log-Likelihood: | -126.59 | \n", "
\n", "\n", " No. Observations: | 100 | AIC: | 259.2 | \n", "
\n", "\n", " Df Residuals: | 97 | BIC: | 267.0 | \n", "
\n", "\n", " Df Model: | 2 | | | \n", "
\n", "\n", " Covariance Type: | nonrobust | | | \n", "
\n", "
\n", "\n", "\n", " | coef | std err | t | P>|t| | [0.025 | 0.975] | \n", "
\n", "\n", " const | 0.5470 | 0.199 | 2.756 | 0.007 | 0.153 | 0.941 | \n", "
\n", "\n", " x1 | 0.1396 | 0.030 | 4.671 | 0.000 | 0.080 | 0.199 | \n", "
\n", "\n", " x2 | 4.9989 | 0.006 | 872.449 | 0.000 | 4.988 | 5.010 | \n", "
\n", "\n", " x3 | 4.9989 | 0.006 | 872.449 | 0.000 | 4.988 | 5.010 | \n", "
\n", "
\n", "\n", "\n", " Omnibus: | 2.677 | Durbin-Watson: | 2.150 | \n", "
\n", "\n", " Prob(Omnibus): | 0.262 | Jarque-Bera (JB): | 1.871 | \n", "
\n", "\n", " Skew: | 0.133 | Prob(JB): | 0.392 | \n", "
\n", "\n", " Kurtosis: | 2.385 | Cond. No. | 1.41e+16 | \n", "
\n", "
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The smallest eigenvalue is 1.39e-28. This might indicate that there are
strong multicollinearity problems or that the design matrix is singular."], "text/plain": ["\n", "\"\"\"\n", " OLS Regression Results \n", "==============================================================================\n", "Dep. Variable: y R-squared: 1.000\n", "Model: OLS Adj. R-squared: 1.000\n", "Method: Least Squares F-statistic: 3.806e+05\n", "Date: Sat, 12 Feb 2022 Prob (F-statistic): 1.27e-189\n", "Time: 18:53:59 Log-Likelihood: -126.59\n", "No. Observations: 100 AIC: 259.2\n", "Df Residuals: 97 BIC: 267.0\n", "Df Model: 2 \n", "Covariance Type: nonrobust \n", "==============================================================================\n", " coef std err t P>|t| [0.025 0.975]\n", "------------------------------------------------------------------------------\n", "const 0.5470 0.199 2.756 0.007 0.153 0.941\n", "x1 0.1396 0.030 4.671 0.000 0.080 0.199\n", "x2 4.9989 0.006 872.449 0.000 4.988 5.010\n", "x3 4.9989 0.006 872.449 0.000 4.988 5.010\n", "==============================================================================\n", "Omnibus: 2.677 Durbin-Watson: 2.150\n", "Prob(Omnibus): 0.262 Jarque-Bera (JB): 1.871\n", "Skew: 0.133 Prob(JB): 0.392\n", "Kurtosis: 2.385 Cond. No. 1.41e+16\n", "==============================================================================\n", "\n", "Notes:\n", "[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.\n", "[2] The smallest eigenvalue is 1.39e-28. This might indicate that there are\n", "strong multicollinearity problems or that the design matrix is singular.\n", "\"\"\""]}, "execution_count": 20, "metadata": {}, "output_type": "execute_result"}], "source": ["model = smapi.OLS(y, X)\n", "results = model.fit()\n", "results.summary()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Arbre / tree\n", "\n", "Les arbres de d\u00e9cision n'aiment pas plus les variables corr\u00e9l\u00e9es."]}, {"cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": ["from sklearn.datasets import load_iris\n", "iris = load_iris()\n", "X = iris.data[:,:2]\n", "Y = iris.target"]}, {"cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [{"data": {"text/plain": ["DecisionTreeClassifier(max_depth=3)"]}, "execution_count": 22, "metadata": {}, "output_type": "execute_result"}], "source": ["from sklearn.tree import DecisionTreeClassifier\n", "clf1 = DecisionTreeClassifier(max_depth=3)\n", "clf1.fit(X, Y)"]}, {"cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0.76759205, 0.23240795])"]}, "execution_count": 23, "metadata": {}, "output_type": "execute_result"}], "source": ["clf1.feature_importances_"]}, {"cell_type": "markdown", "metadata": {}, "source": ["On recopie la variables $X_1$."]}, {"cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": ["import numpy\n", "X2 = numpy.hstack([X, numpy.ones((X.shape[0], 1))])\n", "X2[:,2] = X2[:,0]"]}, {"cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [{"data": {"text/plain": ["DecisionTreeClassifier(max_depth=3)"]}, "execution_count": 25, "metadata": {}, "output_type": "execute_result"}], "source": ["clf2 = DecisionTreeClassifier(max_depth=3)\n", "clf2.fit(X2, Y)"]}, {"cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [{"data": {"text/plain": ["array([0.14454858, 0.23240795, 0.62304347])"]}, "execution_count": 26, "metadata": {}, "output_type": "execute_result"}], "source": ["clf2.feature_importances_"]}, {"cell_type": "markdown", "metadata": {}, "source": ["On voit que l'importance de la variable 1 est dilu\u00e9e sur deux variables."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Exercice 3 : variables corr\u00e9l\u00e9es pour un arbre de d\u00e9cision\n", "\n", "Un arbre de d\u00e9cision est compos\u00e9 d'un ensemble de fonctions de seuil. Si $X_i > s_i$ alors il faut suivre cette branche, sinon, telle autre. Les arbres de d\u00e9cision ne sont pas sensibles aux probl\u00e8mes d'\u00e9chelle de variables. Si deux variables sont corr\u00e9l\u00e9es $cor(X_1, X_2)= 1$, l'arbre subit les m\u00eames probl\u00e8mes qu'un mod\u00e8le lin\u00e9aire. Dans le cas lin\u00e9aire, il suffit de changer l'\u00e9chelle $(X_1, \\ln X_2)$ pour \u00e9viter ce probl\u00e8me. \n", "\n", "* Pourquoi cette transformation ne change rien pour un arbre de d\u00e9cision ?\n", "* Quelle corr\u00e9lation il faudrait calculer pour rep\u00e9rer les variables identiques selon le point de vue d'un arbre de d\u00e9cision ?"]}, {"cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "code", "execution_count": 27, "metadata": {}, "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.9.5"}}, "nbformat": 4, "nbformat_minor": 2}