find the dot product of sub-arrays in numpy - python

In numpy, the numpy.dot() function can be used to calculate the matrix product of two 2D arrays. I have two 3D arrays X and Y (say), and I'd like to calculate the matrix Z where Z[i] == numpy.dot(X[i], Y[i]) for all i. Is this possible to do non-iteratively?

How about:
from numpy.core.umath_tests import inner1d
Z = inner1d(X,Y)
For example:
X = np.random.normal(size=(10,5))
Y = np.random.normal(size=(10,5))
Z1 = inner1d(X,Y)
Z2 = [np.dot(X[k],Y[k]) for k in range(10)]
print np.allclose(Z1,Z2)
returns True
Edit Correction since I didn't see the 3D part of the question
from numpy.core.umath_tests import matrix_multiply
X = np.random.normal(size=(10,5,3))
Y = np.random.normal(size=(10,3,5))
Z1 = matrix_multiply(X,Y)
Z2 = np.array([np.dot(X[k],Y[k]) for k in range(10)])
np.allclose(Z1,Z2) # <== returns True
This works because (as the docstring states), matrix_multiplyprovides
matrix_multiply(x1, x2[, out]) matrix
multiplication on last two dimensions

Related

Defining a quadratic function with numpy.meshgrid

Let's consider a function of two variables f(x1, x2) , where x1 spans over a vector v1 and x2 spans over a vector v2.
If f(x1, x2) = np.exp(x1 + x2), we can represent this function in Python as a matrix by means of the command numpy.meshgrid like this:
xx, yy = numpy.meshgrid(v1, v2)
M = numpy.exp(xx + yy)
This way, M is a representation of the function f over the cartesian product "v1 x v2", since M[i,j] = f(v1[i],v2[j]).
But this works because both sums and exponential work in parallel componentwise. My question is:
if my variable is x = numpy.array([x1, x2]) and f is a quadratic function f(x) = x.T # np.dot(Q, x), where Q is a 2x2 matrix, how can I do the same thing with the meshgrid function (i.e. calculating all the values of the function f on "v1 x v2" at once)?
Please let me know if I should include more details!
def quad(x, y, q):
"""Return an array A of a shape (len(x), len(y)) with
values A[i,j] = [x[i],y[j]] # q # [x[i],y[j]]
x, y: 1d arrays,
q: an array of shape (2,2)"""
from numpy import array, meshgrid, einsum
a = array(meshgrid(x, y)).transpose()
return einsum('ijk,kn,ijn->ij', a, q, a)
Notes
meshgrid produces 2 arrays of a shape (len(y), len(x)), where first one is with x values along the second dimension. If we apply to this pair np.array then a 3d array of shape (2, len(y), len(x)) will be produced. With transpose we obtain an array, where an element indexed by [i,j,k] is x[i] if k==0 else y[j], where k is 0 or 1, i.e. first or second array from meshgrid.
With 'ijk,kn,ijn->ij' we tell einsum to return the sum written bellow for each i, j:
sum(a[i,j,k]*q[k,n]*a[i,j,n] for k in range(2) for n in range(2))
Note, that a[i,j] == [x[i], y[j]].

matrix in object datatype python

Can you pls explain how to create a matrix in python to be created in object datatype. My code :
w, h = 8, 5;
Matrix = ([[0 for x in range(w)] for y in range(h)],dtype=object)
gives a syntax error. I tried various other ways. But still none of them working.
Thanks a lot
In your code the Matrix line tries to create a tuple, however you are giving it an expression dtype=object.
Matrix = ([[0 for x in range(w)] for y in range(h)],dtype=object)
The line reads: Set matrix to the tuple (2D array, dtype=object). However, the second part cannot be set. You can create the matrix as follows:
Matrix = [[0 for x in range(w)] for y in range(h)]
Or if you would like to have a numpy array with dtype object:
import numpy as np
Matrix = np.array([[0 for x in range(w)] for y in range(h)], dtype=object)
Or even more clean:
import numpy as np
Matrix = np.zeros((h, w), dtype=object)
Let me present you two options using numpy module and loops.
import numpy as np
print("Using numpy module:")
x = np.array([1,5,2])
y = np.array([7,4,1])
sum = x + y
subtract = x - y
mult = x * y
div = x / y
print("Sum: {}".format(sum))
print("Subtraction: {}".format(subtract))
print("Multiplication: {}".format(mult))
print("Division: {}".format(div))
print("----------------------------------------")
print("Using for loops:")
x = [1,5,2]
y = [7,4,1]
sum = []
subtract = []
mult =[]
div = []
for i,j in zip(x,y):
sum.append(i+j)
subtract.append(i-j)
mult.append(i*j)
div.append(i/j)
print(sum)
print(subtract)
print(mult)
print(div)

dot product with diagonal matrix, without creating it full matrix

I'd like to calculate a dot product of two matrices, where one of them is a diagonal matrix. However, I don't want to use np.diag or np.diagflat in order to create the full matrix, but instead use the 1D array directly filled with the diagonal values. Is there any way or numpy operation which I can use for this kind of problem?
x = np.arange(9).reshape(3,3)
y = np.arange(3) # diagonal elements
z = np.dot(x, np.diag(y))
and the solution I'm looking for should be without np.diag
z = x ??? y
Directly multiplying the ndarray by your vector will work. Numpy conveniently assumes that you want to multiply the nth column of x by the nth element of your y.
x = np.random.random((5, 5)
y = np.random.random(5)
diagonal_y = np.diag(y)
z = np.dot(x, diagonal_y)
np.allclose(z, x * y) # Will return True
The Einstein summation is an elegant solution to these kind of problems:
import numpy as np
x = np.random.uniform(0,1, size=5)
w = np.random.uniform(0,1, size=(5, 3))
diagonal_x = np.diagflat(x)
z = np.dot(diagonal_x, w)
zz = np.einsum('i,ij->ij',x , w)
np.allclose(z, zz) # Will return True
See: https://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html#numpy.einsum

Python: Covariance matrix by hand

I have two vectors X0 and X1 (mx0 and mx1 are the means of each vector) and I am trying to find the covariance matrix between them. I have managed to find each element in the matrix through doing:
b1=numpy.zeros(N*1).reshape((N,1))
b2=numpy.zeros(N*1).reshape((N,1))
for i in range(0,N):
b1[i]=X0[i]-mX0
for j in range(0,N):
b2[j]=X1[j]-mX1
bii=sum(p*q for p,q in zip(b1,b1))/(N-1)
bij=sum(p*q for p,q in zip(b1,b2))/(N-1)
bji=sum(p*q for p,q in zip(b2,b1))/(N-1)
bjj=sum(p*q for p,q in zip(b2,b2))/(N-1)
but I want a nicer way of doing this through a loop, rather than doing each element separately.
If you want to compute the covariance matrix by hand, study/mimick how numpy.cov does it, or if you just want the result, use np.cov(b1, b2) directly.
import numpy as np
np.random.seed(1)
N = 10
b1 = np.random.rand(N)
b2 = np.random.rand(N)
X = np.column_stack([b1, b2])
X -= X.mean(axis=0)
fact = N - 1
by_hand = np.dot(X.T, X.conj()) / fact
print(by_hand)
# [[ 0.04735338 0.01242557]
# [ 0.01242557 0.07669083]]
using_cov = np.cov(b1, b2)
assert np.allclose(by_hand, using_cov)

combining arrays

I have three separate 1d arrays of a list of numbers, their squares and cubes (created by a 'for' loop).
I would like these arrays to appear in three corresponding columns, however I have tried the column_stack function and python says its not defined. I have read about the vstack and hstack functions but am confused about which to use and what exactly they do.
My code so far reads;
import numpy
makearange = lambda a: numpy.arange(int(a[0]),int(a[1]),int(a[2]))
x = makearange(raw_input('Enter start,stop,increment: ').split(','))
y = numpy.zeros(len(x), dtype=int)
z = numpy.zeros(len(x), dtype=int)
for i in range(len(x)):
y[i] = x[i]**2
for i in range(len(x)):
z[i] = x[i]**3
print 'original array: ',x
print 'squared array: ',y
print 'cubed array: ', z
I would appreciate any advice
Why don't you define y and z directly?
y = x**2
z = x**3
and then simply:
stacked = np.column_stack((x,y,z))
which gives you a 2D array of shape len(x) * 3
import numpy
makearange = lambda a: numpy.arange(int(a[0]),int(a[1]),int(a[2]))
x = makearange(raw_input('Enter start,stop,increment: ').split(','))
a = np.zeros((len(x),3))
a[:,0] = x
a[:,1] = x**2
a[:,2] = x**3
When using arrays you should avoid for loops as much as possible, that's kind of the point of arrays.
a = np.zeros((len(x),3)) creates an array of length same as x and with 3 columns
a[:,i] is a reference to the 'i'th column of this array (i.e. select all values (denoted by :) along this (i) column)
I would strongly recommend you look at the Numpy Tutorial.
You do want column_stack. Have you tried:
w = numpy.column_stack((x,y,z))
print(w)

Categories