Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V* in SVD should be transposed #47

Closed
nblumoe opened this issue Mar 28, 2015 · 4 comments
Closed

V* in SVD should be transposed #47

nblumoe opened this issue Mar 28, 2015 · 4 comments

Comments

@nblumoe
Copy link

nblumoe commented Mar 28, 2015

I am not 100% sure if vectorz does it wrong or other libs, I am continuing to investigate this. However, here is the issue, illustrated with an example:

user=> (clojure.core.matrix/set-current-implementation :vectorz)
:vectorz
(:V* (decomp-svd (covariance [[1 2 3 ] [ 4 5 6 ] [7 8 9] [10 11 12]])))
#<mikera.matrixx.Matrix@492d4c90
[[0.5773502691896257,0.5773502691896255,0.5773502691896257],
[0.816496580927726,-0.40824829046386285,-0.40824829046386296],
[0.0,-0.7071067811865475,0.7071067811865475]]>

user=> (clojure.core.matrix/set-current-implementation :clatrix)
:clatrix
user=> (:V* (decomp-svd (covariance [[1 2 3 ] [ 4 5 6 ] [7 8 9] [10 11 12]])))
((-0.5773502691896256 0.8164965809277263 0.0)
 (-0.5773502691896258 -0.40824829046386285 -0.7071067811865476)
 (-0.577350269189626 -0.40824829046386296 0.7071067811865475))

This is done via Incanter / core.matrix. As you can see the resulting V* are different as one is the transpose of the other. There are also differences in the signs, but they are not significant for SVD and we don't need to bother.

R returns the same data as the clatrix implementation:

> svd(cov(dat))
...
$v
           [,1]       [,2]       [,3]
[1,] -0.5773503  0.0000000  0.8164966
[2,] -0.5773503 -0.7071068 -0.4082483
[3,] -0.5773503  0.7071068 -0.4082483

Thus I think vectorz does it wrong. The other parts of the return value (U,S) are correct (aka the same) in all implementations and R.

@mikera
Copy link
Owner

mikera commented Mar 29, 2015

I think Vectorz is correct - V* is the transpore of V, and this is the natural form to return given the decomposition:

M = U. Σ . V*

If you want V, you can just transpose it as you observe.

Here's my test which I believe demonstrates that Vectorz has the correct behaviour:

(let [m (array :vectorz [[1 2 3 ] [ 4 5 6 ] [7 8 9]])
        {:keys [U S V*]} (svd m)]
    (inner-product U (diagonal-matrix S) V*))
=> #<Matrix [[0.9999999999999991,1.9999999999999991,2.999999999999998],
[4.000000000000001,5.000000000000003,6.000000000000001],
[7.000000000000001,8.000000000000002,9.0]]>

i.e. you can reconstruct the matrix from the decomposition (modulo minor numerical inaccuracy)

@mikera
Copy link
Owner

mikera commented Mar 29, 2015

I suspect this is Clatrix doing it wrong, and returning V instead of V*

@mikera
Copy link
Owner

mikera commented Apr 8, 2015

Closing this because not a vectorz-clj issue

@nblumoe
Copy link
Author

nblumoe commented Jun 15, 2015

Yes, you are absolutely right.

In contrast to what I said earlier, this is also in line with R. The subtle difference is, that svd in R returns V, whereas La.svd in R returns V*. Somehow I confused those.

So, everything is good. vectorz is doing it right - just like you said.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants