Accueil » Développeur » Tutoriels » Tutoriels MRPiZ » Gestion des obstacles avec neurone artificiel

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.