1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| import random
import math
def f(x) :
return 1/(1+math.e**(-x))
def derivee(x) :
return (math.e**(-x)) / ((1+math.e**(-x))**2)
class ReseauDeNeurones :
"""Gere les principales fonctionalites d'un reseau de neurones."""
def __init__( self, nb_neurones_par_couche=[10,8,1], valeur_par_defaut_synapses = "random.random()*2-1", fonction = f, derivee=derivee ) :
"""Constructeur de l'objet.
nb_neurones_par_couche : liste contenant le nombre de neurones par couche
le premier etant les entrees et le dernier les sorties
valeur_par_defaut_synapses : contient la valeur par defaut des synapses sous la forme de str /!\
fonction : fonction d'activation
derivee : derivee de la fonction d'activation"""
self.f = self.fonction = fonction
self.f_ = derivee
self.couches = []#contient self.couches[couche][neurone][poids]
for nb in range(len(nb_neurones_par_couche)-1) :
self.couches.append([])#une couche de plus
for i in range(nb_neurones_par_couche[nb]) :
self.couches[-1].append([])#un neurone de plus
for synapse in range(nb_neurones_par_couche[nb+1]) :
self.couches[nb][i].append(eval(valeur_par_defaut_synapses))
def executer(self,*entrees) :
"""Execute le reseau de neurones avec les entrees donnees (qui doivent etre egales au nombre de neurones).
Les neurones de sortie et d'entree n'appliquent pas la fonction d'activation."""
sortie=[0]*len(self.couches[1])
for i in range(len(entrees)) :
entree=self.f(entrees[i])
for ii in range(len(self.couches[0][i])) :
poids = self.couches[0][i][ii]
sortie[ii]+=poids*entree
for couche in self.couches[1:] :
sortie,entrees = [0]*len(couche[0]), sortie
for i in range(len(entrees)) :
entree=self.fonction(entrees[i])
for ii in range(len(couche[i])) :
poids = couche[i][ii]
sortie[ii]+=poids*entree
return [self.f(v) for v in sortie]
def _executer_(self,*entrees) :
"""Execute le reseau de neurones avec les entrees donnees (qui doivent etre egales au nombre de neurones).
Les neurones de sortie et d'entree n'appliquent pas la fonction d'activation.
fonction renvoyant les sorties des differentes couches"""
S = []
sortie=[0]*len(self.couches[1])
for i in range(len(entrees)) :
entree=self.f(entrees[i])
for ii in range(len(self.couches[0][i])) :
poids = self.couches[0][i][ii]
sortie[ii]+=poids*entree
S.append(list(sortie))
for couche in self.couches[1:] :
sortie,entrees = [0]*len(couche[0]), sortie
for i in range(len(entrees)) :
entree=self.fonction(entrees[i])
for ii in range(len(couche[i])) :
poids = couche[i][ii]
sortie[ii]+=poids*entree
S.append(list(sortie))
return S #-> valeurs brutes sans seuillage par la fonction f
def retropropagation(self, entree, sortie) :
"""entree -> entrees voulues
sortie -> sortie voulue
s -> sortie obtenue avant modification
deja pour 3 couches"""
nouveaux_poids = []
for couche in range(len(self.couches)) :
nouveaux_poids.append([])
for neurone in self.couches[couche] :
nouveaux_poids[-1].append(list(neurone))
s = self._executer_()
#dernière couche : k
E=[]
for i in range(len(s[1])) : #i : position du neurone dans la couche 2 = sortie
erreur_neurone = self.f_(s[1][i]) * ( sortie[i] - self.f(s[1][i]) )
#on "repare" l'erreur
for j in range(len(self.couches[1])) :
nouveaux_poids[1][j][i] -= erreur_neurone * self.couches[1][j][i]
E.append(erreur_neurone)
for i in range(len(s[0])) : #i : position du neurone dans la couche 1
somme = 0
for k in range(len(self.couches[1][i])) :
somme+=E[k]*self.couches[1][i][k]
erreur = self.f_(s[0][i])*somme
#on "repare" l'erreur
for j in range(len(self.couches[0])) :
nouveaux_poids[0][j][i] -= erreur * self.couches[1][j][i]
self.couches = nouveaux_poids |
Partager