Aller au contenu

Approximer une fonction à l'aide d'un réseau de neurones⚓︎

Les 2 neurones

Nous allons maintenant réaliser un petit réseau de neurones pour approximer la fonction valeur absolue. Pour cela, nous n'utiliserons qu'une seule couche cachée composée de deux neurones. Intuitivement, l'idée est qu'un des neurones servira lorsque le nombre est positif et l'autre lorsque le nombre est négatif.

On codera les paramètres à l'aide d'une liste [a01, a02, a13, a23, b1, b2, b3]\(a_{ij}\) est le poids entre le neurone \(i\) et le neurone \(j\). Les \(b_i\) sont les biais des neurones \(N_1\) à \(N_3\). La fonction d'activation utilisée pour les neurones \(N_1\) et \(N_2\) sera une ReLU :

Fonction d'activation ReLU
def relu(x):
    return max(0, x)
Calcul des résultats

L'image d'un nombre par le réseau de neurone est donné par la fonction suivante :

Utiliser le réseau de neurones
def calcule_resultat(x, coeffs):
    a01, a02, a13, a23, b1, b2, b3 = coeffs
    y1 = relu(a01*x + b1)
    y2 = relu(a02*x + b2)
    return a13*y1 + a23*y2 + b3

On peut remarquer que les coefficients #py [1, -1, 1, 1, 0, 0, 0] permettent d'obtenir exactement la fonction valeur absolue :

Exemples
>>> calcule_resultat(5, [1, -1, 1, 1, 0, 0, 0])
5
>>> calcule_resultat(-5, [1, -1, 1, 1, 0, 0, 0])
5
Exercice 8

Écrire le code de la fonction calcule_cout qui prend en paramètres 3 listes de nombres xi, yi et coeffs et qui calcule le coût, avec la méthode des moindres carrés, du réseau de neurones avec les paramètres coeffs et le nuage de points défini par xi et yi.

Exemples
>>> calcule_cout(xi2, yi2, [1, -1, 1, 1, 0, 0, 0])
0.0
>>> calcule_cout(xi2, yi2, [1, 0, 1, 1, 0, 0, 0])
5.0
>>> calcule_cout(xi2, yi2, [0, 0, 0, 0, 0, 0, 0])
10.0
>>> calcule_cout(xi2, yi2, [0, 0, 1, 1, 1, 1, 2])
4.181818181818182

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : 5/5

.12801340mtP7s*lig+dav hw[(. b_S=):2o3c"1]yx5n-,pfrek/u6010f0L060g0c0b090i0y0b0g09090s0z060c0I0z000o01090O05050g0K0C000r0w0b0O0(0w0F010N0/0;0?0^0-0f0c0h0i0=0K0M0f0w0k0F0&0A0z0i09060C0b0L0&1d0d0c0F0u0A0n080L050i0A1C1m0,0Q1a0Y0!0$0&0j0c0d0j0b1Q0j060+010T0p1r1L0#0%0z1P1R1T1R061Z1r1X060K001Y0j0Y0{090I0g1j0z0v1m0Z1%0&0J0V0L0F0g050L1X1`1|1$1N0z251r282a0+020i070K0w0I0w090c0~0F0i0R1^0K0K0L0y2w122d0F1=0N060j2J1:1=2O1Y0f2f1&1T0F272t1X191b222g2V2X2!1X0I2C1=2H2J2-0.1{2x2$1&0F0w0K0=0b0+0A2G2;1I2H2T0&2^2`0g2|000v301|322;340z362{0+0x3c2I0-332?352_3j00033m3e2e3q3h3s380+0E3w3o3f3z3i3C000P3F2:3y1M2@3B39083w122*0L2J2!2N0f2P2S3z0y0w0R2Z1a1=3X2,313V3(0R3/3P230z0M0+0R0J3w0i3O2=3Q350J0+0y380y0O1r0q3(0}3V3p440z0*000m4g3H4i0F0+0D0c4n3^2g4k0H40423g4q000C4t133:4h3_4x4z4I2g4C3(0L0J0J094u434J0+0t0u3F0i4#414M2@470w4f4G3d4%4o3_0w0+0s4L4.2g050c0+044!4$4A3I0+114+2I4-4v1&4:004=5400564V4N0p0+2j4U3g4k4m5c504p4r4F2/4&0&4k0t4}4#5p3_3{000J2_4?57350+5s315e3g1h5J532-5M3I5h000K1|0d0L5k3z5m5!5q005Q4H4@1&5w4Z5c0o4$5:5S5&0C5G5f584;5^4B47494b0L0q2C0/0b0T065%4W4l694N5r6c5+0+0l6f5I005K3d5A4w0+0B4y5c5=3_4O0w4Q4S6j4j4X5y5;6o4'004e686t6F0&595b5R6L3h4(4*6P5u0z590e5|5#0+5n5t5*6k5@6K6V590G6Z5?6m2I6Q4k6i5o6V4C6/3@5_5v6q5x6@6&6W0+0a0a6A4_0+3b5.5:6Q5C2C060O0K5(4,6Q6w6T5L6Q590N6-6v523N0N3=3Y3W2+123!12063$7D1;7D0g1!7y0N3!0-7M3,7O0R0T0V0900
Pour visualiser le résultat

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : /∞

Le tracé sera affiché ici

Rétropropagation et apprentissage

Pour pouvoir faire la rétropropagation, il faut pouvoir calculer les dérivées de la fonction de coût par rapport à chaque paramètre. Normalement, on utilise des fonctions qui calculent de façon exacte les dérivées. Pour simplifier le problème, nous utiliserons des valeurs approchées. Pour éviter de calculer le coût pour chaque paramètre, on le passe en paramètre de la fonction.

Calcul de la dérivée
def derivee(xi, yi, coeffs, k, cout, h=0.0001):
    coeffs2 = coeffs.copy()
    coeffs2[k] += h
    return (calcule_cout(xi, yi, coeffs2)-cout) / h

On fait maintenant une fonction qui calcule les nouvelles valeurs des paramètres :

Rétropropagation des modifications
def mise_a_jour(xi, yi, coeffs, c, pas=0.1):
    deltas = []
    c = calcule_cout(xi, yi, coeffs)
    for k in range(len(coeffs)):
        deltas.append(pas * derivee(xi, yi, coeffs, k, c))
    return [coeffs[i] - deltas[i] for i in range(len(coeffs))]

Et enfin, on peut faire l’apprentissage :

Apprentissage
def apprentissage(xi, yi, coeffs, pas=1, seuil=0.00001, nmax=10000):
    n = 0 # compteur d'étapes
    while pas > seuil:
        cout = calcule_cout(xi, yi, coeffs)
        coeffs2 = mise_a_jour(xi, yi, coeffs, cout, pas)
        cout2 = calcule_cout(xi, yi, coeffs2)
        if cout2 > cout: # On s'éloigne du minimum
            pas = pas / 2
        else:
            cout = cout2
            coeffs = coeffs2
        n += 1
        if n > nmax: # on a dépassé le nombre max d'étapes
            break
    return coeffs2
Exercice 9

Vous pouvez maintenant tester l'apprentissage de notre réseau. Il se peut que le réseau ne converge pas tout à fait vers les valeurs attendues. Vous pouvez tester plusieurs fois jusqu’à obtenir le résultat voulu. Vous pouvez alors regarder les valeurs des coefficients.

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Évaluations restantes : /∞

Le tracé sera affiché ici

Pour aller plus loin

Vous pouvez tester ce fichier qui permet d'approximer des fonctions booléennes à deux paramètres à l'aide d'un réseau de neurones pouvant avoir plusieurs couches.

Vous pouvez aussi aller voir la fantastique série de vidéos de 3Blue1Brown sur les réseaux de neurones sur sa chaîne Youtube.