ML Learning Hub
Fondationsdébutant

Algèbre Linéaire pour le ML

La géométrie derrière chaque modèle — produits scalaires, transformations matricielles et décomposition propre

Vecteurs, produits scalaires, multiplication matricielle, décomposition propre et SVD — avec l'intuition visuelle de la transformation de l'espace.

45 min
10 diagrammes
8 Concepts Couverts

Prérequis

Python ML Stack

Concepts Couverts

Dot ProductMatrix MultiplyEigenvaluesEigenvectorsSVDRankDeterminantPCA Connection

Formules Clés

Produit Scalaire

Mesure l'alignement de deux vecteurs — zéro signifie orthogonal, maximal quand parallèles

Multiplication de Matrices

Composition de deux transformations linéaires — appliquer B d'abord, puis A

Décomposition en Valeurs Propres

Les vecteurs propres v restent sur leur espace sous A ; λ est le facteur d'échelle

Décomposition en Valeurs Singulières (DVS)

Toute matrice se décompose en rotation × échelle × rotation — utilisé dans ACP, LSA, systèmes de recommandation

Simulation Interactive

Loading visualization…
🎯

Pourquoi l'Algèbre Linéaire EST le Machine Learning

motivation

Une couche de réseau de neurones, c'est y = Wx + b — une multiplication matricielle. La descente de gradient nécessite le calcul du gradient, qui est une matrice Jacobienne. L'ACP trouve les vecteurs propres principaux de la matrice de covariance. L'attention dans les Transformers est Q·Kᵀ·V — trois multiplications matricielles. Chaque passe avant, chaque rétropropagation, chaque étape d'optimisation est de l'algèbre linéaire.

Le produit scalaire a·b = ‖a‖‖b‖cos(θ) est la base de la similarité cosinus (NLP), de l'astuce du noyau (SVM) et des mécanismes d'attention (Transformers).

💡

Les Matrices comme Transformateurs d'Espace

intuition

Chaque matrice m×n A représente une transformation linéaire de ℝⁿ vers ℝᵐ. Multiplier un vecteur v par A l'étire, le fait tourner, le réfléchit ou le projette. Le déterminant vous indique le facteur de mise à l'échelle du volume : |det(A)| = 2 signifie que chaque région double en surface. det = 0 signifie que la matrice effondre l'espace sur une dimension inférieure.

Visualisez toute matrice 2×2 en regardant où va le carré unité [0,1]×[0,1]. Les quatre coins vont en (0,0), la première colonne, la deuxième colonne, et leur somme.

⚙️

Décomposition Propre Étape par Étape

algorithm
1

Trouver les valeurs propres : résoudre det(A - λI) = 0 (polynôme caractéristique). Pour 2×2 : λ = (tr(A) ± √(tr²-4det)) / 2.

2

Pour chaque valeur propre λᵢ : résoudre (A - λᵢI)v = 0 pour trouver le vecteur propre vᵢ. Normaliser : ‖vᵢ‖ = 1.

3

Empiler les vecteurs propres comme colonnes de Q : A = QΛQ⁻¹ où Λ = diag(λ₁, λ₂, …)

4

Pour les matrices symétriques (matrices de covariance) : Q est orthogonale (Q⁻¹ = Qᵀ), valeurs propres réelles.

5

Aⁿ = QΛⁿQ⁻¹ — les grandes valeurs propres dominent l'application répétée (ex. : itération de puissance).

6

ACP : calculer la covariance C = XᵀX/n, décomposer en vecteurs propres, prendre les k premiers comme matrice de projection.

</>

Algèbre Linéaire avec NumPy

code
python65 lines
import numpy as np

class="tok-comment"># ── Vecteurs et produits scalaires ────────────────────────────────────────────
a = np.array([class="tok-num">3., class="tok-num">4.])
b = np.array([class="tok-num">1., class="tok-num">0.])

print(fclass="tok-str">"a·b = {np.dot(a, b):.2f}")             class="tok-comment"># class="tok-num">3.0
print(fclass="tok-str">"‖a‖ = {np.linalg.norm(a):.2f}")        class="tok-comment"># class="tok-num">5.0
print(fclass="tok-str">"cos(θ) = {np.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)):.3f}")  class="tok-comment"># class="tok-num">0.6

class="tok-comment"># Similarité cosinus (NLP / recommandation)
def cosine_sim(u, v):
    return np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v))

class="tok-comment"># ── Opérations matricielles ───────────────────────────────────────────────────
A = np.array([[class="tok-num">2., class="tok-num">1.],
              [class="tok-num">0., class="tok-num">3.]])

B = np.array([[class="tok-num">1., class="tok-num">0.],
              [class="tok-num">2., class="tok-num">1.]])

print(class="tok-str">"A @ B =")
print(A @ B)                     class="tok-comment"># multiplication matricielle (composition)
print(fclass="tok-str">"det(A) = {np.linalg.det(A):.2f}")   class="tok-comment"># class="tok-num">6.0 — facteur d'échelle volumique
print(fclass="tok-str">"rang(A) = {np.linalg.matrix_rank(A)}")   class="tok-comment"># class="tok-num">2 — rang plein

A_inv = np.linalg.inv(A)
print(class="tok-str">"A @ A_inv ≈ I :", np.allclose(A @ A_inv, np.eye(class="tok-num">2)))

class="tok-comment"># ── Décomposition propre ──────────────────────────────────────────────────────
val_propres, vect_propres = np.linalg.eig(A)
print(fclass="tok-str">"Valeurs propres : {val_propres}")          class="tok-comment"># [class="tok-num">2. class="tok-num">3.]
print(fclass="tok-str">"Vecteurs propres (colonnes) :\n{vect_propres.round(class="tok-num">3)}")

class="tok-comment"># Vérification : A @ v = λ * v
for i in range(len(val_propres)):
    v = vect_propres[:, i]
    lam = val_propres[i]
    print(fclass="tok-str">"λ{i+class="tok-num">1}={lam:.2f}, Aclass="tok-dec">@v = {Aclass="tok-dec">@v.round(class="tok-num">3)}, λ*v = {(lam*v).round(class="tok-num">3)}")

class="tok-comment"># Reconstruction de A depuis la décomposition propre
Q = vect_propres
Lambda = np.diag(val_propres)
A_reconstruit = Q @ Lambda @ np.linalg.inv(Q)
print(class="tok-str">"Erreur de reconstruction :", np.linalg.norm(A - A_reconstruit))

class="tok-comment"># ── Décomposition en Valeurs Singulières (DVS) ────────────────────────────────
M = np.random.randn(class="tok-num">4, class="tok-num">3)               class="tok-comment"># matrice rectangulaire class="tok-num">4×class="tok-num">3
U, S, Vt = np.linalg.svd(M, full_matrices=False)
print(fclass="tok-str">"U : {U.shape}, S : {S.shape}, Vt : {Vt.shape}")

class="tok-comment"># Approximation de rang faible (garder les k valeurs singulières principales)
k = class="tok-num">2
M_approx = U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
print(fclass="tok-str">"Erreur approx rang-{k} : {np.linalg.norm(M - M_approx):.4f}")

class="tok-comment"># ── ACP depuis zéro ───────────────────────────────────────────────────────────
X = np.random.randn(class="tok-num">200, class="tok-num">5)
X -= X.mean(axis=class="tok-num">0)                     class="tok-comment"># centrer
C = (X.T @ X) / (len(X) - class="tok-num">1)           class="tok-comment"># matrice de covariance
val_propres, vect_propres = np.linalg.eigh(C)   class="tok-comment"># eigh pour matrices symétriques
idx = np.argsort(val_propres)[::-class="tok-num">1]     class="tok-comment"># trier par ordre décroissant
CP = vect_propres[:, idx[:class="tok-num">2]]           class="tok-comment"># class="tok-num">2 premières composantes principales
X_proj = X @ CP                         class="tok-comment"># projection en 2D
print(fclass="tok-str">"Variance expliquée : {val_propres[idx[:class="tok-num">2]] / val_propres.sum() * class="tok-num">100}")
⚠️

Stabilité Numérique et Mauvais Conditionnement

pitfall

Le numéro de condition κ(A) = σ_max/σ_min mesure la sensibilité aux perturbations. Numéro de condition élevé → mal conditionné → les erreurs numériques s'amplifient. La descente de gradient converge lentement sur des paysages de perte mal conditionnés — c'est pourquoi la mise à l'échelle des caractéristiques est importante. N'inversez jamais directement une matrice avec np.linalg.inv(A) si vous résolvez Ax=b — utilisez np.linalg.solve(A,b) qui est plus rapide et plus stable.

np.linalg.cond(A) vous donne le numéro de condition. κ > 10⁶ signifie des problèmes — les solutions auront ~6 chiffres significatifs de moins que prévu.

?Vérification des Connaissances

La progression est sauvegardée dans votre navigateur — aucun compte requis.

Besoin d'un ingénieur IA ou data scientist ?

Je conçois des modèles ML sur mesure, des agents IA, de la vision par ordinateur et de l'automatisation — de l'idée à la production.