0

I'm implementing an SVD algorithm and wanting to use the .eig method (following this tutorial here: https://datajobs.com/data-science-repo/SVD-Tutorial-[Kirk-Baker].pdf)

We are given a 2x3 matrix: A = [[3,1,1],[-1,3,1]]

And the first step is to work out the eigenvalues and eigenvectors for AA.T.

np.linalg.eig correctly returns [12, 10] as the eigenvalues.

The eigenvectors, however, for eigenvalue 10 are returned in the opposite order to that in the tutorial. That is, the tutorial says that for this eigenvalue, the eigenvector is [1, -1]. Numpy would say the unnormalised eigenvector is [-1, 1]. Both are valid solutions.

However, using Numpy's [-1, 1] leads to the reconstruction of the matrix with the rows permuted: [[-1,3,1],[3,1,1]].

If I use the SVD method however, I am returned the correct matrix.

Code:

A = np.array([[3,1,1],[-1,3,1]])

## Find U (i.e. calculate AA^T)
U_ = np.matmul(A, A.T)
print(U_)

## Calculate the eigenvectors/eigenvalues of U
U_eig_values, U_eig_vectors = np.linalg.eig(U_)
print(U_eig_values)
# [12., 10.]
print(U_eig_vectors) 
# [[ 0.70710678 -0.70710678]
# [ 0.70710678  0.70710678]]

## Find V (i.e. calculate A^TA)
V_ = np.matmul(A.T, A)

## Calculate the eigenvectors/eigenvalues of V
V_eig_values, V_eig_vectors = np.linalg.eig(V_)
print(V_eig_values)
# [ 0., 10., 12.]

## Transpose and sort V
V_eig_vectors = -1 * V_eig_vectors[:, [2,1,0]].T
print(V_eig_vectors)
# [[ 4.08248290e-01,  8.16496581e-01,  4.08248290e-
# [ 8.94427191e-01, -4.47213595e-01, -5.07702013e-
# [-1.82574186e-01, -3.65148372e-01,  9.12870929e-01]]

## Initialise S as an m x n matrix
m = len(U[0])
n = len(V[0])
S = np.zeros((m, n))

## Populate the diagonal of S with the square root of the non-zero eigenvalues from U and V.
## The diagonal should be in decending order (from largest to smallest) of these values.
np.fill_diagonal(S, np.sqrt(U_eig_values))

## Apply the SVD formula: A = USV.T
first_part = U_eig_vectors.dot(S)
reconstructed_A = first_part.dot(V_eig_vectors)
print(reconstructed_A)
# [[-1.  3.  1.]
# [ 3.  1.  1.]]

As mentioned, using the SVD method returns a correct reconstruction

u, s, vh = np.linalg.svd(A)
print(u)
print(s)
print(vh)
## Initialise S as an m x n matrix
m = len(u)
n = len(vh)
S = np.zeros((m, n))

## Populate the diagonal of S with the square root of the non-zero eigenvalues from U and V.
## The diagonal should be in decending order (from largest to smallest) of these values.
np.fill_diagonal(S, np.sqrt(U_eig_values))

## Apply the SVD formula: A = USV.T
first_part = u.dot(S)
reconstructed_A = first_part.dot(vh)
print(reconstructed_A)
# [[ 3.  1.  1.]
# [-1.  3.  1.]]

How can I use the .eig method to return the reconstructed matrix in the correct order, WITHOUT having to do something hacky like U_eig_vectors = U_eig_vectors[[1,0],:]?

Nihir
  • 344
  • 2
  • 16
  • Instead of `[2,1,0]`, do `::-1`. – Mad Physicist Jul 15 '20 at 07:50
  • Can you explain why you transpose and reverse one set of eigenvectors but not the other? – Mad Physicist Jul 15 '20 at 07:51
  • `len(U[0])` -> `U.shape[1]` – Mad Physicist Jul 15 '20 at 07:52
  • @MadPhysicist The eigenvectors V should be transposed. By reverse do you mean the [2,1,0]? I do this because SVD requires the eigenvectors to be sorted in in descending order. This is the case with the U eigenvectors but not with V (np.linalg.eig doesn't guarantee ordering). – Nihir Jul 18 '20 at 14:54
  • If ordering isn't guaranteed, use `np.argsort`. I'll look into this more later today. Currently on mobile – Mad Physicist Jul 18 '20 at 16:42
  • Thanks @MadPhysicist, my actual code does use `argsort`, but issue comes from the calculation of the actual eigenvector returned by numpy being permuted and having the opposite sign (although the magnitudes of the components are correct). This behaviour doesn't occur on every `A` array - I suspect just the ones with negatives in them – Nihir Jul 20 '20 at 17:37
  • You are free to scale the eigenvectors however you choose. That's sort of the point of an eigenvector. – Mad Physicist Jul 20 '20 at 18:43
  • I have not said otherwise! – Nihir Jul 20 '20 at 19:44

0 Answers0