diff --git a/fondamentaux/01-regression_lineaire.py b/fondamentaux/01-regression_lineaire.py index 14a5a4a..064af97 100644 --- a/fondamentaux/01-regression_lineaire.py +++ b/fondamentaux/01-regression_lineaire.py @@ -1,6 +1,7 @@ import time import numpy as np import sklearn +from sklearn.linear_model import LinearRegression import matplotlib.pyplot as plt ############################################################################### diff --git a/fondamentaux/02-descente_gradient.py b/fondamentaux/02-descente_gradient.py index aa143e4..43cb094 100644 --- a/fondamentaux/02-descente_gradient.py +++ b/fondamentaux/02-descente_gradient.py @@ -119,6 +119,21 @@ for i in range(n): # Résultats ############################################################################### +# Cartes des coûts (cc) +# FIXME : la carte des coûts ne correspond au RMSE calculé +# resol_cc=0.000000001 +# resol_cc=0.1 +# theta0_cc=np.linspace(theta[0]-resol_cc, theta[0]+resol_cc, 100).reshape(-1, 1) +# theta1_cc=np.linspace(theta[1]-resol_cc, theta[1]+resol_cc, 100).reshape(-1, 1) +theta0_cc=np.linspace(-5, 7, 100).reshape(-1, 1) +theta1_cc=np.linspace(-5, 7, 100).reshape(-1, 1) +theta0_cc_mg, theta1_cc_mg = np.meshgrid(theta0_cc, theta1_cc) +r, c = theta0_cc_mg.shape +rmse_cc = np.array([[0 for _ in range(c)] for _ in range(r)]) +for i in range(r): + for j in range(c): + rmse_cc[i,j] = round(float(rmse(np.array([theta0_cc_mg[i,j], theta1_cc_mg[i,j]]))),3) + # Plot des données donnees_ax.set_title("Données") donnees_ax.plot(x1_new, y_predict, 'r-', label="Prédictions") @@ -128,10 +143,21 @@ donnees_ax.legend() # Plot des paramètres du modèle model_ax.set_title("Paramètres du modèle") -model_ax.plot(theta0, theta1, '.', ls=':', color='c', fillstyle='none', label="Chemin", markevery=10) +# model_ax.set(xlim=(theta[0]-resol_cc, theta[0]+resol_cc), ylim=(theta[1]-resol_cc, theta[1]+resol_cc)) +model_ax.plot(theta0, theta1, '.', ls=':', color='r', fillstyle='none', label="Chemin", markevery=10) model_ax.plot(exact_solution[0], exact_solution[1], "o", color='k', fillstyle='full', label="Equation normale") model_ax.set_xlabel(r'$\theta_0$') model_ax.set_ylabel(r'$\theta_1 $', rotation=0) +# levels = np.arange(20, 200, 0.25) +# cc=model_ax.contour(theta0_mg, theta1_mg, carte_cout, levels) +# model_ax.clabel(cc, inline=True, fontsize=10) + +# FIXME : la carte des coûts ne correspond au RMSE calculé +# for i in range (0, 5000, 10): # Texte sur les points +# model_ax.text(theta0[i], theta1[i], str(i)+" - "+str(round(float(rmse(np.array([theta0[i],theta1[i]]))),3)), va='center', ha='center') +# cc_img = model_ax.pcolor(theta0_cc_mg, theta1_cc_mg, rmse_cc) +# fig.colorbar(cc_img, ax=model_ax) + model_ax.legend() # Plot du coût @@ -157,4 +183,5 @@ plt.show() print ("Theta th : theta0 : "+str(4)+" ; theta1 : "+str(3)) print ("Theta : theta0 : "+str(round(float(theta[0]),3))+" ; theta1 : "+str(round(float(theta[1]),3))) print ("Erreurs : theta0 : "+str(round(float(theta[0]-4),3))+" ; theta1 : "+str(round(float(theta[1]-3),3))) +print ("Coûts RMSE : "+str(round(float(rmse(theta)),3))) print ("Temps : "+str(time.time()-t_debut)) diff --git a/fondamentaux/03-descente_gradient_stochastique.py b/fondamentaux/03-descente_gradient_stochastique.py index 6555a1e..396f119 100644 --- a/fondamentaux/03-descente_gradient_stochastique.py +++ b/fondamentaux/03-descente_gradient_stochastique.py @@ -156,7 +156,7 @@ donnees_ax.legend() # Plot des paramètres du modèle model_ax.set_title("Paramètres du modèle") -model_ax.plot(theta0, theta1, '.', ls=':', color='c', fillstyle='none', label="Chemin", markevery=10) +model_ax.plot(theta0, theta1, '.', ls=':', color='r', fillstyle='none', label="Chemin", markevery=10) model_ax.plot(exact_solution[0], exact_solution[1], "o", color='k', fillstyle='full', label="Equation normale") model_ax.set_xlabel(r'$\theta_0$') model_ax.set_ylabel(r'$\theta_1 $', rotation=0) diff --git a/fondamentaux/04-descente_gradient_mini-lots.py b/fondamentaux/04-descente_gradient_mini-lots.py index 8f5bf86..2d2da88 100644 --- a/fondamentaux/04-descente_gradient_mini-lots.py +++ b/fondamentaux/04-descente_gradient_mini-lots.py @@ -166,7 +166,7 @@ donnees_ax.legend() # Plot des paramètres du modèle model_ax.set_title("Paramètres du modèle") -model_ax.plot(theta0, theta1, '.', ls=':', color='c', fillstyle='none', label="Chemin", markevery=10) +model_ax.plot(theta0, theta1, '.', ls=':', color='r', fillstyle='none', label="Chemin", markevery=10) model_ax.plot(exact_solution[0], exact_solution[1], "o", color='k', fillstyle='full', label="Equation normale") model_ax.set_xlabel(r'$\theta_0$') model_ax.set_ylabel(r'$\theta_1 $', rotation=0) diff --git a/fondamentaux/06-regression_logistique.py b/fondamentaux/06-regression_logistique.py index 9d04a62..1aea69c 100644 --- a/fondamentaux/06-regression_logistique.py +++ b/fondamentaux/06-regression_logistique.py @@ -1,7 +1,10 @@ import time import numpy as np import sklearn +from sklearn.linear_model import LogisticRegression +from sklearn import datasets import matplotlib.pyplot as plt +from matplotlib.colors import ListedColormap ############################################################################### # 06-regression_logistique.py @@ -17,12 +20,14 @@ import matplotlib.pyplot as plt # Commandes NumPy : # - np.array : créer un tableau à partir d'une liste de listes # - np.linspace : créer un tableau 1D de la valeur de début à la valeur de fin avec n valeurs +# - np.meshgrid : créer un tableau 2D avec l'ensemble des combinaisons allant des deux valeurs de début aux deux valeurs de fin # - .reshape : reformater la tableau avec le nombre de lignes et le nombre de colonnes ### ### # Commandes Scikit-Learn : -# - sklearn.linear_model.LogisticRegression : créer un modèle de régression logistique (méthode des moindres carrés) +# - sklearn.linear_model.LogisticRegression : créer un modèle de régression logistique +# - sklearn.linear_model.LogisticRegression(multi_class="multinomial", solver="lbfgs", C=10) : créer un modèle de régression logistique multi-classes du type Softmax # - .fit : entrainement du modèle # - .predict : prédiction du modèle ### @@ -37,55 +42,114 @@ t_debut = time.time() # Init des plots fig = plt.figure(figsize=(15, 5)) fig.suptitle("Régression logistique") -donnees_ax = fig.add_subplot(111) # Observations : x1 et cibles : y -# donnees_ax = fig.add_subplot(141) # Observations : x1 et cibles : y -# model_ax = fig.add_subplot(142) # Modèle : theta0, theta1 -# couts_ax = fig.add_subplot(143) # Coûts : RMSE, MSE, ... -# app_ax = fig.add_subplot(144) # Taux d'apprentissage : eta +donnees1_ax = fig.add_subplot(131) # Observations : x1 et cibles : y1 +donnees2_ax = fig.add_subplot(132) # Observations : x1, x2 et cibles : y11 (type de marque) +donnees3_ax = fig.add_subplot(133) # Observations : x1, x2 et cibles : y (type de marque) ############################################################################### # Observations ############################################################################### -# Observations d'apprentisage +# Observations d'apprentisage iris = sklearn.datasets.load_iris() # Jeu de données Iris -x1 = iris['data'][:, 3].reshape(-1, 1) # Largeur de pétale, reshape : -1 -> nb de ligne automatique -y = (iris["target"] == 2).astype(np.int32) # Si Iris virginica -> 1 sinon -> 0 -donnees_ax.plot(x1[y==0], y[y==0], "bs", label="Observations - Iris non-virginica") -donnees_ax.plot(x1[y==1], y[y==1], "g^" , label="Observations - Iris virginica") +x1 = iris['data'][:, 2].reshape(-1, 1) # Longueur de pétale +x2 = iris['data'][:, 3].reshape(-1, 1) # Largeur de pétale +X = iris['data'][:, (2, 3)] # Matrice de données +y1 = (iris["target"] == 2).astype(np.int32) # Si Iris virginica -> 1 sinon -> 0 +y = (iris["target"]) # Type d'Iris + +# Plot x1,y1 (largeur de pétale, probabilité d'être Iris virginica) +donnees1_ax.plot(x2[y1==1], y1[y1==1], "g^" , label="Iris virginica") +donnees1_ax.plot(x2[y1==0], y1[y1==0], "rs", label="Iris non-virginica") + +# Plot x1,x2 et y1 (longeur de pétale, largeur de pétale et probabilité d'être Iris virginica (format de la marque)) +donnees2_ax.plot(x1[y1==1], x2[y1==1], "g^" , label="Iris virginica") +donnees2_ax.plot(x1[y1==0], x2[y1==0], "rs", label="Iris non-virginica") + +# Plot x1,x2 et y (longeur de pétale, largeur de pétale et type de Iris (format de la marque)) +donnees3_ax.plot(x1[y==0], x2[y==0], "yo", label="Iris setosa (0)") +donnees3_ax.plot(x1[y==1], x2[y==1], "bs" , label="Iris versicolor (1)") +donnees3_ax.plot(x1[y==2], x2[y==2], "g^" , label="Iris virginica (2)") # Nouvelles observations -x1_new=np.linspace(0, 3, 1000).reshape(-1, 1) # reshape : -1 -> nb de ligne automatique +x1_new=np.linspace(0, 8, 1000).reshape(-1, 1) +x2_new=np.linspace(0, 3.5, 1000).reshape(-1, 1) +x1_new_mg, x2_new_mg = np.meshgrid(x1_new, x2_new) +X_new = np.c_[x1_new_mg.ravel(), x2_new_mg.ravel()] ############################################################################### # Phase d'apprentissage ############################################################################### -model = sklearn.linear_model.LogisticRegression() # Modèle régression logistique -model.fit(x1, y) # Entrainement +model_1d = sklearn.linear_model.LogisticRegression() # Modèle régression logistique +model_1d.fit(x2, y1) # Entrainement + +model_2d = sklearn.linear_model.LogisticRegression() # Modèle régression logistique +model_2d.fit(X, y1) # Entrainement + +model = LogisticRegression(multi_class="multinomial", solver="lbfgs", C=10) # Modèle régression logistique du type Softmax (multi-classes, multinomial) +model.fit(X, y) # Entrainement ############################################################################### # Phase d'inférence ############################################################################### -y_predict=model.predict(x1_new) # Prédiction -y_proba = model.predict_proba(x1_new) # Probabilité -frontiere_decision = x1_new[y_proba[:, 1] >= 0.5][0][0] +# Analyse 1D +y1_predict_1d=model_1d.predict(x2_new) # Prédiction +y1_proba_1d = model_1d.predict_proba(x2_new) # Probabilité +frontiere_decision_1d = x2_new[y1_proba_1d[:, 1] >= 0.5][0][0] + +# Analyse 2D +y1_predict_2d=model_2d.predict(X_new) # Prédiction +y1_proba_2d = model_2d.predict_proba(X_new) # Probabilité +left_right = np.array([2.9, 7]) +frontiere_decision_2d = -(model_2d.coef_[0][0] * left_right + model_2d.intercept_[0]) / model_2d.coef_[0][1] +y1_proba_2d_contour = y1_proba_2d[:, 1].reshape(x1_new_mg.shape) + +# Analyse multi-classes (Softmax) +y_predict=model.predict(X_new) # Prédiction +y_proba = model.predict_proba(X_new) # Probabilité +y_proba_contour0 = y_proba[:, 0].reshape(x1_new_mg.shape) +y_proba_contour1 = y_proba[:, 1].reshape(x1_new_mg.shape) +y_proba_contour2 = y_proba[:, 2].reshape(x1_new_mg.shape) +y_predict_map = y_predict.reshape(x1_new_mg.shape) ############################################################################### # Résultats ############################################################################### -# Plot des données -donnees_ax.set_title("Frontière de décision") -# donnees_ax.plot(x1_new, y_predict, 'r-', label="Prédictions") -donnees_ax.plot(x1_new, y_proba[:,1], 'b:', label="Probabilité - Scikit-Learn") -donnees_ax.plot(x1_new, y_predict, 'y-', label="Prédictions - Scikit-Learn") -donnees_ax.set_xlabel(r'$x_1$'+" - Largeur de pétale") -donnees_ax.set_ylabel(r'$y$'+" - Probabilité d'être Iris virginica") -donnees_ax.legend() +# Plot x1,y1 (largeur de pétale, probabilité d'être Iris virginica) +donnees1_ax.set_title("Binomiale - Frontière de décision à 1 entrée") +donnees1_ax.plot(x2_new, y1_proba_1d[:,1], 'b:', label="Probabilité") +donnees1_ax.plot(x2_new, y1_predict_1d, 'y-', label="Prédictions") +donnees1_ax.set_xlabel(r'$x_2$'+" - Largeur de pétale") +donnees1_ax.set_ylabel(r'$y$'+" - Probabilité d'être Iris virginica") +donnees1_ax.legend(loc="center left") + +# Plot x1,y1 (largeur de pétale, probabilité d'être Iris virginica) +donnees2_ax.set_title("Binomiale - Frontière de décision à 2 entrées") +donnees2_ax.set(xlim=(0, 7.5), ylim=(0, 3.5)) +donnees2_ax.plot(left_right, frontiere_decision_2d, "k--") +donnees2_ax.set_xlabel(r'$x_1$'+" - Longueur de pétale") +donnees2_ax.set_ylabel(r'$x_2$'+" - Largeur de pétale") +donnees2_ax.legend(loc="upper left") + +donnees2_contour = donnees2_ax.contour(x1_new_mg, x2_new_mg, y1_proba_2d_contour, cmap=plt.cm.brg) # Contour pour la classe Iris versicolor (type 1) +donnees2_ax.clabel(donnees2_contour, inline=1, fontsize=10) + +# Plot x1,x2 et y1 (largeur de pétale, longeur de pétale et type de Iris (format de la marque)) +donnees3_ax.set_title("Multinomiale (régression Softmax)") +donnees3_ax.set(xlim=(0, 7.5), ylim=(0, 3.5)) +donnees3_ax.set_xlabel(r'$x_1$'+" - Longueur de pétale") +donnees3_ax.set_ylabel(r'$x_2$'+" - Largeur de pétale") +donnees3_ax.legend(loc="upper right") + +custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0']) +donnees3_ax.contourf(x1_new_mg, x2_new_mg, y_predict_map, cmap=custom_cmap) +donnees3_contour = donnees3_ax.contour(x1_new_mg, x2_new_mg, y_proba_contour1, cmap=plt.cm.brg) # Contour pour la classe Iris versicolor (type 1) +donnees3_ax.clabel(donnees3_contour, inline=1, fontsize=10) plt.show() # Performances -print ("Frontière de décision : "+str(round(frontiere_decision, 6))) +print ("Frontière de décision 1D sur la largeur de pétale : "+str(round(frontiere_decision_1d, 6))) print ("Temps : "+str(time.time()-t_debut)) diff --git a/fondamentaux/img/06-regression_logistique.png b/fondamentaux/img/06-regression_logistique.png index feb0bc8..14085cf 100644 Binary files a/fondamentaux/img/06-regression_logistique.png and b/fondamentaux/img/06-regression_logistique.png differ