Skip to content
Snippets Groups Projects
Commit 8c2e3d05 authored by Cyrille BERTELLE's avatar Cyrille BERTELLE
Browse files

Replace m2iwocs-apa-chap3-regression-polynomiale.ipynb

parent ce1706d6
Branches
No related merge requests found
%% Cell type:markdown id: tags:
# Chapitre 3 : Régression polynomiale,
## Over-fitting, under-fitting et régularisation
%% Cell type:markdown id: tags:
**Références** :
- [Le data scientist - régression polynomiale avec Python](https://ledatascientist.com/regression-polynomiale-avec-python/) : suite d'un cours sur le [régression linéaire](https://ledatascientist.com/creer-un-modele-de-regression-lineaire-avec-python/) ; utilse la bibliothèque Seaborn ; Utilise la bibliothèque sklearn ; programmes accessible via des notebooks.
- [Regression polynomiale avec scikit-learn](https://darques.eu/blog/index.php/2017/05/09/regression-polynomiale-avec-scikit-learn/)
- [Implémentaer une regression linéaire polynomiale avec scikit-learn et python3](https://moonbooks.org/Articles/Implementer-une-regression-lineaire-polynomiale-avec-scikit-learn-et-python-3/)
%% Cell type:code id: tags:
``` python
%matplotlib inline
```
%% Cell type:markdown id: tags:
### Modéliser des données par une régression polynomiale
%% Cell type:markdown id: tags:
Dans ce chapitre, on s'intéresse à un nouveau type de régression qui est la régression polynomiale.
Dans un premier temps, on décrit ce nouveau modèle qui va généraliser le modèle linéaire vu précédemment.
Ce modèle va soulever des questionnements qui sont d'importance pour la data science : l'over-fitting (sur-apprentissage) ou l'under-fitting (sous-apprentissage).
Pour analyser ces questions, on va introduire le compromis biais-variance qui permet d'introduire des mesures aidant à analyser ces phénomènes.
On présente enfin des techniques de régularisation qui permettent d'automatiser des mécanismes de contrôle pour gérer ces phénomènes liès à l'analyse des données et afin de produire des modèles pertinents.
Par ailleurs, après avoir introduit les outils mathématiques matriciels qui sont à la base des algorithmes de régression (minimisation de critères de moindres carrés, méthode de descente), on va maintenant s'intéresser à l'utilisation de fonctions déjà définies dans les bibliothèques Python dédiées au machine learning et notamment aux fonctions disponibles dans la bibliothèque Scikit-learn ou sklearn.
%% Cell type:markdown id: tags:
Jusqu'à présent, nous avons présenté des modèles de régression linéaire qui consiste à mettre en évidence des relations de linéarité entre des données : on cherche à retrouver des corrélations entre les variables des données démontrant qu'elles peuvent se positionner ou s'approcher d'une droite ou d'un plan, notamment lorsque l'on est respectivement en dimension 2 ou 3.
Si maintenant, nous disposons de données qui ne présentent pas cette propriété de linéarité, il faut alors trouver d'autres modèles ou hypothèses pour réussir à dégager des relations comme illustrées dans la figure suivante.
<img src="images/tds-regpol1.png" width="500"/>
<img src="tds-regpol1.png" width="500"/>
%% Cell type:markdown id: tags:
Le propos de ce chapitre consiste alors à généraliser le modèle linéaire ou l'hypothèse de linéarité par des modèles polynomiaux.
Nous représentons ci-dessous sur l'intervalle \[-3, 3\], 3 polynomes de degré respectif 1, 2 et 3 permettant ainsi de comprendre l'enrichissement apporté par l'usage de polynomes de divers degrés pour définir des hypothèses.
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-3.5,3.5,100)
y1 = -10-3*x
y2 = -10-3*x+x**2
y3 = -10-3*x+x**2+0.5*x**3
y4 = -10-3*x+x**2+0.5*x**3-0.2*x**4
fig = plt.figure(1, figsize=(10, 6))
plt.plot(x,y1, label="$p_1(x) = -10-3x$")
plt.plot(x,y2, label="$p_2(x) = -10-3x+x^2$")
plt.plot(x,y3, label="$p_3(x) = -10-3x+x^2+0.5x^3$")
plt.plot(x,y4, label="$p_4(x) = -10-3x+x^2+0.5x^3-0.2x^4$")
plt.legend()
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
Ainsi nous allons pouvoir formuler à partir d'un jeu de données (X,y) des hypothèses de la forme suivante :
- si X n'est composé que d'une seule variable explicative (régression univariée), l'hypothèse à base d'un polynome de degré $k$ s'écrit de la manière suivante :
$$
h(X) = \theta_0 + \Theta_1 X_1 + \Theta_2 X_1^2 + \Theta_3 X_1^3 + \dots = \theta_0 + \sum_{j=1}^k \theta_j X_1^j
$$
- si X est composé de plusieurs variables explicatives (régression multivariée), par exemple ici 2, l'hypothèse à base d'un polynome de degré $k$ s'écrit de la manière suivante :
$$
h(X) = \theta_0 + \sum_{j=1}^k \left( \theta_{1,j} X_1^j + \theta_{2,j} X_2^j \right)
$$
En pratique, les calculs (minimisation de critères de moindres carrés, méthode de descente, ...) s'opèrent de la même manière que dans le cas de la régression linéaire univariée ou multivariée (qui correspond au cas $k=1$). La généralisation des formules vues dans le cas linéaire est sans difficulté. Elles ne sont pas reprises ici et font l'objet d'un exercice de TP.
Dans les implémentations qui suivent, nous ne développons donc pas ces formules de calcul mais nous nous intéressons à l'usage de fonctions de calcul implémentées dans la bibliothèse `scikit-learn` ou `sklearn` spécialisée pour le maching learning.
%% Cell type:markdown id: tags:
### Mise en oeuvre avec `scikit-learn`
Pour comprendre l'intérêt d'une régression polynomiale, nous commençons par générer un jeu de données basée sur l'utilisation d'un polynome dans lequel on introduit du "bruit" aléatoire.
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(0)
x = 2 - 3 * np.random.normal(0, 1, 20)
y = x - 2 * (x ** 2) + 0.5 * (x ** 3) + np.random.normal(-3, 3, 20)
plt.scatter(x,y, s=10) # s pour size/taille des points
plt.show()
```
%% Output
%% Cell type:markdown id: tags:
Nous implémentons ci-dessous un calcul de régression linéaire sur le jeu de données précédent, en utilisant la bibliothèque *scikit-learn* appelée `sklearn`.
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
np.random.seed(0)
x = 2 - 3 * np.random.normal(0, 1, 20)
y = x - 2 * (x ** 2) + 0.5 * (x ** 3) + np.random.normal(-3, 3, 20)
print("x.shape : ",x.shape) # sert à comprendre la transformation à effectuer
# transformation des vecteurs 1D de format (n,) en une matrice 2D de n lignes et 1 colonne, de format (n,1)
x = x[:, np.newaxis]
y = y[:, np.newaxis]
print("x.shape : ",x.shape) # sert à comprendre la transformation effectuée
model = LinearRegression()
model.fit(x, y)
y_pred = model.predict(x)
plt.scatter(x, y, s=10)
plt.plot(x, y_pred, color='r')
plt.show()
rmse = np.sqrt(mean_squared_error(y,y_pred))
r2 = r2_score(y,y_pred)
print("rmse =", rmse, ", r2 =", r2)
```
%% Output
x.shape : (20,)
x.shape : (20, 1)
rmse = 15.908242501429998 , r2 = 0.6386750054827146
%% Cell type:markdown id: tags:
Le programme se termine par le calcul de 2 indicateurs :
- `rmse` - Root of Mean Squared Error - correspond la distance entre les valeurs prédites, $\{h(x_i), 0 \leq i \leq n\}$ et les valeurs des données $\{y_i, 0 \leq i \leq n\}$, c'est à dire
$$
\sqrt{\frac{1}{n}\sum_{i=1}^{n}(h(x_i)-y_i)^2}
$$
Cet indicateur mesure ainsi la proximité de la courbe de régression (de l'hypothèse) avec les données. Sa valeur numérique dépend de l'ordre de grandeur des données. Il permet donc de comparer deux ou plusieurs hypothèses.
- `r2` ou `r2_score`, appelé *coefficient de détermination* va permettre d'évaluer la qualité de la prédiction :
$$
1-\frac{\sum_{i=1}^n (h(x_i)-y_i)^2}{\sum_{i=1}^n (\overline{y}-y_i)^2}
$$
avec $\overline{y} = \frac{1}{n}\sum_{i=1}^n y_i$.
Sa valeur numérique est comprise entre 0 et 1. Si il vaut 1, la régression est parfaite par rapport au jeu de données. Si il vaut 0, la régression n'est pas du tout pertinente pour le jeu de données.
%% Cell type:markdown id: tags:
Nous allons maintenant passer à une hypothèse basée sur une régression basée sur un polynome d'ordre k :
$$
h(x) = \theta_0 + \sum_{j=1}^k \theta_j x^j
$$
Cette expression reste linéaire par rapport aux coefficients à calculer, $\theta_j$.
La manière de traiter le problème avec la bibliothèque `sklearn`est la suivante.
Pour simplifier l'explication, nous allons nous placer dans le cas d'un jeu de données de la forme $(x_i, y_i)$ avec la recherche d'un modèle/hypothèse univarié de regression polynomiale de degré 3 :
$$
h(x) = \theta_0 + \theta_1 x + \theta_2 x^2 + \theta_3 x^3
$$
On commence par déclarer le degré du modèle :
`poly = PolynomialFeatures(degree=3)`
Ensuite on transforme ou réécrit le modèle précédent sous la forme linéaire suivante :
$$
h(t,u,v,w) = \theta_0 t + \theta_1 u + \theta_2 v + \theta_3 w
$$
avec $t=1$, $u=x$, $v=x^2$ et $w=x^3$
On a alors transformé un modèle polynomial de degré 3, à 1 variable explicative $(x)$ en un modèle linéaire à 4 variables explicatives $(t,u,v,w)$.
La fonction
`x_poly = poly.fit_transform(x)`
construit une matrice de données telle que la ligne i correspond à $(t_i, u_i, v_i, w_i)$, c'est à dire
$(1, x_i, x_i^2, x_i^3)$.
Il ne reste plus qu'à appeler un calcul de régression linéaire dans ce nouvel espace de données, comme cela a été fait dans le script qui précède.
%% Cell type:code id: tags:
``` python
import operator
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import PolynomialFeatures
np.random.seed(0)
x = 2 - 3 * np.random.normal(0, 1, 20)
x.sort()
y = x - 2 * (x ** 2) + 0.5 * (x ** 3) + np.random.normal(-3, 3, 20)
# transformation des vecteurs 1D en matrice à 1 colonne
x = x[:, np.newaxis]
y = y[:, np.newaxis]
print("x =\n",x)
#version interactive du choix du polynome
print("Donner le degré de régression polynomiale souhaité : ")
ndegre=int(input())
polynomial_features= PolynomialFeatures(degree=ndegre)
x_poly = polynomial_features.fit_transform(x)
print("x_poly =\n",x_poly)
model = LinearRegression()
model.fit(x_poly, y)
y_poly_pred = model.predict(x_poly)
rmse = np.sqrt(mean_squared_error(y,y_poly_pred))
r2 = r2_score(y,y_poly_pred)
print("rmse =", rmse, ", r2 =", r2)
plt.scatter(x, y, s=10)
plt.plot(x, y_poly_pred, color='r')
plt.show()
```
%% Output
x =
[[-4.7226796 ]
[-3.60267397]
[-3.29215704]
[-2.48223722]
[-2.36282052]
[-0.93621395]
[-0.85026525]
[-0.28311318]
[ 0.6684103 ]
[ 0.76820449]
[ 0.79952837]
[ 0.99897702]
[ 1.0607969 ]
[ 1.56786929]
[ 1.63497495]
[ 2.30965656]
[ 2.45407162]
[ 2.61547479]
[ 4.56228722]
[ 4.93183364]]
Donner le degré de régression polynomiale souhaité :
10
x_poly =
[[ 1.00000000e+00 -4.72267960e+00 2.23037026e+01 -1.05333241e+02
4.97455149e+02 -2.34932128e+03 1.10950917e+04 -5.23985631e+04
2.47461625e+05 -1.16868197e+06 5.51931049e+06]
[ 1.00000000e+00 -3.60267397e+00 1.29792597e+01 -4.67600412e+01
1.68461183e+02 -6.06910720e+02 2.18650145e+03 -7.87725188e+03
2.83791703e+04 -1.02240898e+05 3.68340622e+05]
[ 1.00000000e+00 -3.29215704e+00 1.08382980e+01 -3.56813789e+01
1.17468703e+02 -3.86725416e+02 1.27316080e+03 -4.19144529e+03
1.37988961e+04 -4.54281330e+04 1.49556548e+05]
[ 1.00000000e+00 -2.48223722e+00 6.16150161e+00 -1.52943086e+01
3.79641021e+01 -9.42359073e+01 2.33915877e+02 -5.80634695e+02
1.44127305e+03 -3.57758161e+03 8.88040623e+03]
[ 1.00000000e+00 -2.36282052e+00 5.58292081e+00 -1.31914399e+01
3.11690048e+01 -7.36467642e+01 1.74014086e+02 -4.11164053e+02
9.71506861e+02 -2.29549635e+03 5.42384588e+03]
[ 1.00000000e+00 -9.36213952e-01 8.76496565e-01 -8.20588313e-01
7.68246228e-01 -7.19242837e-01 6.73365179e-01 -6.30413876e-01
5.90202266e-01 -5.52555596e-01 5.17310259e-01]
[ 1.00000000e+00 -8.50265253e-01 7.22951000e-01 -6.14700114e-01
5.22658148e-01 -4.44398062e-01 3.77856231e-01 -3.21278023e-01
2.73171540e-01 -2.32268268e-01 1.97489638e-01]
[ 1.00000000e+00 -2.83113175e-01 8.01530701e-02 -2.26923902e-02
6.42451465e-03 -1.81886474e-03 5.14944573e-04 -1.45787593e-04
4.12743885e-05 -1.16853232e-05 3.30826895e-06]
[ 1.00000000e+00 6.68410302e-01 4.46772332e-01 2.98627229e-01
1.99605516e-01 1.33418383e-01 8.91782219e-02 5.96076422e-02
3.98423621e-02 2.66310453e-02 1.78004650e-02]
[ 1.00000000e+00 7.68204494e-01 5.90138145e-01 4.53346775e-01
3.48263030e-01 2.67537225e-01 2.05523298e-01 1.57883922e-01
1.21287138e-01 9.31733246e-02 7.15761667e-02]
[ 1.00000000e+00 7.99528375e-01 6.39245622e-01 5.11095014e-01
4.08634966e-01 3.26715250e-01 2.61218113e-01 2.08851293e-01
1.66982535e-01 1.33507275e-01 1.06742855e-01]
[ 1.00000000e+00 9.98977018e-01 9.97955082e-01 9.96934192e-01
9.95914346e-01 9.94895544e-01 9.93877783e-01 9.92861064e-01
9.91845385e-01 9.90830745e-01 9.89817143e-01]
[ 1.00000000e+00 1.06079690e+00 1.12529005e+00 1.19370419e+00
1.26627770e+00 1.34326345e+00 1.42492970e+00 1.51156100e+00
1.60345922e+00 1.70094456e+00 1.80435671e+00]
[ 1.00000000e+00 1.56786929e+00 2.45821410e+00 3.85415839e+00
6.04281656e+00 9.47434649e+00 1.48545369e+01 2.32899721e+01
3.65156320e+01 5.72517378e+01 8.97632414e+01]
[ 1.00000000e+00 1.63497495e+00 2.67314309e+00 4.37052199e+00
7.14569397e+00 1.16830307e+01 1.91014625e+01 3.12304126e+01
5.10609424e+01 8.34833617e+01 1.36493205e+02]
[ 1.00000000e+00 2.30965656e+00 5.33451340e+00 1.23208939e+01
2.84570333e+01 6.57259734e+01 1.51804425e+02 3.50616086e+02
8.09802742e+02 1.87036621e+03 4.31990358e+03]
[ 1.00000000e+00 2.45407162e+00 6.02246754e+00 1.47795667e+01
3.62701153e+01 8.90094607e+01 2.18435592e+02 5.36056588e+02
1.31552126e+03 3.22838340e+03 7.92268410e+03]
[ 1.00000000e+00 2.61547479e+00 6.84070838e+00 1.78917003e+01
4.67952912e+01 1.22391904e+02 3.20112941e+02 8.37247327e+02
2.18979928e+03 5.72736481e+03 1.49797783e+04]
[ 1.00000000e+00 4.56228722e+00 2.08144647e+01 9.49615661e+01
4.33241939e+02 1.97657416e+03 9.01769903e+03 4.11413330e+04
1.87698578e+05 8.56334822e+05 3.90684541e+06]
[ 1.00000000e+00 4.93183364e+00 2.43229830e+01 1.19956906e+02
5.91607504e+02 2.91770979e+03 1.43896593e+04 7.09674058e+04
3.49999439e+05 1.72613901e+06 8.51303043e+06]]
rmse = 2.1731828361864 , r2 = 0.993678187628542
%% Cell type:code id: tags:
``` python
import operator
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import PolynomialFeatures
np.random.seed(0)
x = 2 - 3 * np.random.normal(0, 1, 20)
x.sort()
y = x - 2 * (x ** 2) + 0.5 * (x ** 3) + np.random.normal(-3, 3, 20)
# transformation des vecteurs 1D en matrice à 1 colonne
x = x[:, np.newaxis]
y = y[:, np.newaxis]
fig = plt.figure(1, figsize=(14, 8))
plt.scatter(x, y, s=10)
for ndegre in [1,2,3,20]:
polynomial_features= PolynomialFeatures(degree=ndegre)
x_poly = polynomial_features.fit_transform(x)
model = LinearRegression()
model.fit(x_poly, y)
y_poly_pred = model.predict(x_poly)
#rmse = np.sqrt(mean_squared_error(y,y_poly_pred))
#r2 = r2_score(y,y_poly_pred)
#print("rmse =", rmse, ", r2 =", r2)
plt.plot(x, y_poly_pred, label="degre "+str(ndegre))
plt.legend()
plt.show()
```
%% Output
%% Cell type:code id: tags:
``` python
import operator
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import PolynomialFeatures
np.random.seed(0)
x = 2 - 3 * np.random.normal(0, 1, 20)
x.sort()
y = x - 2 * (x ** 2) + 0.5 * (x ** 3) + np.random.normal(-3, 3, 20)
# transformation des vecteurs 1D en matrice à 1 colonne
x = x[:, np.newaxis]
y = y[:, np.newaxis]
fig, g = plt.subplots(6, figsize=(8, 24))
ig = 0
for ndegre in [1,2,3,6,10,20]:
g[ig].scatter(x,y,s=10)
polynomial_features= PolynomialFeatures(degree=ndegre)
x_poly = polynomial_features.fit_transform(x)
model = LinearRegression()
model.fit(x_poly, y)
y_poly_pred = model.predict(x_poly)
rmse = np.sqrt(mean_squared_error(y,y_poly_pred))
r2 = r2_score(y,y_poly_pred)
g[ig].plot(x, y_poly_pred, c='r', label="degre "+str(ndegre)+"\n rmse ="+str(rmse)+"\n r2 ="+str(r2))
g[ig].legend()
ig = ig+1
#plt.show()
```
%% Output
%% Cell type:markdown id: tags:
La régression polynomiale de degré 20 fait apparaître des irrégularités qui correspondent au "bruit" qui est présent dans les données (ici dans la génération des données). On parle alors de phénomène de sur-apprentissage (over-fitting). La courbe s'approche de près des données présentes mais si on ajoutait des données intermédiaires, la courbe du polynome de degré 20 pourrait en être assez distant.
A l'opposé, la régression de degré 1 passe assez loin des données car la complexité du modèle (hypothèse) est trop faible. On parle alors de sous-apprentissage (under-fitting).
Ces deux situations de sous-apprentissage et de sur-apprentissage ne sont pas caractéristiques du problème de régresssion polynomiale mais peut se rencontrer dans bon nombre d'autres types de modèles/hypothèses.
Le phénomène de sur-apprentissage est un problème difficile en science des données, puisqu'il faudrait savoir identifier ou mesurer le bruit présent dans les données. La question est donc de savoir choisir une complexité de modèle pertinente, ici le degré "optimal" de régression polynomiale. La notion de **compromis biais-variance** vise à apporter des méthodes d'analyse pour identifier ce degré optimal ou plus généralement les modèles/hypothèses optimaux.
%% Cell type:markdown id: tags:
### Le compromis biais-variance
**Le biais** correspond à l'écart entre les données et le modèle. Si sa valeur est élevée, cela signifie que l'on est dans la situation de sous-apprentissage. les valeurs de `rmse`ou de `r2` peuvent permettre de mesurer le biais.
**La variance** correspond à l'erreur de généralisation ou de prévision du modèle. Il mesure le phénomène de sur-apprentissage du à l'usage d'un modèle "trop" complexe et qui prédit mal les valeurs en dehors des données ou encore qui est très sensible à des petites modifications apportées sur les données. On dira que le modèle n'est pas stable.
On illustre ces valeurs du biais et de la variance sur les calcul de régression polynomiale précédents :
![biais-variance](images/tds-regpol4.png)
On peut décrire les tendances d'évolution des valeurs des erreurs de biais (courbe décroissante) et des erreurs de variance (courbe croissante) en fonction de la complexité du modèle comme cela est représenté sur la figure suivante. Un modèle / une hypothèse sera dit optimal lorsque l'on minimise la somme de ces deux erreurs (voir sur la figure). On parle du meilleur compromis biais-variance.
**Attention** : l'erreur totale mentionnée dans ce graphique, ne correspond pas à l'erreur "classique" qui consiste à évaluer la distance entre les jeux de données et les valeurs du modèle / de l'hypothèse. Cette erreur "classique" s'évalue génaralement en utilsant l'erreur de moindre carrée telle que calculé précédemment avec le coefficient `rmse`. On a vu sur les calculs précédents que ce calcul d'erreur ne permet pas d'évaluer le sur-apprentissage. On va alors définir un nouveau calcul d'erreur appelé *erreur de prédiction attendue* ou *erreur attendue* [3]. C'est cette erreur de prédiction attendue qui est appelée erreur totale sur le graphique ci-dessous. On en donne sa dévinition dans la section relative au compromis biais-variance.
![optimal](images/tds-regpol5.png)
**Définition mathématique**
Soit un jeu de données $\{(x_i, y_i); 1 \leq i \leq n\}$, on recherche un modèle/hypothèse $h(x)$ tel que tous les $h(x_i)$ s'approchent "au mieux" des $y_i$. Les données $(x_i)$ sont les données d'entrée du modèle (chaque $x_i$ peut être une valeur simple (problème univarié) ou un vecteur de plusieurs valeurs (problème multivarié)) et les données $(y_i)$ sont les données cibles.
La définition mathématique du biais et de la variance d'après [1,2,3], s'obtient en partant de l'hypothèse "abstraite" : il existe une fonction $f(x)$ permettant de définir une relation fonctionnelle bruitée : $y_i = f(x_i) + \epsilon_i$, où $\epsilon_i$ est un bruit dont la moyenne, $\mu(\epsilon)$ est nulle et la variance est notée $\sigma^2$.
*Rappels* des définitions de la moyenne et de la variance :
- la moyenne sa calcule ainsi
$$\mu(\epsilon) = \frac{1}{n} \sum_{i=1}^{n} \epsilon_i$$
$$
\mu(\epsilon) = \frac{1}{n} \sum_{i=1}^{n} \epsilon_i
$$
- la variance notée $V(x)$ ou $\sigma^2$, est la moyenne des carrés des écarts à la moyenne
$$\sigma^2 = V(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu(x))^2$$
$$
\sigma^2 = V(x) = \frac{1}{n}\sum_{i=1}^{n}(x_i - \mu(x))^2
$$
On peut montrer que
$$\sigma^2 = V(x) = \left( \frac{1}{n}\sum_{i=1}^n x_i^2 \right) - \mu(x)^2 = \mu(x^2) - \mu(x)^2$$
- $\sigma$ est appelé l'écart-type, c'est donc la racine carrée de la variance, $\sigma = \sqrt{V(x)}$. Il permet de mesurer la dispersion des valeurs $x_i$ autour de la moyenne $\mu(x)$.
$$
\sigma^2 = V(x) = \left( \frac{1}{n}\sum_{i=1}^n x_i^2 \right) - \mu(x)^2 = \mu(x^2) - \mu(x)^2
$$
- $\sigma$ est appelé l'écart-type, c'est donc la racine carrée de la variance, $\sigma = \sqrt{V(x)}$. Il permet de mesurer la dispersion des valeurs $x_i$ autour de la moyenne $\mu(x)$.
A partir du jeu de données $\{(x_i, y_i); 1 \leq i \leq n\}$, on va construire un ensemble $S$ de $m$ échantillons, que l'on appelle aussi échantillons d'apprentissage, et qui correspondent à des extractions de ce jeu de données de taille inférieure à $n$. Pour chaque échantillon de données, on note $x^p$, l'échantillon $p$ des données d'entrée (attention à la notation, ce n'est pas une élévation à la puissance mais un indice supérieur), on calcule l'hypothèse $h_{x^p}(x))$. Il faut comprendre ici que pour les modèles de regression polynomiale, l'hypothèse est indépendante de l'échantillon : il s'agit notamment de choisir le degré du polynome. Par contre le calcul des coefficients du polynome pour le degré choisit, va dépendre du jeu de données.
A partir de cette échantillonage $S$, on va calculer des *espérances mathématiques* de fonctions, relatives à un nouvel échantillon que l'on va considérer ici comme étant l'ensemble complet des données, c'est à dire $x$ pour les données d'entrée.
Par exemple, $E_S[h(x)]$ correspond à l'espérance mathématique des fonctions hypothèses relatives aux échantillons de $S$.
Une espérance mathématique est un calcul de moyenne pondérée ou la pondération est une probabilité affectée à chaque terme de la moyenne ; la somme des probalités étant égale à 1. Ici, si l'on considère que chaque échantillon a la même importance (ou même probabilité d'apparaître ou d'exister), l'espérance sera calculée comme une moyenne simple.
On calcule déjà une fonction $G(t)$ par
$$
G(t) = \frac{1}{m}\sum_{x_p \in S} h_{x_p}(t)
$$
où l'on rappelle que $m$ est le nombre d'échantillons $x_p$ dans $S$.
Puis l'espérance de l'hypothèse $h$ pour le jeu de données dont les valeurs d'entrée sont $x = {x_i, 1 \leq i \leq n}$
$$
E_S[h(x)] = \frac{1}{n}\sum_{i=1}^{n} G(x_i)
$$
Une fois effectués ces rappels et ces notations (parfois imprécises dans la littérature), on va donner des expressions du biais et de la variance
- le biais se calcule par $$B(h(x))= E[(h-f)(x)]$$,
- la variance se calcule par $$Var(h(x))=E[h^2(x)]-(E[h(x)])^2$$
- le biais se calcule par
$$
B(h(x))= E[(h-f)(x)]
$$
- la variance se calcule par
$$
Var(h(x))=E[h^2(x)]-(E[h(x)])^2
$$
On définit ensuite l'*erreur de prédiction attendue* par
$$
Err(h(x)) = B^2(h(x)) + Var(h(x)) + \sigma^2
$$
On rappelle que l'on a fait l'hypothèse qu'il existait une fonction $f(x)$ telle que $y_i = f(x_i) + \epsilon_i$, où $\epsilon_i$ est un bruit dont la variance est notée $\sigma^2$.
$f(x)$ n'étant pas une fonction connue, on ne pourra pas calculer directement le biais qui mesure l'écart entre l'hypothèse et les données au sens "classique". Par contre, il est assez bien estimé par les indicateurs que nous avons utilisés lors des tracés des régression polynomiale, à savoir `rmse`et `r2`. Il faut simplement se rappeler que l'hypothèse de l'existance de $f$ signifie qu'il y a un bruit et que ces indicateurs ne visent donc pas à être trop petits si le bruit est important.
$f(x)$ n'étant pas une fonction connue, on ne pourra pas calculer directement le biais qui mesure l'écart entre l'hypothèse et les données au sens "classique". Par contre, il est assez bien estimé par les indicateurs que nous avons utilisés lors des tracés des régression polynomiale, à savoir `rmse`et `r2`. Il faut simplement se rappeler que l'hypothèse de l'existance de $f$ signifie qu'il y a un bruit et que ces indicateurs ne visent donc pas à être trop petits si le bruit est important.
La Variance peut par contre être évaluée, à condition de mettre en place un échantillonage $S$. Elle mesure la dispersion des fonctions hypothèses liées à un échantillon à la moyenne de ces fonctions hypothèses pour tous les échantillons. En cas de sur-apprentissage, cette dispersion peut être grande comme cela a été expliqué dans les exemples précédents.
En conclusion de cette section sur le compromis biais-variance, on constate que la difficulté est de déterminer la fonction $f(x)$ et en conséquence d'évaluer le bruit $\epsilon_i$ contenu dans les données. Une discussion intéressante à ce sujet fait l'objet du dernier paragraphe de l'entrée relative au dilemme biais-variance sur wikipedia [1] et la référence aux propos de Gerd Gigerenzer et ses co-auteurs [4] qui sortent largement des objectifs de ce cours d'apprentissage.
**Référence sur le compromis biais-variance**
1. [Dilemme biais-variance : article de Wikipedia](https://fr.wikipedia.org/wiki/Dilemme_biais-variance)
2. Scott Fortmann-Roe. "Understanding the Bias-Variance Tradeoff", [blog en ligne](http://scott.fortmann-roe.com/docs/BiasVariance.html), 2012
3. T. Hasyie, R. Tibshirani, J. Friedman. "The Elements of Statistical Learning", Springer, 2017 (2nd edition)
4. G. Gigerenzer, H. Brighton (2009) "Homo Heuristicus: Why biased Minds make Better Inferences", Topics in Cognitive Science 1, 107-143. Accessible en ligne [ici](https://pure.mpg.de/rest/items/item_2099728/component/file_2563980/content)
%% Cell type:markdown id: tags:
### Techniques de régularisation
Dans les méthodes de régression qui ont été présentées, la fonction de coût $J(\Theta)$ sert à ajuster les paramètres de la fonction modèle ou hypothèse pour qu'elle s'approche au mieux des données.
Avec la régression polynomiale, il a été constaté que des problème de sur-apprentissagepouvaient apparaître et que si cette fonction de coût était bien minimisée, le modèle pouvait avoir un comportement "instable", c'est à dire être très sensible à des modifications mineures des données. Ainsi de petites modifications sur ces données peut générer des nouveaux modèles très différents et présentant surtout des oscillations (observation typiques du sur-apprentissage en régression polynomiale).
Pour pallier à ce problème, l'idée est de contraindre l'espace de recherche des paramètres $\theta$ et pour cela, il faut donc modifier leur recherche (qui consiste à minimiser la fonction coût), c'est à dire modifier la fonction coût : $J(\theta)$.
On parle alors de rétressissement de l'espace de recherche d'où le terme de méthodes de $shrinkage* en anglais.
Pratiquement, on va donc modifier la focntion coût en ajoutant une *fonction de pénalité* $P(\lambda,\theta)$ qui dépend de $\theta$ et d'un paramètre $\lambda$ que l'on va ajuster afin produire l'effet de régularisation souhaitée :
$$
J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}\left(h_\theta(x_i)-y_i\right)^2+P(\lambda,\theta)
$$
En reprenant les notations utilisées jusqu'alors, à savoir que $\{(x_i, y_i); 1 \leq i \leq m\}$ correspond aux données et que le modèle ou fonction hypothèse possède $n+1$ paramètres, ${(\theta_j; 0 \leq j \leq n}$.
Plusieurs techniques de régularisation ont été proposées et nous en présentons quelques unes ici. Pour plus de détails, on pourra consulter le livre de Biernat et Lutz [1].
**Régression ridge**
La fonction de pénalisation se base sur l'utilisation de la norme $L_2$ du vecteur $\theta$. Appelée aussi norme euclidienne, elle correspond aux métriques et notamment aux distances usuelles en géométrie. Par exemple, un cercle de rayon $r$, centré sur l'origine correspond à tous les points de coordonnées $(x,y)$ dont la norme $L_2$ vaut $r$. C'est aussi la norme utilisée dans le critère des moindres carrées. La fonction de pénalisation s'écrit :
$$
P_r(\lambda, \theta) = \lambda \sum_{j=0}^{n}\theta_j^2
$$
et donc la fonction coût "pénalisée" s'écrit
$$
J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}\left(h_\theta(x_i)-y_i\right)^2+\lambda \sum_{j=0}^{n}\theta_j^2
$$
**Régression lasso**
La fonction de pénalisation lasso (Least Absolute Shrinkage and Selection Operator) est identique mais se base sur la norme $L_1$ :
$$
P_l(\lambda, \theta) = \lambda \sum_{j=0}^{n} \lvert \theta_j \rvert
$$
**Régression ElasticNet**
La fonction de pénalisation est une composition des deux précédentes, en ajoutant un nouveau paramètre $\alpha$ mesurant l'importance donnée à l'une des deux fonctions de pénalisation précédente par rapport à l'autre.
$$
P_e(\lambda, \theta) = \lambda \sum_{j=0}^{n} \left( \alpha \theta_j^2 + (1-\alpha) \lvert \theta_j \rvert \right)
$$
L'impact des techniques de régularisation avec ces fonctions de pénalisation sera étudié dans les TP.
**Références sur les techniques de régularisation**
1. E. Biernat et M. Lutz (2015) "Data science : fondamentaux et études de cas: Machine learning avec Python et R", Editions Eyrolles
2. [Blog de Xavier Dupré, Régression Ridge, Lasso et nouvel estimateur](http://www.xavierdupre.fr/app/papierstat/helpsphinx/notebooks/2020-02-07_sklapi.html)
%% Cell type:code id: tags:
``` python
```
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment