makov
%% Cell type:markdown id: tags: | ||
# Modèle linéaire généralisé (Generalize Linear Model) | ||
***Introduction:*** Nous nous intéressons à la modélisation probabiste de données: Elles sont constituées d'input $x_i$ et d'ouput $y_i$. | ||
* exemple 1: $y_i$ est le prix du $i$-ième appartement et $x_i$=(surface, ensoleillement, quatier) | ||
* exemple 2: $y_i$ est le nombre d'accident du $i$-ième client d'une assurance, et $x_i$ c'est toutes ses données personnelles. | ||
On va chercher une loi de probabilité qui décrive au mieux la distribution (=la loi) d'un output lorsqu'on observe un input donné. Cette loi pourra dépendre d'un certain paramètre $w$ qu'il faudra ensuite ajuster au mieux. | ||
***Vocabulaire:*** | ||
* input = variable explicative = descripteur = variable exogène | ||
* output = variable réponse = variable cible = variable endogène | ||
***Mathématiquement 1:*** On imagine une fonction $L(x,y,w)$ et l'on décrète que la proba d'observer $y_i$ en présence de $x_i$ est: | ||
$$ | ||
L( x_i , y_i , w ) \qquad \qquad \hbox{ pour un certain } w | ||
$$ | ||
En supposant les observations indépendantes, la proba d'observer simultanément $y[0],y[1],y[2]...$ est donc de | ||
$$ | ||
L(x[0],y[0],w) * L(x[1],y[1],w) * L(x[2],y[2],w) * ... = \prod_i L( x_i , y_i , w ) | ||
$$ | ||
Le meilleur $w$ possible, est naturellement celui qui rend le plus probable (=vraissemblable) nos données, à savoir: | ||
$$ | ||
\hat w = \hbox{argmax}_w \prod_i L( x_i , y_i , w ) | ||
$$ | ||
ce qu'on reformule souvent comme ceci: | ||
$$ | ||
\hat w = \hbox{argmin}_w - \sum_i \log L( x_i , y_i , w ) | ||
$$ | ||
Cette manière de choisir $w$ s'appelle: "la technique du maximum de vraissemblance". | ||
***Mathématiquement 2:*** L'explication précédente est simple, mais elle n'est rigoureuse que lorsque les données sont "discrètes" \[ex: $y_i$ est un nombre d'accident\]. Pour des variables continues \[ex: $y_i$ est le prix d'un appartement\], la probabilité d'observer exactement une donnée en particulier est nulle (en théorie). | ||
Reformulons notre méthodologie pour la rendre rigoureuse dans tous les cas: On imagine une fonction $L(x,y,w)$, et l'on décrète que les $y_i$ (petit y) sont des observations de v.a $Y_i$ (grand Y) dont la densité est: | ||
$$ | ||
y \to L(x_i,y,w) | ||
$$ | ||
Ainsi la densité jointe de $Y_0,Y_1,Y_2...$ c'est | ||
$$ | ||
\prod_i L( x_i , y_i , w ) | ||
$$ | ||
et le paramètre qui rend le plus vraissemblable l'ensemble de nos données est toujours: | ||
$$ | ||
\hat w =\hbox{argmax}_w \prod_i L( x_i , y_i , w ) | ||
$$ | ||
La seule différence c'est que la fonction $L$ peut dépasser 1. | ||
***A quoi ça sert?*** A deux choses: | ||
1/ À comprendre l'influence de l'input $x$ sur l'output $y$. Ex: on pourra en déduire que le prix d'un appartement est une fonction affine de la surface, qu'il dépend exponentiellement de la 'chicosité' du quartier, mais aussi que, plus le quartier est chic, et plus la variance des prix augmente, etc. | ||
2/ À prédire: supposons que l'on dispose d'un input $x'$ qui n'est pas dans nos données initiales; quel est l'output $y'$ qui lui correspondrait le mieux? ex: considérons un appartement $x'$=(surface: 33$m^2$, ensoleillement: sombre, quartier: très chic). Quelle est l'estimation de son prix?. Pour cela on peut prendre: | ||
* le $y'$ qui maximise la vraissemblance $y\to L(x',y,\hat w)$ | ||
* l'espérance de la v.a $Y$ dont la densité est $y\to L(x',y,\hat w)$ | ||
On choisi en général la seconde estimation (qui coincide parfois avec la première). | ||
%% Cell type:code id: tags: | ||
``` python | ||
""" maintenant on va coder. On importe les libraires utiles.""" | ||
import numpy as np | ||
import pandas as pd | ||
import statsmodels.api as sm | ||
from scipy import stats | ||
from matplotlib import pyplot as plt | ||
np.set_printoptions(linewidth=50000,suppress=True,precision=2) | ||
% matplotlib inline | ||
``` | ||
%% Cell type:markdown id: tags: | ||
# Comparaison de deux jeux de données | ||
Observez les points ci-dessous. | ||
* ressemblance: ils ont la même tendance : plus `x[i]` est grand, et plus `y[i]` est grand, et cette dépendance semble être linéaire. | ||
* dissemblance: sur le second, plus `x[i]` est grand, le plus la variabilité des `x[i]` est grande. De plus les `y[i]` sont tous positifs. | ||
On imagine bien qu'il ne faudra pas modéliser ces deux jeux de la même manière. | ||
%% Cell type:code id: tags: | ||
``` python | ||
x0=np.loadtxt("data/data0_x.csv") | ||
y0=np.loadtxt("data/data0_y.csv") | ||
x1=np.loadtxt("data/data1_x.csv") | ||
y1=np.loadtxt("data/data1_y.csv") | ||
plt.figure(figsize=(12,6)) | ||
plt.subplot(1,2,1) | ||
plt.plot(x0,y0,'.') | ||
plt.ylim([-20,100]) | ||
plt.subplot(1,2,2) | ||
plt.plot(x1,y1,'.') | ||
plt.ylim([-20,100]); | ||
``` | ||
%% Output | ||
%% Cell type:markdown id: tags: | ||
***Exo:*** En utilisant la technique des moindres carrés, calculer avec python la meilleur droite de régression pour ces deux jeux de données. Superposer cette droite avec les données. | ||
%% Cell type:markdown id: tags: | ||
# Le modèle linéaire Gaussien | ||
%% Cell type:markdown id: tags: | ||
Considérons le premier jeu de données. Il est bien modélisé par une formule du type | ||
y[i] = w0 + w1 x[i] + Bruit[i] | ||
Si on suppose en plus que `Bruit[i]` c'est des v.a gaussiennes centrées de variance σ² (qui ne dépend pas de `i`), alors notre modèle est : | ||
y[i] ~ Normale (esp = μ[i] , var = σ² ), μ[i] = w0 + w1 x[i] | ||
Remarque: Le second jeu de données serait mieux modélisé par des v.a de loi Gamma : elles sont positives, et leur variance augmente quand l'espérance augmente (quant le paramètre de forme est fixé). On verra cela plus tard. | ||
Maintenant estimons les paramètres `w0` (=le biais) et `w1` (=la pente de la tendance) en utilisant la librairie `statsmodel` qui utilise la technique du maximum de vraissemblance. | ||
%% Cell type:code id: tags: | ||
``` python | ||
def estimate_linear_drift(x, y,verbose=False): | ||
""" on étend les descripteurs `x` en ajoutant une colonne de '1' . Car dans le modèle | ||
mu[i]= w0*'1' + w1*x[i] """ | ||
x_ext=np.stack([ np.ones(len(x)) , x],axis=1) | ||
model = sm.GLM(endog=y, exog=x_ext, family=sm.families.Gaussian()) | ||
model_results = model.fit() | ||
w=model_results.params | ||
if verbose: print(model_results.summary()) | ||
return w | ||
print("estimation de w0 w1:",estimate_linear_drift(x0, y0)); | ||
``` | ||
%% Output | ||
estimation de w0 w1: [ 4.63 9.75] | ||
%% Cell type:code id: tags: | ||
``` python | ||
""" traçons cette tendance """ | ||
w=estimate_linear_drift(x0, y0) | ||
plt.plot(x0,y0,'.') | ||
xx=np.linspace(np.min(x0),np.max(x0),100) | ||
plt.plot(xx,w[0]+w[1]*xx); | ||
``` | ||
%% Output | ||
%% Cell type:markdown id: tags: | ||
***Exo:*** Calculez la vraissemblance $\prod_i L(x_i,y_i,w)$ dans le modèle gaussien. Ecrivez et simplifiez le problème de maximisation qui permet d'obtenir $\hat w$. Montrez qu'on retrouve la formule des moindres carrés. | ||
%% Cell type:markdown id: tags: | ||
Mais le fait d'avoir ajusté un modèle probabiliste sur les données nous permet de juger de la qualité de nos estiamtions. Observons le "summary" fourni par `statsmodel`: | ||
%% Cell type:code id: tags: | ||
``` python | ||
estimate_linear_drift(x0, y0,verbose=True); | ||
``` | ||
%% Output | ||
Generalized Linear Model Regression Results | ||
============================================================================== | ||
Dep. Variable: y No. Observations: 1000 | ||
Model: GLM Df Residuals: 998 | ||
Model Family: Gaussian Df Model: 1 | ||
Link Function: identity Scale: 90.9263687696 | ||
Method: IRLS Log-Likelihood: -3673.0 | ||
Date: Wed, 06 Jun 2018 Deviance: 90745. | ||
Time: 09:34:04 Pearson chi2: 9.07e+04 | ||
No. Iterations: 2 | ||
============================================================================== | ||
coef std err z P>|z| [0.025 0.975] | ||
------------------------------------------------------------------------------ | ||
const 4.6305 0.613 7.557 0.000 3.430 5.832 | ||
x1 9.7461 0.519 18.770 0.000 8.728 10.764 | ||
============================================================================== | ||
%% Cell type:markdown id: tags: | ||
Observons la ligne "const" ci dessus: | ||
* `coef` c'est $\hat w_0$: le terme constant de notre droite de regression, qui approxime le "vrai" $w_0$. On l'appel aussi "biais" ou "intercept". | ||
* `std err` c'est l'écartype estimé de l'estimateur $\hat w_0$. | ||
* `\[0.025 0.975\]` c'est l'intervalle de confiance à 95%. Le vrai paramètre $w_0$ appartient à cet intervalle avec une probabilité de 95%. | ||
* `P>|z|` c'est la p-value associé au test de nullité de $w_0$. Rappelons simplement la recette: | ||
1/ On choisit un niveau de test, disons $\alpha=5\%$. | ||
2/ Quand `p-value[j]`$<\alpha$, on choisi l'hypothèse H1 c.à.d qu'on décrète que `w[j]` est non-nul. | ||
3/ Quand `p-value[j]`$>\alpha$, on choisi l'hypothèse H0 c.à.d qu'on décrète que `w[j]` est nul, donc les input `x[:,j]` n'ont pas d'influence sur l'output. On a toujours intérêt à enlever des inputs inutiles car ils parasitent l'interprétation des résultats. | ||
%% Cell type:markdown id: tags: | ||
### Résidus | ||
Reprenons nos deux jeux de données. | ||
Les résidus ce sont les données `y[i]` moins l'estimation `mu[i]=b+w X[i]` (graphiquement :on soustrait aux points la droite de tendance). Quand le modèle linéaire gaussien est (approximativement) le bon, les résidus ont (approximativement) une distribution gaussienne. | ||
%% Cell type:code id: tags: | ||
``` python | ||
w0=estimate_linear_drift(x0, y0) | ||
w1=estimate_linear_drift(x1, y1) | ||
xx=np.linspace(np.min(x0),np.max(x0),100) | ||
plt.figure(figsize=(12,6)) | ||
plt.subplot(1,2,1) | ||
plt.plot(x0,y0,'.') | ||
plt.plot(xx,w0[0]+w0[1]*xx); | ||
plt.ylim([-20,100]) | ||
plt.subplot(1,2,2) | ||
plt.plot(x1,y1,'.') | ||
plt.plot(xx,w1[0]+w1[1]*xx); | ||
plt.ylim([-20,100]); | ||
``` | ||
%% Output | ||