TIPE:Chakir Oussama
Mathématiques Appliquées et informatiquepratique
[]: inport nnpy as np # Essentielu
-pour les array, calculs,
import matplotlib.pyplot as plt # Pour lesy
-graphiques/images
from scipy import signal :
# Calcul de convolution le coder soi-même est
3imple mais les boucles for
# sont trs couteuses et n'optimisent pas lesy
calculs (réseau trop Lent)
from skimage.measure import block_reduce # Calcul de mazpooling (même raison
que convolution, néanmoins pour
la rétropropagation, il n 'y a pasU
de telle fonction donc on utilise
# des boucles etc ce qui rend les
programme plus lent)
import tine # Chronomtre
import scipy # Pour la fonction scipy.special.ezpit qui permet dey
-calculer sigmoid sans overflow
1 Implémentation du réseau de neurones
1.1 Couches
[]: class Dense ():
definit_(self, taille_entree,taille_sortie):
self.poids = np.random.randn(taille_sortie, taille_entree)
self.biais = np.random.randn(taille_sortie, 1)
def propagation_directe(self, entree):
self.entree entree
return (np.dot(self .
poids, self.entree) + self.biais)
def retropropagation(self,grad_sortie, pas_apprentissage):
grad_poids = np.dot (grad_sortie,self.entree.T)
1
self poids-= pas_apprentissage * grad_poids
self.biais -= pas_apprentissage * grad _sortie
return np.dot(self.poids .T, grad_sortie)
[]: class Convolution(0:
def _init__(self, dimensions_entree, taille_filtre, profondeur_sortie):
profondeur_ sortie = nombrede filtres
self profondeur_sortie = profondeur_sortie
self.profondeur_entree, self .hauteur_entree, self .largeur_entree
u
.dimensions_entree
self.dimensions_entree = dimensions_entree
self.dimensions_sortie = (profondeur_sortie, self .hauteur_entree u
taille_filtre + 1,
self.largeur_entree - taille_filtre + 1)
self.dimensions filtres (profondeur_sortie, self-profondeur_entree,u
taille_filtre, taille_filtre)
self.filtres = np. random.randn(*self.dinensions_filtres)
self.biais = np. random.randn(*self.dinensions_sortie)
def propagation_directe(self,entree):
self.entree = entree
.
self.sortie = np.copy (self biais)
for i in range (self .profondeur_sortie) :
.
for j in range(self profondeur_entree):
self.sortie[i) += signal.correlate2d(self.entree [j], self.
filtres [i,j], "valid")
return self.sortie
def retropropagation(self, grad_sortie, pas_apprentissage) :
grad_filtres =
np.zeros (self.dimensions_filtres)
grad_entree = np.zeros(self.dimensions _entree)
for i in range(self .profondeur_sortie):
.
for j in range(self profondeur_entree):
grad_filtres [i,j] = signal.correlate2d(self. entree[j],u
-grad_sortie [i], "valid")
grad_entree[j]+= signal.correlate2d (grad_sortie[i), self.
filtres[i,j], "full")
grad_biais = grad_sortie
# Mise å jour
self.filtres -= pas_apprentissage grad_filtres
self.biais -= pas_apprentissage * grad_biais
return grad _entree
2
[]: class Maxpooling() :
def _init__(self, dimensions_entree, taille_filtre, stride):
self profondeur_entree, .
self.hauteur_entree, self largeur_entree u
.dimensions_entree
self.dimensions_entree = dimensions_entree
self.taille_filtre = taille_filtre
self .filtre_h, self .filtre_l = taille_filtre
self .stride = stride
self.hauteur_sortie = int (1 + (self .hauteur_entree - self. filtre_h) u
-stride)
self.largeur_sortie = int (1 + (self .largeur_entree self.filtre _1) /u
stride)
self.profondeur_sortie = self .prof ondeur_entree
def propagation_directe (self,entree):
self.entree = entree
( .
sortie = np.zeros (self prof ondeur_sortie, self.hauteur_sortie, self.
largeur_sortie))
stride= self.stride
for c in range (self.profondeur_sortie):
for i in range(self . hauteur_sortie):
for j in range (self .largeur_sortie):
sortie [c, i, j]= np.max(entree [c, i * stride : i * stride
t self.filtre_h j stride : j * stride + self.filtre_l ])
return sortie
def retropropagation(self, grad_sortie, pas_apprentissage) :
grad_entree = np.zeros( (self profondeur_entree, self . hauteur _entree,u
-
self.largeur_entree) )
entree =
self.entree
stride= self.stride
for c in range(self .profondeur_sortie):
for i in range(self hauteur_sortie):
for j in range (self.largeur_sortie):
internediaire = entree [c, i * stride : i* stride + self.
filtre _h,j* stride : j* stride + self.filtre_1]
i_max, j_max = np.where(np.max(intermediaire)
intersediaire)
i_max, j_max =
i_max [0], j_max[o]
grad_entree [c,i *stride : i * stride + self.filtre_h, j *u
-stride : j* stride + self.filtre_1] [i_max, j_max] = grad_sortie [c, i, j]
3
return grad_entree
[]: class Dropout ():
def _init__(self, q_bernouilli) :
self.p_bernouilli = 1 - q_bernouilli
def propagation_directe (self, entree) :
self.entree= entree
self.masque_binaire = np.random.binomial (1, self.p_bernouilli, size =u
entree.shape)/ self.p_bernouilli
self.sortie entree self .masque_binaire
return self. sortie
def retropropagation(self, grad_sortie, pas_apprentissage) :
return grad_sortie self .masque_binaire
[]: class Dimension () :
,
def _init__(self dimension_entree, dimension_sortie) :
self.dimension_entree= dimension_entree
self.dimension_sortie = dimension_sortie
def propagation_directe (self, entree) :
return np.reshape (entree, self.dimension_sortie)
def retropropagation(self, grad_sortie, pas_apprentissage) :
return np.reshape (grad_sortie, self .dimension_entree)
1.2 Couches d'Activation
4
[]: # Tang en te hyperbolique
class Tanh ()
:
def _init__(self):
tanh = lambda x : np.tanh (x)
tanh_p lambda 1 x:
- np.tanh (x)**2
self.activation = tanh
self.derivee_activation = tanh_p
def propagation_directe (self, entree):
self.entree = entree
return self.activation(self.entree)
def retropropagation(self, grad _sortie, pas_apprentissage) :
return np.multiply (grad_sortie, self .derivee_activation (self.entree) )
[]:#Sigmoide
class Signoide () :
def _init__(self):
def sigmoide (x) :
return scipy.special.expit (x)
def signoide_p(sig):
return sig (1- sig)
self.activation = sigmoide
self.derivee_activation = sigmoide_p
def propagation_directe (self, entree):
self.entree = entree
self .sig = self.activation(self .entree)
return self.sig
def retropropagation (self ,grad_sortie, pas_apprentissage) :
return np.multiply (grad_sortie, self. derivee_activation(self.sig))
[]:# Sof tmaz
class Softmax():
def propagation_directe (self,entree):
maxi = np.max(entree)
entree entree maxi
expo = np.exp(entree)
self.sortie =
expo/np.sun(expo)
5
return self.sortie
def retropropagation (self, grad_sortie, pas_apprent issage): # L'erreuru
utilisée étant toujours cce
# en comp lémen t de softmam, et comme on a déjå calculé la dérivée de
'erreur par rapport å
#L'entrée du softmaz, on La transmet (cf cce)
return grad_sortie
[]:# ReLU
class Relu ():
def propagat ion_directe (self, entree) :
self.entree = entree
self.sortie = np.maximun(0, entree)
return self.sortie
def retropropagation (self, grad_sortie, pas_apprentissage) :
inter = grad_sortie.copy ()
inter (inter (= 0] = 0
return inter
1.3 Erreur
[]:#Erreur quadratique moyenne (eqm)
[]: def eqm(sortie_voulue, sortie):
return np.mean (np.power(sortie_voulue - sortie, 2))
def eqm_derivee(sortie_voulue, sortie) :
return 2 * (sortie - sortie_voulue) / np. size(sortie)
[]:# Erreur croisée binaire (binary crossentropy notée bce)
def bce (sortie_voulue, sortie) :
sortie_voulue = np.clip(sortie_voulue, le-7, 1 - le-7) # Pour ne pas avoinu
de diuision par zero/ log (0)
sortie = np.clip(sortie, le-7, 1 - 1e-7) # Pour ne pas avoir de divisiony
-par zero/ log (0)
return -np.mean (sortie_voulue * np.log(sortie) + (1 - sortie_voulue)* np.
log(1-sortie) )
def bce_derivee(sortie_voulue, sortie):
sortie =
np.clip(sortie, 1e-7, 1 - le-7)
6
sortie_voulue = np.clip(sortie_voulue, le-7, 1 le-7) -
return ((1 sortie_voulue) / (1 - sortie) - sortie_voulue/ (sortie)) np.
-size (sortie)
[]:# Erreur croisée (categori cal crossentropy noté cce)
def cce (sortie_voulue, sortie):
sortie_voulue = np.clip(sortie_voulue, 1e-7, 1 - le-7)
sortie = np.clip(sortie, le-7, 1 - le-7)
return -np.sum(np.log(sortie) sortie_voulue)
def cce_derivee(sortie_voulue, sortie): # Ici, pour un soucis de rapidi té de
calcul, on cal cule directe
# la dérivée de l 'erreur par rapport åu
'entrée du softmaz en utilisant
# cce comme erreur d la derniêre couche.
En effet, la formu le est bien
# plus simple comme ceci, et onu
utilisera toujours Softmaz comme fonction
# d'activation en derniëre couche avecu
cce (cf. Softmaz)
sortie_voulue = np.clip(sortie_voulue, le-7, 1 - le-7)
sortie = np.clip(sortie, le-7, - le-7) 1
return sortie- sortie_voulue
1.4 Réseau de neurones
[]:def precision_erreur(res, entree_t, sortie_t):
succes = 0
total= 0
e 0
for i in range (1en(entree_t) : )
s= prediction(entree_t[i])
res.
e t= res.erreur(sortie_t[i],s)
maxi = np.argmax(s)
if maxi =* np.argmax(sortie_t[i]) :
succes 1
+
total t= 1
return (succes/total,e/total)
[]:class Reseau ():
def_init__(self, couches, erreur, erreur_derivee):
self.couches = couches
7
self.erreur = erreur
self.erreur_derivee = erreur_derivee
def prediction (self, entree):
sortie = entree
for couche in self.couches:
sortie = couche. propagation_directe (sortie)
return sortie
def entrainement (self,entree_e , sortie_e, entree_t, sortie_t, iterations,u
-pas_apprentissage): #entree_e et sortie_e : entrée et sortie entrainement
nb_entrainements = len (entree_e)
liste_erreur = O
liste_erreur_t = 0
precision_e
precision_t = O
tini = time.time ()
for itera in range(iterations) :
print ("Itération numéro ", itera+1)
erreur = 0
titer = time.tine ()
succes_e= 0
tot_e = 0
for i in range (nb_entrainements) :
# Propagation directe
sortie= entree_e[i]
for couche in self.couches:
sortie = couche. propagation_directe (sortie)
if np.argmax(sortie) = np. argmax(sortie_e [i]):
succes_e + 1
tot_e t=
1
# Ajout de l'erreur
,
erreur t= self. erreur (sortie_e [il sortie)
# Rétropropaga tion
sortie_retro = self .erreur_derivee (sortie_e [1J , sortie)
for couche in reversed(self.couches):
sortie_retro =
couche.retropropagation (sortie_retro,u
pas_apprentissage)
# Traitement de 'erreur
erreur /= nb_entrainements
liste_erreur. append(erreur)
print ("Erreur:", erreur)
prec_test, err_test = precision_erreur(self,entree_t, sortie_t)
liste_erreur_t.append(err_test)
print ("Erreur sur la base de test :", liste_erreur_t[-1])
precision_e.append(succes_e/tot_e)
precision_t.append(prec_test)
print ("Précision sur la base entrainement :", precision_e[-1])
print ("Précision sur la base test ", precision_t [-1])
print("Durêe de 1'itération :", round (time.time() - titer, 2),"s")
print ()
print ()
print ("Fin de l'apprentissage")
print ("Durée de l'apprentissage : ", round(time .time() tini,2), "s")
return (1iste_erreur, liste_erreur_t, precision_e , precision_t)
def test (self, entree_t, sortie_t):
nb_entrainements = len(entree_t)
erreur = 0
for i in range (nb_entrainements)
:
# Propagation directe
sortie = entree_t [1]
for couche in self.couches:
sOrtie couche.propagation_directe(sortie)
# Ajout de l'erreur
erreur += self.erreur(sortie_t[i],sortie)
erreur /= nb_entrainements
return erreur
Voici trois applications de ce code ci-dessOus :
2 XOR (ou exclusif)
[]:# Données (entree_e et sortie_ e : liste des entrées/sorties voulues)
(
entree_e = np.reshape [O,0], (2,1) ),np.reshape([o,1],(2,1)), np.
,
-reshape([1,0] (2,1)), np.reshape([1,1],(2,1))]
sortie_e = np.array(
[o]),np.array ( [1])
[1]),np. array( ,np.array( [o])]
# Structure du réseau (Reseau (couches, erreur, erreur_derivee))
9
couches = (Dense(2,5), Tanh (), Dense(5,3), Tanh () ,Dense(3,1), Tanh ()]
reseau1 (
= Reseau [Dense(2,5), Tanh), Dense(5,3), Tanh (),Dense (3,1) ,u
Tanh () ,eqm,eqm_derivee)
reseau2 =Reseau ([Dense(2,5), Tanh (), Dense(5,3), Tanh (),Dense(3,1) ,u
-Tanh()),
eqm,eqm_derivee)
(
reseau3 = Reseau [Dense (2,5), Tanh (), Dense(5,3), Tanh (O,Dense(3,1),u
-Tanh ()],eqm,eqm_derivee)
,
#Entrainement (reseau. en trainement(entree_ e, sortie_e, iterations,u
-pas_ apprentissage))
err_pas1, - reseaul.entrainement(entree_e, sortie_e, entree_e,U
sortie_e, 100, 0.01)
err_pas2, --t reseau2. entrainement (entree_e, sortie_e, entree_e,u
sortie_e, 100, 0.1)
err_pas3, -b-t reseau3.entrainement (entree_e, sortie_e, entree_e,u
-sortie_e, 100, 1)
[]:x = xfor x in range(1,101)]
plt.plot(x,err_pas1)
plt.plot(x, err_pas2)
plt.plot(x, err_pas3)
plt.legend(["0.01","o.1", "1"])
plt.savefig("XOR : pas d'apprentissage 2")
plt.show()
[]: couches = [Dense(2,5), Tanh(), Dense (5,3) , Tanh ()
,Dense (3,1) , Tanh ()]
reseau_al1 = Reseau ([Dense(2,5), Tanh (), Dense (5,3), Tanh ,Dense(3,1) ,u
()
,
Tanh ()] eqm,eqm_derivee)
(
reseau_al2 = Reseau [Dense(2,5), Tanh (), Dense(5,3), Tanh () ,Dense(3,1),u
,
-Tanh ()] eqm, eqm_ derivee)
reseau_al3 =Reseau ([Dense(2,5), Tanh (), Dense (5,3), Tanh (),Dense(3,1) ,u
-Tanh ()],eqm,eqm_derivee)
(
reseau_al4 = Reseau [Dense(2,5), Tanh (), Dense (5,3), Tanh () , Dense (3,1),u
-Tanh()],eqm,eqm_derivee)
reseau_al5 = Reseau( [Dense(2,5), Tanh (),Dense (5,3), Tanh ,Dense(3,1) ,u
()
-Tanh ()],eqm,eqm_derivee)
err_aleal, - = reseau_al1.entrainement(entree_e, sortie_e, entree_e,u
-sortie_e, 100, 0.1)
err_alea2, - =reseau_al2. entrainement(entree_e, sortie_e, entree_e,u
-sortie_e, 100, 0.1)
err_alea3, -t- reseau_al3.entrainement (entree_e, sortie_e, entree_e,u
-sortie_e, 100, 0.1)
10
err_alea4,
sortie_e,
err_alea5,
,=
,-=100, 0.1)
reseau_al4.entrainement (entree_e, sortie_e, entree_e,u
reseau_al5. entrainement(entree_e, sortie_e, entree_e,u
-8ortie_e, 100, 0.1)
[]: x = [x for x in range (1,101) )
plt.plot(x, err_alea1)
plt.plot (x,err_alea2)
plt.plot(x,err_alea3)
plt plot (x, err_alea4)
plt.plot (x,err_alea5)
plt.savefig(" X0R : initialisation des poids et biais 2")
plt.show()
11
##INFLUEN CE DU CHOIX DE LA FONCTION
net1= N.Network ([784,30,10])
net2= N.Network ([784 ,30,10] )
(
net3= N.NetwOrk [784,30,10] )
(
net4= N.Network [784 ,30,10] )
x,y1= net1.evolution_entrainement (training_data ,10,3.0,test ,
sigmoid ,ds)
-.y2= net2.evolution_entrainement (training-data ,10, 3.0 ,
test , tanh, dtanh)
-.y3= net3.evolution_entrainement (training_data ,10,3.0,test ,
f3,df3)
-,y4= net4.evolution_entrainement (training_dat a ,10,3.0,test ,
.
f4,df4)
:
Plot s ome data on the (implicit) axes .
'
'
plt. plot (x[0:5000:10],y1 [0:5000: 10], label= Sigmoid ') #
plt plot (x [0 5000: 10], y2 [0:5000: 10), label= tanh ') # etc.
. :
plt plot (x [O 5000:10] , y3 [O:5000: 10], label=1/1+z^2)
plt. plot (x [0: 5000:10] , y4 [0:5000:10] , label='arctan')
plt. xlabel("nombres d'images ")
plt .ylabel ('pr cision ')
plt.title ("Influence du choix de la fonction f")
plt.legend ()
plt. show ()
#influence de la structure du r seau
(
structure1 = N.Network [784 ,10] )
,
structure2 = N.Network ([784 16,10])
structure3 = N.Network([784 ,16,16,10])
a1,b1= structure 1.evolution_entrainement(training_data
,
,10,3.0,test sigmoid , ds)
11
-,b2 =
structure2 .evolution_entrainement (training_data
,
,10,3.0,test ,sigmoid ds)
-,b3 = structure3. evolution_entrainement (training_data
,
,10,3.0,test ,sigmoid ds)
.plot (a1 [O:5000:10] , b1[O:5000:10],
plt
couches)
'
1abel = r seau
plt .plot (a1 [O:5000:10], b2 [O:5000:10], label = r seau
couches ')
plt .plot(a1 [O:5000:10], b3 [O:5000:10], label ='r seau
2
3
4
couches ')
plt. xlabel ("nombres d'images ")
plt.ylabel (' pr cision )
plt.title ("Influence de la structure du r seau ")
plt. legend()
plt.show ()
11