Perché non riesco a ottenere un SVD valido di X tramite decomposizione autovalore di XX 'e X'X?


9

Sto cercando di fare SVD a mano:

m<-matrix(c(1,0,1,2,1,1,1,0,0),byrow=TRUE,nrow=3)

U=eigen(m%*%t(m))$vector
V=eigen(t(m)%*%m)$vector
D=sqrt(diag(eigen(m%*%t(m))$values))

U1=svd(m)$u
V1=svd(m)$v
D1=diag(svd(m)$d)

U1%*%D1%*%t(V1)
U%*%D%*%t(V)

Ma l'ultima riga non ritorna mindietro. Perché? Sembra avere qualcosa a che fare con i segni di questi autovettori ... O ho frainteso la procedura?



Mi è stato ripetutamente detto che il segno non ha importanza negli SVD ... in questo modo
artista fallito

@Amoeba Grazie per averlo chiarito. Mi stavo concentrando sulla domanda inglese piuttosto che sul codice. Statista fallito: vedi cosa D=diag(c(-1,1,1)*sqrt(eigen(m%*%t(m))$values))fa e tieni a mente che la radice quadrata (così come qualsiasi autovettore normalizzato) è definita solo per firmare. Per ulteriori informazioni, passare ma m <- matrix(-2,1,1)e includere ,1,1)alla fine di ciascuna delle chiamate a diag. Questo è un esempio che crea lo stesso problema, ma è così semplice che la natura del problema diventerà completamente ovvia. 1×1
whuber

1
Fatto. Grazie! Hai una regola generale per determinare il vettore c (-1, 1, 1)? O come dovrebbero essere collegati i segni delle due decomposizioni?
artista fallito

1
Nota che il trucco di @ whuber c(-1,1,1)funziona, ma Ddefinito in questo modo non ti dà valori singolari. I valori singolari devono essere tutti positivi per definizione. La domanda su come collegare i segni di Ued Vè buona, e non ho una risposta. Perché non fai un SVD? :-)
amoeba,

Risposte:


13

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=UDV=UIDIV=U(S2)D(S2)V=(US)(SDS)(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 DA

(US)(US)=SUUS=SIpS=SS=S2=Ip
USVSSD
SDS=DS2=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

AA=(UDV)(UDV)=UDVVDU=UD2U
V
AA=VD2V.
DD2UV

Una soluzione

Invece, dopo aver trovato una tale e una tale , usale per calcolareVUV

UAV=U(UDV)V=(UU)D(VV)=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 :AAAASDSDUS

A=UDV=(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!).AA=(4)U=(1)D=(4)=(2)AA=(4)V=(1)

UDV=(1)(2)(1)=(2)A.
D=UAV=(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

  1. Il metodo ricrea mcorrettamente.
  2. U e sono davvero ancora ortonormali.V
  3. 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

1
+1. Questo è molto chiaro Aggiungo solo che in pratica è sufficiente calcolare uno Uo Vpoi ottenere un'altra matrice tramite la moltiplicazione con A. In questo modo si eseguono solo una (invece di due) composizioni di eigend e i segni risulteranno giusti.
amoeba,

2
@Amoeba Esatto: nello spirito del calcolo manuale di un SVD, che evidentemente è un esercizio educativo, qui non si presta attenzione all'efficienza.
whuber

2
Grazie per il tuo gentile aiuto! Penso di aver capito questo problema (finalmente).
artista fallito

3
@Federico Grazie per questo promemoria. Hai perfettamente ragione: ho implicitamente supposto che tutti gli autovalori siano distinti, perché in effetti questo sarà quasi sicuramente il caso nelle applicazioni statistiche e ci si abitua a considerare le ambiguità con gli eigenspace "degenerati".
whuber

3
Hai ragione, questo è solo un caso marginale, e in effetti uno complicato. In un certo senso, si tratta di un'altra manifestazione dello stesso problema che a delineare nella sua risposta, che questo metodo non garantisce un "matching" tra le colonne di e . Il calcolo dell'SVD a partire dalle composizioni eigend è ancora un ottimo esempio di apprendimento. UV
Federico Poloni,

5

Come ho sottolineato in un commento alla risposta di @ whuber, questo metodo per calcolare SVD non funziona per ogni matrice . Il problema non si limita ai segni.

Il problema è che possono esserci ripetuti autovalori, e in questo caso la composizione genetica di e non è unica e non tutte le scelte di e possono essere utilizzate per recuperare il fattore diagonale dell'SVD. Ad esempio, se prendi una matrice ortogonale non diagonale (ad esempio, ), . Tra tutte le possibili scelte per la matrice autovettore di , verrà restituito , quindi in questo caso non è diagonale.AAAAUVA=[3/54/54/53/5]AA=AA=IIeigenU=V=IUAV=A

Intuitivamente, questa è un'altra manifestazione dello stesso problema che @whuber delinea, che deve esserci una "corrispondenza" tra le colonne di e e che calcolare due composizioni di eigend separatamente non lo garantisce.UV

Se tutti i valori singolari di sono distinti, la composizione elettronica è unica (fino a ridimensionamento / segni) e il metodo funziona. Nota: non è ancora una buona idea usarlo nel codice di produzione su un computer con aritmetica in virgola mobile, perché quando si formano i prodotti e il risultato calcolato può essere disturbato da una quantità dell'ordine di , dove è la precisione della macchina. Se la grandezza dei valori singolari differisce notevolmente (di più di , approssimativamente), ciò è dannoso per l'accuratezza numerica dei più piccoli.A A A A A 2 u u 2 × 10 - 16 10 - 8AAAAAA2uu2×1016108

Il calcolo dell'SVD dalle due eigendecomposizioni è un ottimo esempio di apprendimento, ma nella vita reale le applicazioni usano sempre la svdfunzione di R per calcolare la decomposizione del valore singolare.


1
Questo commento è un buon consiglio. Si noti, tuttavia, che questo thread non è preoccupato per il modo corretto di calcolare SVD (e credo che nessuno sosterrebbe contro la tua raccomandazione). L'OP accetta implicitamente che svdfunzioni. In effetti, lo usano come standard rispetto al quale confrontare un calcolo manuale, il cui scopo è verificare l'intesa, non sostituirlo svdin alcun modo.
whuber

@whuber Osservazione corretta; Ho riformulato l'ultimo paragrafo.
Federico Poloni,
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.