Quanta regolarizzazione aggiungere per rendere stabile SVD?


10

Ho usato SVD di Intel MKL ( dgesvdtramite SciPy) e ho notato che i risultati sono significativamente diversi quando cambio precisione tra float32e float64quando la mia matrice è mal condizionata / non di rango massimo. Esiste una guida sulla quantità minima di regolarizzazione da aggiungere per rendere insensibili i risultati a float32-> float64modifica?

In particolare, facendo , vedo che la norma L di V T X si sposta di circa 1 quando cambio precisione tra e . La norma L 2 di A è 10 5 e ha circa 200 autovalori zero su 784 totali.A=UDVTLVTXfloat32float64L2A105

Fare SVD su con λ = 10 - 3 ha fatto svanire la differenza.λI+Aλ=103


Qual è la dimensione di un N × N matrice A per questo esempio (è ancora una matrice quadrata)? 200 zero autovalori o valori singolari? Una norma di Frobenius | | A | | F per un esempio rappresentativo sarebbe anche utile. NN×NA||A||F
Anton Menshov

In questo caso matrice 784 x 784, ma sono più interessato alla tecnica generale per trovare un buon valore di lambda
Yaroslav Bulatov

Quindi, la differenza in solo nelle ultime colonne corrisponde agli zero valori singolari? V
Nick Alger,

2
Se esistono diversi valori singolari uguali, svd non è univoco. Nel tuo esempio, suppongo che il problema derivi dai multipli zero valori singolari e che una diversa precisione porti a una scelta diversa della base per il rispettivo spazio singolare. Non so perché questo cambi quando regolarizzi ...
Dirk,

1
... che cos'è ? X
Federico Poloni,

Risposte:


1

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:

inserisci qui la descrizione dell'immagine

Qui i bit di ordine inferiore nelle mantisse della matrice di Hilbert vengono azzerati A.astype(np.float__).astype(np.float64), quindi np.linalg.svdviene eseguito float64. (I risultati sono quasi svdtutti float32uguali.)

Il semplice troncamento a float32potrebbe 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.


tra l'altro, scipy sembra aggiungere un fattore 1e3 per float32 e 1e6 per float64, curioso da dove provengano
Yaroslav Bulatov,

@Yaroslav Bulatov, numpye scipy.linalg.svdchiama LAPACK gesdd , vedi il parametro JOBRin dgejsv: "Specifica la GAMMA per i valori singolari. Emette la licenza per impostare a zero piccoli valori singolari positivi se sono all'esterno ..." ( scipy.sparse.linalg.svdsavvolge ARPACK e ha un parametro tol, Tolerance per valori singolari.)
denis

13

A=ATM=UΣVT

H=[0MMT0]=[U00V][0ΣΣ0][U00V]T

ϵ>0

Aϵ=[1ϵϵ1]=VΛϵVT,Bϵ=[1+ϵ001ϵ]=UΛϵUT
Λϵ=diag(1+ϵ,1ϵ)
V=12[1111],U=[1001].
AϵBϵVUϵ>0U,VUV

M0=U0Σ0V0Tfloat64Mϵ=UϵΣϵVϵTfloat32Σ0,Σϵϵ107U0,UϵV0,Vϵ



1
È un ottimo riferimento. Non lo so, ho imparato questo particolare esempio molti anni fa durante le lezioni di matematica :-)
Richard Zhang,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.