TP Régression probabiliste

Tutoriel

Créer un jeu de données

On a chaque fois, on va récupérer les données $X$ (double tableau de tailles nombre de données $n$, taille des données $d$), les sorties $Y$ ((double tableau de tailles nombre de données $n$, taille des sorties $m$) et le tableau qui contient les solutions $(\omega,b)$.

from sklearn.datasets import make_regression

X, y, coef = datasets.make_regression(
    n_samples=100, ## n
    n_features=10, ## d
    n_informative=8, ## nombres de features non nulles
    noise=0.1, ## ecart type du bruit gaussien
    n_targets=2, ## m
    bias=1.0, ## valeur du biais $b$
    coef=True, ## On renvoit les coefs
)

ou

X, y= datasets.make_regression(
    n_samples=100, ## n
    n_features=10, ## d
    n_informative=8, ## nombres de features non nulles
    noise=0.1, ## ecart type du bruit gaussien
    n_targets=2, ## m
    bias=1.0, ## valeur du biais $b$
    coef=False, ## On renvoit pas les coefs
)

Séparer en jeux de données test et train:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
...     X, y, test_size=0.33, random_state=42) ## Vous pouvez changer la taille du jeux de données test: test_size

On coupe $X$ en $X_{test}$ et $X_{train}$, pareil pour le $y$. On donne le pourcentage de données dans le jeu test.

Jeux de données classification:

from sklearn import datasets
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target

data_bc = datasets.load_breast_cancer()
X, y = data_bc.data, data_bc.target

il y a aussi "iris (classification), digits (classification), wive (classification)".

Régression

Régression:

Soit $X, Y$ les jeux de données. $X$ est l'observable et $Y$ les labels.

from sklearn.linear_model import BayesianRidge,  Ridge

clf2 = Ridge(alpha=0.1,fit_intercept=True,tol=1e-3) ## coef de régularisation, est ce qu'on cherche un biais, tolérance et oblige ton la positivité des poids

clf2.fit(X, y)
print(cfl.coef_) ## renvoit les coefficients $\omega$,
print(cfl.intercept_) ## renvoit le coefficient $b$,

y_pred=cfl.predict(X_test) ## renvoit le résultat y du modèle pour $X_{test}$ en entrée.

Cas général (Sk-learn):

$$ P(y\mid X,\theta)= \mathcal{N}( (\omega,X)+b, \alpha) $$

avec $\theta=(\omega,b)$ les paramètres du modèle et $\alpha$ un a priori. Sur les poids on se donne un a priori Gaussien:

$$ P(\theta\mid \lambda)=\mathcal{N}( 0, \frac{1}{\lambda}) $$

On va donc construire:

$$ P(\theta \mid X_1,...X_n, y_1, ... y_n) $$

On a $\color{red}{\text{deux paramètres libres $\alpha$ et $\lambda$}}$. Ils sont eux mêmes calculés en maximisant la vraisemblance.

Dans Sk-learn $\lambda$ et $\alpha$ suivent des lois gamma, cela dépend de 4 paramètres $\lambda_1$, $\lambda_2$, $\alpha_1$ et $\alpha_2$ que l'ont prend souvent à $10^{-6}$. Les changer:

$$ \alpha = \mathcal{\Gamma}(\alpha_1,\alpha_2), \quad \lambda = \mathcal{\Gamma}(\lambda_1,\lambda_2) $$

Regression:

Soit $X, Y$ les jeux de données. $X$ est l'observable et $Y$ les labels.

from sklearn.linear_model import BayesianRidge,  Ridge

clf = BayesianRidge(alpha_1=1e-6,alpha_2=1e-6,lambda_1=1e-6,lambda_2=1e-6,fit_intercept=True)
clf.fit(X, y)
print(cfl.coef_) ## renvoit les coefficients $\omega$,
print(cfl.intercept_) ## renvoit le coefficient $b$,
print(cfl.alpha_) ## renvoit l'hyper-paramètre $\alpha$,
print(cfl.lambda_) ## renvoit l'hyper-paramètre $\lambda$,

ymean =cfl.predict(X_test) ## renvoit le résultat y du modèle pour $X_{test}$ en entrée. ### ou 
ymean, ystd =cfl.predict(X_test,return_std=True)

Validation régression

On mesure l'erreur de prédiction:

from sklearn.metrics import mean_squared_error

error= mean_squared_error(y_pred,y) ## error= mean_squared_error(y_mean,y)
print("erreur du jeux de données test:",error)## il faut remplacer le y par celui que vous comparer à vos prediction. Par exemple : le test

cfl.score(X_test,y_test) ## calcul un score indiquant la performance du model.

Régression logistique

Utiliser la régression logisitique:

from sklearn.linear_model import LogisticRegression
log=LogisticRegression(penalty='l2', tol=0.0001, C=1.0, fit_intercept=True, class_weight=None, max_iter=100, multi_class='auto', verbose=0)
  • "panlty": quelle type de régularisation,
  • "tol": a quel niveau d'erreur s'arrête la méthode,
  • "C": inverse du paramètre de régularisation,
  • "fit_intercept": biais ou pas,
  • "class_weight": poids entre les classes ou pas,
  • "max_iter": quand arrêter l'algorithme,
  • "multi_class": quel algo pour gérer le cas avec plus de deux classes.

Fonctions pour la régression logistique:

log.fit(X, y)
log.predict(X_test) ## renvoit les classes des données test
log.predict_proba(X_test) ## renvoit les probabilités d'être dans chaque classe des données test

Données:

print(cfl.coef_) ## renvoit les coefficients $\omega$,
print(cfl.intercept_) ## renvoit le coefficient $b$,
print(cfl.classes_) ## renvoit les numéros des classes,

Plot régression:

clf = LogisticRegression(multi_class="auto").fit(X, y)

# On cree un maillage
h = 0.02 
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

# On affiche la frontière de décision en variant les couleurs
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) ## points du maillage on prédit leurs classes
Z = Z.reshape(xx.shape)
plt.figure()
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.title("Decision surface of LogisticRegression (%s)" % multi_class)
plt.axis("tight")

# On affiche les points d'entrainement.
colors = "bry"
for i, color in zip(clf.classes_, colors):
    idx = np.where(y == i)
     plt.scatter(
        X[idx, 0], X[idx, 1], c=color, cmap=plt.cm.Paired, edgecolor="black", s=20
    )

plt.show()

Processus gaussien

from sklearn.gaussian_process import GaussianProcessRegressor
gp=GaussianProcessRegressor(kernel=None, alpha=1e-10)
  • "kernel": choix du noyau utilisé
  • "alpha": coefficient de régularisation

Comment on définit un noyau:

from sklearn.gaussian_process.kernels import DotProduct, WhiteKernel, RBF, Matern, RationalQuadratic, ExpSineSquared

kernel= RBF() ## un RBF de base
kernel= RBF()* WhiteKernel() + Matern() ## on peut les sommer et les multiplier
kernel= WhiteKernel(1.0,0.01) ## en modifiant leurs paramètres

Les noyaux:

  • WhiteKernel$(\alpha,\beta)$ $$ k(x,y)= \alpha \mbox{ si } x==y \mbox{ sinon }\beta $$

  • RBF$(\alpha)$ $$ k(x,y)=exp^{-\frac{d(x,y)^2}{2\alpha}} $$ etc

Voir SK-learn

Fonctions Processus gaussien:

gp.fit(X, y)
gp.predict(X_test) ## renvoit la valeur (moyenne) de $y$ pour l'entrée $X_test$
gp.sample_y(X_test) ## renvoit une valeur possible de $y$ 
gp.get_params() ## donne les paramètres du modèle

TP

Regression lineaire bayesienne

On regarde le problème:

$$ y= \sum_{i}^d w_i x_i +b $$

avec $w_i$ généré par une loi $\mathcal{N}(0,\alpha)$.

Pour cela on utilisera

import numpy as np
sigma = np.identity(d)*alpha
sigma[0,0] +=0.2
sigma[1,1] -=0.04

w= np.random.multivariate_normal(np.array([0.0 for i in range(0,d)]),sigma,1)

1) Choisissez un biais $b$.

2) Construisez les échantillons $X$ et $y$,

Pour cela on génère un $X$ avec

pyton
X= np.random.uniform(0,1,n)

et on applique la transformation linéaire pour calculer le $y$

3) On sépare en jeux test et train.

In [16]:
import numpy as np
d=50
n=20
alpha=0.1
sigma = np.identity(d)*alpha
sigma[0,0] +=0.2
sigma[1,1] -=0.04

w= np.random.multivariate_normal(np.array([0.0 for i in range(0,d)]),sigma,1)
X= np.zeros((n,d))
y = np.zeros(n)
b=0.2
for i in range(0,n):
    X[i]=np.random.uniform(0,1,d)
    for j in range(0,d):
        
        y[i]= y[i]+w[0,j]*X[i,j]+b
    
[-0.10621925 -0.00917765  0.23139385 -0.70467461  0.25290647  0.40724129
 -0.31035919 -0.06619805 -0.18664506  0.00176984 -0.31691463  0.36335415
  0.02628879 -0.19039286 -0.02172533 -0.28115907  0.11015946  0.50350081
 -0.23219944 -0.0827916   0.0617943  -0.17990244 -0.10942431 -0.49638334
  0.28524101  0.0886419  -0.05763693  0.09706633  0.26198626 -0.03233417
  0.01179356  0.21991452 -0.300733    0.05186605 -0.1997337   0.19827193
 -0.31352429  0.34654548 -0.22805841  0.2954359   0.2872441   0.01788362
 -0.38363957  0.01770769  0.1074852  -0.18397433  0.43665866  0.03087959
  0.09486937  0.46789264]

Régression logistique

1) Récuperer les données du jeux IRIS.

2) Appliquer une régression logistique et tracer le résultat.

3) Jouer avec le paramètre de régularisation.

Régression avec processus gaussien

On va explorer un peu la régression par processus Gaussien. Pour cela on va regarder la fonction

$$ f(x)=x sin(x) $$

Pour cela on construit le jeu de données

X = np.linspace(start=0, stop=10, num=1_000).reshape(-1, 1)
y = np.squeeze(X * np.sin(X))

1) Coder une regression avec des processus Gaussien, et une avec les kernel ridge

2) faire varier les kernel et les paramètres

Pour afficher on peut utiliser

plt.plot(X, y, label=r"$f(x) = x \sin(x)$", linestyle="dotted")
plt.scatter(X_train, y_train, label="Observations")
plt.plot(X, gp_prediction)
plt.fill_between(
    X.ravel(),
    gp_prediction - 1.96 * std_prediction,
    p_prediction + 1.96 * std_prediction,
    alpha=0.5,
    label=r"95% confidence interval",
)
plt.legend()

3) Le refaire en ajoutant du bruit

noise_std = 0.75
y_train_noisy = y_train + rng.normal(loc=0.0, scale=noise_std, size=y_train.shape)