Embora a pergunta tenha uma ótima resposta, aqui está uma regra prática para pequenos valores singulares, com um gráfico.
Se um valor singular for diferente de zero, mas muito pequeno, você deve definir seu recíproco como zero, pois seu valor aparente provavelmente é um artefato de erro de arredondamento, não um número significativo. Uma resposta plausível à pergunta "quão pequeno é pequeno?" é editar desta forma todos os valores singulares cuja razão para o maior é menor que vezes a precisão da máquina ϵ .Nϵ
- Receitas numéricas p. 795
Adicionado: as duas linhas a seguir calculam essa regra de ouro.
#!/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
A matriz Hilbert parece ser amplamente utilizada como um caso de teste para erro de arredondamento:
Aqui, os bits de baixa ordem nas mantissas da matriz Hilbert são zerados
A.astype(np.float__).astype(np.float64)
e depois np.linalg.svd
executados float64
. (Os resultados com svd
todos float32
são praticamente os mesmos.)
Simplesmente truncar float32
pode até ser útil para excluir dados de alta dimensão, por exemplo, para classificação de trem / teste.
Casos de teste reais seriam bem-vindos.