Dlaczego nie mogę uzyskać prawidłowego SVD X za pomocą rozkładu wartości własnych XX 'i X'X?

9

Próbuję wykonać SVD ręcznie:

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)

Ale ostatnia linia nie mwraca. Dlaczego? Wydaje się, że ma to coś wspólnego z oznakami tych wektorów własnych ... Czy też źle zrozumiałem procedurę?

failedstatistician
źródło
Wielokrotnie mówiono mi, że znak nie ma znaczenia w SVD ... tak to
failedstatistician
@Amoeba Dziękujemy za wyjaśnienie tego. Koncentrowałem się raczej na pytaniu angielskim niż na kodzie. Failedstatistician: zobacz, co D=diag(c(-1,1,1)*sqrt(eigen(m%*%t(m))$values))robi i pamiętaj, że pierwiastek kwadratowy (jak również każdy znormalizowany wektor własny) jest definiowany tylko do znaku. Aby uzyskać więcej wglądu, zmiany mdo m <- matrix(-2,1,1)i zawierają ,1,1)na końcu każdego z wywołań diag. Jest to przykład który stwarza ten sam problem - ale jest to tak proste, że charakter problemu stanie się całkowicie oczywisty. 1×1
whuber
1
Rozumiem. Dziękuję Ci! Czy masz ogólną zasadę określania wektora c (-1, 1, 1)? Lub w jaki sposób powiązać oznaki dwóch dekompozycji?
failedstatistician
1
Zauważ, że sztuczka @ Whubera z c(-1,1,1)działa, ale Dzdefiniowana w ten sposób nie daje ci pojedynczych wartości. Wszystkie wartości osobliwe muszą być z definicji dodatnie. Pytanie, jak połączyć znaki Ui, Vjest dobre i nie mam odpowiedzi. Dlaczego nie zrobisz SVD? :-)
ameba

Odpowiedzi:

13

Analiza problemu

SVD matrycy nigdy nie jest unikalne. Niech macierz ma wymiary i niech jej SVD będzieAn×k

A=UDV

dla macierzy z kolumnami ortonormalnymi, diagonalnej macierzy z nieujemnymi wpisami oraz macierzy z kolumnami ortonormalnymi.n×pUp×pDk×pV

Teraz wybrać, dowolnie każdy diagonalny macierzy o s po przekątnej, tak, jest tożsamość . Następniep×pS±1S2=Ip×pIp

A=UDV=UIDIV=U(S2)D(S2)V=(US)(SDS)(VS)

jest SVD ponieważ pokazuje ma ortonormalnych kolumny i podobne obliczenia pokazują, że ma kolumny ortonormalne. Ponadto, ponieważ i są ukośne, dojeżdżają do pracy, skąd pokazuje, że nadal ma nieujemne wpisy.A

(US)(US)=SUUS=SIpS=SS=S2=Ip
USVSSD
SDS=DS2=D
D

Metoda zaimplementowana w kodzie w celu znalezienia SVD znajduje która przekątna i podobnie która przekątna Kontynuuje obliczanie w oparciu o wartości własne znalezione w . Problemem jest to nie zapewnia spójną dopasowanie kolumn z kolumnami .U

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

Rozwiązanie

Zamiast tego, po znalezieniu takiego i takiego , użyj ich do obliczeniaUV

UAV=U(UDV)V=(UU)D(VV)=D

bezpośrednio i skutecznie. Wartości diagonalne tego niekoniecznie są dodatnie. D (Jest tak, ponieważ nie ma nic w procesie diagonalizacji lub który to zagwarantuje, ponieważ te dwa procesy zostały przeprowadzone osobno.) Ustaw je pozytywnie, wybierając wpisy wzdłuż przekątnej wyrównać znaki wpisów , aby miała wszystkie wartości dodatnie. Zrekompensuj to, mnożąc odpowiednio przez :AAAASDSDUS

A=UDV=(US)(SD)V.

To jest SVD.

Przykład

Niech z . SVD jestn=p=k=1A=(2)

(2)=(1)(2)(1)

z , i .U=(1)D=(2)V=(1)

Jeśli przekątna naturalnie wybrałbyś i . Podobnie, jeśli przekątna , wybierzesz . Niestety, Zamiast tego oblicz Ponieważ jest to ujemne, ustaw . To dostosowuje do i do . Otrzymałeś który jest jednym z dwóch możliwych SVD (ale nie takim samym jak oryginał!).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),

Kod

Oto zmodyfikowany kod. Jego wydajność potwierdza

  1. Metoda odtwarza się mpoprawnie.
  2. U i nadal są ortonormalne.V
  3. Ale wynik nie jest tym samym SVD zwróconym przez svd. (Oba są jednakowo ważne.)
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
Whuber
źródło
1
+1. To jest bardzo jasne. Dodam tylko, że w praktyce wystarczy obliczyć albo Ualbo V, a następnie, aby uzyskać inną matrycę poprzez pomnożenie A. W ten sposób wykonuje się tylko jedną (zamiast dwóch) eigend-kompozycje, a znaki wyjdą dobrze.
ameba
2
@Amoeba Zgadza się: w duchu ręcznego obliczania SVD, które najwyraźniej jest ćwiczeniem edukacyjnym, nie zwraca się tutaj uwagi na wydajność.
whuber
2
Dziękuję za miłą pomoc! Myślę, że rozumiem ten problem (w końcu).
failedstatistician
3
@Federico Dziękuję za to przypomnienie. Masz całkowitą rację - domyślnie założyłem, że wszystkie wartości własne są odrębne, ponieważ w rzeczywistości jest to prawie na pewno w przypadku zastosowań statystycznych i człowiek nie ma zwyczaju rozważać dwuznaczności w „zdegenerowanych” przestrzeniach własnych.
whuber
3
Masz rację, to tylko przypadek skrajny i rzeczywiście trudny. W pewnym sensie jest to kolejny przejaw tego samego problemu, który zarysowałeś w odpowiedzi, że ta metoda nie zapewnia „dopasowania” między kolumnamiU i V. Obliczanie SVD, począwszy od kompozycji elektronicznych, jest wciąż doskonałym przykładem do nauki.
Federico Poloni
5

Jak nakreśliłem w komentarzu do odpowiedzi @ whuber, ta metoda obliczania SVD nie działa dla każdej matrycy . Problem nie ogranicza się do znaków.

Problem polega na tym, że mogą występować powtarzające się wartości własne, w tym przypadku składająca się z osobna AA i AA nie jest wyjątkowy i nie wszystkie wybory U i Vmoże być użyty do odzyskania współczynnika przekątnej SVD. Na przykład, jeśli weźmiesz dowolną nie przekątną macierz ortogonalną (powiedzmy,A=[3/54/54/53/5]), następnie AA=AA=I. Wśród wszystkich możliwych wyborów macierzy wektorów własnychI, eigenwróciU=V=I, więc w tym przypadku UAV=A nie jest przekątna.

Intuicyjnie jest to kolejny przejaw tego samego problemu, który zarysowuje @whuber, że musi istnieć „dopasowanie” między kolumnami U i V, a osobne obliczenie dwóch osobnych kompozycji nie gwarantuje tego.

Jeśli wszystkie liczby w liczbie pojedynczej Asą różne, wówczas skład eigend jest unikalny (aż do skalowania / znaków) i metoda działa. Uwaga: nadal nie jest dobrym pomysłem stosowanie go w kodzie produkcyjnym na komputerze z arytmetyką zmiennoprzecinkową, ponieważ podczas tworzenia produktówAA i AA obliczony wynik może być zaburzony o wielkość rzędu A2u, gdzie to precyzja maszyny. Jeśli wielkości pojedynczych wartości znacznie się różnią (z grubsza ponad ), jest to szkodliwe dla dokładności liczbowej najmniejszych.u2×1016108

Obliczanie SVD z dwóch eigend-kompozycji jest doskonałym przykładem uczenia się, ale w rzeczywistych aplikacjach zawsze używaj svdfunkcji R do obliczania dekompozycji liczby pojedynczej.

Federico Poloni
źródło
1
Ten komentarz jest dobrą radą. Pamiętaj jednak, że ten wątek nie dotyczy właściwego sposobu obliczania SVD (i uważam, że nikt nie sprzeciwiłby się twojej rekomendacji). PO domyślnie przyjmuje, że to svddziała. Rzeczywiście używają go jako standardu do porównania obliczeń ręcznych, których celem jest sprawdzenie zrozumienia, a nie zamiana svdw jakikolwiek sposób.
whuber
@whuber Prawidłowa obserwacja; Przeredagowałem ostatni akapit.
Federico Poloni