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 m
wraca. Dlaczego? Wydaje się, że ma to coś wspólnego z oznakami tych wektorów własnych ... Czy też źle zrozumiałem procedurę?
r
svd
eigenvalues
failedstatistician
źródło
źródło
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, zmianym
dom <- 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.c(-1,1,1)
działa, aleD
zdefiniowana w ten sposób nie daje ci pojedynczych wartości. Wszystkie wartości osobliwe muszą być z definicji dodatnie. Pytanie, jak połączyć znakiU
i,V
jest dobre i nie mam odpowiedzi. Dlaczego nie zrobisz SVD? :-)Odpowiedzi:
Analiza problemu
SVD matrycy nigdy nie jest unikalne. Niech macierz ma wymiary i niech jej SVD będzieZA n × k
dla macierzy z kolumnami ortonormalnymi, diagonalnej macierzy z nieujemnymi wpisami oraz macierzy z kolumnami ortonormalnymi.n × p U p × p re k × p V.
Teraz wybrać, dowolnie każdy diagonalny macierzy o s po przekątnej, tak, jest tożsamość . Następniep × p S. ± 1 S.2)= Ja p × p jap
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.ZA
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
Rozwiązanie
Zamiast tego, po znalezieniu takiego i takiego , użyj ich do obliczeniaU V.
bezpośrednio i skutecznie. Wartości diagonalne tego niekoniecznie są dodatnie.re (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 :ZA′ZA ZAZA′ S. re S.re U S.
To jest SVD.
Przykład
Niech z . SVD jestn = p = k = 1 A = ( - 2 )
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ł!).A′A=(4) U=(1) D=(4–√)=(2) AA′=(4) V=(1)
Kod
Oto zmodyfikowany kod. Jego wydajność potwierdza
m
poprawnie.svd
. (Oba są jednakowo ważne.)źródło
U
alboV
, a następnie, aby uzyskać inną matrycę poprzez pomnożenieA
. W ten sposób wykonuje się tylko jedną (zamiast dwóch) eigend-kompozycje, a znaki wyjdą dobrze.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 osobnaA′A i AA′ nie jest wyjątkowy i nie wszystkie wybory U i V moż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/5−4/54/53/5] ), następnie AA′=A′A=I . Wśród wszystkich możliwych wyborów macierzy wektorów własnychI , U=V=I , więc w tym przypadku U′AV=A nie jest przekątna.
eigen
wróciIntuicyjnie jest to kolejny przejaw tego samego problemu, który zarysowuje @whuber, że musi istnieć „dopasowanie” między kolumnamiU i V , a osobne obliczenie dwóch osobnych kompozycji nie gwarantuje tego.
Jeśli wszystkie liczby w liczbie pojedynczejA są 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ówA′A i AA′ obliczony wynik może być zaburzony o wielkość rzędu ∥A∥2u , 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.u≈2×10−16 10−8
Obliczanie SVD z dwóch eigend-kompozycji jest doskonałym przykładem uczenia się, ale w rzeczywistych aplikacjach zawsze używaj
svd
funkcji R do obliczania dekompozycji liczby pojedynczej.źródło
svd
działa. Rzeczywiście używają go jako standardu do porównania obliczeń ręcznych, których celem jest sprawdzenie zrozumienia, a nie zamianasvd
w jakikolwiek sposób.