Intelligence artificielle et Deep Learning

Apprentissage machine

John Samuel
CPE Lyon

Année: 2024-2025
Courriel: john.samuel@cpe.fr

Creative Commons License

2.1. Neurones biologiques

Neurones biologiques

Neurone biologique1
  1. https://en.wikipedia.org/wiki/File:Neuron3.png

2.1. Neurones biologiques

Introduction

Réseaux de neurones artificiels

2.1. Neurones biologiques

Aspect Neurone Biologique Neurone Artificiel
Structure Composé de dendrites, d’un soma (corps cellulaire), et d’un axone Composé de poids (équivalents aux connexions), biais, et activation
Fonction Transmet des impulsions électriques entre les neurones Calcule une valeur de sortie en fonction de la somme pondérée des entrées
Entrée Reçoit des signaux par les dendrites Reçoit des valeurs pondérées (par les poids)
Poids des connexions La force des synapses influence l’intensité du signal transmis Les poids déterminent l’importance de chaque entrée

2.1. Neurones biologiques

Aspect Neurone Biologique Neurone Artificiel
Activation Un potentiel d’action est déclenché si le signal dépasse un seuil Une fonction d’activation est appliquée pour déterminer la sortie
Sortie Envoie un signal via l’axone vers d’autres neurones Produit une sortie, souvent transmise aux neurones suivants dans le réseau
Apprentissage Renforce les connexions synaptiques en fonction de l’expérience (plasticité synaptique) Ajuste les poids via des algorithmes d’apprentissage (ex. rétropropagation)
Rôle Participe à des processus cognitifs complexes Contribue aux calculs et à la reconnaissance de motifs

2.1. Neurones biologiques

Réseau de neurones

Les réseaux de neurones sont couramment utilisés dans le domaine de l'apprentissage machine, en particulier dans des tâches telles que la classification, la régression, la reconnaissance d'images, le traitement du langage naturel, et bien d'autres. Un réseau de neurones artificiels est une collection d'unités interconnectées appelées neurones artificiels. Ces réseaux sont inspirés de la structure du cerveau biologique

2.1. Neurones biologiques

Réseau de neurones

2.2. Perceptron

Perceptron

Le perceptron est un algorithme d'apprentissage supervisé utilisé pour la classification binaire. Il est conçu pour résoudre des problèmes où l'objectif est de déterminer si une entrée donnée appartient ou non à une classe particulière.

2.2. Perceptron

Perceptron

Perceptron en mettant à jour sa limite linéaire à mesure que d'autres exemples de formation sont ajoutés.1
  1. Source: https://en.wikipedia.org/wiki/File:Perceptron_example.svg

2.2. Perceptron

Perceptron

Perceptron

2.2. Perceptron

Perceptron: Définition formelle

2.2. Perceptron

Perceptron: Définition formelle

2.2. Perceptron

Perceptron : Étapes

  1. Initialiser les poids et les seuils
  2. Pour chaque exemple, \((x_j, d_j)\) dans l'ensemble d'entraînement
    • Calculer la sortie actuelle : \[y_j(t)= f[w(t).x_j]\] \[= f[w_0(t)x_{j,0} + w_1(t)x_{j,1} + w_2(t)x_{j,2} + \dotsb + w_n(t)x_{j,n}]\]
    • Calculer le poids: \[w_i(t + 1) = w_i(t) + r. (d_j-y_j(t))x_{j,i}\]
    \(r\) est le taux d'apprentissage.

2.2. Perceptron

Perceptron : Étapes

  1. Répétez l'étape 2 jusqu'à l'erreur d'itération \[\frac{1}{s} (Σ |d_j - y_j(t)|)\] est inférieur au seuil spécifié par l'utilisateur \(\gamma\), ou un nombre prédéterminé d'itérations ont été effectuées, où \(s\) est à nouveau la taille de l'ensemble de l'échantillon.

2.2. Perceptron

Fonction d'Échelon (Step Function)

Le perceptron utilise généralement une fonction d'activation simple, et la fonction d'échelon (step function) est fréquemment choisie pour cette tâche.

Définition

La fonction d'échelon attribue une sortie de 1 si la somme pondérée des entrées dépasse un certain seuil, et 0 sinon.

\( f(x) = \begin{cases} 1 & \text{si } x \geq \text{seuil} \\ 0 & \text{sinon} \end{cases} \)

2.2. Perceptron

Perceptron

import numpy as np

class Perceptron:
    def __init__(self, taux_apprentissage=0.01, n_iterations=1000):
        self.taux_apprentissage = taux_apprentissage
        self.n_iterations = n_iterations
        self.poids = None
        self.biais = None

2.2. Perceptron

Perceptron

class Perceptron:

    def ajuster(self, X, y):
        n_exemples, n_caracteristiques = X.shape
        self.poids = np.zeros(n_caracteristiques)
        self.biais = 0

        for _ in range(self.n_iterations):
            for i in range(n_exemples):
                ligne = X[i]
                y_calculé = np.dot(ligne, self.poids) + self.biais
                prediction = 1 if y_calculé >= 0 else 0
                erreur = y[i] - prediction
                # Mise à jour des poids et biais
                self.poids += self.taux_apprentissage * erreur * ligne
                self.biais += self.taux_apprentissage * erreur

2.2. Perceptron

Perceptron


class Perceptron:
    def predire(self, X):
        y_calculé = np.dot(X, self.poids) + self.biais
        return np.where(y_calculé >= 0, 1, 0)

2.2. Perceptron

Perceptron

# Données d'exemple
X = np.array([[1, 1], [2, 2], [1.5, 1.5], [0, 0], [0.5, 0.5], [1, 0]])
y = np.array([1, 1, 1, 0, 0, 0])

# Création et entraînement du perceptron
perceptron = Perceptron(taux_apprentissage=0.1, n_iterations=10)
perceptron.ajuster(X, y)

# Prédiction
print(perceptron.predire(np.array([[1, 1], [0, 0]])))  # Sortie : [1 0]

2.3. Perceptron multicouches

Un MLP est composé de plusieurs couches de neurones. Chaque neurone dans une couche est connecté à tous les neurones de la couche suivante (d’où le nom de “réseau de neurones entièrement connecté”). Un MLP possède typiquement

2.3. Perceptron multicouches

Les poids \( W \) et les biais \( b \) sont initialisés aléatoirement pour chaque connexion entre les neurones. Par exemple, pour une couche \( l \) de \( n_l \) neurones connectée à la couche \( l+1 \) de \( n_{l+1} \) neurones :

2.3. Perceptron multicouches

import numpy as np

# Initialisation de la structure du réseau
couches = [3, 5, 4, 1]  # exemple : 3 neurones d'entrée, 2 couches cachées de 5 et 4 neurones, et 1 neurone de sortie

# Initialisation des poids et biais aléatoires
poids = [np.random.rand(couches[i], couches[i + 1]) for i in range(len(couches) - 1)]
biais = [np.random.rand(1, couches[i + 1]) for i in range(len(couches) - 1)]

2.3. Perceptron multicouches

Propagation Avant

La propagation avant consiste à faire passer les données d’entrée à travers chaque couche du réseau. À chaque neurone, on effectue une combinaison linéaire de ses entrées (poids * entrée + biais) suivie d’une fonction d’activation.

Les fonctions d’activation courantes sont : -

2.3. Perceptron multicouches

Propagation Avant

La propagation avant est le processus par lequel les données d’entrée traversent les couches du réseau. À chaque neurone de la couche \( l \), on calcule une activation basée sur une combinaison linéaire des activations de la couche précédente, suivie d’une fonction d’activation.

Soit \( a^{(l)} \) l’activation de la couche \( l \) :

  1. Combinaison Linéaire : \[ z^{(l+1)} = a^{(l)} W^{(l)} + b^{(l)} \] où \( z^{(l+1)} \) est l’entrée nette pour chaque neurone de la couche \( l+1 \).

2.3. Perceptron multicouches

Propagation Avant

  1. Application de la Fonction d’Activation :
    • Par exemple, pour la fonction d’activation ReLU utilisée dans les couches cachées : \[ a^{(l+1)} = \text{ReLU}(z^{(l+1)}) = \max(0, z^{(l+1)}) \]
    • Pour la couche de sortie, dans un problème de classification binaire, on utilise souvent la fonction sigmoïde : \[ a^{(L)} = \sigma(z^{(L)}) = \frac{1}{1 + e^{-z^{(L)}}} \] où \( L \) représente la dernière couche.

2.3. Perceptron multicouches

# Fonction d'activation Sigmoïde
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# Fonction d'activation ReLU
def relu(x):
    return np.maximum(0, x)

2.3. Perceptron multicouches

# Propagation avant à travers le réseau
def propagation_avant(entree, poids, biais):
    activation = entree
    activations = [activation]  # stocke les activations de chaque couche pour le backprop

    # Propagation à travers chaque couche cachée
    for i in range(len(poids) - 1):
        z = np.dot(activation, poids[i]) + biais[i]
        activation = relu(z)  # on utilise ReLU pour les couches cachées
        activations.append(activation)

    # Couche de sortie (par ex., sigmoid pour une tâche de classification binaire)
    z = np.dot(activation, poids[-1]) + biais[-1]
    activation = sigmoid(z)
    activations.append(activation)

    return activations

2.3. Perceptron multicouches

Calcul de l’erreur

Une fois les prédictions faites, il est essentiel de calculer l’erreur. Dans le cas de la classification binaire, la log-loss ou l’entropie croisée binaire est couramment utilisée. Cette étape permet de quantifier l’écart entre les prédictions et les vraies étiquettes.

2.3. Perceptron multicouches

Calcul de l’erreur

Pour évaluer la qualité des prédictions, on utilise une fonction de perte. Dans le cas d’une tâche de classification binaire, la log-loss (ou entropie croisée binaire) est souvent utilisée.

Si \( y \) est la véritable étiquette et \( \hat{y} \) la prédiction, la perte pour un exemple est donnée par : \[ \text{Perte} = - \left( y \cdot \log(\hat{y}) + (1 - y) \cdot \log(1 - \hat{y}) \right) \]

Pour un ensemble de \( m \) exemples, la perte totale devient : \[ \text{J}(W, b) = -\frac{1}{m} \sum_{i=1}^{m} \left( y^{(i)} \cdot \log(\hat{y}^{(i)}) + (1 - y^{(i)}) \cdot \log(1 - \hat{y}^{(i)}) \right) \]

2.3. Perceptron multicouches

# Fonction de perte (Binary Cross-Entropy)
def calcul_perte(y_pred, y_vrai):
    m = y_vrai.shape[0]
    perte = -np.sum(y_vrai * np.log(y_pred) + (1 - y_vrai) * np.log(1 - y_pred)) / m
    return perte

2.3. Perceptron multicouches

Rétropropagation

La rétropropagation ajuste les poids et les biais en fonction de l’erreur obtenue. Elle utilise le gradient de la perte pour chaque paramètre du réseau, appliqué depuis la couche de sortie jusqu’à la couche d’entrée.

  1. Calcul du gradient pour la couche de sortie.
  2. Propager les gradients en arrière à travers chaque couche cachée en utilisant la dérivée des fonctions d’activation.

La rétropropagation est utilisée pour calculer le gradient de la perte par rapport aux paramètres \( W \) et \( b \), et ajuster ces paramètres pour réduire l’erreur.

2.3. Perceptron multicouches

Rétropropagation: Calcul du Gradient pour la Couche de Sortie

  1. Si \( L \) est la couche de sortie, l’erreur (ou delta) pour cette couche est : \[ \delta^{(L)} = a^{(L)} - y \]
  2. Le gradient de la perte par rapport aux poids de cette couche est alors : \[ \frac{\partial J}{\partial W^{(L-1)}} = (a^{(L-1)})^T \delta^{(L)} \]
  3. Et le gradient de la perte par rapport aux biais : \[ \frac{\partial J}{\partial b^{(L-1)}} = \delta^{(L)} \]

2.3. Perceptron multicouches

Rétropropagation: Calcul des Gradients pour les Couches Cachées

2.3. Perceptron multicouches

Rétropropagation: Mise à Jour des Poids et des Biais

Les poids et les biais sont ajustés à chaque itération pour minimiser la perte en utilisant le **gradient descend** avec un taux d’apprentissage \( \alpha \) :

\[ W^{(l)} := W^{(l)} - \alpha \frac{\partial J}{\partial W^{(l)}} \]

\[ b^{(l)} := b^{(l)} - \alpha \frac{\partial J}{\partial b^{(l)}} \]

2.3. Perceptron multicouches

Rétropropagation

# Fonction de dérivée pour Sigmoïde et ReLU
def derivee_sigmoid(x):
    return x * (1 - x)

def derivee_relu(x):
    return np.where(x > 0, 1, 0)

2.3. Perceptron multicouches

Rétropropagation

# Rétropropagation
def retropropagation(activations, poids, biais, y_vrai, taux_apprentissage=0.01):
    # Étape 1 : Calculer le gradient de la perte pour la couche de sortie
    erreur = activations[-1] - y_vrai
    deltas = [erreur * derivee_sigmoid(activations[-1])]

    # Étape 2 : Calculer les gradients pour chaque couche cachée
    for i in reversed(range(len(poids) - 1)):
        delta = np.dot(deltas[-1], poids[i + 1].T) * derivee_relu(activations[i + 1])
        deltas.append(delta)

2.3. Perceptron multicouches

Rétropropagation

    # Inverser les deltas pour qu'ils correspondent à chaque couche du réseau
    deltas = deltas[::-1]

    # Mise à jour des poids et biais
    for i in range(len(poids)):
        poids[i] -= taux_apprentissage * np.dot(activations[i].T, deltas[i])
        biais[i] -= taux_apprentissage * np.sum(deltas[i], axis=0, keepdims=True)

2.3. Perceptron multicouches

Entraînement

L’entraînement du réseau consiste à itérer sur les étapes de propagation avant, de calcul de l’erreur, et de rétropropagation plusieurs fois (époques) pour ajuster les paramètres et minimiser l’erreur.

2.3. Perceptron multicouches

Entraînement

def entrainer_mlp(X, y, couches, epochs=1000, taux_apprentissage=0.01):
    # Initialisation des poids et biais
    poids = [np.random.rand(couches[i], couches[i + 1]) for i in range(len(couches) - 1)]
    biais = [np.random.rand(1, couches[i + 1]) for i in range(len(couches) - 1)]

    # Boucle d'entraînement
    for epoch in range(epochs):
        # Propagation avant
        activations = propagation_avant(X, poids, biais)
        # Calcul de la perte
        perte = calcul_perte(activations[-1], y)
        # Rétropropagation
        retropropagation(activations, poids, biais, y, taux_apprentissage)
        # Afficher la perte à intervalles réguliers
        if epoch % 100 == 0:
            print(f"Epoch {epoch}, Perte: {perte:.4f}")
    return poids, biais

2.3. Perceptron multicouches

Prédiction

Après l’entraînement, le modèle peut être utilisé pour faire des prédictions sur de nouvelles données en effectuant simplement une propagation avant.

Pour effectuer une prédiction après l'entraînement, on utilise simplement la propagation avant. La sortie de la couche finale \( a^{(L)} \) est interprétée en fonction de la tâche :

Pour la classification binaire, on utilise une règle de décision, par exemple : \[ \hat{y} = \begin{cases} 1 & \text{si } a^{(L)} \geq 0.5 \\ 0 & \text{sinon} \end{cases} \]

2.3. Perceptron multicouches

Prédiction

# Fonction de prédiction
def predire(X, poids, biais):
    activations = propagation_avant(X, poids, biais)
    return activations[-1]

2.3. Perceptron multicouches

Résumé des étapes

  1. Initialisation : Créer et initialiser les poids et biais.
  2. Propagation Avant : Calculer les activations de chaque couche.
  3. Calcul de l’Erreur : Mesurer la différence entre la sortie prédite et la sortie attendue.
  4. Rétropropagation : Calculer les gradients et mettre à jour les poids et biais.
  5. Entraînement : Répéter les étapes précédentes pour minimiser l’erreur.
  6. Prédiction : Utiliser le réseau entraîné pour prédire les sorties de nouvelles entrées.

2.4. Réseaux de neurones artificiels

Les couches

Les neurones sont organisés en couches. Il existe généralement trois types de couches dans un réseau de neurones :

2.4. Réseaux de neurones artificiels

Les couches

2.4. Réseaux de neurones artificiels

L'entraînement

L'objectif global de l'entraînement est d'ajuster les poids du réseau de manière à ce qu'il puisse généraliser à de nouvelles données, produisant des résultats précis pour des exemples qu'il n'a pas vu pendant l'entraînement.

2.4. Réseaux de neurones artificiels

L'entraînement

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

Neurones

Chaque neurone artificiel a des entrées, qui peuvent être les valeurs caractéristiques d'un échantillon de données externe, et produit une seule sortie. Cette sortie peut être envoyée à plusieurs autres neurones, formant ainsi la structure interconnectée du réseau neuronal. La fonction d'activation joue un rôle crucial dans le calcul de la sortie d'un neurone. Le processus comprend les étapes suivantes :

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

Connexions et poids

Le réseau de neurones est constitué de connexions, où chaque connexion transmet la sortie d'un neurone comme entrée à un autre neurone. Chaque connexion possède un poids qui représente son importance relative dans la transmission du signal.

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

Fonction de propagation

Calcul de l'entrée d'un neurone : La fonction de propagation calcule l'entrée d'un neurone en prenant la somme pondérée des sorties de ses prédécesseurs, où chaque sortie est multipliée par le poids de la connexion correspondante. Cela peut être représenté mathématiquement comme suit :

\[ \text{Entrée du Neurone} = \sum_{i=1}^{n} (\text{Sortie du Prédécesseur}_i \times \text{Poids}_i) \] où \(n\) est le nombre de connexions d'entrée.

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

Fonction de propagation

Ajout d'un terme de biais : Un terme de biais peut être ajouté au résultat de la propagation. Le terme de biais est un paramètre supplémentaire, souvent représenté par \(b\) dans les équations, qui permet au modèle d'apprendre un décalage ou une translation. Cela donne la forme finale de l'entrée du neurone :

\[ \text{Entrée du Neurone} = \sum_{i=1}^{n} (\text{Sortie du Prédécesseur}_i \times \text{Poids}_i) + \text{Biais} \]

2.4. Réseaux de neurones artificiels

Composants des réseaux de neurones artificiels

Fonction de propagation

Fonction d'Activation : Après avoir calculé l'entrée du neurone, celle-ci est passée à travers une fonction d'activation. Cette fonction introduit une non-linéarité dans le modèle, permettant au réseau de neurones de capturer des relations complexes et d'apprendre des modèles non linéaires. Certaines des fonctions d'activation couramment utilisées comprennent :

2.4. Réseaux de neurones artificiels

Fonction d'activation: fonction d'identité

Équation

\[f(x)=x\]

Dérivée

\[f'(x)=1\]

Fonction d'identité

2.4. Réseaux de neurones artificiels

Fonction d'activation: pas binaire

Équation

\[f(x) = \begin{cases} 0 & \text{for } x < 0\\ 1 & \text{for } x \ge 0 \end{cases} \]

Dérivée

\[f'(x) = \begin{cases} 0 & \text{for } x \ne 0\\ ? & \text{for } x = 0\end{cases}\]

Pas binaire

2.4. Réseaux de neurones artificiels

Fonction d'activation: fonction sigmoïde

Équation

\[f(x)=\sigma(x)=\frac{1}{1+e^{-x}}\]

Dérivée

\[f'(x)=f(x)(1-f(x))\]

La fonction sigmoïde

2.4. Réseaux de neurones artificiels

Fonction d'activation: TanH

Équation

\[f(x)=\tanh(x)=\frac{(e^{x} - e^{-x})}{(e^{x} + e^{-x})}\]

Dérivée

\[f'(x)=1-f(x)^2\]

TanH

2.4. Réseaux de neurones artificiels

Fonction d'activation: Rectified linear unit: ReLU

Équation

\[f(x) = \begin{cases} 0 & \text{for } x \le 0\\ x & \text{for } x > 0\end{cases} = \max\{0,x\}= x \textbf{1}_{x>0}\]

Dérivée

\[f'(x) = \begin{cases} 0 & \text{for } x \le 0\\ 1 & \text{for } x > 0\end{cases}\]

Unité linéaire rectifiée (ReLU)

2.4. Réseaux de neurones artificiels

Fonction d'activation: Gaussien

Équation

\[f(x)=e^{-x^2}\]

Dérivée

\[f'(x)=-2xe^{-x^2}\]

Gaussien

2.4. Réseaux de neurones artificiels

Perceptron multiclasse

Références

Articles de recherche

Références:

Web

  1. Google acquiert DNNresearch, spécialisé dans les réseaux de neurones profonds: https://www.lemondeinformatique.fr/actualites/lire-google-acquiert-dnnresearch-specialise-dans-les-reseaux-de-neurones-profonds-52829.html
  2. Pourquoi Microsoft rachète Linkedin: https://www.lemondeinformatique.fr/actualites/lire-pourquoi-microsoft-rachete-linkedin-65136.html
  3. Scikit-learn: http://scikit-learn.org/stable/
  4. Perceptron: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Perceptron.html

Références:

Wikipédia

Références:

Wikipédia

Références:

Couleurs

Images