Python Dot-Product with Matrix-elements - python

I want to implement the following calculation in python :
With
and
.
Here are matrices themselves.
Thus python should compute a matrix-times-vector multiplication, where the vector-elements are matrices.Is this possible without a for-loop?

Using numpy:
In [1]: import numpy as np
In [2]: M1 = np.array([[1, 2], [3, 4]])
In [3]: M2 = np.array([[10, 20], [30, 40]])
In [4]: E = np.array([[1, 1], [1, -1]])
In [5]: v = np.array([M1, M2])
In [6]: np.tensordot(E, v, 1)
Out[6]:
array([[[ 11, 22],
[ 33, 44]],
[[ -9, -18],
[-27, -36]]])

if you're familiar with einstein summation notation, you can imagine E subscripted as E_ij, and v as v_jkl, and more generally write the np.tensordot in #steve-kern's example as:
In [6]: np.einsum('ij,jkl',E,v)

Related

Get indices of element of one array using indices in another array

Suppose I have an array a of shape (2, 2, 2):
a = np.array([[[7, 9],
[19, 18]],
[[24, 5],
[18, 11]]])
and an array b that is the max of a: b=a.max(-1) (row-wise):
b = np.array([[9, 19],
[24, 18]])
I'd like to obtain the index of elements in b using index in flattened a, i.e. a.reshape(-1):
array([ 7, 9, 19, 18, 24, 5, 18, 11])
The result should be an array that is the same shape with b with indices of b in flattened a:
array([[1, 2],
[4, 6]])
Basically this is the result of maxpool2d when return_indices= True in pytorch, but I'm looking for an implementation in numpy. I've used where but it seems doesn't work, also is it possible to combine finding max and indices in one go, to be more efficient? Thanks for any help!
I have a solution similar to that of Andras based on np.argmax and np.arange. Instead of "indexing the index" I propose to add a piecewise offset to the result of np.argmax:
import numpy as np
a = np.array([[[7, 9],
[19, 18]],
[[24, 5],
[18, 11]]])
off = np.arange(0, a.size, a.shape[2]).reshape(a.shape[0], a.shape[1])
>>> off
array([[0, 2],
[4, 6]])
This results in:
>>> a.argmax(-1) + off
array([[1, 2],
[4, 6]])
Or as a one-liner:
>>> a.argmax(-1) + np.arange(0, a.size, a.shape[2]).reshape(a.shape[0], a.shape[1])
array([[1, 2],
[4, 6]])
The only solution I could think of right now is generating a 2d (or 3d, see below) range that indexes your flat array, and indexing into that with the maximum indices that define b (i.e. a.argmax(-1)):
import numpy as np
a = np.array([[[ 7, 9],
[19, 18]],
[[24, 5],
[18, 11]]])
multi_inds = a.argmax(-1)
b_shape = a.shape[:-1]
b_size = np.prod(b_shape)
flat_inds = np.arange(a.size).reshape(b_size, -1)
flat_max_inds = flat_inds[range(b_size), multi_inds.ravel()]
max_inds = flat_max_inds.reshape(b_shape)
I separated the steps with some meaningful variable names, which should hopefully explain what's going on.
multi_inds tells you which "column" to choose in each "row" in a to get the maximum:
>>> multi_inds
array([[1, 0],
[0, 0]])
flat_inds is a list of indices, from which one value is to be chosen in each row:
>>> flat_inds
array([[0, 1],
[2, 3],
[4, 5],
[6, 7]])
This is indexed into exactly according to the maximum indices in each row. flat_max_inds are the values you're looking for, but in a flat array:
>>> flat_max_inds
array([1, 2, 4, 6])
So we need to reshape that back to match b.shape:
>>> max_inds
array([[1, 2],
[4, 6]])
A slightly more obscure but also more elegant solution is to use a 3d index array and use broadcasted indexing into it:
import numpy as np
a = np.array([[[ 7, 9],
[19, 18]],
[[24, 5],
[18, 11]]])
multi_inds = a.argmax(-1)
i, j = np.indices(a.shape[:-1])
max_inds = np.arange(a.size).reshape(a.shape)[i, j, multi_inds]
This does the same thing without an intermediate flattening into 2d.
The last part is also how you can get b from multi_inds, i.e. without having to call a *max function a second time:
b = a[i, j, multi_inds]
This is a long one-liner
new = np.array([np.where(a.reshape(-1)==x)[0][0] for x in a.max(-1).reshape(-1)]).reshape(2,2)
print(new)
array([[1, 2],
[4, 3]])
However number = 18 is repeated twice; So which index is the target.

Override numpy.matmul function

I want to override numpy.matmul() function, such that instead of dot product of two matrix vectors, calculate how many elements are element-wise equal between those two vectors.
Example:
In [1]: import numpy as np
In [2]: m1 = np.matrix([[1, 2], [3, 4]])
In [3]: m2 = np.matrix([[1, 3], [2, 4]])
In [4]: np.matmul(m1, m2)
Out[4]:
matrix([[ 5, 11],
[11, 25]])
Instead of the result above, I want to have following:
In [4]: myfunction(m1, m2)
Out[4]:
matrix([[2, 0],
[0, 2]])
[1, 2] and [1, 2] dot product is 5, but I want np.sum([1,2] == [1,2]), which is 2.
My question is how can I change in np.matmul() function np.dot() product of two v1 and v2 vectors with np.sum(v1 == v2)
In [93]: m1,m2=np.array([[1,2],[3,4]]),np.array([[1,3],[2,4]])
In [94]: np.matmul(m1,m2)
Out[94]:
array([[ 5, 11],
[11, 25]])
The dot product can be calculated with:
In [95]: (m1[:,:,None]*m2[None,:,:]).sum(axis=1)
Out[95]:
array([[ 5, 11],
[11, 25]])
This doesn't have the speed of matmul because it doesn't pass anything to BLAS-like functions, but it is still reasonably fast, making full use of numpy array operations.
I think your desired version would be:
In [96]: (m1[:,:,None]==m2[None,:,:]).sum(axis=1)
Out[96]:
array([[2, 0],
[0, 2]])

np.dot of two 2D arrays

I am new to using numpy so sorry if this sounds obvious, I did try to search through stackoverflow before I post this though..
I have two "list of lists" numpy arrays of length n (n = 3 in the example below)
a = np.array([[1, 2], [3, 4], [5, 6]])
b = np.array([[2, 2], [3, 3], [4, 4]])
I want to get a 1d array with the dot product of the lists at each corresponding index, i.e.
[(1*2 + 2*2), (3*3 + 4*3), (5*4 + 6*4)]
[6, 21, 44]
how should I go about doing it? thanks in advance!
You can do this
np.sum(a*b,axis=1)
The sum method in the other answer is the most straight forward method:
In [19]: a = np.array([[1, 2], [3, 4], [5, 6]])
...: b = np.array([[2, 2], [3, 3], [4, 4]])
In [20]: a*b
Out[20]:
array([[ 2, 4],
[ 9, 12],
[20, 24]])
In [21]: _.sum(1)
Out[21]: array([ 6, 21, 44])
With dot we have think a bit outside the box. einsum is easiest way of specifying a dot like action with less-than-obvious dimension combinations:
In [22]: np.einsum('ij,ij->i',a,b)
Out[22]: array([ 6, 21, 44])
Note that the i dimension is carried through. dot does ij,jk->ik, which would require extracting the diagonal (throwing away extra terms). In matmul/# terms, the i dimension is a 'batch' one, that doesn't actually participate in the sum-of-products. To use that:
In [23]: a[:,None,:]#b[:,:,None]
Out[23]:
array([[[ 6]],
[[21]],
[[44]]])
and then remove the extra size 1 dimensions:
In [24]: _.squeeze()
Out[24]: array([ 6, 21, 44])
In einsum terms this is i1j,ij1->i11

Numpy matrix power function and matrix multiplication [duplicate]

This question already has answers here:
how does multiplication differ for NumPy Matrix vs Array classes?
(8 answers)
Closed 3 years ago.
What is the difference between the calculation in numpy.linalg.matrix_power and directly multiplying the matrix by itself those many times? This is what I observed and was confused about.
>> Matrix A:
[[2 4 5],
[4 4 5],
[8 3 1]]
>> numpy.linalg.matrix_power(A, 3)
[[556 501 530]
[676 579 600]
[708 500 471]]
>> (A * A) * A
[[556 501 530]
[676 579 600]
[708 500 471]]
But
>> A = normalize(A, axis=1, norm='l1')
[[0.18181818 0.36363636 0.45454545]
[0.30769231 0.30769231 0.38461538]
[0.66666667 0.25 0.08333333]]
>> numpy.linalg.matrix_power(A, 3)
[[0.34477471 0.31773179 0.3374935],
[0.36065187 0.31371769 0.32563044],
[0.42154896 0.2984543 0.27999674]]
>> (A * A) * A
[[0.00601052 0.04808415 0.09391435]
[0.02913063 0.02913063 0.05689577]
[0.2962963 0.015625 0.0005787 ]]
Why are the results different? Which one is the correct (expected) computation?
This is the simple code I am checking
import numpy as np
A = np.matrix([[2, 4, 5], [4, 4, 5], [8, 3, 1]])
#A = normalize(A, axis=1, norm='l1') #uncommented for the 2nd part
print(A)
print(np.linalg.matrix_power(A, 3))
print((A * A) * A)
In [1]: from sklearn.preprocessing import normalize
Start with a numpy array:
In [2]: A = np.array([[2,4,5],[4,4,5],[8,3,1]])
make a np.matrix from it:
In [3]: M = np.matrix(A)
In [4]: A
Out[4]:
array([[2, 4, 5],
[4, 4, 5],
[8, 3, 1]])
In [5]: M
Out[5]:
matrix([[2, 4, 5],
[4, 4, 5],
[8, 3, 1]])
* is element-wise for A:
In [6]: (A*A)
Out[6]:
array([[ 4, 16, 25],
[16, 16, 25],
[64, 9, 1]])
But matrix multiplication for M:
In [7]: M*M
Out[7]:
matrix([[60, 39, 35],
[64, 47, 45],
[36, 47, 56]])
In [8]: A#A # also np.dot(A,A)
Out[8]:
array([[60, 39, 35],
[64, 47, 45],
[36, 47, 56]])
Pass M through normalize:
In [9]: N = normalize(M)
In [10]: N
Out[10]:
array([[0.2981424 , 0.59628479, 0.74535599],
[0.52981294, 0.52981294, 0.66226618],
[0.92998111, 0.34874292, 0.11624764]])
The result is numpy array, not Matrix. So N*N will be elementwise.
Confusion like is part of why np.matrix is no longer recommended.

Can I produce the result of np.outer using np.dot?

I am trying to improve my understanding of numpy functions. I understand the behaviour of numpy.dot. I'd like to understand the behaviour of numpy.outer in terms of numpy.dot.
Based on this Wikipedia article https://en.wikipedia.org/wiki/Outer_product I'd expect for array_equal to return True in the following code. However it does not.
X = np.matrix([
[1,5],
[5,9],
[4,1]
])
r1 = np.outer(X,X)
r2 = np.dot(X, X.T)
np.array_equal(r1, r2)
How can I assign r2 so that np.array_equal returns True? Also, why does numpy's implementation of np.outer not match the definition of outer multiplication on Wikipedia?
Using numpy 1.9.2
In [303]: X=np.array([[1,5],[5,9],[4,1]])
In [304]: X
Out[304]:
array([[1, 5],
[5, 9],
[4, 1]])
In [305]: np.inner(X,X)
Out[305]:
array([[ 26, 50, 9],
[ 50, 106, 29],
[ 9, 29, 17]])
In [306]: np.dot(X,X.T)
Out[306]:
array([[ 26, 50, 9],
[ 50, 106, 29],
[ 9, 29, 17]])
The Wiki outer link mostly talks about vectors, 1d arrays. Your X is 2d.
In [310]: x=np.arange(3)
In [311]: np.outer(x,x)
Out[311]:
array([[0, 0, 0],
[0, 1, 2],
[0, 2, 4]])
In [312]: np.inner(x,x)
Out[312]: 5
In [313]: np.dot(x,x) # same as inner
Out[313]: 5
In [314]: x[:,None]*x[None,:] # same as outer
Out[314]:
array([[0, 0, 0],
[0, 1, 2],
[0, 2, 4]])
Notice that the Wiki outer does not involve summation. Inner does, in this example 5 is the sum of the 3 diagonal values of the outer.
dot also involves summation - all the products followed summation along a specific axis.
Some of the wiki outer equations use explicit indices. The einsum function can implement these calculations.
In [325]: np.einsum('ij,kj->ik',X,X)
Out[325]:
array([[ 26, 50, 9],
[ 50, 106, 29],
[ 9, 29, 17]])
In [326]: np.einsum('ij,jk->ik',X,X.T)
Out[326]:
array([[ 26, 50, 9],
[ 50, 106, 29],
[ 9, 29, 17]])
In [327]: np.einsum('i,j->ij',x,x)
Out[327]:
array([[0, 0, 0],
[0, 1, 2],
[0, 2, 4]])
In [328]: np.einsum('i,i->',x,x)
Out[328]: 5
As mentioned in the comment, np.outer uses ravel, e.g.
return a.ravel()[:, newaxis]*b.ravel()[newaxis,:]
This the same broadcasted multiplication that I demonstrated earlier for x.
numpy.outer only works for 1-d vectors, not matrices. But for the case of 1-d vectors, there is a relation.
If
import numpy as np
A = np.array([1.0,2.0,3.0])
then this
np.matrix(A).T.dot(np.matrix(A))
should be the same as this
np.outer(A,A)
Another (clunky) version similar to a[:,None] * a[None,:]
a.reshape(a.size, 1) * a.reshape(1, a.size)

Categories

Resources