numpy array each element multiplication with matrix - python

I have a matrix
A = [[ 1. 1.]
[ 1. 1.]]
and two arrays (a and b), every array contains 20 float numbers How can I multiply the using formula:
( x' = A * ( x )
y' ) y
Is this correct? m = A * [a, b]

Matrix multiplication with NumPy arrays can be done with np.dot.
If X has shape (i,j) and Y has shape (j,k) then np.dot(X,Y) will be the matrix product and have shape (i,k). The last axis of X and the second-to-last axis of Y is multiplied and summed over.
Now, if a and b have shape (20,), then np.vstack([a,b]) has shape (2, 20):
In [66]: np.vstack([a,b]).shape
Out[66]: (2, 20)
You can think of np.vstack([a, b]) as a 2x20 matrix with the values of a on the first row, and the values of b on the second row.
Since A has shape (2,2), we can perform the matrix multiplication
m = np.dot(A, np.vstack([a,b]))
to arrive at an array of shape (2, 20).
The first row of m contains the x' values, the second row contains the y' values.
NumPy also has a matrix subclass of ndarray (a special kind of NumPy array) which has convenient syntax for doing matrix multiplication with 2D arrays. If we define A to be a matrix (rather than a plain ndarray which is what np.array(...) creates), then matrix multiplication can be done with the * operator.
I show both ways (with A being a plain ndarray and A2 being a matrix) below:
import numpy as np
A = np.array([[1.,1.],[1.,1.]])
A2 = np.matrix([[1.,1.],[1.,1.]])
a = np.random.random(20)
b = np.random.random(20)
c = np.vstack([a,b])
m = np.dot(A, c)
m2 = A2 * c
assert np.allclose(m, m2)

Related

Multiplying matrixes of different dimensions in Python

I need to invert the following matrix in Python using the single value decomposition and i need to multiply these matrix to obtain the initial matrix just for confirmation. How can i do so while the matrices has different dimensions?
X_b= [[array([2.52390408]), array([2.4962137]), array([2.46467486]), array([2.48760957])], [array([2.52390408]), array([2.4962137]), array([2.46467486]), array([2.48760957])]]
I used the command
svd=linalg.svd(x_b, full_matrices=True, compute_uv=True, hermitian=False)
And the results was
a=svd[0]
a =[[ 0.50615947 -0.50060626 -0.49428127 -0.49888074]
[ 0.50060626 0.83361215 -0.16428559 -0.16581433]
[ 0.49428127 -0.16428559 0.8377901 -0.16371932]
[ 0.49888074 -0.16581433 -0.16371932 0.83475721]]]
b=svd[1]
b= [[4.98638127]
[4.98638127]]
c=svd[2]
c= [[[1.]]
[[1.]]]
I apply the same method for the example
R = [[190.93095651 189.30517758] [187.01785506 185.38861727] [183.29225361 181.47205695]]
u, s, vh = np.linalg.svd(R, full_matrices=True)
When i tried to reconstruct it using print((u * s) # vh) i got the error
" operands could not be broadcast together with shapes (3,3) (2,)"
In the documentation page of numpy.linalg.svd it is explained how to reconstruct the input matrix using the returned values of svd:
linalg.svd(a, full_matrices=True, compute_uv=True, hermitian=False)
Parameters:
a (…, M, N) array_like
A real or complex array with a.ndim >= 2.
Returns:
u { (…, M, M), (…, M, K) } array
Unitary array(s). The first a.ndim - 2 dimensions have the same size as those of the input a. The size of the last two dimensions depends on the value of full_matrices. Only returned when compute_uv is True.
s (…, K) array
Vector(s) with the singular values, within each vector sorted in descending order. The first a.ndim - 2 dimensions have the same size as those of the input a.
vh { (…, N, N), (…, K, N) } array
Unitary array(s). The first a.ndim - 2 dimensions have the same size as those of the input a. The size of the last two dimensions depends on the value of full_matrices. Only returned when compute_uv is True.
[...]
When a is a 2D array, it is factorized as u # np.diag(s) # vh = (u * s) # vh, where u and vh are 2D unitary arrays and s is a 1D array of a’s singular values. When a is higher-dimensional, SVD is applied in stacked mode [...].
You can adapt the given examples to your use case:
>>> X_b = np.array([[[2.52390408], [2.4962137], [2.46467486], [2.48760957]],
[[2.52390408], [2.4962137], [2.46467486], [2.48760957]]])
>>> u, s, vh = np.linalg.svd(X_b[...,0], full_matrices=True)
>>> u.shape, s.shape, vh.shape
((2, 2), (2,), (4, 4))
Reconstructing X_b:
>>> (u * s) # vh[:2,:]
array([[2.52390408, 2.4962137 , 2.46467486, 2.48760957],
[2.52390408, 2.4962137 , 2.46467486, 2.48760957]])
>>> np.allclose((u * s) # vh[:2,:], X_b[...,0])
True

Python loop to populate a matrix

I'm trying to populate an array in python more efficiently. I have a 5x3 matrix A that I am transforming into a 3x3 matrix (Z) by calculating z11, z12, ..., z33 independently. The code below works, but it's clunky and I'm hoping to automate this into a loop so that it will take an A matrix of any size (n x m) and transform it into a Z matrix of size (m x m). If someone could help me out I would greatly appreciate it!
import numpy as np
A = np.array([[1,0,0],
[0,1,0],
[0,1,1],
[0,0,-1],
[0,0,1]])
A1=A[:,0]
A2=A[:,1]
A3=A[:,2]
C = np.array([-2,-2, -9,-6,-4])
X = np.array([-4,-4,-8])
z11 = (sum(A1*A1))*(C[0]/X[0])
z12 = (sum(A1*A2))*(C[0]/X[1])
z13 = (sum(A1*A3))*(C[0]/X[2])
z21 = (sum(A2*A1))*(C[1]/X[0])
z22 = (sum(A2*A2))*(C[1]/X[1])
z23 = (sum(A2*A3))*(C[1]/X[2])
z31 = (sum(A3*A1))*(C[2]/X[0])
z32 = (sum(A3*A2))*(C[2]/X[1])
z33 = (sum(A3*A3))*(C[2]/X[2])
Z = np.array([[z11,z12,z13],
[z21,z22,z23],
[z31,z32,z33]])
We can use the broadcasting to achieve the same. First let's increase A by one dimension using A[:, None] and then multiply it with A. Since shape of A[:, None] is (3, 1, 5) and shape of A is (3, 5), numpy first repeats(intuitively) the array corresponding to dimension where both array don't match and then does the multiplication. This way each column of A gets multiplied with every other column(to makes sure that columns are multiplied, I have used transpose) Then we can take sum along the last axis and multiply with C[:, None] to achieve the desired output.
Use:
m = A.shape[1]
B = A[:, None].T * A.T
Z = np.sum(B, axis = -1).astype(float)*C[:m, None]/X
Output:
>>> Z
array([[0.5 , 0. , 0. ],
[0. , 1. , 0.25 ],
[0. , 2.25 , 3.375]])

Matrix and Tensor Multiplication with Numpy

I am trying to do a matrix multiplication with a tensor, but I'm uncertain how to do it with Numpy. I have been trying to work with np.tensordot(), but I haven't been able to do so
In a simpler way, if we were to do matrix multiplications and we had a vector v (Nx1) and a matrix S (NxN), we can do the operation
v^T S v => (1xN)(NxN)(Nx1) => a number
v = np.ones((3,1))
S = np.ones((3,3))
y = v.T.dot(S).dot(v)
y.shape = (1) or ()
Now, I'd like to do the following:
Let matrix M (3x5) and tensor Z (5x3x3) so that I can have
M^T Z M
where (M^T Z) yields a (5x3) matrix, and M^T Z M yields a (1x5) vector
M = np.ones((3,5))
Z = np.ones((5,3,3))
Y = <?> M.T * Z * M <?>
Y.shape = (5,) or (1,5)
Does anyone know how to do this using Numpy without using Tensorflow?
I think this computes what you want:
import numpy as np
M = np.ones((3, 5))
Z = np.ones((5, 3, 3))
# Multiply (5, 1, 3) x (5, 3, 3) x (5, 3, 1)
result = (M.T[:, np.newaxis] # Z # M.T[:, :, np.newaxis]).squeeze()
print(result)
Output:
[9. 9. 9. 9. 9.]
I have used the # operator for convenience, but you can replace it with np.matmul if you like it more or are using an older Python version:
result = np.matmul(np.matmul(M.T[:, np.newaxis], Z), M.T[:, :, np.newaxis]).squeeze()

Numpy array and column extracted from a matrix, different shape

I'm trying to do an integration with numpy:
A = n.trapz(B,C)
but I have some issues with B and C shapes
B is a filled array inizialized with numpy zeros function
B=np.zeros((N,1))
C is a column extracted from a matrix, always inizialized with numpy:
C = D[:,0]
D = np.zeros((N,2))
the problem is that:
n.shape(B) # (N,1)
n.shape(C) # (N,)
how can I manage this?
Try
B = np.zeros(N)
np.trapz(B, C)
Also, you np.trapz accepts multi-dimensional arrays, so arrays of shape (N, 1) are ok; you just need to specify an axis to handle it properly.
B = np.zeros((N, 1))
C = D[:, 0]
np.trapz(B, C.reshape(N, 1), axis=1)

Efficiently generating a Cauchy matrix from two Numpy arrays

A Cauchy matrix (Wikipedia article) is a matrix determined by two vectors (arrays of numbers). Given two vectors x and y, the Cauchy matrix C generated by them is defined entry-wise as
C[i][j] := 1/(x[i] - y[j])
Given two Numpy arrays x and y, what is an efficient way to generate a Cauchy matrix?
This is the most efficient way I found, using array broadcasting to take advantage of vectorization.
1.0 / (x.reshape((-1,1)) - y)
Edit: #HYRY and #shx2 have suggested that, instead of x.reshape((-1,1)), which makes a copy, you can use x[:,np.newaxis], which returns a view of the same array. #HYRY also suggests 1.0/np.subtract.outer(x,y), which is slightly slower for me but maybe more explicit.
Example:
>>> x = numpy.array([1,2,3,4]) #x
>>> y = numpy.array([5,6,7]) #y
>>>
>>> #transpose x, to nx1
... x = x.reshape((-1,1))
>>> x
array([[1],
[2],
[3],
[4]])
>>>
>>> #array of differences x[i] - y[j]
... #an nx1 array minus a 1xm array is an nxm array
... diff_matrix = x-y
>>> diff_matrix
array([[-4, -5, -6],
[-3, -4, -5],
[-2, -3, -4],
[-1, -2, -3]])
>>>
>>> #apply the multiplicative inverse to each entry
... cauchym = 1.0/diff_matrix
>>> cauchym
array([[-0.25 , -0.2 , -0.16666667],
[-0.33333333, -0.25 , -0.2 ],
[-0.5 , -0.33333333, -0.25 ],
[-1. , -0.5 , -0.33333333]])
I tried a few other methods, all of which were significantly slower.
This is the naive approach, which costs list comprehension:
cauchym = numpy.array([[ 1.0/(x_i-y_j) for y_j in y] for x_i in x])
This one generates the matrix as a 1-dimensional array (saving the cost of nested Python lists) and reshapes it to a matrix afterward. It also moves the division to a single Numpy operation:
cauchym = 1.0/numpy.array([(x_i-y_j) for x_i in x for y_j in y]).reshape([len(x),len(y)])
Using numpy.repeat and numpy.tile (which respectively tile the array horizontally and vertically). This way makes unnecessary copies:
lenx = len(x)
leny = len(y)
xm = numpy.repeat(x,leny) #the i'th row is s_i
ym = numpy.tile(y,lenx)
cauchym = (1.0/(xm-ym)).reshape([lenx,leny]);
I created a function hope it helps u to understand in a better way.
# Creating a function in order to form a cauchy matrix
def cauchy_matrix(arr1,arr2):
"""
Enter two arrays in order to get a cauchy matrix.The input array should be a 1-D array.
arr1 = First 1-D array
arr2 = Second 1-D array
It returns the cauchy matrix having shape equal to m*n, where m is size of arr1 and n is size of arr2.
"""
my_list = []
try:
for i in range(len(arr1)):
for j in range(len(arr2)):
z = 1/(arr1[i]-arr2[j])
my_list.append(z)
return np.array(my_list).reshape(arr1.shape[0],arr2.shape[0])
except ZeroDivisionError:
print("Check if both the arrays has '0' as one of it's element. One array can have a zero but both the arrays having '0' is not acceptable!")

Categories

Resources