Skip to content
Snippets Groups Projects
Commit aa4c6ee8 authored by Dellandrea Emmanuel's avatar Dellandrea Emmanuel
Browse files

Ajout correction

parent d20f423d
No related branches found
No related tags found
No related merge requests found
import matplotlib.pyplot as plt
import numpy as np
def lecture_donnees(nom_fichier, delimiteur=','):
""" Lit le fichier contenant les données et renvoiee les matrices correspondant
Parametres
----------
nom_fichier : nom du fichier contenant les données
delimiteur : caratère délimitant les colonne dans le fichier ("," par défaut)
Retour
-------
x : matrice des données de dimension [N, nb_var]
d : matrice contenant les valeurs de la variable cible de dimension [N, nb_cible]
N : nombre d'éléments
nb_var : nombre de variables prédictives
nb_cible : nombre de variables cibles
"""
data = np.loadtxt(nom_fichier, delimiter=delimiteur)
nb_cible = 1
nb_var = data.shape[1] - nb_cible
N = data.shape[0]
x = data[:, :nb_var]
d = data[:, nb_var:].reshape(N,1)
return x, d, N, nb_var, nb_cible
def normalisation(x):
""" Normalise les données par un centrage-réduction des variables prédictives
Parametres
----------
X : matrice des données de dimension [N, nb_var]
avec N : nombre d'éléments et nb_var : nombre de variables prédictives
Retour
-------
X_norm : matrice des données centrées-réduites de dimension [N, nb_var]
mu : moyenne des variables de dimension [1,nb_var]
sigma : écart-type des variables de dimension [1,nb_var]
"""
mu = np.mean(x, 0)
sigma = np.std(x, 0)
x_norm = (x - mu) / sigma
return x_norm, mu, sigma
def decoupage_donnees(x,d,prop_val=0.2, prop_test=0.2):
""" Découpe les données initiales en trois sous-ensembles distincts d'apprentissage, de validation et de test
Parametres
----------
x : matrice des données de dimension [N, nb_var]
d : matrice des valeurs cibles [N, nb_cible]
prop_val : proportion des données de validation sur l'ensemble des données (entre 0 et 1)
prop_test : proportion des données de test sur l'ensemble des données (entre 0 et 1)
avec N : nombre d'éléments, nb_var : nombre de variables prédictives, nb_cible : nombre de variables cibles
Retour
-------
x_app : matrice des données d'apprentissage
d_app : matrice des valeurs cibles d'apprentissage
x_val : matrice des données d'apprentissage
d_val : matrice des valeurs cibles d'apprentissage
x_test : matrice des données d'apprentissage
d_test : matrice des valeurs cibles d'apprentissage
"""
assert prop_val + prop_test < 1.0
N = x.shape[0]
indices = np.arange(N)
np.random.shuffle(indices)
nb_val = int(N*prop_val)
nb_test = int(N*prop_test)
nb_app = N - nb_val - nb_test
x = x[indices,:]
d = d[indices,:]
x_app = x[:nb_app,:]
d_app = d[:nb_app,:]
x_val = x[nb_app:nb_app+nb_val,:]
d_val = d[nb_app:nb_app+nb_val,:]
x_test = x[N-nb_test:,:]
d_test = d[N-nb_test:,:]
return x_app, d_app, x_val, d_val, x_test, d_test
def calcule_cout_entropie_croisee(y, d):
""" Calcule la valeur de la fonction cout entropie croisée
Parametres
----------
y : matrice des données prédites (softmax)
d : matrice des données réelles encodées par 1
Return
-------
cout : nombre correspondant à la valeur de la fonction cout
"""
N = y.shape[1]
cout = - np.sum(d*np.log(y)) / N
return cout
def passe_avant(x, W, b, activation):
""" Réalise une passe avant dans le réseau de neurones
Parametres
----------
x : matrice des entrées, de dimension nb_var x N
W : liste contenant les matrices des poids du réseau
b : liste contenant les matrices des biais du réseau
activation : liste contenant les fonctions d'activation des couches du réseau
avec N : nombre d'éléments, nb_var : nombre de variables prédictives
Return
-------
a : liste contenant les potentiels d'entrée des couches du réseau
h : liste contenant les sorties des couches du réseau
"""
h = [x]
a = []
for i in range(len(b)):
a.append( W[i].dot(h[i]) + b[i] )
h.append( activation[i](a[i]) )
return a, h
def passe_arriere(delta_h, a, h, W, activation):
""" Réalise une passe arrière dans le réseau de neurones (rétropropagation)
Parametres
----------
delta_h : matrice contenant les valeurs du gradient du coût par rapport à la sortie du réseau
a : liste contenant les potentiels d'entrée des couches du réseau
h : liste contenant les sorties des couches du réseau
W : liste contenant les matrices des poids du réseau
activation : liste contenant les fonctions d'activation des couches du réseau
Return
-------
delta_W : liste contenant les matrice des gradients des poids des couches du réseau
delta_b : liste contenant les matrice des gradients des biais des couches du réseau
"""
delta_b = []
delta_W = []
for i in range(len(W)-1,-1,-1):
delta_a = delta_h * activation[i](a[i], True)
delta_b.append( delta_a.mean(1).reshape(-1,1) )
delta_W.append( delta_a.dot(h[i].T) )
delta_h = (W[i].T).dot(delta_a)
delta_b = delta_b[::-1]
delta_W = delta_W[::-1]
return delta_W, delta_b
def sigmoide(z, deriv=False):
""" Calcule la valeur de la fonction sigmoide ou de sa dérivée appliquée à z
Parametres
----------
z : peut être un scalaire ou une matrice
deriv : booléen. Si False renvoie la valeur de la fonction sigmoide, si True renvoie sa dérivée
Return
-------
s : valeur de la fonction sigmoide appliquée à z ou de sa dérivée. Même dimension que z
"""
s = 1 / (1 + np.exp(-z))
if deriv:
return s * (1 - s)
else :
return s
def lineaire(z, deriv=False):
""" Calcule la valeur de la fonction linéaire ou de sa dérivée appliquée à z
Parametres
----------
z : peut être un scalaire ou une matrice
deriv : booléen. Si False renvoie la valeur de la fonction linéire, si True renvoie sa dérivée
Return
-------
s : valeur de la fonction linéaire appliquée à z ou de sa dérivée. Même dimension que z
"""
if deriv:
return np.ones(z.shape)
else :
return z
def relu(z, deriv=False):
""" Calcule la valeur de la fonction relu ou de sa dérivée appliquée à z
Parametres
----------
z : peut être un scalaire ou une matrice
deriv : booléen. Si False renvoie la valeur de la fonction relu, si True renvoie sa dérivée
Return
-------
s : valeur de la fonction relu appliquée à z ou de sa dérivée. Même dimension que z
"""
r = np.zeros(z.shape)
if deriv:
pos = np.where(z>=0)
r[pos] = 1.0
return r
else :
return np.maximum(r,z)
def softmax(z, deriv=False):
""" Calcule la valeur de la fonction softmax ou de sa dérivée appliquée à z
Parametres
----------
z : matrice des données
deriv : booléen. Si False renvoie la valeur de la fonction softmax, si True renvoie sa dérivée
Return
-------
s : valeur de la fonction softmax appliquée à z ou de sa dérivée. Même dimension que z
"""
if deriv:
return 1
else :
return np.exp(z) / np.sum(np.exp(z),axis=0)
def encodage_a_1(d):
""" Réalise un encodage 1 parmi n : sur les neurones de sortie du réseau, seul 1 aura la valeur 1, tous les autres à 0
Parametres
----------
d : matrice contenant les valeurs de la variable cible (classe des éléments) de dimension [N, 1]
avec N : nombre d'éléments
Retour
-------
e : matrice des données encodées de dimension [N, nb_classes]
avec N : nombre d'éléments et nb_classes le nombre de classes (maximum+1) des valeurs dans d
"""
d = d.astype(int).flatten()
N = d.shape[0]
nb_classes = d.max() + 1
e = np.zeros((N,nb_classes))
e[range(N),d] = 1
return e
def taux_classification(y,d):
""" Calcule le taux de classification (proportion d'éléments bien classés)
Parametres
----------
y : matrice des sorties du réseau de dimension [nb_neurones_sortie x N]
d : matrice des vraies valeurs [nb_neurones_sortie x N]
avec N : nombre d'éléments et nb_neurones_sortie : le nombre de neurones sur la couche de sortie
Retour
-------
t : taux de classification
"""
ind_y = np.argmax(y,axis=0)
ind_d = np.argmax(d,axis=0)
t = np.mean(ind_y == ind_d)
return t
# ===================== Partie 1: Lecture et normalisation des données =====================
print("Lecture des données ...")
x, d, N, nb_var, nb_cible = lecture_donnees("iris.txt")
# x, d, N, nb_var, nb_cible = lecture_donnees("scores.txt")
# Affichage des 10 premiers exemples du dataset
print("Affichage des 10 premiers exemples du dataset : ")
for i in range(0, 10):
print(f"x = {x[i,:]}, d = {d[i]}")
# Normalisation des variables (centrage-réduction)
print("Normalisation des variables ...")
x, mu, sigma = normalisation(x)
d = encodage_a_1(d)
# Découpage des données en sous-ensemble d'apprentissage, de validation et de test
x_app, d_app, x_val, d_val, x_test, d_test = decoupage_donnees(x,d)
# ===================== Partie 2: Apprentissage =====================
# Choix du taux d'apprentissage et du nombre d'itérations
alpha = 0.0001
nb_iters = 10000
couts_apprentissage = np.zeros(nb_iters)
couts_validation = np.zeros(nb_iters)
# Dimensions du réseau
D_c = [nb_var, 15, 15, d_app.shape[1]] # liste contenant le nombre de neurones pour chaque couche
activation = [relu, relu, softmax] # liste contenant les fonctions d'activation des couches cachées et de la couche de sortie
# Initialisation aléatoire des poids du réseau
W = []
b = []
for i in range(len(D_c)-1):
W.append(2 * np.random.random((D_c[i+1], D_c[i])) - 1)
b.append(np.zeros((D_c[i+1],1)))
x_app = x_app.T # Les données sont présentées en entrée du réseau comme des vecteurs colonnes
d_app = d_app.T
x_val = x_val.T # Les données sont présentées en entrée du réseau comme des vecteurs colonnes
d_val = d_val.T
x_test = x_test.T # Les données sont présentées en entrée du réseau comme des vecteurs colonnes
d_test = d_test.T
for t in range(nb_iters):
#############################################################################
# Passe avant : calcul de la sortie prédite y sur les données de validation #
#############################################################################
a, h = passe_avant(x_val, W, b, activation)
y_val = h[-1] # Sortie prédite
###############################################################################
# Passe avant : calcul de la sortie prédite y sur les données d'apprentissage #
###############################################################################
a, h = passe_avant(x_app, W, b, activation)
y_app = h[-1] # Sortie prédite
###########################################
# Calcul de la fonction perte de type MSE #
###########################################
couts_apprentissage[t] = calcule_cout_entropie_croisee(y_app,d_app)
couts_validation[t] = calcule_cout_entropie_croisee(y_val,d_val)
####################################
# Passe arrière : rétropropagation #
####################################
delta_h = (y_app-d_app) # Pour la dernière couche
delta_W, delta_b = passe_arriere(delta_h, a, h, W, activation)
#############################################
# Mise à jour des poids et des biais ##### #
#############################################
for i in range(len(b)-1,-1,-1):
b[i] -= alpha * delta_b[i]
W[i] -= alpha * delta_W[i]
print("Coût final sur l'ensemble d'apprentissage : ", couts_apprentissage[-1])
print("Taux de classification sur l'ensemble d'apprentissage : ", taux_classification(y_app, d_app))
print("Coût final sur l'ensemble de validation : ", couts_validation[-1])
print("Taux de classification sur l'ensemble de validation : ", taux_classification(y_val, d_val))
# Affichage de l'évolution de la fonction de cout lors de la rétropropagation
plt.figure(0)
plt.title("Evolution de le fonction de coût lors de la retropropagation")
plt.plot(np.arange(couts_apprentissage.size), couts_apprentissage, label="Apprentissage")
plt.plot(np.arange(couts_validation.size), couts_validation, label="Validation")
plt.legend(loc="upper left")
plt.xlabel("Nombre d'iterations")
plt.ylabel("Coût")
plt.show()
# ===================== Partie 3: Evaluation sur l'ensemble de test =====================
#######################################################################
# Passe avant : calcul de la sortie prédite y sur les données de test #
#######################################################################
a, h = passe_avant(x_test, W, b, activation)
y_test = h[-1] # Sortie prédite
cout = calcule_cout_entropie_croisee(y_test,d_test)
print("Coût sur l'ensemble de test : ", cout)
print("Taux de classification sur l'ensemble de test : ", taux_classification(y_test, d_test))
......@@ -213,7 +213,7 @@ def lineaire(z, deriv=False):
"""
if deriv:
return 1
return np.ones(z.shape)
else :
return z
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment