Assume that I have an affinity matrix A and a diagonal matrix D. How can I compute the Laplacian matrix in Python with nympy?
L = D^(-1/2) A D^(1/2)
Currently, I use L = D**(-1/2) * A * D**(1/2). Is this a right way?
Thank you.
Please note that it is recommended to use numpy's array instead of matrix: see this paragraph in the user guide. The confusion in some of the responses is an example of what can go wrong... In particular, D**0.5 and the products are elementwise if applied to numpy arrays, which would give you a wrong answer. For example:
import numpy as np
from numpy import dot, diag
D = diag([1., 2., 3.])
print D**(-0.5)
[[ 1. Inf Inf]
[ Inf 0.70710678 Inf]
[ Inf Inf 0.57735027]]
In your case, the matrix is diagonal, and so the square root of the matrix is just another diagonal matrix with the square root of the diagonal elements. Using numpy arrays, the equation becomes
D = np.array([1., 2., 3.]) # note that we define D just by its diagonal elements
A = np.cov(np.random.randn(3,100)) # a random symmetric positive definite matrix
L = dot(diag(D**(-0.5)), dot(A, diag(D**0.5)))
Numpy allows you to exponentiate a diagonal "matrix" with positive elements and a positive exponent directly:
m = diag(range(1, 11))
print m**0.5
The result is what you expect in this case because NumPy actually applies the exponentiation to each element of the NumPy array individually.
However, it indeed does not allow you to exponentiate any NumPy matrix directly:
m = matrix([[1, 1], [1, 2]])
print m**0.5
produces the TypeError that you have observed (the exception says that the exponent must be an integer–even for matrices that can be diagonalized with positive coefficients).
So, as long as your matrix D is diagonal and your exponent is positive, you should be able to directly use your formula.
Well, the only problem I see is that if you are using Python 2.6.x (without from __future__ import division), then 1/2 will be interpreted as 0 because it will be considered integer division. You can get around this by using D**(-.5) * A * D**.5 instead. You can also force float division with 1./2 instead of 1/2.
Other than that, it looks correct to me.
Edit:
I was trying to exponentiate a numpy array, not a matrix before, which works with D**.5. You can exponentiate a matrix element-wise using numpy.power. So you would just use
from numpy import power
power(D, -.5) * A * power(D, .5)
Does numpy have square root function for matrixes? Then you could do sqrt(D) instead of (D**(1/2))
Maybe the formula should realy be written
L = (D**(-1/2)) * A * (D**(1/2))
Based on previous comment this formula should work in case of D being diagonal matrix (I have not chance to prove it now).
Related
I am trying to implement the QR decomposition via householder reflectors. While attempting this on a very simple array, I am getting weird numbers. Anyone who can tell me, also, why using the # vs * operator between vec and vec.T on the last line of the function definition gets major bonus points.
This has stumped two math/comp sci phds as of this morning.
import numpy as np
def householder(vec):
vec[0] += np.sign(vec[0])*np.linalg.norm(vec)
vec = vec/vec[0]
gamma = 2/(np.linalg.norm(vec)**2)
return np.identity(len(vec)) - gamma*(vec*vec.T)
array = np.array([1, 3 ,4])
Q = householder(array)
print(Q#array)
Output:
array([-4.06557377, -7.06557377, -6.06557377])
Where it should be:
array([5.09, 0, 0])
* is elementwise multiplication, # is matrix multiplication. Both have their uses, but for matrix calculations you most likely want the matrix product.
vec.T for an array returns the same array. A simple array only has one dimension, there is nothing to transpose. vec*vec.T just returns the elementwise squared array.
You might want to use vec=vec.reshape(-1,1) to get a proper column vector, a one-column matrix. Then vec*vec.T does "by accident" the correct thing. You might want to put the matrix multiplication operator there anyway.
For example, I have an equation for projection matrix which works for 1 dimensional vectors:
where P is projection matrix and T is transpose.
We know that we can't simplify this fraction more (by cancelling terms) since denominator is a dot product (thus 0 dimensional scalar, number) and numerator is a matrix (column multiplied by row is a matrix).
I'm not sure how could I define function for this equation in numpy, considering that the current function that I'm using does not differentiate between these terms, multiplication is treated as it has commutative property. I'm using numpy.multiply method:
>>> import numpy as np
>>> a = np.array(a)
>>> a*a.T
array([1, 4, 9])
>>> a.T*a
array([1, 4, 9])
As you see, both of them output vectors.
I've also tried using numpy.matmul method:
>>> np.matmul(a, a.T)
14
>>> np.matmul(a.T, a)
14
which gives dot product for both of the function calls.
I also did try numpy.dot but it obviously doesn't work for numerator terms.
From my understanding, the first function call should output matrix (since column is multiplied by row) and the second function call should output a scalar in a proper case.
Am I mistaken? Is there any method that differentiates between a multiplied by a transpose and a transpose multiplied by a?
Thank you!
Note that 1-dimensional numpy arrays are not column vectors (and operations such as transposition do not make sense). If you want to obtain a column vector you should define your array as a 2-dimensional array (with the second dimension size equal to 1).
However, you don't need to define a column vector, as numpy offers functions to do what you want by manipulating an 1D array as follows
P = np.outer(a,a)/np.inner(a,a)
Stelios' answer is the best, no doubt but for completeness you can use the # operator with 2-d arrays:
a = np.array([1,4,9])[np.newaxis]
P = (a.T # a) / (a # a.T)
I am trying to find out a way to do a matrix power for a sparse matrix M: M^k = M*...*M k times where * is the matrix multiplication (numpy.dot), and not element-wise multiplication.
I know how to do it for a normal matrix:
import numpy as np
import scipy as sp
N=100
k=3
M=(sp.sparse.spdiags(np.ones(N), 0, N, N)-sp.sparse.spdiags(np.ones(N), 2, N, N)).toarray()
np.matrix_power(M,k)
How can I do it for sparse M:
M=(sp.sparse.spdiags(np.ones(N), 0, N, N)-sp.sparse.spdiags(np.ones(N), 2, N, N))
Of course, I can do this by recursive multiplications, but I am wondering if there is a functionality like matrix_power for sparse matrices in scipy.
Any help is much much appreciated. Thanks in advance.
** has been implemented for csr_matrix. There is a __pow__ method.
After handling some special cases this __pow__ does:
tmp = self.__pow__(other//2)
if (other % 2):
return self * tmp * tmp
else:
return tmp * tmp
For sparse matrix, * is the matrix product (dot for ndarray). So it is doing recursive multiplications.
As math noted, np.matrix also implements ** (__pow__) as matrix power. In fact it ends up calling np.linalg.matrix_power.
np.linalg.matrix_power(M, n) is written in Python, so you can easily see what it does.
For n<=3 is just does the repeated dot.
For larger n, it does a binary decomposition to reduce the total number of dots. I assume that means for n=4:
result = np.dot(M,M)
result = np.dot(result,result)
The sparse version isn't as general. It can only handle positive integer powers.
You can't count on numpy functions operating on spare matrices. The ones that do work are the ones that pass the action on to the array's own method. e.g. np.sum(A) calls A.sum().
You can also use ** notation instead of matrix_power for numpy matrix :
a=np.matrix([[1,2],[2,1]])
a**3
Out :
matrix([[13, 14],
[14, 13]])
try it with scipy sparse matrix.
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]])
I'm wondering if there is a simple way to multiply a numpy matrix by a scalar. Essentially I want all values to be multiplied by the constant 40. This would be an nxn matrix with 40's on the diagonal, but I'm wondering if there is a simpler function to use to scale this matrix. Or how would I go about making a matrix with the same shape as my other matrix and fill in its diagonal?
Sorry if this seems a bit basic, but for some reason I couldn't find this in the doc.
If you want a matrix with 40 on the diagonal and zeros everywhere else, you can use NumPy's function fill_diagonal() on a matrix of zeros. You can thus directly do:
N = 100; value = 40
b = np.zeros((N, N))
np.fill_diagonal(b, value)
This involves only setting elements to a certain value, and is therefore likely to be faster than code involving multiplying all the elements of a matrix by a constant. This approach also has the advantage of showing explicitly that you fill the diagonal with a specific value.
If you want the diagonal matrix b to be of the same size as another matrix a, you can use the following shortcut (no need for an explicit size N):
b = np.zeros_like(a)
np.fill_diagonal(b, value)
Easy:
N = 100
a = np.eye(N) # Diagonal Identity 100x100 array
b = 40*a # Multiply by a scalar
If you actually want a numpy matrix vs an array, you can do a = np.asmatrix(np.eye(N)) instead. But in general * is element-wise multiplication in numpy.