Análise do Problema
O SVD de uma matriz nunca é único. Deixe a matriz ter dimensões deixe que seu SVD sejan × kAn×k
A=UDV′
para um matriz com colunas ortonormais, uma diagonal matriz com entradas não-negativos, e uma matriz com colunas ortonormais.U p × p D k × p Vn×pUp×pDk×pV
Agora escolha, arbitrariamente , qualquer diagonal matriz tendo s na diagonal, para que é a identidade . Entãop×p± 1 S 2 = I p × p I pS±1S2=Ip×pIp
A=UDV′=UIDIV′=U(S2)D(S2)V′=(US)(SDS)(VS)′
também é um SVD de porque demonstra que tem colunas ortonormais e um cálculo semelhante demonstra que o tem colunas ortonormais. Além disso, como e são diagonais, eles comutam, de onde mostra que ainda possui entradas não negativas.( U S ) ' ( U S ) = S ' L ' L S = S ' I P S = S ' S = S 2 = I P L S V S S D S D S = D S 2 = D DA
(US)′(US)=S′U′US=S′IpS=S′S=S2=Ip
USVSSDSDS=DS2=D
D
O método implementado no código para encontrar um SVD encontra um que diagonaliza e, da mesma forma, um que diagonaliza Ele procede ao cálculo de em termos dos valores próprios encontrados em . O problema é que isto não assegurar uma correspondência consistente das colunas de com as colunas de .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′)′=UDV′VD′U′=UD2U′
VA′A=VD2V′.
DD2UV
Uma solução
Em vez disso, depois de encontrar um e um , use-os para calcularVUV
U′AV=U′(UDV′)V=(U′U)D(V′V)=D
direta e eficientemente. Os valores diagonais deste não são necessariamente positivos. D (Isso ocorre porque não há nada sobre o processo de diagonalizar ou que garantirá que, uma vez que esses dois processos foram realizados separadamente.) Torne-os positivos escolhendo as entradas ao longo da diagonal de igualar os sinais das entradas de , para que tenha todos os valores positivos. Para compensar isso, multiplique por :A′AAA′SDSDUS
A=UDV′=(US)(SD)V′.
Isso é um SVD.
Exemplo
Seja com . Um SVD én=p=k=1A=(−2)
(−2)=(1)(2)(−1)
com , e .U=(1)D=(2)V=(−1)
Se você diagonalizar , naturalmente escolheria e . Da mesma forma, se você diagonalizar , escolheria . Infelizmente, Em vez disso, calcule Como isso é negativo, defina . Isso ajusta para e para . Você obteve que é um dos dois SVDs possíveis (mas não o mesmo que o original!).A′A=(4)U=(1)D=(4–√)=(2)AA′=(4)V=(1)
UDV′=(1)(2)(1)=(2)≠A.
D=U′AV=(1)′(−2)(1)=(−2).
S=(−1)UUS=(1)(−1)=(−1)DSD=(−1)(−2)=(2)A=(−1)(2)(1),
Código
Aqui está o código modificado. Sua saída confirma
- O método recria
m
corretamente.
- U e realmente ainda são ortonormais.V
- Mas o resultado não é o mesmo SVD retornado por
svd
. (Ambos são igualmente válidos.)
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