Problème : mon réseau de neurone from scratch ne converge pas

Je ne sait pas si c’est le bon endroit pour poster ça, mais mon réseaude de neurone reffuse de converger vers les valeurs que je souhaite, voicie le code python :
import random
import numpy as np
import math
import joblib

class connection:
def init(self, weight, neurin, neurout):
self.weight = weight
self.neurin = neurin # neurone de départ
self.neurout = neurout # neurone d’arrivée
self.valout = 0 # stocke la valeur de sortie
# fait en sorte que les neurones contiennent leurs connexions
neurin.connectout.append(self)
neurout.connectin.append(self)

def getout(self, val):
    self.valout = val * self.weight
    # Clipping de la valeur pour éviter des overflow
    self.valout = np.clip(self.valout, -1e6, 1e6)  # Limiter les sorties extrêmes
    self.neurout.signal(self.valout)

def updt(self, delta, rate, weight_clip=1):
    # Calcul de l'update de poids
    nd = delta * self.neurin.sigy  # Gradient local
    self.neurin.backprop(nd, self.weight, rate)  # Propagation vers les entrées
    # Mise à jour du poids avec clipping
    self.weight -= rate * nd
    self.weight = np.clip(self.weight, -weight_clip, weight_clip)  # Clipping des poids

class neurone:
def init(self, act, lamb, bias):
self.connectin = # connexions entrantes
self.connectout = # connexions sortantes
self.bias = bias
self.lamb = lamb
self.act = act # fonction d’activation
self.sig = # accumulation des signaux d’entrée
self.sigy = 0
self.nsig = 0
self.deltaback = 0

def inisignal(self, signal):
    # Passe le signal dans la fonction d'activation
    sign = self.act(signal, self.bias, self.lamb)
    for c in self.connectout:
        c.getout(sign)
    self.sigy = sign

def signal(self, signal):
    self.sig.append(signal)
    if len(self.sig) == len(self.connectin):  # Tous les signaux d'entrée sont reçus
        total_signal = sum(self.sig)
        self.sig = []
        self.nsig = total_signal
        self.inisignal(total_signal)

def inibackprop(self, err, rate):
    De = self.act(self.nsig, self.bias, self.lamb, 1) * err
    self.deltaback = De
    # Mise à jour du biais
    self.bias -= rate * De  # Mise à jour du biais avec gradient
    for c in self.connectin:
        c.updt(De, rate)

def backprop(self, delta, w, rate):
    self.sig.append(delta * w)
    if len(self.sig) == len(self.connectout):  # Tous les deltas sont reçus
        total_error = sum(self.sig)
        self.sig = []
        self.inibackprop(total_error, rate)

class layered_network:
def init(self, nb_in, nb_out, nb_hidden, nb_perhidden, maxlamb, maxbias, maxstreigh, fonctex, foncthid):
self.layers =
# Initialisation des couches d’entrée
In = [neurone(fonctex, random.uniform(0.1, maxlamb), random.uniform(0.1, maxbias)) for _ in range(nb_in)]
self.layers.append(In)
# Initialisation des couches cachées
for _ in range(nb_hidden):
hidden_layer = [neurone(foncthid, random.uniform(0.1, maxlamb), random.uniform(0.1, maxbias))
for _ in range(nb_perhidden)]
self.layers.append(hidden_layer)
# Initialisation des couches de sortie
Out = [neurone(fonctex, random.uniform(0.1, maxlamb), random.uniform(0.1, maxbias)) for _ in range(nb_out)]
self.layers.append(Out)
# Création des connexions entre les couches
for i in range(len(self.layers) - 1):
L1, L2 = self.layers[i], self.layers[i + 1]
for n1 in L1:
for n2 in L2:
C = connection(random.uniform(-maxstreigh, maxstreigh), n1, n2)

def getoutput(self, Input):
    for i, val in enumerate(Input):
        self.layers[0][i].inisignal(val)
    return [n.sigy for n in self.layers[-1]]

def onelearn(self, Input, expected, rate):
    output = self.getoutput(Input)
    dif = np.array(output) - np.array(expected)
    for i, n in enumerate(self.layers[-1]):
        n.inibackprop(dif[i], rate)

def multilearn(self, Input, expected, rate):
    for i, I in enumerate(Input):
        self.onelearn(I, expected[i], rate)

def cyclelearn(self, Input, expected, rate, nb):
    for i in range(nb):
        # Décroissant cosinusoïdal
        self.multilearn(Input, expected, rate*abs(i/30))

def moyError(self, Input, expected):
    R = []
    for i in range(len(Input)):
        output = self.getoutput(Input[i])
        err = np.average(np.abs(np.array(output) - np.array(expected[i])))
        R.append(err)
    return np.average(R)

def save(self, dir):
    saveobject(dir, self.layers)

def load(self, dir):
    self.layers = loadobject(dir)

def Csigmoid(signal, bias, lamb, mod=0):
max_input = 500
input_val = -(signal + bias) * lamb
input_val = np.clip(input_val, -max_input, max_input)
n = np.exp(input_val)
if mod == 0:
return 100 / (1 + n)
elif mod == 1:
sigmoid_val = 100 / (1 + n)
return lamb * n * (sigmoid_val ** 2)

def tanh(signal, bias, lamb, mod=0):
max_input = 100
input_val = (signal + bias) * lamb
input_val = np.clip(input_val, -max_input, max_input)
if mod == 0:
return np.tanh(input_val)
elif mod == 1:
return lamb * (1 - np.tanh(input_val) ** 2)

def relu(signal, bias, lamb, mod=0):
if mod == 0:
a = signal + bias * lamb
return a if a > 0 else 0
if mod == 1:
return lamb if signal + bias > 0 else 0

def Lrelu(signal, bias, lamb, mod=0):
if mod == 0:
return lamb * (signal + bias) if signal + bias > 0 else (signal + bias) / lamb
if mod == 1:
return lamb if signal + bias > 0 else 1 / lamb

def saveobject(Dir, obj):
with open(Dir, « wb ») as F:
joblib.dump(obj, F)

def loadobject(Dir):
with open(Dir, « rb ») as F:
return joblib.load(F)

je ne comprend pourquoi ça ne marche pas…