How to find non-normalized eigen vector? - python

My goal is to validate whether an eigen vector is part of an nxn square.
The formula that I know A * x = lamda * x
Example
import numpy as np
A = np.array([[1,-1],
[6,4]])
eigvalues, eigvectors = np.linalg.eig(A)
The eigvectors output are normalized eigen vector.
According to this website, normalized eigen vector is an eigvector having unit length.
In this case I want to check whether eigen vector is part of an n x n square matrix.
x = [ 1
3 ]
So, what I did is that to multiply the eigen vector in question with the square root of the eigen vector:
normalized_eigvector = np.array([1,3]) * npsqrt(1 + 9)
np.array_equal(normalized_eigvector, np.absolute(eigectors[1]))
Is this the correct way to do it?

Related

Why is scipy's probability density function not accepting size of my mean?

I am using a function to calculate a likelihood density.
I am running through two xs which are vectors of length 7.
def lhd(x0, x1, dt): #Define a function to calculate the likelihood density given two values.
d = len(x0) #Save the length of the inputs for the below pdf input.
print(d)
print(len(x1))
lh = multivariate_normal.pdf(x1, mean=(1-dt)*x0, cov=2*dt*np.identity(d)) #Take the pdf from a multivariate normal built from x0, given x1.
return lh #Return this pdf value.
The mean here is a vector of length 7, and the covariance is a (7,7) array.
When I run this, I get the error
ValueError: Array 'mean' must be a vector of length 49.
but looking at the formula of the pdf I do not think this is correct. Any idea what is going wrong here?
If dt is a (7,7) array, (1-dt) is also (7,7), the * operator in (1-dt)*x0 is the element-wise multiplication, if x0 is a vector of length 7 the result will be a (7,7) array.
I guess you meant to use matrix multiplication, you can that this using the x0 - dt # x0 (where # denotes the matrix multiplication operator).

Why is numpy saying that my totally positive matrix is not positive semi-definite?

I generate a correlation matrix by drawing from a uniform distribution:
corr = np.random.uniform(low=0.1, high=0.3, size=[20, 20])
and set the main diagonal elements to one
corr[np.diag_indices_from(corr)] = 1
Then, I make the correlation matrix symmetric
corr[np.triu_indices(n=20, k=1)] = corr.T[np.triu_indices(n=20, k=1)]
which yields a totally positive matrix ,i.e., all values of the matrix are strictly positive.
According to numpy, however, the matrix is not positive (semi-) definit.
np.all(np.linalg.eigvals(corr) >= 0)
False
That's still not guaranteed to be PSD
I will give you two easy ways:
Sny square non-singular matrix can be used to create a PSD matrix with
A = A # A.T
Any matrix can be used to produce a PSD matrix with
A = (A + A.T)/2
A = A - np.eye(len(A)) * (np.min(np.linalg.eigvalsh(A)) - 0.001)
If you want the minimum perturbation to a symmetric matrix (the least squares projection to the positive semidefinite cone)
A_ = (v * np.maximum(w, 0.01)) # v.T
print(np.linalg.eigvalsh(A_))
Notice that I am giving a margin of 0.01, if I used strictly zero your test could fail due to numerical errors.

Numpy cross covariance

Let X be a (d_x,n) matrix containing n observations of a d_x-dimensional variable x, and let w be a vector of weights (probabilities) of dimension n. The weighted covariance is given in numpy by
CX = numpy.cov(X, ddof=0, aweights=w)
Let now Y be a (d_y,n) matrix containing n observations of a d_y-dimensional vector. Is there a clever way to compute the weighted cross covariance, in pseudocode
CXY = sum(W[i] * numpy.outer((X[i, :] - X_mean),(Y[i, :] - Y_mean)))
?

How to find two largest eigenvector in python?

I can find eigenvectors of a matrix in Python as follows:
from numpy import linalg as LA
w, v = LA.eig(np.diag((1, 2, 3)))
But how to find the largest two eigenvectors for a larger matrix of size 100*200?
Eigenvalue decomposition is not defined for a non-square matrix. The closest operation is single value decomposition. SVD and EIG for a non-square matrix are related in that the single values are the square root of the eigenvalues of the transpose of the matrix times itself.
B = A' * A
SVD(A) * SVD(A) ~= EIG(B)
So one potential answer to your question is:
import numpy as np
A = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
B = np.matmul(np.transpose(A), A)
u,s,v = np.linalg.svd(A)
V, D = np.linalg.eig(B)
print(f'Compare s*s to V {s*s - V}')
While s is not directly the eigenvalues of A it is somewhat related.

Return the eigenvector corresponding to the max eigenvalue of A

As the title says, I must compute the eigenvector v corresponding to the max eigenvalue. I'm not sure what commands do this. Any tips?
import numpy as np
import scipy.linalg as la
#x and y both 1D NumPy arrays of same length
def eigen_X(x,y):
xa = np.mean(x)
ya = np.mean(y)
x_bar = x - xa
y_bar = y - ya
X = np.column_stack(x_bar,y_bar)
A = X.transpose()#X
#The rest of the code goes here
scipy.linalg.eig provides a function that calculates eigenvalues and eigenvectors of a 2D, square matrix. To get the (right?) eigenvector corresponding to the largest eigenvalue, use
w, vl, vr = la.eig(A)
largest_eigenvector = vr[:, np.argmax(w)]
Replace vr[:, np.argmax(w)] above with vl[np.argmax(w)] if you're looking for the corresponding left eigenvector.
It's possible to do this with just numpy's "linalg" library. The eig() function can give you the eigenvalues and eigenvectors. I converted the eigenvalues from a numpy array into a list in order to use "index" here to find the position of the largest eigenvalue. Then I picked the corresponding column from the eigenvector array.
>>> from numpy import linalg as LA
>>> M = ((1,-3,3), (3,-5,3), (6,-6,4))
>>> vals, vects = LA.eig(M)
>>> maxcol = list(vals).index(max(vals))
>>> eigenvect = vects[:,maxcol]
>>> print eigenvect
[-0.40824829+0.j -0.40824829+0.j -0.81649658+0.j]
If you need "dominant eigenvalue" you need to find the position of the largest eigenvalue, all in absolute value. Try
import numpy.linalg as npla
import numpy as np
M = np.array([[0.12,6.1,-5.2], [4.6,-7.8,9.3], [3.1,2.4,8.7]])
# egv, vects = npla.eig(M)
egv = npla.eigvals(M)
print('egv dominant of M ', egv[np.argmax(np.abs(egv))])
You can ignore np.abs(egv) and leave agv alone for max eigenvalue

Categories