Numpy Matrix Difference row by row into 3D tensor [duplicate] - python

I know I can do np.subtract.outer(x, x). If x has shape (n,), then I end up with an array with shape (n, n). However, I have an x with shape (n, 3). I want to output something with shape (n, n, 3). How do I do this? Maybe np.einsum?

You can use broadcasting after extending the dimensions with None/np.newaxis to form a 3D array version of x and subtracting the original 2D array version from it, like so -
x[:, np.newaxis, :] - x
Sample run -
In [6]: x
Out[6]:
array([[6, 5, 3],
[4, 3, 5],
[0, 6, 7],
[8, 4, 1]])
In [7]: x[:,None,:] - x
Out[7]:
array([[[ 0, 0, 0],
[ 2, 2, -2],
[ 6, -1, -4],
[-2, 1, 2]],
[[-2, -2, 2],
[ 0, 0, 0],
[ 4, -3, -2],
[-4, -1, 4]],
[[-6, 1, 4],
[-4, 3, 2],
[ 0, 0, 0],
[-8, 2, 6]],
[[ 2, -1, -2],
[ 4, 1, -4],
[ 8, -2, -6],
[ 0, 0, 0]]])

Related

Pairwise difference of vectors

Say i have a matrix that is composed of N vectors as columns: matrix=[v_1, v_2, .. v_N] where v is from R^N. I want a new matrix that gives: for all (r in N, s in N) v(r)-v(s). For example if N=3, then i want a 3x3x3 and for a particular index i,j,k, it Represents the kth index of v(i)-v(j).
You can use broadcasting on a new dimension:
out = matrix[:,None]-matrix
Example:
matrix = np.arange(9).reshape(3,3)
out = matrix[:,None]-matrix
Output:
array([[[ 0, 0, 0],
[-3, -3, -3],
[-6, -6, -6]],
[[ 3, 3, 3],
[ 0, 0, 0],
[-3, -3, -3]],
[[ 6, 6, 6],
[ 3, 3, 3],
[ 0, 0, 0]]])

Facing ValueError : shape mismatch

How to index the arrays into the empty_array matrix using np. ix_?
please don,t get confused by other details, dict_A and dict_B are used just to calculate the index positions.
However, because my code is too long, that's why I just mentioned the value of 'arrays' directly below here( making an np.array), without mentioning it's background and how it came.
import numpy as np
dict_A = { 1:[1,2], 2:[2,3], 3:[3,4], 4:[4,5], 5:[5,6] }
dict_B = {1:[1,2], 2:[3,4], 3:[5,6], 4:[7,8], 5:[9,10], 6:[11,12] } # these are the values used for indexing the arrays in to K matrix
empty_array = np.zeros((40,40))
arrays = np.array([[[[ 1, -7, -1, 7 ], # five matrix obtained from a loop
[ -7, 3, 7, -3],
[-1, 7, 1, -7 ],
[ 7, -3, -7, 3]]],
[[[ 1, -6, -1, 6],
[ -6, 2, 6, -2],
[-1, 6, 1, -6],
[ 6, -2,-6, 2]]],
[[[ 1, -6, -5,-2],
[ 2, 0, 5, 9 ],
[-5, 1, 6, 8 ],
[-12, 1, 4, 5 ]]],
[[[ 2, 5, 4, 2],
[ -4, 5, 1, 7],
[7, -5, -2, 3],
[ 0, 2, 5, 3]]],
[[[ 3, 0, 2, 5],
[ -2, 6, 3, 1],
[-2, 5, 3, 5],
[ 2, 6, 12, 3 ]]]])
# this is just a small process by which i am combining values of 'dict_B' to create an 'index', for positioning arrays.
a_list = []
for i in dict_A:
index= []
a_list.append(index)
for j in dict_A[i]:
index.extend(dict_B[j])
print(index)
empty_array[np.ix_(index,index)] = empty_array[np.ix_(index,index)] + arrays
#ValueError: shape mismatch: value array of shape (5,1,4,4) could not be broadcast to indexing result of shape (4,4)
print(K)

reshaping numpy array/matrix

im trying to reshape the following numpy array.
from this:
array([[[ 1, 2, 3],
[ 2, 3, 4],
[ 3, 4, 5]],
[[-1, -2, -3],
[-2, -3, -4],
[-3, -4, -5]]], dtype=int64)
to something like this:
array([[[ 1, 2, 3],
[-1, -2, -3]],
[[ 2, 3, 4],
[-2, -3, -4]],
[[ 3, 4, 5],
[-3, -4, -5]]], dtype=int64)
Tried to use the reshape function, but that didnt work for me.
thanks
Just np.stack along axis 1:
arr = np.array([[[ 1, 2, 3],
[ 2, 3, 4],
[ 3, 4, 5]],
[[-1, -2, -3],
[-2, -3, -4],
[-3, -4, -5]]])
np.stack(arr, 1)
results in
array([[[ 1, 2, 3],
[-1, -2, -3]],
[[ 2, 3, 4],
[-2, -3, -4]],
[[ 3, 4, 5],
[-3, -4, -5]]])
This would work:
import numpy as np
x = np.array([[[ 1, 2, 3],
[ 2, 3, 4],
[ 3, 4, 5]],
[[-1, -2, -3],
[-2, -3, -4],
[-3, -4, -5]]], dtype=np.int64)
np.vstack(map(lambda x: [x], zip(*(x))))
array([[[ 1, 2, 3],
[-1, -2, -3]],
[[ 2, 3, 4],
[-2, -3, -4]],
[[ 3, 4, 5],
[-3, -4, -5]]], dtype=int64)
You should be able to use use the numpy.reshape function without any error.
Here's how:
a = array([[[ 1, 2, 3],
[ 2, 3, 4],
[ 3, 4, 5]],
[[-1, -2, -3],
[-2, -3, -4],
[-3, -4, -5]]], dtype=int64)
a = a.reshape(3, 2, 3)
Here's what array 'a' will be converted into:
array([[[ 1 2 3]
[ 2 3 4]]
[[ 3 4 5]
[-1 -2 -3]]
[[-2 -3 -4]
[-3 -4 -5]]])
This isn't a reshape problem. It's transpose task - reordering the axes:
In [293]: arr.transpose(1,0,2)
Out[293]:
array([[[ 1, 2, 3],
[-1, -2, -3]],
[[ 2, 3, 4],
[-2, -3, -4]],
[[ 3, 4, 5],
[-3, -4, -5]]])
stack works by iterating on the first dimension, and concatenating on a new middle axis. transpose just makes a view so will be faster.

Fastest Pairwise Difference of Rows

I have an n by 3 numpy array, with each row representing a vector in 3D space.
I'd like to have a 3D n by n by 3 array with the vector at [i, j] representing the differences between each component of vectors i and j.
>>> x = np.random.randint(10, size=(4, 3))
>>> x
array([[4, 0, 8],
[8, 5, 3],
[4, 1, 6],
[2, 2, 4]])
>>> x[:, np.newaxis] - x
array([[[ 0, 0, 0],
[-4, -5, 5],
[ 0, -1, 2],
[ 2, -2, 4]],
[[ 4, 5, -5],
[ 0, 0, 0],
[ 4, 4, -3],
[ 6, 3, -1]],
[[ 0, 1, -2],
[-4, -4, 3],
[ 0, 0, 0],
[ 2, -1, 2]],
[[-2, 2, -4],
[-6, -3, 1],
[-2, 1, -2],
[ 0, 0, 0]]])
This works, but is the slowest line in my program by far...slower even than my Euclidean distance code (which takes advantage of dot products and einsum...)
Are there any clever matrix math methods for doing what I want in a more efficient way?

How do I get the dot product but without the summation

consider array's a and b
a = np.array([
[-1, 1, 5],
[-2, 3, 0]
])
b = np.array([
[1, 1, 0],
[0, 2, 3],
])
Looking at
d = a.T.dot(b)
d
array([[-1, -5, -6],
[ 1, 7, 9],
[ 5, 5, 0]])
d[0, 0] is -1. and is the sum of a[:, 0] * b[:, 0]. I'd like a 2x2 array of vectors where the [0, 0] position would be a[:, 0] * b[:, 0].
with the above a and b, I'd expect
d = np.array([[a[:, i] * b[:, j] for j in range(a.shape[1])] for i in range(b.shape[1])])
d
array([[[-1, 0],
[-1, -4],
[ 0, -6]],
[[ 1, 0],
[ 1, 6],
[ 0, 9]],
[[ 5, 0],
[ 5, 0],
[ 0, 0]]])
The sum of d along axis==2 should be the dot product a.T.dot(b)
d.sum(2)
array([[-1, -5, -6],
[ 1, 7, 9],
[ 5, 5, 0]])
Question
What is the most efficient way of getting d?
Here's one way:
In [219]: a
Out[219]:
array([[-1, 1, 5],
[-2, 3, 0]])
In [220]: b
Out[220]:
array([[1, 1, 0],
[0, 2, 3]])
In [221]: a.T[:,None,:] * b.T[None,:,:]
Out[221]:
array([[[-1, 0],
[-1, -4],
[ 0, -6]],
[[ 1, 0],
[ 1, 6],
[ 0, 9]],
[[ 5, 0],
[ 5, 0],
[ 0, 0]]])
Or...
In [231]: (a[:,None,:] * b[:,:,None]).T
Out[231]:
array([[[-1, 0],
[-1, -4],
[ 0, -6]],
[[ 1, 0],
[ 1, 6],
[ 0, 9]],
[[ 5, 0],
[ 5, 0],
[ 0, 0]]])
Most efficient one would be with broadcasting as shown in #Warren Weckesser's post as we are basically dealing with element-wise multiplication without any sum-reduction.
An alternative one with np.einsum would be like so -
np.einsum('ij,ik->jki',a,b)
for r in a.T:
print(np.multiply(r,b.T))
[[-1 0]
[-1 -4]
[ 0 -6]]
[[1 0]
[1 6]
[0 9]]
[[5 0]
[5 0]
[0 0]]

Categories

Resources