Matière : Machine Learning
Enseignant : Pr El Alami Hassoun Mohamed
Séance : TP 1.1 — NumPy
Durée : 1h30
Nom de l'étudiant : à compléter
Objectif : découvrir et pratiquer les bases de NumPy, des tableaux simples jusqu’aux opérations utilisées en Machine Learning.
Dans tout ce TP, nous utiliserons NumPy, la bibliothèque de base pour le calcul scientifique en Python.
import numpy as np
# (optionnel) : pour afficher les nombres avec moins de décimales
np.set_printoptions(precision=3)
print(np.random.rand(8))
[0.609 0.857 0.996 0.698 0.625 0.968 0.313 0.924]
Un tableau NumPy (ndarray) est la structure de données de base utilisée en Machine Learning :
# TODO : créer un tableau contenant les entiers de 0 à 9
# Utiliser np.arange
# Rappel : np.arange(n) renvoie [0, 1, ..., n-1]
tableau_1d = np.arange(10)
print("Tableau 1D :", tableau_1d)
print("Type de l'objet :", type(tableau_1d))
Tableau 1D : [0 1 2 3 4 5 6 7 8 9] Type de l'objet : <class 'numpy.ndarray'>
# np.random.rand(3, 3) crée un tableau 2D de taille (3, 3)
# avec des valeurs aléatoires entre 0 et 1.
tableau_2d = np.random.rand(3, 3)
print("Matrice 3x3 aléatoire :")
print(tableau_2d)
Matrice 3x3 aléatoire : [[0.597 0.104 0.479] [0.592 0.692 0.049] [0.048 0.146 0.664]]
# Tableau de zéros 4x5
tableau_zeros = np.zeros((4, 5))
print("Tableau de zéros (4x5) :")
print(tableau_zeros)
# Tableau de uns 3x2
tableau_uns = np.ones((3, 2))
print("\nTableau de uns (3x2) :")
print(tableau_uns)
# Carrés de 0 à 9 (opération vectorisée)
tableau_carres = np.arange(10) ** 2
print("\nCarrés de 0 à 9 :")
print(tableau_carres)
# Séquence de 10 à 50 avec un pas de 5
tableau_sequence = np.arange(10, 51, 5)
print("\nSéquence 10 → 50 (pas de 5) :")
print(tableau_sequence)
Tableau de zéros (4x5) : [[0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.]] Tableau de uns (3x2) : [[1. 1.] [1. 1.] [1. 1.]] Carrés de 0 à 9 : [ 0 1 4 9 16 25 36 49 64 81] Séquence 10 → 50 (pas de 5) : [10 15 20 25 30 35 40 45 50]
Ces propriétés sont cruciales en Machine Learning, car les modèles attendent des formes précises.
print("Nombre de dimensions (ndim) :", tableau_2d.ndim)
print("Forme (shape) :", tableau_2d.shape)
print("Taille totale (size) :", tableau_2d.size)
print("Type des éléments (dtype) :", tableau_2d.dtype)
Nombre de dimensions (ndim) : 2 Forme (shape) : (3, 3) Taille totale (size) : 9 Type des éléments (dtype) : float64
# En ML, on travaille presque toujours en float (valeurs réelles).
tableau_float = np.array([1, 2, 3, 4, 5], dtype=float)
print("Tableau float :", tableau_float)
print("dtype :", tableau_float.dtype)
print("Maximum :", tableau_float.max())
print("Minimum :", tableau_float.min())
Tableau float : [1. 2. 3. 4. 5.] dtype : float64 Maximum : 5.0 Minimum : 1.0
L’indexation et le slicing permettent d’extraire des sous-parties d’un tableau :
print("Tableau 1D :", tableau_1d)
# Accès au 2e élément (index 1, car on commence à 0)
print("Deuxième élément :", tableau_1d[1])
# Slicing : éléments d'index 2 à 5 (5 non inclus)
print("Slicing (indices 2 à 5) :", tableau_1d[2:6])
Tableau 1D : [0 1 2 3 4 5 6 7 8 9] Deuxième élément : 1 Slicing (indices 2 à 5) : [2 3 4 5]
print("Matrice 3x3 :")
print(tableau_2d)
# Élément en (1, 1)
print("\nÉlément (1,1) :", tableau_2d[1, 1])
# Ligne 1 complète
print("Ligne 1 complète :", tableau_2d[1, :])
# Deux premières lignes et les trois colonnes
print("\nSous-matrice (2 premières lignes, 3 colonnes) :")
print(tableau_2d[:2, :3])
Matrice 3x3 : [[0.597 0.104 0.479] [0.592 0.692 0.049] [0.048 0.146 0.664]] Élément (1,1) : 0.6922150718494621 Ligne 1 complète : [0.592 0.692 0.049] Sous-matrice (2 premières lignes, 3 colonnes) : [[0.597 0.104 0.479] [0.592 0.692 0.049]]
# np.arange(10) crée [0 1 2 3 4 5 6 7 8 9]
indices = np.arange(10)
indices_inverse = indices[::-1]
print("Indices :", indices)
print("Indices inversés :", indices_inverse)
Indices : [0 1 2 3 4 5 6 7 8 9] Indices inversés : [9 8 7 6 5 4 3 2 1 0]
NumPy applique les opérations élément par élément :
c’est la base des calculs vectorisés utilisés en Machine Learning (fonctions de coût, gradients, etc.).
# Deux tableaux aléatoires 1D de taille 5
tableau_a = np.random.rand(5)
tableau_b = np.random.rand(5)
print("Tableau A :", tableau_a)
print("Tableau B :", tableau_b)
addition = tableau_a + tableau_b
soustraction = tableau_a - tableau_b
multiplication = tableau_a * tableau_b
division = tableau_a / tableau_b
print("\nAddition :", addition)
print("Soustraction :", soustraction)
print("Multiplication :", multiplication)
print("Division :", division)
Tableau A : [1. 0.492 0.508 0.187 0.592] Tableau B : [0.226 0.293 0.485 0.411 0.713] Addition : [1.226 0.785 0.993 0.599 1.305] Soustraction : [ 0.774 0.199 0.023 -0.224 -0.12 ] Multiplication : [0.226 0.144 0.246 0.077 0.422] Division : [4.419 1.679 1.047 0.456 0.831]
somme_total = tableau_a.sum()
moyenne = tableau_a.mean()
ecart_type = tableau_a.std()
produit_total = tableau_a.prod()
print("Somme :", somme_total)
print("Moyenne :", moyenne)
print("Écart type :", ecart_type)
print("Produit :", produit_total)
Somme : 2.7794180733152465 Moyenne : 0.5558836146630493 Écart type : 0.26103532093187665 Produit : 0.027729697307867823
Ces opérations servent à restructurer les données, très utile pour préparer des inputs de modèles ML.
# Création d'un tableau 1D de 12 éléments
base = np.arange(12)
print("Base 1D :", base)
# Reshape en matrice 3x4
tableau_reshape = base.reshape((3, 4))
print("\nTableau reshape (3x4) :")
print(tableau_reshape)
Base 1D : [ 0 1 2 3 4 5 6 7 8 9 10 11] Tableau reshape (3x4) : [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
tableau_concat = np.concatenate((tableau_a, tableau_b))
print("Tableau concaténé :", tableau_concat)
Tableau concaténé : [1. 0.492 0.508 0.187 0.592 0.226 0.293 0.485 0.411 0.713]
matrice_a = np.array([[1, 2], [3, 4]])
matrice_b = np.array([[5, 6], [7, 8]])
print(matrice_a)
empile_verticale = np.vstack((matrice_a, matrice_b))
empile_horizontale = np.hstack((matrice_a, matrice_b))
print("Empilement vertical :")
print(empile_verticale)
print("\nEmpilement horizontal :")
print(empile_horizontale)
Empilement vertical : [[1 2] [3 4] [5 6] [7 8]] Empilement horizontal : [[1 2 5 6] [3 4 7 8]]
np.where pour créer un tableau binaire¶# On transforme tableau_a en tableau binaire :
# 1 si valeur > 0.5, 0 sinon.
tableau_binaire = np.where(tableau_a > 0.5, 1, 0)
print("Tableau A :", tableau_a)
print("Tableau binaire (A > 0.5) :", tableau_binaire)
Tableau A : [1. 0.492 0.508 0.187 0.592] Tableau binaire (A > 0.5) : [1 0 1 0 1]
Les modèles de Machine Learning reposent fortement sur l’algèbre linéaire :
produits matriciels, déterminants, valeurs propres, SVD, etc.
# Deux matrices 2x2
matrice_1 = np.array([[1, 2],
[3, 4]])
matrice_2 = np.array([[5, 6],
[7, 8]])
# Produit matriciel (attention : ce n'est PAS une multiplication élément par élément)
produit_matriciel = np.dot(matrice_1, matrice_2)
print("Produit matriciel :")
print(produit_matriciel)
Produit matriciel : [[19 22] [43 50]]
# Déterminant d'une matrice 2x2
matrice = np.array([[1, 2],
[3, 4]])
determinant = np.linalg.det(matrice)
print("Déterminant de la matrice :", determinant)
Déterminant de la matrice : -2.0000000000000004
# Valeurs propres et vecteurs propres d'une matrice 3x3
matrice_3x3 = np.array([[1, 2, 3],
[0, 1, 4],
[5, 6, 0]])
valeurs_propres, vecteurs_propres = np.linalg.eig(matrice_3x3)
print("Valeurs propres :")
print(valeurs_propres)
print("\nVecteurs propres :")
print(vecteurs_propres)
Valeurs propres : [-5.23 -0.026 7.256] Vecteurs propres : [[ 0.226 -0.758 -0.499] [ 0.526 0.632 -0.467] [-0.82 -0.162 -0.73 ]]
# Décomposition en valeurs singulières (SVD)(La SVD permet de résumer une matrice complexe en ses directions les plus importantes.)
#Parce que la SVD est utilisée dans :
#PCA (analyse en composantes principales)
#Réduction de dimension
#Compression d’images
#Reconstruction d’une matrice
#Systèmes de recommandation
#La SVD décompose une matrice en trois parties :
# U : les directions dans l’espace des lignes
# S : l’importance de chaque direction
# Vt : les directions dans l’espace des colonnes
# Cela permet de comprendre la structure d’une matrice, de réduire sa dimension ou de comprimer des données.
matrice_svd = np.array([[1, 2],
[3, 4],
[5, 6]])
U, S, Vt = np.linalg.svd(matrice_svd)
print("Matrice U :")
print(U)
print("\nValeurs singulières S :")
print(S)
print("\nMatrice Vt :")
print(Vt)
Dans cette partie, nous allons :
Remplacer
"data.csv"par le nom réel de votre fichier.
import pandas as pd
# Charger le fichier CSV (à adapter)
# Exemple : df = pd.read_csv("mon_fichier.csv")
df = pd.read_csv("data.csv")
print("Aperçu des données :")
print(df.head())
print("Statistiques descriptives :")
print(df.describe())
import matplotlib.pyplot as plt
# Histogrammes de toutes les colonnes numériques
df.hist()
plt.tight_layout()
plt.show()
# Exemple de filtre : garder les lignes où une colonne est > à un seuil
# À adapter : remplacer 'column_name' et 'seuil' par des valeurs pertinentes
column_name = "column_name" # à modifier
seuil = 0 # à modifier
filtre = df[df[column_name] > seuil]
print("Lignes filtrées :")
print(filtre.head())
Dans cette section, on relie NumPy directement au Machine Learning :
# Matrice de données : 2 exemples, 3 caractéristiques
X = np.array([[1, 2, 3],
[4, 5, 6]])
# Moyenne par colonne (par feature)
mean = X.mean(axis=0)
print("Moyenne par feature :", mean)
# Broadcasting : X - mean
# NumPy "étend" automatiquement le vecteur mean sur les lignes de X.
X_normalized = X - mean
print("\nDonnées normalisées :")
print(X_normalized)
# Vecteurs des valeurs vraies et prédites
y_true = np.array([1, 2, 3])
y_pred = np.array([1.2, 1.9, 3.1])
# Erreurs point par point
erreurs = y_true - y_pred
print("Erreurs :", erreurs)
# MSE vectorisé : moyenne des carrés des erreurs
mse = (erreurs ** 2).mean()
print("Erreur quadratique moyenne (MSE) :", mse)
X_nan = np.array([1, np.nan, 3, np.nan, 5])
print("Données avec NaN :", X_nan)
# np.nanmean ignore automatiquement les NaN
moyenne_sans_nan = np.nanmean(X_nan)
print("Moyenne en ignorant les NaN :", moyenne_sans_nan)
# 3 exemples, 2 caractéristiques (par ex. taille, poids)
X = np.array([[5.1, 3.5],
[4.9, 3.0],
[6.2, 2.8]])
# Labels associés (par ex. 0 = classe A, 1 = classe B)
y = np.array([0, 0, 1])
print("X = matrice de caractéristiques :")
print(X)
print("Shape de X :", X.shape)
print("\ny = vecteur de labels :")
print(y)
print("Shape de y :", y.shape)
# Objectif : apprendre w dans le modèle y ≈ w * x
# Données simples : y = 2 * x
x = np.array([1, 2, 3])
y = np.array([2, 4, 6])
# Paramètre du modèle (poids), initialisé à 0
w = 0.0
# Taux d'apprentissage
alpha = 0.1
print("Poids initial w :", w)
for i in range(50):
# Prédiction du modèle
y_pred = w * x
# Gradient de la MSE par rapport à w
# d/dw MSE = mean( 2 * (w*x - y) * x )
gradient = ((y_pred - y) * x).mean()
# Mise à jour du paramètre
w -= alpha * gradient
# Affichage toutes les 10 itérations
if i % 10 == 0:
mse = ((y_pred - y) ** 2).mean()
print(f"Iteration {i:2d} | w = {w:.4f} | MSE = {mse:.4f}")
print("\nPoids final appris w ≈", w)
© Pr El Alam — Cours ML — Séance de TP 11 : NumPy