diff --git a/perceptron-tp3.py b/perceptron-tp3.py
new file mode 100644
index 0000000000000000000000000000000000000000..1a82b67b89d8f5e801418aa45227ac371f2d54e9
--- /dev/null
+++ b/perceptron-tp3.py
@@ -0,0 +1,93 @@
+# Author : Capt Thibault , Souza Luz Juliano
+# Date : 31.10.2023
+# Project : Perceptron
+# Description : Ce fichier représente notre travail pour le tp du perceptron
+import numpy as np
+import pandas as pd
+from matplotlib import pyplot as plt
+
+
+def upd_weights(wi_old, learning, t, y, xi):
+    """
+    Mettre à jour les poids
+    :param wi_old: Les anciens poids
+    :param learning: Le taux d'apprentissage ( qui contrôle la vitesse de convergence)
+    :param t: La valeur cible
+    :param y: La sortie actuelle du modèle pour l'exemple donné
+    :param xi: Les caractéristiques de l'exemple d'apprentissage
+    :return: Les poids mis à jour
+    """
+    return wi_old + learning * (t - y) * y * (1 - y) * xi
+
+
+def sigmoide(x):
+    """
+    Calcule la fonction sigmoïde (fonction d'activation) pour une valeur x
+    :param x: La valeur d'entrée.
+    :return: La sigmoide en fonction de x.
+    """
+    return 1 / (1 + np.exp(-x))
+
+
+if __name__ == '__main__':
+    dataset = pd.read_csv("Data/student-data-train.csv", header=0)
+    # Normalisation des colonnes
+    dataset['norm_grade_1'] = (dataset['grade_1'] - dataset['grade_1'].mean()) / dataset['grade_1'].std()
+    dataset['norm_grade_2'] = (dataset['grade_2'] - dataset['grade_2'].mean()) / dataset['grade_2'].std()
+
+    # Extraction des données
+    X = dataset[['norm_grade_1', 'norm_grade_2']].values
+    y = dataset.iloc[:, 0].values
+    num_features = X.shape[1]
+    # ------------------- Paramètres ------------------
+    learning_rate = 1e-2  # Taux d'apprentissage
+    max_iterations = 5
+    # Initialisation aléatoire des poids (+1 pour le biais)
+    poids = [np.random.uniform(-0.5, 0.5) for _ in range(num_features + 1)]
+    print("Poids initiaux:", poids)
+    # Boucle d'apprentissage
+    for iteration in range(max_iterations):
+        total_error = 0
+        for i in range(len(X)):
+            # Ajout du biais (X0 = 1)
+            input_data = np.insert(X[i], 0, 1)
+            cible = y[i]
+            # Calcul de la sortie du réseau
+            sortie = sigmoide(np.dot(poids, input_data))
+            # Mise à jour des poids
+            poids = upd_weights(poids, learning_rate, cible, sortie, input_data)
+            # Calcul de l'erreur quadratique
+            total_error += (cible - sortie) ** 2
+
+        # Affichage de l'erreur à chaque itération (à enlever pour de meilleures performances)
+        print(f"Iteration {iteration + 1}: Erreur = {total_error}")
+
+    # Calcul du taux de classification correcte
+    correct_classifications = 0
+    for i in range(len(X)):
+        input_data = np.insert(X[i], 0, 1)
+        cible = y[i]
+        sortie = sigmoide(np.dot(poids, input_data))
+        pred = 1 if sortie >= 0.5 else 0
+        if pred == cible:
+            correct_classifications += 1
+
+    accuracy = correct_classifications / len(X)
+    print(f"Taux de classifications correctes: {accuracy * 100}%")
+
+    # Affichage de la droite de séparation des classes
+    w1, w2, b = poids[1], poids[2], poids[0]
+    pente = -w1 / w2
+    intercept = -b / w2
+    print(f"Droite de séparation: y = {pente}x + {intercept}")
+
+    # Tracer la droite de séparation (diagonale)
+    plt.figure()
+    plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='red', label='Classe 0')
+    plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='blue', label='Classe 1')
+    plt.plot([-2, 2], [-2 * pente + intercept, 2 * pente + intercept], color='green', label='Droite de séparation')
+    plt.title('Données avec la droite de séparation')
+    plt.xlabel('Norm_Grade_1')
+    plt.ylabel('Norm_Grade_2')
+    plt.legend()
+    plt.show()
diff --git a/perceptron.py b/perceptron.py
index d2a49244200d8d9f3f65c8c2ac39d8298cbb56d8..63f9d30a8be50ba8a031e586bceb56f72ac323be 100644
--- a/perceptron.py
+++ b/perceptron.py
@@ -57,7 +57,7 @@ if __name__ == '__main__':
             # Mise à jour des poids
             poids = upd_weights(poids, learning_rate, cible, sortie, input_data)
             # Calcul de l'erreur quadratique
-            total_error += (cible - sortie) ** 2
+            total_error += (cible - sortie) ** 2 / 2
 
         # Affichage de l'erreur à chaque itération (à enlever pour de meilleures performances)
         print(f"Iteration {iteration + 1}: Erreur = {total_error}")