Un neurone
Ce tutoriel va vous permettre de réaliser une gestion des obstacles avec un neurone artificiel sur le robot MRPiZ. Un neurone artificiel est inspiré des neurones biologiques afin de faire de l’apprentissage artificiel. Un neurone possède des entrées avec un poids pour chaque entrée, et une sortie liée aux entrées et aux poids.
- Xi : entrées
- Wi : poids des entrées
- Y : sortie
- n : nombre d’entrées
La sortie Y est égale à :
Y = 1 si X >= Θ
Y = 0 si X < Θ
- Θ : seuil (threshold)
Fonction d’activation de type Sign.
D’autres fonctions d’activation sont possibles comme par exemple la fonction Step, Sigmoid ou linéaire.
L’algorithme perceptron
Le but de l’algorithme est de trouver les différents poids des entrées pour obtenir la sortie souhaités.
La façon la plus simple de réaliser un apprentissage par un neurone est l’algorithme perceptron inventé par Frank Rosenblatt.
Comment fonctionne l’apprentissage ?
Calcul de l’erreur entré la sortie actuelle et la sortie désirée :
e(t) = Yd(t) – Y(t)
avec :
- e(t) : erreur
- Yd(t) : sortie désirée
- Y(t) : sortie actuelle
- t : itération
La formule d’apprentissage de la mise à jour du poids d’un neurone :
Wi(t+1) = Wi(t) + ∅.Xi(t).e(t)
avec :
- W : poids d’une entrée
- e : erreur
- X : entrée
- ∅ : constante d’apprentissage (learning rate)
Apprentissage d’une porte logique OR
Voici le codage en langage python d’un apprentissage d’une porte logique OR avec un neurone perceptron à deux entrées binaire.
Définition de la classe d’un neurone avec deux entrées :
1 2 3 4 5 6 7 8 9 10 | class Perceptron_neuron: def __init__(self): self.input1 = [ 0.0, 0.0, 1.0, 1.0] self.input2 = [ 0.0, 1.0, 0.0, 1.0] self.weight1 = 0.0 self.weight2 = 0.0 self.output = 0.0 self.threshold = 0.0 self.learning_rate = 0.1 self.erreur = [ 0.0, 0.0, 0.0, 0.0] |
Le seuil est fixé à la valeur 0.1.
Définition de la classe des sorties désirés pour une porte logique OR :
1 2 3 4 | # initialisation des sorties voulue class Desired_output: def __init__(self): self.output = [ 0.0, 1.0, 1.0, 1.0] |
La fonction d’activation step :
1 2 3 4 5 6 | def step_function(a): if a < -0.0000001: a = 0.0 else: a = 1.0 return a |
La phase d’initialisation:
1 2 3 4 5 6 7 8 9 10 | # initialisation des sorties Desired_output = Desired_output() # creation du neurone Neuron1 = Perceptron_neuron() # initialisation du seuil et des poids à une valeur aux hasards. Neuron1.threshold = random.uniform(0.0, 0.5) Neuron1.weight1 = random.uniform(0.0, 0.5) Neuron1.weight2 = random.uniform(0.0, 0.5) |
Le programme complet :
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 | #!/usr/bin/env python # Mace Robotics # version : 0.1 # Test de neurone perceptron # apprentissage de la porte logique import random def step_function(a): if a < -0.0000001: a = 0.0 else: a = 1.0 return a # initialisation des sorties voulue class Desired_output: def __init__(self): self.output = [ 0.0, 1.0, 1.0, 1.0] class Perceptron_neuron: def __init__(self): self.input1 = [ 0.0, 0.0, 1.0, 1.0] self.input2 = [ 0.0, 1.0, 0.0, 1.0] self.weight1 = 0.0 self.weight2 = 0.0 self.output = 0.0 self.threshold = 0.0 self.learning_rate = 0.1 self.erreur = [ 0.0, 0.0, 0.0, 0.0] ########################################################### ########################################################### # MAIN Desired_output = Desired_output() # creation du neurone perceptron Neuron1 = Perceptron_neuron() # initialisation des weight et threshold avec une valeur aux hasard Neuron1.threshold = random.uniform(0.0, 0.5) Neuron1.weight1 = random.uniform(0.0, 0.5) Neuron1.weight2 = random.uniform(0.0, 0.5) print "\nNeuron threshold = ", Neuron1.threshold print "\nNeuron weight1 = ", Neuron1.weight1 print "\nNeuron weight2 = ", Neuron1.weight2 etat = True while etat == True: print "\n\nApprentissage : " count = 0 while count < 4: # boucle # activation Neuron1.output = Neuron1.input1[count]*Neuron1.weight1 + Neuron1.input2[count]*Neuron1.weight2 - Neuron1.threshold # fonction step Neuron1.output = step_function(Neuron1.output) #print "output = ", Neuron1.output print "Desired output = ", Desired_output.output[count] print "Actual output = ", Neuron1.output # calcul erreur Neuron1.erreur[count] = Desired_output.output[count] - Neuron1.output print "erreur = ", Neuron1.erreur[count] # mise a jour des poids delta_weight1 = Neuron1.learning_rate*Neuron1.input1[count]*Neuron1.erreur[count] delta_weight2 = Neuron1.learning_rate*Neuron1.input2[count]*Neuron1.erreur[count] Neuron1.weight1 = Neuron1.weight1 + delta_weight1 Neuron1.weight2 = Neuron1.weight2 + delta_weight2 print Neuron1.weight1, Neuron1.weight2 count = count + 1 # condition arret apprentissage if (Neuron1.erreur[0] == 0)and(Neuron1.erreur[1] == 0)and(Neuron1.erreur[2] == 0)and(Neuron1.erreur[3] == 0): print "END LEARNING ! " etat = False |
Apprentissage d’une porte logique AND
Il suffit de modifier les sorties désirés:
1 2 3 4 5 | # initialisation des sorties voulue # initialisation des sorties voulue class Desired_output: def __init__(self): self.output = [ 0.0, 0.0, 0.0, 1.0] |
Gestion des obstacles avec un neurone
Cette partie décrit la mise en place d’un neurone artificiel perceptron dans le robot MRPiZ afin des gérer les obstacles. Les deux entrées seront reliés aux capteurs de distance du robot MRPiZ et la sortie aux moteurs du robot.
Entrée n°1 = capteur de distance n°2 du robot MRPiZ
Entrée n°2 = capteur de distance n°4 du robot MRPiZ
Les entrées capteurs seront transformé en valeur binaire en fonction d’un seuil, le seuil représente une valeur en millimètre.
1 2 3 4 5 6 | def step_proxSensor(a): if a < _SEUIL_OBS: a = 1.0 else: a = 0.0 return a |
La sortie du neurone va permettre de contrôler le robot:
Sortie = 1 => stop le robot
Sortie = 0 => le robot avance
1 2 3 4 5 6 7 8 9 10 | # control output def Control_output(a): if a == 0: print "forward" forward(25) # forward MRPiZ time.sleep(0.1) else: print "stop" stop() # stop MRPiZ time.sleep(0.5) |
Le programme complet :
La première boucle While permet l’apprentissage et la seconde permet de tester l’apprentissage de gestion des obstacles sur le robot.
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | #!/usr/bin/env python # Mace Robotics # version : 0.1 # Test de neurone perceptron from mrpiZ_lib import * import random import time _SEUIL_OBS = 70 def step_proxSensor(a): if a < _SEUIL_OBS: a = 1.0 else: a = 0.0 return a def step_function(a): if a < -0.0000001: a = 0.0 else: a = 1.0 return a # control output def Control_output(a): if a == 0: print "forward" forward(25) # forward MRPiZ time.sleep(0.1) else: print "stop" stop() # stop MRPiZ time.sleep(0.5) # initialisation des sorties voulue class Desired_output: def __init__(self): self.output = [ 0.0, 1.0, 1.0, 1.0] class Perceptron_neuron: def __init__(self): self.input1 = [ 0.0, 0.0, 1.0, 1.0] self.input2 = [ 0.0, 1.0, 0.0, 1.0] self.weight1 = 0.0 self.weight2 = 0.0 self.output = 0.0 self.threshold = 0.0 self.learning_rate = 0.1 self.erreur = [ 1.0, 1.0, 1.0, 1.0] ########################################################### ########################################################### # MAIN Desired_output = Desired_output() # creation du neurone perceptron Neuron1 = Perceptron_neuron() # initialisation des weight et threshold avec une valeur aux hasard Neuron1.threshold = random.uniform(0.0, 0.5) Neuron1.weight1 = random.uniform(0.0, 0.5) Neuron1.weight2 = random.uniform(0.0, 0.5) print "\nNeuron threshold = ", Neuron1.threshold print "\nNeuron weight1 = ", Neuron1.weight1 print "\nNeuron weight2 = ", Neuron1.weight2 etat = True while etat == True: # lire capteur 2 et 4 prox2 = proxSensor(2)# input 1 prox4 = proxSensor(4) # input 2 print "prox2= ", prox2 print "prox4= ", prox4 time.sleep(0.5) prox2 = step_proxSensor(prox2) prox4 = step_proxSensor(prox4) print prox2, prox4 if((prox2==0)and(prox4==0)): count = 0 elif((prox2==0)and(prox4==1)): count = 1 elif((prox2==1)and(prox4==0)): count = 2 elif((prox2==1)and(prox4==1)): count = 3 print "\n\nApprentissage en cours", count # activation Neuron1.output = Neuron1.input1[count]*Neuron1.weight1 + Neuron1.input2[count]*Neuron1.weight2 - Neuron1.threshold # fonction step Neuron1.output = step_function(Neuron1.output) # control output Control_output(Neuron1.output) print "Desired output = ", Desired_output.output[count] print "Actual output = ", Neuron1.output # calcul erreur Neuron1.erreur[count] = Desired_output.output[count] - Neuron1.output print "erreur = ", Neuron1.erreur[count] # mise a jour des poids delta_weight1 = Neuron1.learning_rate*Neuron1.input1[count]*Neuron1.erreur[count] delta_weight2 = Neuron1.learning_rate*Neuron1.input2[count]*Neuron1.erreur[count] Neuron1.weight1 = Neuron1.weight1 + delta_weight1 Neuron1.weight2 = Neuron1.weight2 + delta_weight2 print Neuron1.weight1, Neuron1.weight2 # condition arret apprentissage if (Neuron1.erreur[0] == 0)and(Neuron1.erreur[1] == 0)and(Neuron1.erreur[2] == 0)and(Neuron1.erreur[3] == 0): print "END LEARNING ! " etat = False # fin boucle print "Neuron weight1= ", Neuron1.weight1 print "Neuron weight2= ", Neuron1.weight2 while 1: # lire capteur 2 et 4 prox2 = proxSensor(2)# input 1 prox4 = proxSensor(4) # input 2 print "prox2= ", prox2 print "prox4= ", prox4 time.sleep(0.1) prox2 = step_proxSensor(prox2) prox4 = step_proxSensor(prox4) print prox2, prox4 if((prox2==0)and(prox4==0)): count = 0 elif((prox2==0)and(prox4==1)): count = 1 elif((prox2==1)and(prox4==0)): count = 2 elif((prox2==1)and(prox4==1)): count = 3 print "\n\nApprentissage terminer = ", count # activation Neuron1.output = Neuron1.input1[count]*Neuron1.weight1 + Neuron1.input2[count]*Neuron1.weight2 - Neuron1.threshold # fonction step Neuron1.output = step_function(Neuron1.output) # control output Control_output(Neuron1.output) |
Fin du tutoriel.