Bien que la question ait une excellente réponse, voici une règle de base pour les petites valeurs singulières, avec un tracé.
Si une valeur singulière est non nulle mais très petite, vous devez définir sa réciproque à zéro, car sa valeur apparente est probablement un artefact d'erreur d'arrondi, pas un nombre significatif. Une réponse plausible à la question "comment petit est petit?" consiste à éditer de cette façon toutes les valeurs singulières dont le rapport à la plus grande est inférieur à fois la précision de la machine ϵ .Nϵ
- Recettes numériques p. 795
Ajouté: les deux lignes suivantes calculent cette règle empirique.
#!/usr/bin/env python2
from __future__ import division
import numpy as np
from scipy.sparse.linalg import svds # sparse, dense or LinOp
#...............................................................................
def howsmall( A, singmax=None ):
""" singular values < N float_eps sing_max may be iffy, questionable
"How small is small ?"
[Numerical Recipes p. 795](http://apps.nrbook.com/empanel/index.html?pg=795)
"""
# print "%d singular values are small, iffy" % (sing < howsmall(A)).sum()
# small |eigenvalues| too ?
if singmax is None:
singmax = svds( A, 1, return_singular_vectors=False )[0] # v0=random
return max( A.shape ) * np.finfo( A.dtype ).eps * singmax
La matrice de Hilbert semble être largement utilisée comme cas de test pour l'erreur d'arrondi:
Ici, les bits de poids faible dans les mantisses de la matrice de Hilbert sont mis à zéro
A.astype(np.float__).astype(np.float64)
, puis np.linalg.svd
exécutés float64
. (Les résultats avec svd
tous float32
sont à peu près les mêmes.)
Une simple troncature à float32
pourrait même être utile pour débruiter des données de grande dimension, par exemple pour la classification des trains / tests.
De vrais cas de test seraient les bienvenus.