3D array multiplication - python

I have arrays A and B both of dimension MxNxH.
I would like to define a binary operator, to "multiply", such that the result is MxN dimensions.
The equivalent operation would be:
C = A[:,:,0] * B[:,:,0] + A[:,:,1] * B[:,:,1] + .... + A[:,:,H] * B[:,:,H]
Is there a way to do this operation in a more efficient way?
For example, using a built in function in numpy?
I have tried tensordot, but this gives a different result.

The easiest is:
C = numpy.sum(A * B, -1)
I think this might work too:
C = numpy.einsum("...i,...i->...", A, B)

try this: numpy.sum( A*B, axis=2 )
this is similar to the other suggestion but perhaps clearer (axes are numbered from 0, so axis=2 is the 3rd axis or H out of MxNxH)

Related

Broadcast an array by N dimensions

I have two arrays,
import numpy as np
a = np.ones(100)
b = np.ones(1000).reshape(100, 1, 10)
dims_difference = b.ndim - a.ndim
Assume that b has more dimensions than a, but not necessarily two. I want to extend a to make sure the operation a + b works as intended (over the first axis). When I know that it is two, I can do that by hard-coding:
a = a[:, None, None]
How can I do this in a general way when the number of dimensions that need to be added at the and are contained in dims_difference?
One - not so elegant - solution based on #hpaulj's comment is the following:
for i in np.arange(dims_difference)+1:
a = np.expand_dims(a, i)

Python - matrix multiplication

i have an array y with shape (n,), I want to compute the inner product matrix, which is a n * n matrix
However, when I tried to do it in Python
np.dot(y , y)
I got the answer n, this is not what I am looking for
I have also tried:
np.dot(np.transpose(y),y)
np.dot(y, np.transpose(y))
I always get the same answer n
I think you are looking for:
np.multiply.outer(y,y)
or equally:
y = y[None,:]
y.T#y
example:
y = np.array([1,2,3])[None,:]
output:
#[[1 2 3]
# [2 4 6]
# [3 6 9]]
You can try to reshape y from shape (70,) to (70,1) before multiplying the 2 matrices.
# Reshape
y = y.reshape(70,1)
# Either below code would work
y*y.T
np.matmul(y,y.T)
One-liner?
np.dot(a[:, None], a[None, :])
transpose doesn't work on 1-D arrays, because you need atleast two axes to 'swap' them. This solution adds a new axis to the array; in the first argument, it looks like a column vector and has two axes; in the second argument it still looks like a row vector but has two axes.
Looks like what you need is the # matrix multiplication operator. dot method is only to compute dot product between vectors, what you want is matrix multiplication.
>>> a = np.random.rand(70, 1)
>>> (a # a.T).shape
(70, 70)
UPDATE:
Above answer is incorrect. dot does the same things if the array is 2D. See the docs here.
np.dot computes the dot product of two arrays. Specifically,
If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
If both a and b are 2-D arrays, it is matrix multiplication, but using matmul or a # b is preferred.
Simplest way to do what you want is to convert the vector to a matrix first using np.matrix and then using the #. Although, dot can also be used # is better because conventionally dot is used for vectors and # for matrices.
>>> a = np.random.rand(70)
(70,)
>>> a.shape
>>> a = np.matrix(a).T
>>> a.shape
(70, 1)
>>> (a # a.T).shape
(70, 70)

Want to define an ndarray in numpy elementwise

I have 2 2d numpy arrays, A with shape (i,j) and B (i, k) where j >> k. I want to define a new 3d array C such that each element in C is the broadcasted element wise product of each column in A with the whole matrix B. In other words as a normal python loop I would do it like this
for x in range(j):
C[x] = A[:,x]*B
However j is very large in this case and it would benefit me a lot if I am able to use Numpy's functionality to maybe define an ndarray C elementwise like in my loop above.
Thank you for your help
You can use broadcasting like this:
a.T[:, :, None] * b
Example:
import numpy as np
np.random.seed(444)
i, j, k = 2, 10, 3
a = np.random.randn(i, j)
b = np.random.randn(i, k)
c = a.T[:, :, None] * b
print(c.shape)
# (10, 2, 3)
Transposing stems from the fact that you want to internally operate for each column in a, and [:, :, None] expands the dimensionality to enable broadcasting, as explained in NumPy's broadcasting rules.

Normalize 2d arrays

Consider a square matrix containing positive numbers, given as a 2d numpy array A of shape ((m,m)). I would like to build a new array B that has the same shape with entries
B[i,j] = A[i,j] / (np.sqrt(A[i,i]) * np.sqrt(A[j,j]))
An obvious solution is to loop over all (i,j) but I'm wondering if there is a faster way.
Two approaches leveraging broadcasting could be suggested.
Approach #1 :
d = np.sqrt(np.diag(A))
B = A/d[:,None]
B /= d
Approach #2 :
B = A/(d[:,None]*d) # d same as used in Approach #1
Approach #1 has lesser memory overhead and as such I think would be faster.
You can normalize each row of your array by the main diagonal leveraging broadcasting using
b = np.sqrt(np.diag(a))
a / b[:, None]
Also, you can normalize each column using
a / b[None, :]
To do both, as your question seems to ask, using
a / (b[:, None] * b[None, :])
If you want to prevent the creation of intermediate arrays and do the operation in place, you can use
a /= b[:, None]
a /= b[None, :]

numpy matrix multiplication

I am trying to figure out how to do a kind of scalar matrix multiplication in numpy.
I have
a = array(((1,2,3),(4,5,6)))
b = array((11,12))
and i want to do
a op b
to result in
array(((1*11,2*11,3*11),(4*12,5*12,6*12))
right now I am using the following expression
c= a * array((b, b, b)).transpose()
It seems like there must be a more efficient way of doing this though
Taking advantage of broadcasting:
(a.T * b).T
The alternative to transposing a is to change the shape of b to make broadcasting give the result you're looking for:
a * b[:, np.newaxis]
Note that adding the new axis to b gives the following array:
array([[11],
[12]])

Categories

Resources