Numpy matrx and arrary simple calculation - python

I need to do simple calculation on matricies and vector using np.array and np.matrix. My problem is that I do not know what is the difference between np.array and np.matrix. Calculation do I need to do is (among others):
A - matrix
B - matrix
x - vector
1. A * x
2. A * B
3. (A * A^T)^-1
Once, I need to do in using np.array and again using np.matrix.
I have tried many ways like:
Ax = A.dot(x) # multiplication by vector
AB = np.dot(A, B) # multiplication by matrix
ab = np.matmul(A, B) # multiplication by matrix
At = A.transpose()
At = np.transpose(A)
inv = np.linalg.inv(a) # and inverse matrix, but I do not know which is np. matrix or np.array.
Kindly help.

Here's an answer clarifying the differences and the advantages of vectors and matrices.
It also explains multiplications between them.

Related

In which scenario would one use another matrix than the identity matrix for finding eigenvalues?

The scipy.linalg.eigh function can take two matrices as arguments: first the matrix a, of which we will find eigenvalues and eigenvectors, but also the matrix b, which is optional and chosen as the identity matrix in case it is left blank.
In what scenario would someone like to use this b matrix?
Some more context: I am trying to use xdawn covariances from the pyRiemann package. This uses the scipy.linalg.eigh function with a covariance matrix a and a baseline covariance matrix b. You can find the implementation here. This yields an error, as the b matrix in my case is not positive definitive and thus not useable in the scipy.linalg.eigh function. Removing this matrix and just using the identity matrix however solves this problem and yields relatively nice results... The problem is that I do not really understand what I changed, and maybe I am doing something I should not be doing.
This is the code from the pyRiemann package I am using (modified to avoid using functions defined in other parts of the package):
# X are samples (EEG data), y are labels
# shape of X is (1000, 64, 2459)
# shape of y is (1000,)
from scipy.linalg import eigh
Ne, Ns, Nt = X.shape
tmp = X.transpose((1, 2, 0))
b = np.matrix(sklearn.covariance.empirical_covariance(tmp.reshape(Ne, Ns * Nt).T))
for c in self.classes_:
# Prototyped response for each class
P = np.mean(X[y == c, :, :], axis=0)
# Covariance matrix of the prototyper response & signal
a = np.matrix(sklearn.covariance.empirical_covariance(P.T))
# Spatial filters
evals, evecs = eigh(a, b)
# and I am now using the following, disregarding the b matrix:
# evals, evecs = eigh(a)
If A and B were both symmetric matrices that doesn't necessarily have to imply that inv(A)*B must be a symmetric matrix. And so, if i had to solve a generalised eigenvalue problem of Ax=lambda Bx then i would use eig(A,B) rather than eig(inv(A)*B), so that the symmetry isn't lost.
One practical application is in finding the natural frequencies of a dynamic mechanical system from differential equations of the form M (d²x/dt²) = Kx where M is a positive definite matrix known as the mass matrix and K is the stiffness matrix, and x is displacement vector and d²x/dt² is acceleration vector which is the second derivative of the displacement vector. To find the natural frequencies, x can be substituted with x0 sin(ωt) where ω is the natural frequency. The equation reduces to Kx = ω²Mx. Now, one can use eig(inv(K)*M) but that might break the symmetry of the resultant matrix, and so I would use eig(K,M) instead.
A - lambda B x it means that x is not in the same basis as the covariance matrix.
If the matrix is not definite positive it means that there are vectors that can be flipped by your B.
I hope it was helpful.

How to multiply a series of matrices together?

I have a numpy array of matrices which i am trying to multiply together in the form A * B * C * D where A is the first matrix, B is the second and so on. I have tried this code:
matrix = matrices[0]
for m in matrices[1:]:
matrix = np.matmul(matrix, m)
However I believe this multiplication is wrong as i get incorrect output variables, and I have triple checked the rest of my code so I believe this is the issue. How can I multiply all the matrices in this array together? Also the array length will vary depending on the input file, thus i cant use an A * B * C approach.
Your code for multiply a series of matrices together should work. Here is an example using your method with some simple matrices.
import numpy as np
matrices = []
matrices.append(np.eye(3,dtype=float))
matrices.append(np.matrix('1.0,2.0,3.0;4.0,5.0,6.0;7.0,8.0,8.0'))
matrices.append(np.eye(3,dtype=float))
matrices.append(np.linalg.inv(np.matrix('1.0,2.0,3.0;4.0,5.0,6.0;7.0,8.0,8.0')))
matrix = matrices[0]
for m in matrices[1:]:
matrix = np.matmul(matrix, m)
print(matrix)
directmul = np.matmul(matrices[1],matrices[3])
print(np.subtract(matrix,directmul))
Your problem is somewhere else: maybe how you are filling the list of matrices, or how are you filling the matrices. Have you tried unit testing on your code? Have you give a try to the python debugger?

Numpy multiplication matrix (more than two matrix)

If I need to do multiplication between 5 matrix (taking into account the good shape of the matrix to be able to multiplicate), np.dot doesn't work. For ex, in matlab you can easily write:
Rf = T^-1 * S^-1 * R * S * T
to multiply two matrices you can use:
np.matmul(matrix1, matrix2).shape
then use for loop to multiply 5 matrices.
for more info check numpy documentation :
https://docs.scipy.org/doc/numpy/reference/generated/numpy.matmul.html

Efficient linear algebra for block-diagonal matrices in compressed format

I have a linear system in which all the matrices are block diagonal. They have N blocks identical in shape.
Matrices are stored in compressed format as numpy arrays with shape (N, n, m), while the shape of the vectors is (N, m).
I currently implemented the matrix-vector product as
import numpy as np
def mvdot(m, v):
return (m * np.expand_dims(v, -2)).sum(-1)
Thanks to broadcasting rules, if all the blocks of a matrix are the same I have to store it only once in an array with shape (1, n, m): the product with a vector (N, m) still gives the correct (N, n) vector.
My questions are:
how to implement an efficient matrix-matrix product that yields the matrix with shape (N, n, m) from two matrices with shapes (N, n, p) and (N, p, m)?
is there a way to perform these operations with a numpy built-in (possibly faster) function? Functions like np.linalg.inv make me think that numpy was designed to support this compressed format for block diagonal matrices.
If I understand your question correctly, you have two arrays of shape (N,n,p) and (N,p,m), respectively, and their product should be of shape (N,n,m) where element [i,:,:] is the matrix product of M1[i,:,:] and M2[i,:,:]. This can be achieved using numpy.einsum:
import numpy as np
N = 7
n,p,m = 3,4,5
M1 = np.random.rand(N,n,p)
M2 = np.random.rand(N,p,m)
Mprod = np.einsum('ijk,ikl->ijl',M1,M2)
# check if all the submatrices are what we expect
all([np.allclose(np.dot(M1[k,...],M2[k,...]),Mprod[k,...]) for k in range(N)])
# True
Numpy's einsum is an incredibly versatile construction for complicated linear operations, and it's usually pretty efficient with two operands. The idea is to rewrite your operation in an indexed way: what you need is to multiply M1[i,j,k] with M2[i,k,l] for each i,j,l, and sum over k. This is exactly what the above call to einsum does: it collapses the index k, and performs the necessary products and assignments along the remaining dimensions in the given order.
The matrix-vector product can be done similarly:
M = np.random.rand(N,n,m)
v = np.random.rand(N,m)
Mvprod = np.einsum('ijk,ik->ij',M,v)
It's possible that numpy.dot can be coerced with the proper transposes and dimension tricks to directly do what you want, but I couldn't make that work.
Both of the above operations can be done in the same function call by allowing an implicit number of dimensions within einsum:
def mvdot(M1,M2):
return np.einsum('ijk,ik...->ij...',M1,M2)
Mprod = mvdot(M1,M2)
Mvprod = mvdot(M,v)
In case the input argument M2 is a block matrix, there will be a leading dimension appended to the result, creating a block matrix. In case M2 is a "block vector", the result will be a block vector.
Since Python 3.5 and above, the previous example can be simplified using the matrix multiplication operator # (numpy.matmul) which treats this case as a stack of matrices residing in the last two indexes and broadcast accordingly:
import numpy as np
N = 7
n,p,m = 3,4,5
M1 = np.random.rand(N,n,p)
M2 = np.random.rand(N,p,m)
Mprod = M1 # M2 # similar to np.matmul(M1, M2)
all([np.allclose(np.dot(M1[k,...],M2[k,...]),Mprod[k,...]) for k in range(N)])
#True

Defining and Multiplying matrices in numpy (python)

I'm trying to use numpy and i couldn't figure out how to properly define a n by n matrix in numpy.
I've used the numpy.zeros(n,n)... but I'm not really sure if it is ok.
is it correct to use numpy like this?
im trying to get (matrix^T * vector) - vector.
matrix = np.zeros((n,n))
start = [(1/float(n)) for _ in range(n)]
vector = np.array(start)
newvector = np.dot(np.transpose(matrix) , vector)
ans= np.subtract(newvector , vector)
I'm asking this because im getting the wrong results and im not sure where is my problem
To define a matrix in numpy, you have several choices:
numpy.zeros defines a matrix filled with zeros.
numpy.ones defines a matrix filled with ones.
numpy.array defines a matrix based on something else (a list, for example)
numpy.empty defines a matrix without assigning values to it (so it contains what currently is in memory a the place it was allocated).
All those functions use as first argument a tuple with the dimensions of the matrix. This is why parenthesis are doubled.
With numpy, you can use any usual operator (+, -, * /, **), which are performed elementwise.
To perform matrix multiplication, you need to use numpy.dot function.
You can then wirte you function as:
n = 10
matrix = numpy.zeros((n,n))
vector = numpy.ones(n) / n
newvector = numpy.dot(matrix.T, vector)
ans = newvector - vector
But I suppose that matrix should be something else than a matrix of zeros, or the transpose operation isn't needed.
Basically you are right how you to use numpy. To ease the usage I would write the start vector in a different way and use object methods to calculate the desired values.
n = 10
matrix = np.zeros((n, n))
vector = np.ones((n,)) * 1.0/n
new_vector = matrix.T.dot(vector)
ans = new_vector - vector
print ans
>>> [-0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1]
The output should be correct (Matrix times vector should be a vector full of zeros minus one devided by ten, voila). I'm quite not sure about the general form of an NxM matrix and the usage of transpose (that would need another minute to think about ;-) )
In addition to the answer by #CharlesBrunet, there is a specialized class for mathematical matrices where A*B is the standard matrix multiplication (as opposed to element-wise).
numpy.matrix
Returns a matrix from an array-like object, or from a string of data. A matrix is a specialized 2-D array that retains its 2-D nature through operations. It has certain special operators, such as * (matrix multiplication) and ** (matrix power).
Creation examples from the docs:
>>> a = numpy.matrix('1 2; 3 4')
>>> print a
[[1 2]
[3 4]]
>>> numpy.matrix([[1, 2], [3, 4]])
matrix([[1, 2],
[3, 4]])

Categories

Resources