Ajout de la régression softmax

This commit is contained in:
Philippe Roy 2023-06-22 03:14:37 +02:00
parent 9fe561e5e3
commit 8f54233a6f
6 changed files with 121 additions and 29 deletions

View File

@ -1,6 +1,7 @@
import time
import numpy as np
import sklearn
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
###############################################################################

View File

@ -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))

View File

@ -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)

View File

@ -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)

View File

@ -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))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

After

Width:  |  Height:  |  Size: 510 KiB