Numpy Indexing of multidimensional array - numpy

I have an array x whose shape is (308, 308, 308). I have an array of integer indices v of shape (10, 308, 308, 3). I would like to index x so as to create a matrix y of shape (10, 308, 308) whose (i, j, k)-entry is x[tuple(v[i, j, k])]. Is there a fast way to accomplish this?

Related

how to read the shape of the numpy array after numpy stack

I am doing stack operation on two 2D array using numpy.
a = np.random.randint(1, 5, size=(4, 4))
b = np.random.randint(6, 10, size=(4, 4))
f = np.stack((a, b), axis=2)
I checked the shape of the f array.
f.shape
(4, 4, 2)
in the obtained shape (4, 4, 2), I would like to know what is first 4 represnts, second 4 represents and third element 2 reprents?

Matrix Vector Product across Multiple Dimensions

I have two arrays:
A = torch.rand((64, 128, 10, 10))
B = torch.rand((64, 128, 10))
I would like to compute the product, represented by C, where we do a matrix-vector multiplication across the first and second dimensions of A and B, so:
# C should have shape: (64, 128, 10)
for i in range(0, 64):
for j in range(0, 128):
C[i,j] = torch.matmul(A[i,j], B[i,j])
Does anyone know how to do this using torch.einsum? I tried the following, but I am getting an incorrect result.
C = torch.einsum('ijkl, ijk -> ijk', A, B)
Here's the options with numpy. (I don't have torch)
In [120]: A = np.random.random((64, 128, 10, 10))
...: B = np.random.random((64, 128, 10))
Your iterative reference case:
In [122]: C = np.zeros((64,128,10))
...: # C should have shape: (64, 128, 10)
...: for i in range(0, 64):
...: for j in range(0, 128):
...: C[i,j] = np.matmul(A[i,j], B[i,j])
...:
matmul with full broadcasting:
In [123]: D = np.matmul(A, B[:,:,:,None])
In [125]: C.shape
Out[125]: (64, 128, 10)
In [126]: D.shape # D has an extra size 1 dimension
Out[126]: (64, 128, 10, 1)
In [127]: np.allclose(C,D[...,0]) # or use squeeze
Out[127]: True
The einsum equivalent:
In [128]: E = np.einsum('ijkl,ijl->ijk', A, B)
In [129]: np.allclose(C,E)
Out[129]: True

Efficient way to calculate 3D matrix multiplication using numpy

How can I efficiently write and calculate this multiplication using numpy:
for k in range(K):
for i in range(SIZE):
for j in range(SIZE):
for i_b in range(B_SIZE):
for j_b in range(B_SIZE):
for k_b in range(k+1):
data[k, i * w + i_b, j * h + j_b] += arr1[k_b, i_b, j_b] * arr2[k_b, i, j]
For example:
SIZE, B_SIZE = 32, 8
arr1.shape -> (8, 8, 8)
arr2.shape -> (8, 32, 32)
data.shape -> (K, 256, 256)
Thank you.
You can use Numba for such kind of non-trivial case and rework the loops to use efficiently the CPU cache. Here is an example:
import numba as nb
#nb.njit
def compute(data, arr1, arr2):
for k in range(K):
for k_b in range(k+1):
for i in range(SIZE):
for j in range(SIZE):
tmp = arr2[k_b, i, j]
for i_b in range(B_SIZE):
for j_b in range(B_SIZE):
data[k, i * w + i_b, j * h + j_b] += arr1[k_b, i_b, j_b] * tmp
If you do this operation once, then you can pre-compile the Numba code by providing the types of the arrays. If K is big, then you can parallelize the code using #nb.njit(parallel=True) and use for k in nb.prange(K) rather than for k in range(K). This should be several order of magnitude fater.

I'm getting ValueError: could not broadcast input array from shape (3072) into shape (5000)

num_test = X.shape[0]
num_train = self.X_train.shape[0]
dists = np.zeros((num_test, num_train))
for i in range(num_test):
dists[i,:] = np.sqrt(np.sum(np.square(self.X_train - X[i,:]), axis = 0))
I'm getting
ValueError: could not broadcast input array from shape (3072) into shape (5000)
Shape of X is (500, 3072), so shape of X[i,:] is (3072,)
Shape of self.X_train is (5000, 3072), and dists is an array of zeroes with dimensions(num_test, num_train).
Why am I getting this error?
Did you mean this?:
dists[i,:] = np.sqrt(np.sum(np.square(self.X_train - X[i,:][None,:]), axis = 0))
In the line
dists[i,:] = np.sqrt(np.sum(np.square(self.X_train - X[i,:]), axis = 0))
you need to replace axis=0 with axis=1, since dimension reduction occurs along the axis being summed over.

Pick random tensors from another one in Tensorflow

I have a Tensor X whith shape [B, L, E] (let's say, B batches of L vectors of length E). From this Tensor X, I want to randomly pick N vectors in each batch, and so create Y with shape [B, N, E].
I tried to combine tf.random_uniform and tf.gather but I really struggle with the dimension and can't get Y.
You can use something like this:
import tensorflow as tf
import numpy as np
B = 3
L = 5
E = 2
N = 3
input = np.array(range(B * L * E)).reshape([B, L, E])
print(input)
print("#################################")
X = tf.constant(input)
batch_range = tf.tile(tf.reshape(tf.range(B, dtype=tf.int32), shape=[B, 1, 1]), [1, N, 1])
random = tf.random_uniform([B, N, 1], minval = 0, maxval = L - 1, dtype = tf.int32)
indices = tf.concat([batch_range, random], axis = 2)
output = tf.gather_nd(X, indices)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(indices))
print("#################################")
print(sess.run(output))