Both are correct... The rows of the v
you got from numpy are the eigenvectors of M.dot(M.T)
(the transpose would be a conjugate transpose in the complex case). Eigenvectors are in the general case defined only up to a multiplicative constant, so you could multiply any row of v
by a different number, and it will still be an eigenvector matrix.
There is the additional constraint on v
that it be a unitary matrix, which loosely translates to its rows being orthonormal. This reduces your available choices for every eigenvector to only 2: the normalized eigenvector pointing in either direction. But you still get to multiply any row by -1 and still have a valid v
.
If you want to test it for your matrix, which I have loaded as a
:
>>> u, d, v = np.linalg.svd(a)
>>> D = np.zeros_like(a)
>>> idx = np.arange(a.shape[1])
>>> D[idx, idx] = d
>>> np.allclose(a, u.dot(D).dot(v))
True
>>> v[2] *= -1
>>> np.allclose(a, u.dot(D).dot(v))
True
Actually, you can only multiply the rows of v
by -1 in the real domain, but in the complex case you can multiply them by any complex number of absolute value 1:
>>> vv = v.astype(np.complex)
>>> vv[0] *= (1+1.j)/np.sqrt(2)
>>> np.allclose(a, u.dot(D).dot(v))
True