TP Réduction de dimension

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)$.

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.

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.

Clustering

Exemples de jeux de données de clustering

from sklearn import cluster, datasets

n_samples = 1500
X, y = datasets.make_circles(n_samples=n_samples, factor=0.5, noise=0.05)
X, y = datasets.make_moons(n_samples=n_samples, noise=0.05)
X, y = datasets.make_blobs(n_samples=n_samples, random_state=8)

X, y = datasets.make_blobs(n_samples=n_samples, random_state=random_state)
transformation = [[0.6, -0.6], [-0.4, 0.8]]
X_aniso = np.dot(X, transformation)

K-moyenne

kmeans = MiniBatchKMeans(n_clusters=2,init='random',batch_size=6) ## autre init init='kmean++'
kmeans.fit(X_train), ## calcul le modèle
y_pred=kmeans.fit_predict(X_train), ## calcul le modèle et prédit la classe des points d'entrainement

print(kmeans.cluster_centers_) ## coordonnées des clusters,
print(kmeans.labels_) ## numéro du paquet pour chaque point,

y_test=kmeans.predict(X_test), ## prédire la classe d'un nouveau point

Plot d'un nuage de point 2D

import matplotlib.pyplot as plt
plt.figure(figsize=(12, 12))
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_pred)
plt.title("plot clusters")

Autres méthodes de clustering:

from sklearn.cluster import AgglomerativeClustering, MeanShift, DBSCAN
clustering = MeanShift(bandwidth=2)
clustering = AgglomerativeClustering(n_clusters=2,affinity='euclidean',linkage='ward') ## affinity = distance utilisée, linkage='single', 'average', 'ward', 'complete'
clustering = DBSCAN(eps=3, min_samples=3) ## eps = la distance minimale en deux points dans un même voisinage, min_sample: le nombre de voisins minimum pour avoir une région "dense".

Réduction de dimension

Reduction de dimension PCA

from sklearn.decomposition import PCA  

pca = PCA(n_components=3) ## si on donne pas de n_composentes, il les construit toutes
pca.fit(X) ## construit le modèle
X_reduced = pca.fit_transform(X) ## construit le modèle renvoit la représentation réduite des données d'entrainement
X_reduced_test = pca.transform(X_test) ## transforme des nouvelles données

plt.plot(np.arange(1,d+1),np.cumsum(pca.explained_variance_ratio_)) ## d la dimension des données
axes = plt.gca()
axes.xaxis.set_ticks(np.arange(1,d+1)) 
plt.title("Variance expliquée vs numéro de l'axe principal")
plt.ylabel("Cumul de variance expliquée")
plt.xlabel("Numéro de l'axe principal")
plt.show()

Cas nonlinéaire

from sklearn import manifold, datasets
    iso= manifold.Isomap(n_neighbors=4, n_components=4) ## n_components = nombre de variables réduites, n_neighbors = un paramètre important de la méthode. 
    spectral=manifold.SpectralEmbedding(n_components=4, n_neighbors=4)

Comme PCA, on a fit() et fit_transform()

https://scikit-learn.org/stable/auto_examples/manifold/plot_compare_methods.html#sphx-glr-auto-examples-manifold-plot-compare-methods-py

TP

Jeux de données mamifaires

On va regarder le jeux de données:

X = np.loadtxt('mammals.csv', delimiter=';', usecols=[1,2,3,4,5,6,7,8,9,10], skiprows=1)

#Les colonnes : 
#1 : Poids du corps (kg)
#2 : Poids du cerveau (g)
#3 : sommeil lent (sans reves) (h/jour)
#4 : sommeil paradoxal (avec reves) (h/jour)
#5 : durée totale du sommeil (h/jour)
#6 : Durée de vie maximale (années)
#7 : Temps de gestation (jours)
#8 : indice de prédation
#9 : indice d exposition
#10 : indice de danger global

# on redimentionne les colonnes car les variables sont de nature très différentes entre elles ici
sc_scaled = StandardScaler().fit(X)
X = sc_scaled.transform(X)

# on veut afficher les variables et non les individus donc on transpose la matrice X
sc_scaled = StandardScaler().fit(X.T)
Xcr = sc_scaled.transform(X.T)

1) Récupérer le nombre d'échantillons $n$, et la dimension des données $d$

n=Xcr.shape[0] 
d=Xcr.shape[1]

2) Appliquer une PCA avec $d$ composante aux jeux de données

3) Regarder combien de composantes (on le notera m) il faut garder pour avoir plus de 90% de précision de la compression.

4) Refaire une PCA avec $m$ composantes et transformer le jeu de données réduit

5) Appliquer un algorithme de clustering au choix

Compression d'image

On charge une image

import skimage.io as io
import skimage.color as color
from sklearn.preprocessing import StandardScaler

f = io.imread("lena.tiff")
X = color.rgb2gray(f) 

sc_scaled = StandardScaler().fit(X)
Xcr = sc_scaled.transform(X)
plt.imshow(Xcr, cmap="gray")

1) On récupère $n$ le nombre de données et $d$ la dimension.

2) On fait une ACP sans préciser le nombre de composantes.

3) On transforme $Xcr$ et on stocke les la nouvelle représentation dans "comosantes_principales".

4) Avec le code ici, on affiche le résultat pour plusieurs cas. q est le nombre de dimensions que l'on garde. Faire varier $q$

i=0
q_liste=[5, 20, 40, 60]
for q in q_liste:
    i+=1
    Xnouveau=np.matmul(composantes_principales[:,0:q] ,axes_principaux[0:q,:])
    plt.imshow(Xnouveau, cmap="gray")
    plt.axis('off')
    plt.title('Avec %d composantes principales' %q)
    plt.show()

Régression et réduction de dimension

On va partir d'un problème de régression en dimension 3 qui est en faite en dimension 2 mais nonlinéaire.

On va réduire la dimension avec une méthode nonlinaire puis appliquer une régression linéaire.

On commence par créer le jeux de donnée.

from sklearn import manifold, datasets

n_points = 1000
X, y= datasets.make_s_curve(n_points, random_state=0)

On a donc $X$ en dimension 3 et $y$ en dimension $1$.

1) On applique la réduction isomap.

2) On applique une séparation entre jeux de données tests et train réduit.

3) On fait une régression linéaire.

4) On regarde l'erreur sur le jeu test.

5) On fait la même chose avec une régression directement sur le jeu de données non compressé.

In [ ]: