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 # @title: Fondamentaux - Apprentissage par régression logistique # @project: Mes scripts de ML # @lang: fr # @authors: Philippe Roy # @copyright: Copyright (C) 2023 Philippe Roy # @license: GNU GPL ############################################################################### ### # Commandes NumPy : # - np.array : créer un tableau à partir d'une liste de listes # - np.c_ : concatène les colonnes des tableaux # - 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 # - 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 ### ############################################################################### # Initialisation ############################################################################### # Init du temps t_debut = time.time() # Init des plots fig = plt.figure(figsize=(15, 5)) fig.suptitle("Classificateur par régression logistique") 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 iris = sklearn.datasets.load_iris() # Jeu de données Iris 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, 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_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 ############################################################################### # 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é model_2d_a = -model_2d.coef_[0][0] / model_2d.coef_[0][1] # coef directeur de la frontière de décision model_2d_b = -model_2d.intercept_ / model_2d.coef_[0][1] # ordonée à l'origine de la frontière de décision frontiere_decision_2d = model_2d_a * x1_new + model_2d_b 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 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,x2 et y1 (longeur de pétale, largeur de pétale et 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(x1_new, 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 y (longeur de pétale, largeur 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 1D sur la largeur de pétale : "+str(round(frontiere_decision_1d, 6))) print ("Temps : "+str(time.time()-t_debut))