Co to jest prosty algorytm obliczania SVD macierzy ?
Idealnie chciałbym mieć solidny algorytm liczbowy, ale chciałbym zobaczyć zarówno proste, jak i nie tak proste implementacje. Kod C został zaakceptowany.
Wszelkie odniesienia do artykułów lub kodu?
Odpowiedzi:
Zobacz /math/861674/decompose-a-2d-arbitrary-transform-into-only-scaling-and-rotation (przepraszam, umieściłbym to w komentarzu, ale zarejestrowałem się po prostu opublikować, żeby nie dodawać jeszcze komentarzy).
Ale ponieważ piszę to jako odpowiedź, napiszę również metodę:
To rozkłada macierz w następujący sposób:
Jedyną rzeczą, której należy się wystrzegać za pomocą tej metody jest to, żeG = F.= 0 lub H.= E= 0 dla atan2.
Wątpię, czy może być bardziej solidny( Aktualizacja: patrz odpowiedź Alexa Eftimiadesa!).Odnośnik to: http://dx.doi.org/10.1109/38.486688 (podany tam przez Rahula), który pochodzi z dolnej części tego postu na blogu: http://metamerist.blogspot.com/2006/10/linear-algebra -for-graphics-geeks-svd.html
Aktualizacja: Jak zauważył @VictorLiu w komentarzu,sy może być ujemny. Dzieje się tak wtedy i tylko wtedy, gdy wyznacznik macierzy wejściowej jest również ujemny. Jeśli tak jest w przypadku i chcesz dodatnich wartości pojedynczych, po prostu weź bezwzględną wartość sy .
źródło
@Pedro Gimeno
„Wątpię, czy może być bardziej solidny.”
Wyzwanie przyjęte.
Zauważyłem, że typowym podejściem jest używanie funkcji trig, takich jak atan2. Intuicyjnie nie powinno być potrzeby używania funkcji trig. Rzeczywiście, wszystkie wyniki kończą się jako sinus i cosinus arctans - które można uprościć do funkcji algebraicznych. Trwało to dość długo, ale udało mi się uprościć algorytm Pedro, aby używał tylko funkcji algebraicznych.
Poniższy kod python załatwia sprawę.
źródło
y1
= 0,x1
= 0,h1
= 0 it1
= 0/0 =NaN
.GSL ma SVD 2-by-2 solver którym opiera się część rozkładu QR głównego algorytmu dla SVD
gsl_linalg_SV_decomp
. Zobaczsvdstep.c
plik i wyszukajsvd2
funkcję. Funkcja ma kilka specjalnych przypadków, nie jest trywialna i wygląda na to, że robi kilka rzeczy, aby zachować ostrożność liczbową (np. Używać,hypot
aby uniknąć przepełnienia).źródło
ChangeLog
pliku GSL jest trochę pliku. I możesz spojrzeć nasvd.c
szczegóły dotyczące całego algorytmu. Jedyną prawdziwą dokumentacją wydaje się być funkcja wysokiego poziomu, którą można wywoływać, npgsl_linalg_SV_decomp
.Kiedy mówimy „odporny numerycznie”, zwykle mamy na myśli algorytm, w którym robimy takie rzeczy, jak obracanie, aby uniknąć propagacji błędów. Jednak w przypadku macierzy 2x2 można zapisać wynik w postaci jawnych wzorów - tj. Zapisać wzory dla elementów SVD, które podają wynik tylko w kategoriach danych wejściowych , a nie w odniesieniu do wcześniej obliczonych wartości pośrednich . Oznacza to, że możesz mieć anulowanie, ale brak propagacji błędów.
Chodzi o to, że w przypadku systemów 2x2 martwienie się o solidność nie jest konieczne.
źródło
Kod ten jest oparty na papierze Blinn jest , Ellis papieru , wykład SVD i dodatkowych obliczeń. Algorytm nadaje się do regularnych i pojedynczych rzeczywistych macierzy. Wszystkie poprzednie wersje działają w 100% tak dobrze, jak ta.
źródło
Potrzebowałem algorytmu, który ma
Odwołaj to
Obliczanie obrotu diagonalizującego można wykonać, rozwiązując następujące równanie:
gdzie
Pomysły:
http://www.cs.utexas.edu/users/inderjit/public_papers/HLA_SVD.pdf
http://www.math.pitt.edu/~sussmanm/2071Spring08/lab09/index.html
http: // www.lucidarme.me/singular-value-decomposition-of-a-2x2-matrix/
źródło
Użyłem opisu pod adresem http://www.lucidarme.me/?p=4624 do stworzenia tego kodu C ++. Matryce pochodzą z biblioteki Eigen, ale z tego przykładu można łatwo utworzyć własną strukturę danych:
Ze standardową funkcją znaku
Daje to dokładnie takie same wartości jak
Eigen::JacobiSVD
(patrz https://eigen.tuxfamily.org/dox-devel/classEigen_1_1JacobiSVD.html ).źródło
S2 = hypot( a*a + b*b - c*c - d*d, 2*(a*c + b*d))
źródło
Na własne potrzeby starałem się wyodrębnić minimalne obliczenia dla dysku DVD 2x2. Myślę, że jest to prawdopodobnie jedno z najprostszych i najszybszych rozwiązań. Szczegóły znajdziesz na moim osobistym blogu: http://lucidarme.me/?p=4624 .
Zalety: proste, szybkie i można obliczyć jedną lub dwie z trzech macierzy (S, U lub D) tylko wtedy, gdy nie potrzebujesz trzech macierzy.
Wadą jest atan2, który może być niedokładny i może wymagać biblioteki zewnętrznej (typ. Math.h).
źródło
Oto implementacja rozwiązania SVD 2x2. Oparłem go na kodzie Victora Liu. Jego kod nie działał dla niektórych matryc. Użyłem tych dwóch dokumentów jako matematycznego odniesienia do rozwiązania: pdf1 i pdf2 .
Metoda macierzowa
setData
jest uporządkowana według rzędów. Wewnętrznie reprezentuję dane macierzy jako tablicę 2D podaną przezdata[col][row]
.źródło