Perceptron

Un article de Wikipédia, l'encyclopédie libre.
Aller à : navigation, rechercher

Le perceptron a été inventé en 1957 par Frank Rosenblatt au laboratoire d'aéronautique de l'université Cornell. C'est un modèle inspiré des théories cognitives de Friedrich Hayek et de Donald Hebb.

Définition[modifier | modifier le code]

Perceptron avec 2 entrées et une fonction d'activation à seuil

Le perceptron peut être vu comme le type de réseau de neurones le plus simple. C'est un classifieur linéaire. Ce type de réseau neuronal ne contient aucun cycle (en anglais feedforward neural network). Dans sa version simplifiée, le perceptron est mono-couche et n'a qu'une seule sortie à laquelle toutes les entrées sont connectées. Les entrées et la sortie sont booléennes.

Le potentiel post-synaptique biaisé est représenté par Z = \sum W_i X_i - \theta. Ici, θ définit le seuil (ou biais) à dépasser pour que la sortie Y soit à 1, et W_i est le poids de l'entrée X_i.

La fonction d'activation est la fonction de Heaviside (la fonction signe est parfois utilisée)

Y = H(Z)=\left\{\begin{matrix} 0 & \mathrm{si} & Z < 0 \\ 1 & \mathrm{si} & Z \ge 0\end{matrix}\right.

La règle de Hebb[modifier | modifier le code]

La règle de Hebb établie par Donald Hebb est une règle d'apprentissage des réseaux de neurones artificiels dans le contexte de l'étude d'assemblées de neurones.

Cette règle suggère que lorsque deux neurones sont excités conjointement, il se crée ou renforce un lien les unissant.

Dans le cas d'un neurone artificiel seul utilisant la fonction signe comme fonction d'activation cela signifie que :

W'_i = W_i + \alpha (Y . X_i)

W'_i représente le poids i corrigé et \alpha représente le pas d'apprentissage.

Cette règle n'est malheureusement pas applicable dans certains cas bien que la solution existe.

La règle d'apprentissage du perceptron[modifier | modifier le code]

Le perceptron de Frank Rosenblatt est très proche de la règle de Hebb, la grande différence étant qu'il tient compte de l'erreur observée en sortie.

W'_i = W_i + \alpha (Y_t - Y)  X_i

Y_t représente la sortie attendue, W'_i le poids i corrigé et \alpha le pas d'apprentissage.

Exemple de programme[modifier | modifier le code]

Ceci est un programme en C++, apprenant la fonction NAND appliquée à un ensemble de 2 bits (x1 et x2), auxquels on rajoute 1 bit (x0), qui est une constante à 1, on a donc 100,101,110,111 comme inputs, les résultats attendus étant respectivement 1,1,1,0. Pour une autre fonction (AND, OR ou NOR mais pas le XOR en raison des limitations du perceptron), le seul changement à opérer est le tableau des résultats attendus.

Le programme fonctionne par cycles où chaque exemple est testé une fois, tant que tous les exemples ne sont pas corrects (résultat produit = résultat attendu) dans le cycle, on en refait un. Par contre les poids sont modifiés à chaque exemple qui s'avère incorrect. Ils sont ici initialisés à 0, mais on pourrait tout aussi bien les mettre à 1 ou encore à une valeur aléatoire, cela modifie juste le nombre d'étapes avant d'arriver au résultat.

#include <iostream>
 
using namespace std;
 
int const X(3);         // x1 et x2 les entrées, x0 est une constante à 1
int const NB_EX(4);  	// nombre d'exemples donnés
float const SEUIL(0.5);	// seuil d'activation
float const PAS(0.1); 	// le pas d'apprentissage
 
void affichage(float*,int,int,int);      // affiche l'état actuel des poids
 
int main () {
 
   int tabEntree[NB_EX][X] = { {1,0,0},{1,0,1},{1,1,0},{1,1,1} }; // les exemples donnés avec x0, x1, x2
   int tabResPrevu[NB_EX] = {1,1,1,0}; // les résultats prévus correspondant aux entrées
   float tabPoids[X] = {0,0,0};        // les poids synaptiques
   int res, cptrCycle(0);     // res est le résultat produit, à comparer au résultat prévu
   float somme(0);                     // la somme pondérée
   bool erreurs(true);                 // pour détecter fin apprentissage
 
   affichage(tabPoids,X,0,cptrCycle);
 
   // Phase d'apprentissage
   while (erreurs) {                // on continue tant qu'on a au moins une erreur par cycle
      erreurs = false;
      cptrCycle++;
 
      for (int j=0; j<NB_EX; j++) {         // un cycle
         somme = 0;
 
	 for(int i=0; i<X; i++) {
	    somme += tabEntree[j][i] * tabPoids[i];  // somme pondérée de l'exemple
         }
         res = (somme > SEUIL) ? 1 : 0;  // fonction de seuil
 
         for (int i=0; i<X; i++) {
             tabPoids[i] += (tabResPrevu[j]-res) * PAS * tabEntree[j][i]; // modification des poids
         }
	 erreurs |= ((tabResPrevu[j] - res) != 0);   // détection de fin d'apprentissage
 
         affichage(tabPoids,X,j,cptrCycle);
      }
   }
   cout << "Apprentissage terminé en " << cptrCycle << " cycles" << endl;
   return 0;
}
 
void affichage(float* poids, int n, int cptr, int cptr2) {
   int i;
   cout << "----- Cycle " << cptr2 << " Etape " << cptr << " -----" << endl;
   for (i=0; i<n; i++) {
      cout << "poids[" << i << "] = " << poids[i] << endl;
   }
}

Le même programme en Ruby

SEUIL = 0.5
PAS = 0.1
 
poids = Array.new [0,0,0]
Entrees = Array.new [ [1,0,0], [1,0,1], [1,1,0], [1,1,1] ]
Reponses = Array.new [ 1, 1, 1, 0 ]
 
def afficher(poids, cycle, etape)
  p "--- Cycle #{cycle} - Etape #{etape}"
  poids.each_index do |i|
    p "Poids #{i} = #{poids[i]}"
  end
end
 
cycle_n = 0
erreur = true
while erreur do
  erreur = false
 
  4.times do |exemple_n|
 
    # Prediction
    somme = 0
    3.times do |i|
      somme += poids[i] * Entrees[exemple_n][i] 
    end
    resultat = if (somme > SEUIL) then 1 else 0 end
 
    # Correction
    diff = Reponses[exemple_n] - resultat
    3.times do |i|
      poids[i] += PAS * diff * Entrees[exemple_n][i]
    end
 
 
     erreur = true if Reponses[exemple_n] != resultat
 
    afficher(poids, exemple_n, cycle_n)
 
  end
 
  cycle_n = cycle_n + 1
end
 
p "Apprentissage terminé en #{cycle_n} cycles"

Voir aussi[modifier | modifier le code]

Le perceptron : Algorithme et théorèmes

Réseau neuronal artificiel

Bibliographie[modifier | modifier le code]

  • F. Rosenblatt (1958), "The perceptron: a probabilistic model for information storage and organization in the brain",
- repris dans J.A. Anderson & E. Rosenfeld (1988), Neurocomputing. Foundations of Research, MIT Press