Analisi del problema
L'SVD di una matrice non è mai unico. Lascia che la matrice abbia dimensioni e lascia che sia il suo SVDn × kAn×k
A=UDV′
per matrice con colonne ortonormali, una diagonale matrice con ingressi non negativi, e un matrice con colonne ortonormali.U p × p D k × p Vn×pUp×pDk×pV
Ora scegliere, in modo arbitrario , qualsiasi diagonale matrice avendo s sulla diagonale, in modo che è il identità . PoiS ± 1 S 2 = I p × p I pp×pS±1S2=Ip×pIp
A = UD V'= UioD I.V'= U( S2) D ( S2) V'= ( US) ( SD S) ( VS)'
è anche un SVD di perché dimostra che gli hanno colonne ortonormali e un calcolo simile dimostra che ha colonne ortonormali. Inoltre, poiché e sono diagonali, commutano, da dove mostra che ha ancora voci non negative.( U S ) ′ ( U S ) = S ′ U ′ U S = S ′ I p S = S ′ S = S 2 = I p U S V S S D S D S = D S 2 = D DUN
( US)'( US) = S'U'US= S'iopS= S'S= S2= Ip
USVSSDSD S= D S2= D
D
Il metodo implementato nel codice per trovare un SVD trova una che diagonale e, analogamente, una che diagonale Procede con il calcolo di in termini di autovalori trovati in . Il problema è questo non assicura una corrispondenza coerente delle colonne di con le colonne di .A A ′ = ( U D V ′ ) ( U D V ′ ) ′ = U D V ′ V D ′ U ′ = U D 2 U ′ V A ′ A = V D 2 V ′ . D D 2 U VU
A A'= ( UD V') ( UD V')'= UD V'VD'U'= UD2U'
VUN'A = VD2V'.
DD2UV
Una soluzione
Invece, dopo aver trovato una tale e una tale , usale per calcolareVUV
U'A V= U'( UD V') V= ( U'U) D ( V'V) = D
direttamente ed efficientemente. I valori diagonali di questa non sono necessariamente positivi. D (Questo perché non c'è nulla nel processo di diagonalizzazione di o che garantirà che, poiché quei due processi sono stati eseguiti separatamente.) Rendili positivi scegliendo le voci lungo la diagonale di per eguagliare i segni delle voci di , in modo che abbia tutti i valori positivi. Compensa questo moltiplicando a destra per :UN'UNA A'SDSDUS
A = UD V'= ( US) ( SD ) V'.
Questo è un SVD.
Esempio
Sia con . Un SVD èn = p = k = 1A = ( - 2 )
( - 2 ) = ( 1 ) ( 2 ) ( - 1 )
con , e .U= ( 1 )D = ( 2 )V= ( - 1 )
Se diagonalizzi sceglieresti naturalmente e . Allo stesso modo se diagonalizza sceglieresti . Sfortunatamente, Invece, calcola Poiché questo è negativo, impostare . Questo regola in e in . Hai ottenuto che è uno dei due SVD possibili (ma non uguale all'originale!).UN'A = ( 4 )U= ( 1 )D = ( 4-√) = ( 2 )A A'= ( 4 )V= ( 1 )
UD V'= ( 1 ) ( 2 ) ( 1 ) = ( 2 ) ≠ A .
D = U'A V= ( 1 )'( - 2 ) ( 1 ) = ( - 2 ) .
S=(−1)UUS=(1)(−1)=(−1)DSD=(−1)(−2)=(2)A=(−1)(2)(1),
Codice
Ecco il codice modificato. La sua uscita conferma
- Il metodo ricrea
m
correttamente.
- U e sono davvero ancora ortonormali.V
- Ma il risultato non è lo stesso SVD restituito da
svd
. (Entrambi sono ugualmente validi.)
m <- matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)
U <- eigen(tcrossprod(m))$vector
V <- eigen(crossprod(m))$vector
D <- diag(zapsmall(diag(t(U) %*% m %*% V)))
s <- diag(sign(diag(D))) # Find the signs of the eigenvalues
U <- U %*% s # Adjust the columns of U
D <- s %*% D # Fix up D. (D <- abs(D) would be more efficient.)
U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d,n,n)
zapsmall(U1 %*% D1 %*% t(V1)) # SVD
zapsmall(U %*% D %*% t(V)) # Hand-rolled SVD
zapsmall(crossprod(U)) # Check that U is orthonormal
zapsmall(tcrossprod(V)) # Check that V' is orthonormal