import time import numpy as np import sklearn from sklearn.linear_model import Perceptron from sklearn import datasets import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap ############################################################################### # 01-perceptron.py # @title: Introduction aux réseaux de neurones - Perceptron # @project: Mes scripts de ML # @lang: fr # @authors: Philippe Roy # @copyright: Copyright (C) 2023 Philippe Roy # @license: GNU GPL ############################################################################### ### # Commandes NumPy : # - np.array : créer un tableau à partir d'une liste de listes # - np.c_ : concatène les colonnes des tableaux # - np.linspace : créer un tableau 1D de la valeur de début à la valeur de fin avec n valeurs # - np.meshgrid : créer un tableau 2D avec l'ensemble des combinaisons allant des deux valeurs de début aux deux valeurs de fin # - .reshape : reformater la tableau avec le nombre de lignes et le nombre de colonnes ### ### # Commandes Scikit-Learn : # - sklearn.linear_model.Perceptron() : créer un modèle de Perceptron # - .fit : entrainement du modèle # - .predict : prédiction du modèle ### ############################################################################### # Initialisation ############################################################################### # Init du temps t_debut = time.time() # Init des plots fig = plt.figure(figsize=(15, 5)) fig.suptitle("Classificateur par perceptron") donnees_ax = fig.add_subplot(2,4,(1,5)) # Observations : x1 et cibles : y1 # f_activ_ax = fig.add_subplot(2,3,2) # df_activ_ax = fig.add_subplot(2,3,5) ############################################################################### # Observations ############################################################################### # Observations d'apprentisage iris = sklearn.datasets.load_iris() # Jeu de données Iris x1 = iris['data'][:, 2].reshape(-1, 1) # Longueur de pétale x2 = iris['data'][:, 3].reshape(-1, 1) # Largeur de pétale X = iris['data'][:, (2, 3)] # Matrice de données y1 = (iris["target"] == 2).astype(np.int32) # Si Iris virginica -> 1 sinon -> 0 y = (iris["target"]) # Type d'Iris # Plot x1,x2 et y1 (longeur de pétale, largeur de pétale et probabilité d'être Iris virginica (format de la marque)) donnees_ax.plot(x1[y1==1], x2[y1==1], "g^" , label="Iris virginica") donnees_ax.plot(x1[y1==0], x2[y1==0], "rs", label="Iris non-virginica") # Nouvelles observations x1_new=np.linspace(0, 8, 1000).reshape(-1, 1) x2_new=np.linspace(0, 3.5, 1000).reshape(-1, 1) x1_new_mg, x2_new_mg = np.meshgrid(x1_new, x2_new) X_new = np.c_[x1_new_mg.ravel(), x2_new_mg.ravel()] ############################################################################### # Phase d'apprentissage ############################################################################### # model= sklearn.linear_model.Perceptron(max_iter=1000, tol=1e-3, random_state=42) model = sklearn.linear_model.Perceptron() # Modèle perceptron model.fit(X, y1) # Entrainement ############################################################################### # Phase d'inférence ############################################################################### y_predict=model.predict(X_new) # Prédiction # Frontière de décision model_a = -model.coef_[0][0] / model.coef_[0][1] model_b = -model.intercept_ / model.coef_[0][1] donnees_ax.plot(x1_new, model_a * x1_new + model_b, "k--") # Carte y_predict_map = y_predict.reshape(x1_new_mg.shape) custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0']) donnees_ax.contourf(x1_new_mg, x2_new_mg, y_predict_map, cmap=custom_cmap) ############################################################################### # Résultats ############################################################################### # Plot x1,x2 et y1 (longeur de pétale, largeur de pétale et probabilité d'être Iris virginica) donnees_ax.set_title("Perceptron") donnees_ax.set(xlim=(0, 7.5), ylim=(0, 3.5)) donnees_ax.set_xlabel(r'$x_1$'+" - Longueur de pétale") donnees_ax.set_ylabel(r'$x_2$'+" - Largeur de pétale") donnees_ax.legend(loc="upper left") ############################################################################### # Fonctions d'activation ############################################################################### def sigmoid(_x): return 1 / (1 + np.exp(-_x)) def echelon(_x): # Heaviside return (_x >= 0).astype(_x.dtype) def relu(_x): return np.maximum(0, _x) def tanh(_x): return np.tanh(_x) def derivation(f, _x, eps=0.000001): return (f(_x + eps) - f(_x))/eps # Fonctions d'activation f_activ_ax = fig.add_subplot(2,4,2) f_activ_ax.set_title("Fonctions d'activation") f_activ_x = np.linspace(-5, 5, 200) f_activ_ax.set(xlim=(-5,5), ylim=(-1.25, 1.25)) f_activ_ax.plot(f_activ_x, sigmoid(f_activ_x), "g-", label="Sigmoïde") f_activ_ax.plot(f_activ_x, echelon(f_activ_x), "b-", label="Échelon") f_activ_ax.plot(f_activ_x, tanh(f_activ_x), "r-", label="Tanh") f_activ_ax.plot(f_activ_x, relu(f_activ_x), "m-", label="ReLU") f_activ_ax.text(-4,1, "f (x)", va='center', ha='center') f_activ_ax.legend() # Dérivée df_activ_ax = fig.add_subplot(2,4,6) df_activ_ax.set(xlim=(-5,5), ylim=(0, 1.1)) df_activ_ax.plot(f_activ_x, derivation(sigmoid, f_activ_x), "g-", label="f'(Sigmoïde)") df_activ_ax.plot(f_activ_x, derivation(echelon, f_activ_x), "b-", label="f'(Échelon)") df_activ_ax.plot(f_activ_x, derivation(tanh, f_activ_x), "r-", label="f'(Tanh)") df_activ_ax.plot(f_activ_x, derivation(relu, f_activ_x), "m-", label="f'(ReLU)") df_activ_ax.text(-4,1, "f '(x)", va='center', ha='center') # df_activ_ax.legend() ############################################################################### # Perceptron multi-couches (pmc) ############################################################################### def pmc_xor(x1, x2, activation=echelon): return activation(-activation(x1 + x2 - 1.5) + activation(x1 + x2 - 0.5) - 0.5) x1_mg, x2_mg = np.meshgrid(np.linspace(-0.2, 1.2, 100), np.linspace(-0.2, 1.2, 100)) z1_pmc_xor = pmc_xor(x1_mg, x2_mg, activation=echelon) z2_pmc_xor = pmc_xor(x1_mg, x2_mg, activation=sigmoid) z3_pmc_xor = pmc_xor(x1_mg, x2_mg, activation=tanh) z4_pmc_xor = pmc_xor(x1_mg, x2_mg, activation=relu) pmc_xor_echelon_ax = fig.add_subplot(2,4,3) pmc_xor_echelon_ax.set_title("XOR PMC par Échelon") pmc_xor_echelon_ax.contourf(x1_mg, x2_mg, z1_pmc_xor) pmc_xor_echelon_ax.plot([0, 1], [0, 1], "rs", markersize=15) pmc_xor_echelon_ax.plot([0, 1], [1, 0], "g^", markersize=15) pmc_xor_echelon_ax.grid(True) pmc_xor_sigmoid_ax = fig.add_subplot(2,4,4) pmc_xor_sigmoid_ax.set_title("XOR PMC par Sigmoïde") pmc_xor_sigmoid_ax.contourf(x1_mg, x2_mg, z2_pmc_xor) pmc_xor_sigmoid_ax.plot([0, 1], [0, 1], "rs", markersize=15) pmc_xor_sigmoid_ax.plot([0, 1], [1, 0], "g^", markersize=15) pmc_xor_sigmoid_ax.grid(True) pmc_xor_tanh_ax = fig.add_subplot(2,4,7) pmc_xor_tanh_ax.contourf(x1_mg, x2_mg, z3_pmc_xor) pmc_xor_tanh_ax.plot([0, 1], [0, 1], "rs", markersize=15) pmc_xor_tanh_ax.plot([0, 1], [1, 0], "g^", markersize=15) pmc_xor_tanh_ax.grid(True) pmc_xor_tanh_ax.set_xlabel("XOR PMC par Tanh", fontsize=12) pmc_xor_relu_ax = fig.add_subplot(2,4,8) pmc_xor_relu_ax.contourf(x1_mg, x2_mg, z4_pmc_xor) pmc_xor_relu_ax.plot([0, 1], [0, 1], "rs", markersize=15) pmc_xor_relu_ax.plot([0, 1], [1, 0], "g^", markersize=15) pmc_xor_relu_ax.grid(True) pmc_xor_relu_ax.set_xlabel("XOR PMC par ReLU", fontsize=12) plt.show()