Ce projet implémente un réseau de neurones à 3 couches (entrée, cachée, sortie) entièrement from scratch, sans utiliser de bibliothèques externes comme NumPy, TensorFlow ou PyTorch.
Objectif : comprendre en profondeur les mécanismes internes d’un perceptron multicouche, du forward pass à la backpropagation, en réimplémentant toutes les opérations mathématiques de base.
Comme tout projet "from scratch", j’ai rencontré plusieurs défis techniques :
-
Implémentation des fonctions mathématiques
- Exemple : ma fonction
ln(x)était incorrecte → j’ai appris l’importance des méthodes numériques (séries de Taylor, Newton-Raphson). - Le calcul de l’outer product était en réalité une multiplication élément-par-élément.
- Exemple : ma fonction
-
Stabilité numérique du softmax
- Premier essai :
exp(x)→ OverflowError quand les valeurs étaient trop grandes. - Solution : stabilisation par soustraction du max avant exponentiation.
- Premier essai :
-
Propagation arrière (backpropagation)
- Difficultés d’alignement des dimensions dans
dz2et dans les produits matriciels. - Solution : ajout de contrôles de formes et debug pas à pas.
- Difficultés d’alignement des dimensions dans
-
Prétraitement des données
- Erreur d’ordre dans la normalisation et la transposition.
- Correction après tests unitaires ligne par ligne.
-
Implémentation récursive de certaines fonctions (ex: pow)
- Fonctionnelle mais inefficace → risque de stack overflow pour grandes puissances.
- J’ai appris l’importance de choisir un algorithme adapté (itératif, exponentiation rapide).
-
RNG (Random Number Generator)
- Mon shuffle initial n’était pas un vrai Fisher-Yates → biais dans les données d’entraînement.
- Solution : corriger la borne de la boucle.
- Reproduire les algorithmes de base permet de comprendre pourquoi les frameworks comme NumPy/TensorFlow existent.
- Les erreurs m’ont obligé à investiguer la stabilité numérique et la rigueur des dimensions matricielles.
- Cette expérience m’a permis d’acquérir des réflexes de debug scientifique (impressions intermédiaires, tests unitaires, vérification empirique).
- Car la difference entre mon implementation et une implementation realisé avec TF est flagrante, c'est deux fois plus lent d'ou l'existence de ces algorithmes d'optimisations et frameworks
- Implémentation complète des opérations mathématiques (produit matriciel, softmax, relu, normalisation, etc.)
- Initialisation aléatoire des poids et biais
- Entraînement via gradient descent
- Fonctions d’activation ReLU et Softmax
- Évaluation de la précision (accuracy)
- Sauvegarde et chargement du modèle via
pickle
- Langage : Python pur
- Bibliothèques utilisées : uniquement
pickleettime(aucune dépendance ML externe) - Dataset : CSV inspiré de MNIST (images de chiffres manuscrits), réduit à :
- 1000 échantillons pour l’entraînement
- 200 échantillons pour le test
- Accuracy atteinte sur dataset réduit : ~85% (selon nombre d’epochs/learning rate)
- Preuve que l’architecture et l’algorithme de backpropagation sont correctement implémentés.
- Reproduction fonctionnelle d’un mini-MNIST classifier sans frameworks externes.
- Fonctionnement interne d’un perceptron multicouche (MLP)
- Implémentation manuelle de la backpropagation et de la descente de gradient
- Gestion des matrices et opérations mathématiques fondamentales en Python
- Optimisation et normalisation des données pour l’entraînement
git clone https://github.com/InputOutputStream/scratch_neural_network.git
cd scratch_neural_network
python main.pyfrom model import Model
model = Model(input_size=784, hidden_size=100, output_size=10)
model.fit(X_train, y_train, eval=10, epochs=100, lr=0.1, show_training_info=True)
model.save('model.pkl') loaded_model = Model.load('model.pkl')
predictions = loaded_model.predict(X_test) print("Accuracy:", loaded_model.get_accuracy(predictions, y_test))