# Perceptron Simple
Un perceptron est un neurone artificiel avec un mécanisme d'apprentissage supervisé.
Découvert par Frank Rosenblatt en simulant le neurone artificiel sur une machine IBM 704
Le nombre d'entrées du Perceptron ($x_1$, $x_2$, $x_3$, ...) peut être infini, mais le Perceptron n'aura toujours qu'une seule sortie ($y$). Étant donné que le perceptron ne contient qu'un seul neurone, il n'est capable de sortir qu'une réponse binaire, ce qui veut dire qu'il ne peut faire que de la classification à $2$ classes.
## Structure du Perceptron
Structure classique d'un neurone, avec l'utilisation de la fonction en escalier qui va limiter les valeurs possibles de sortie à $0$ ou $1$.

Voici le procédé qu'un Perceptron utilise pour transformer un exemple d'entrée ($X$) en signal de sortie ($Y$) :
1. On assigne chaque donnée de l'exemple du dataset à une entrée ($x_1$, $x_2$, $x_3$, ...). Dans notre cas, on utilise des points dans un espace 2D, donc $x_1 = \text{ Coordonnee x du point d'exemple}$ et $x_2 = \text{ Coordonnee y du point d'exemple}$ pour la classification.
2. On multiplie chaque entrée par le poids synaptique correspondant ($x_1 \times w_1$, $x_2 \times w_2$, ...), sans oublier l'entrée fictive ($1 \times w_0$).
3. On additionne le tout ($(1 \times w_1) + (x_1 \times w_1) + (x_2 \times w_2) + \cdots$), ce qui donne le *potentiel* ($p$).
4. On passe le potentiel dans la fonction d'activation qui, dans le cas du Perceptron, est la fonction en escalier. Cela revient à faire : si $p < 0$ alors le Perceptron retourne $0$, sinon le Perceptron retourne $1$. Le résultat du Perceptron est le signal $y$.
## Fonctionnement de l'entraînement
1. On initialise les poids synaptiques. Il existe plusieurs manières de les initialiser, ici PerceptronViewer permet de choisir entre "zeros" et "random" (aléatoire). Il n'y a pas beaucoup de différence entre les deux méthodes, si ce n'est qu'avec l'initialisation à $0$, l'on peux reproduire le comportement de l'entraînement. Cette reproductibilité permet de voir directement l'impact de modifications des autres paramètres d'entraînement.
2. On commence l'entraînement : pour chaque exemple du dataset choisis, on évalue la sortie du Perceptron ($y$), avec le procédé vu plus haut. Le passage sur tous les exemples du dataset s'appelle une **époque** ("epoch" en anglais).
3. On fait le calcul de l'erreur (notée $e$), en soustrayant la sortie du Perceptron à la sortie attendue (le *label*). Cela revient à $e = \text{ label } - y$. Si le perceptron a bien estimé la sortie, alors l'erreur est de $0$. Dans le cas contraire où le Perceptron n'a pas bien estimé la sortie, l'erreur est de $1$ ou $-1$.
4. Si l'erreur n'est pas nulle ($\neq 0$), alors on *corrige les poids synaptiques* du Perceptron ($w_0$, $w_1$, $w_2$, ...) comme suit pour chaque poids synaptique :
- Ajouter à la valeur du poids l'erreur multipliée par la valeur de l'exemple assignée à l'entrée, multipliée par une variable nommée **Taux d'apprentissage** (notée $\eta$). Ce qui donne : $w_i' = w_i + \eta \times (\text{label } - y) \times x_i$ pour tout poids synaptique $i$ où $w_i'$ est le poids synaptique corrigé et $x_i$ est l'entrée numéro $i$. Le taux d'apprentissage est défini par le développeur et est un paramètre très important comme on le verra par la suite.
5. Une fois tous les exemples du dataset parcourus. Si le Perceptron a commis une erreur ($e \neq 0$) pour un des exemples de ce dataset, alors l'entraînement n'est pas terminé et l'on recommence à partir du point 2. Si le Perceptron n'a pas commis d'erreur, alors l'entraînement est terminé.
Afin d'éviter que le Perceptron ne s'entraîne sans s'arrêter pour les datasets impossibles, un paramètre **Nombre maximum d'époques** a été ajouté. L'entraînement s'arrêtera si le nombre d'époques maximal a été atteint.
Il est temps de tester ! Essayez de lancer un entraînement avec :
- Dataset : `Classification - Porte logique ET (linéairement séparable)`
Puis cliquez sur "Lancer" tout en laissant les autres paramètres intacts. Le Perceptron devrait vite converger et trouver une solution (de 3 à 8 époques d'après mes tests).
Le graphe du dessus montre le dataset avec chaque donnée représentée comme un point ayant la couleur de la classe correspondante. Dans le cas du dataset de la porte logique ET, il n'y a qu'un seul point faisant partie de la classe 1.
⚠️ Le nommage des classes est arbitraire et ne représente pas l'étiquette. La ligne de décision (en blanc) représente la bordure entre la zone où le Perceptron va considérer le point comme faisant partie de la classe A ou B. Comme on peut le voir, la ligne de décision est très proche des points, c'est une des limites dont nous parlerons plus bas.
Le graphe du dessous montre les erreurs faites par le perceptron, chaque bâton représente une époque, avec chaque bloc de couleur représentant l'erreur pour l'exemple correspondant. Le graphe contient aussi une ligne de l'**Erreur quadratique moyenne de l'époque** qui est une métrique utilisée pour examiner l'évolution de l'erreur du réseau de neurones sur le dataset à chaque époque. Comme on va le voir plus loin, cette métrique permet de mieux comprendre ce qu'il se passe durant l'entraînement et de juger les modifications nécessaires. Pour l'instant, on peut voir que cette métrique tombe à $0$ à la dernière époque, ce qui montre que le Perceptron ne fait plus d'erreurs sur le dataset et a donc terminé son entraînement.
## Comment choisir un dataset ?
Comme vous pouvez le voir dans la liste déroulante "Dataset", il en existe plusieurs types. Voici leurs significations :
### Classification VS Régression
Comme écrit dans l'introduction, la classification et la régression sont deux types de problèmes que les réseaux de neurones que nous voyons ici peuvent résoudre. Comme tous les datasets contiennent des points en 2D, cela veux dire :
- Pour la classification, le Perceptron va avoir 2 entrées ($x_1 = \text{ Coordonnee x du point d'exemple}$ et $x_2 = \text{ Coordonnee y du point d'exemple}$) et une sortie qui indique si le point fait partie d'une classe A ou B.
- Pour la régression, le Perceptron va avoir 1 entrée ($x_1 = \text{ Coordonnee x du point d'exemple}$) et la sortie représentera la coordonnée y du point d'exemple puisqu'il n'y a qu'une seule classe dans un dataset de régression.
### Classification : linéairement séparable ou non linéairement séparable
La notion de séparabilité linéaire dans la classification fait référence à la capacité d'un modèle à séparer les classes par un plan (ou une frontière) simple. Si les données sont linéairement séparables, cela veut dire qu'elles peuvent être séparées à l'aide d'une fonction mathématique linéaire (une droite).
## Limitations du Perceptron
Étant donné que sa sortie est binaire, le Perceptron présente deux limitations fondamentales :
- Il est incapable de faire de la régression. Car il s'arrête dès qu'il ne fait plus d'erreurs, mais avec une seule classe, il est impossible de faire une erreur.
- Il est incapable de faire de la classification à plus de deux classes différentes.
La limite de décision du Perceptron est souvent collée aux points. Une solution parfaite mettrait la limite à égale distance entre les points des deux classes. Cele est dû à l'entraînement qui s'arrête au moment où il n'y a plus d'erreurs, sans chercher à "optimiser" ou "généraliser" la solution.
Pour voir le perceptron qui colle les points, essayez de lancer un entraînement avec :
- Dataset : `Classification - Oblique (linéairement séparable)`
L'on peut voir que l'entraînement dure déjà plus longtemps car il faut que le Perceptron trouve une pente et une hauteur qui fait passer la droite de décision dans un "trou" plus étroit. Mais l'on voit également que le Perceptron va coller les points à l'entrée et à la sortie de ce "trou".
Ces limitations ont été éliminées par [la descente du gradient](/perceptron?type=gradientdescent) qui utilise des entrées et des sorties réelles.