Valeurs propres et SVD : calculer, reconstruire et approximer
Décomposer l’action d’une matrice selon quelques directions permet de comprendre comment elle étire les vecteurs, quelles informations la transformation efface et quelle erreur reste si l’on conserve moins de directions. La vue d’ensemble de l’algèbre linéaire présente les vecteurs, le rang, la projection orthogonale et les moindres carrés. Partons d’un calcul de valeurs propres pour une matrice 2×2, puis utilisons une matrice 3×2 pour effectuer une SVD, reconstruire la matrice et l’approximer par une matrice de rang inférieur. Toutes les matrices sont réelles, les vecteurs sont des colonnes et désigne la transposée.
Une droite invariante sous la transformation
Pour une matrice carrée , un vecteur non nul qui vérifie est un vecteur propre ; est sa valeur propre. Les notes du MIT 18.06SC sur les valeurs propres partent de cette relation : la droite engendrée par reste invariante. Si , le sens est conservé ; si , il est inversé ; si , le vecteur est envoyé sur zéro. Le vecteur nul est exclu, car il vérifierait l’égalité pour toute valeur de .
Prenons
Pour que admette une solution non nulle, doit être singulière. Résolvons d’abord l’équation caractéristique :
Nous obtenons et . Calculons ensuite les noyaux correspondants :
- Pour , , donc les coordonnées vérifient .
- Pour , , donc les coordonnées vérifient .
Après normalisation, choisissons
La multiplication confirme et . Tout vecteur vérifie donc : la première coordonnée est multipliée par trois et la seconde conserve sa longueur.
Une matrice réelle s’écrit sous la forme avec réelles si et seulement si elle possède vecteurs propres réels linéairement indépendants. Une matrice réelle peut avoir des valeurs propres complexes ; l’interprétation par une droite invariante s’applique aux vecteurs propres réels. Par exemple, possède la valeur propre double 1, mais le noyau de se réduit à la droite engendrée par . Ses vecteurs propres ne peuvent pas former une base de dimension deux.
La symétrie permet une décomposition orthogonale
Le théorème spectral présenté dans les notes du MIT sur les matrices symétriques affirme qu’une matrice réelle symétrique possède des valeurs propres réelles et une base orthonormée de vecteurs propres. Pour deux valeurs propres distinctes , l’orthogonalité se déduit directement :
Dans un sous-espace propre associé à une valeur propre multiple, deux vecteurs choisis arbitrairement ne sont pas nécessairement orthogonaux. On peut toutefois y choisir une base orthonormée. Avec , nous avons et ; l’exemple s’écrit
Chaque terme à droite projette sur un axe, puis multiplie par la valeur propre correspondante. La symétrie n’impose pas des valeurs propres positives ; celles de cet exemple le sont toutes les deux.
SVD rectangulaire et dimensions des facteurs
Une matrice 3×2 envoie un vecteur de dimension deux dans un espace de dimension trois. La relation ne permet donc pas de comparer directement l’entrée et la sortie. Les notes du MIT sur la SVD établissent que toute matrice réelle admet une décomposition en valeurs singulières, ou SVD. Deux ensembles de directions orthonormées relient les deux espaces :
Le vecteur singulier droit appartient à l’espace d’entrée ; le vecteur singulier gauche appartient à l’espace de sortie. Les valeurs singulières sont ordonnées selon , où . La multiplication par extrait les coordonnées d’entrée, les étire et les exprime dans l’espace de sortie.
Dans la forme complète, sont des matrices carrées orthogonales. Dans les deux autres formes, leurs colonnes sont orthonormées, mais les matrices peuvent être rectangulaires. Une SVD économique peut encore contenir des valeurs singulières nulles : n’est pas nécessairement le rang .
Le tutoriel d’algèbre linéaire de SciPy nomme les objets renvoyés U, s, Vh. s est un tableau unidimensionnel de valeurs singulières ; pour une matrice réelle, Vh représente , et non . La documentation de scipy.linalg.svd précise les dimensions économiques obtenues avec full_matrices=False.
Reconstruire une matrice avec deux composantes singulières
Prenons
Puisque , les vecteurs propres déjà calculés conviennent : et , avec les valeurs propres 12 et 4. Ainsi,
Pour chaque valeur singulière non nulle, calculons :
Les deux vecteurs ont une norme égale à 1 et . En posant , et , nous obtenons une SVD économique de dimensions . Pour la forme complète, ajoutons et une ligne de zéros au bas de ; .
Développons le produit en produits extérieurs. Chaque composante non nulle est de rang 1 :
Changer simultanément les signes de ne change pas leur produit extérieur. Pour une matrice réelle symétrique, les valeurs singulières sont les valeurs absolues des valeurs propres. Le signe d’une valeur propre négative est porté par les orientations relatives des vecteurs singuliers gauche et droit. Les valeurs singulières ne coïncident avec les valeurs propres elles-mêmes que dans le cas semi-défini positif.
Troncature et erreur d’approximation
Pour , conservons seulement les plus grandes composantes :
La section 5 des notes de Stanford CS168 sur l’approximation de faible rang donne le résultat d’optimalité : parmi les matrices de rang au plus , minimise l’erreur en norme de Frobenius. Cette norme est définie par . Les produits extérieurs distincts sont orthogonaux pour le produit scalaire correspondant, car
Le carré de la norme du résidu est donc la somme des carrés des valeurs singulières écartées :
La norme matricielle mesure l’amplification maximale de la longueur d’un vecteur d’entrée unitaire. Le résidu atteint la valeur indiquée dans la direction . Si , l’erreur de reconstruction est nulle.
Dans notre exemple, conserver la première composante donne
Ainsi, , et l’erreur relative en norme de Frobenius vaut . La fraction conservée du carré de la norme est . Conserver 75 % du carré de la norme ne signifie pas une erreur relative de 25 % en norme : le carré de l’erreur représente 25 %, et sa racine carrée donne l’erreur relative en norme.
PCA : des carrés des valeurs singulières aux variances
La documentation de scikit-learn sur la PCA décrit les composantes orthogonales qui expliquent le plus de variance dans les données centrées. Le centrage ne met pas automatiquement les caractéristiques à la même échelle.
Chaque ligne de représente une observation ; les moyennes des colonnes ont été soustraites et . Avec la convention de covariance empirique utilisant le dénominateur , comme pour la variance expliquée dans l’API PCA, remplaçons par sa SVD complète :
Chaque est donc une direction principale, de variance . Pour les premières directions, la matrice des scores est et la reconstruction vaut . Si les données originales n’étaient pas centrées, il faut ajouter la moyenne pour retrouver leurs coordonnées d’origine.
Les colonnes de notre matrice ont une somme nulle ; elle peut donc servir directement de . Avec , la covariance est et les variances des composantes valent 6 et 2. Les scores de la première composante sont . Leur multiplication par reconstruit , avec une proportion de variance expliquée de .
Clustering et réduction de dimension traite du choix des échelles, des données utilisées pour l’ajustement et de l’évaluation en aval. Les 75 % mesurent la variance conservée dans ces coordonnées ; ils ne permettent pas de conclure qu’une tâche de classification conserve assez d’information.
Moindres carrés : valeurs singulières nulles et petites
Pour , les notes du MIT sur la pseudo-inverse construisent la pseudo-inverse à partir de la SVD en prenant l’inverse des valeurs singulières non nulles. La solution des moindres carrés de norme euclidienne minimale est
Ce calcul projette sur l’espace des colonnes, puis annule l’étirement dans chaque direction. Toute autre solution des moindres carrés s’écrit , avec . Les directions du noyau étant orthogonales à , celui-ci possède la plus petite norme.
Dans notre exemple, pour , les coefficients selon les deux directions singulières valent et . Nous obtenons
Le résidu appartient au noyau gauche : . Comme est de rang colonne plein, les coefficients sont uniques. En la remplaçant par , nous avons : ajouter à une solution ne change pas les prédictions. L’identifiabilité des coefficients exige que la matrice n’efface complètement aucune direction d’entrée.
Une petite valeur singulière non nulle pose un autre problème : la division par cette valeur amplifie les perturbations des données. Pour fixée, entraîne . Par exemple, avec , une perturbation de sur la deuxième coordonnée de sortie devient une perturbation de coefficient de .
Pour une matrice de rang colonne plein, le nombre de conditionnement spectral vaut . Les notes du MIT sur les méthodes numériques, cours 5, relient ces normes aux valeurs propres extrêmes de et montrent que : les valeurs propres sont les carrés des valeurs singulières. Dans notre exemple, ces nombres valent respectivement et 3 ; celui de vaut 1000. L’analyse numérique distingue la sensibilité du problème de la stabilité de l’algorithme ; les moindres carrés ordinaires et la régularisation approfondissent le choix du solveur et l’interprétation des coefficients.
Tronquer une SVD pour réduire la dimension contrôle l’erreur de reconstruction de la matrice. Tronquer une pseudo-inverse pour résoudre un problème écarte des directions de coefficients et modifie l’estimation. Le seuil dépend de l’erreur des données et de l’usage prévu ; une petite valeur singulière non nulle n’est pas un zéro mathématique.
Vérifier les composantes avec Python
Ce code utilise uniquement la bibliothèque standard. Il vérifie les vecteurs propres et les composantes singulières calculés ci-dessus, puis calcule la reconstruction, l’erreur de rang un et les coefficients des moindres carrés. Les fonctions auxiliaires prennent des listes : les deux vecteurs d’un produit scalaire doivent avoir la même longueur, et chaque ligne de la matrice doit avoir la longueur du vecteur d’entrée. Des dimensions incompatibles déclenchent ValueError.
from math import sqrt, isclose
def dot(x, y):
if len(x) != len(y):
raise ValueError("Vector lengths must match")
return sum(a * b for a, b in zip(x, y))
def mv(matrix, vector):
return [dot(row, vector) for row in matrix]
B = [[2, 1], [1, 2]]
vectors = [[1 / sqrt(2), 1 / sqrt(2)],
[1 / sqrt(2), -1 / sqrt(2)]]
for eigenvalue, v in zip([3, 1], vectors):
assert all(isclose(a, eigenvalue * b, abs_tol=1e-12)
for a, b in zip(mv(B, v), v))
A = [[2, 0], [0, 2], [-2, -2]]
s = [sqrt(12), 2.0]
left = [[a / sigma for a in mv(A, v)]
for sigma, v in zip(s, vectors)]
assert isclose(dot(left[0], left[1]), 0, abs_tol=1e-12)
assert all(isclose(dot(u, u), 1) for u in left)
components = [[[sigma * u[i] * v[j] for j in range(2)]
for i in range(3)]
for sigma, u, v in zip(s, left, vectors)]
reconstructed = [[sum(c[i][j] for c in components) for j in range(2)]
for i in range(3)]
assert all(isclose(reconstructed[i][j], A[i][j], abs_tol=1e-12)
for i in range(3) for j in range(2))
A1 = components[0]
error = sqrt(sum((A[i][j] - A1[i][j]) ** 2
for i in range(3) for j in range(2)))
b = [1, 0, 0]
x = [sum(v[j] * dot(u, b) / sigma
for sigma, u, v in zip(s, left, vectors)) for j in range(2)]
print("eigenvalues:", [3, 1])
print("singular values:", [round(t, 6) for t in s])
print("reconstructed:", [[round(t, 6) for t in row] for row in reconstructed])
print("rank-one:", [[round(t, 6) for t in row] for row in A1])
print(f"Frobenius error: {error:.6f}")
print(f"retained variance: {s[0] ** 2 / sum(t * t for t in s):.6f}")
print("least-squares x:", [round(t, 6) for t in x])
Sortie :
eigenvalues: [3, 1]
singular values: [3.464102, 2.0]
reconstructed: [[2.0, 0.0], [0.0, 2.0], [-2.0, -2.0]]
rank-one: [[1.0, 1.0], [1.0, 1.0], [-2.0, -2.0]]
Frobenius error: 2.000000
retained variance: 0.750000
least-squares x: [0.333333, -0.166667]