Sebbene la domanda abbia un'ottima risposta, ecco una regola empirica per piccoli valori singolari, con una trama.
Se un valore singolare è diverso da zero ma molto piccolo, è necessario definirne il reciproco come zero, poiché il suo valore apparente è probabilmente un artefatto di errore di arrotondamento, non un numero significativo. Una plausibile risposta alla domanda "quanto è piccolo?" consiste nel modificare in questo modo tutti i valori singolari il cui rapporto con il più grande è inferiore di volte la precisione della macchina ϵ .Nϵ
- Ricette numeriche p. 795
Aggiunto: la seguente coppia di righe calcola questa regola empirica.
#!/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 di Hilbert sembra essere ampiamente utilizzata come test per l'errore di arrotondamento:
Qui i bit di ordine inferiore nelle mantisse della matrice di Hilbert vengono azzerati
A.astype(np.float__).astype(np.float64)
, quindi np.linalg.svd
viene eseguito float64
. (I risultati sono quasi svd
tutti float32
uguali.)
Il semplice troncamento a float32
potrebbe anche essere utile per denigrare i dati ad alta dimensione, ad esempio per la classificazione dei treni / prove.
Casi di test reali sarebbero i benvenuti.