Expanding matrix dimension by multiplication in pytorch - optimization

I am using pytorch and I have tensor A of dimensions [a,b,c] and tensor B with dimensions [a,d]. I want to create tensor C of dimension [a,b,c,d], that is multiplication of elements in A with elements in B with following operation:
for i in range(a):
for j in range(b):
for k in range(c):
for l in range(d):
C[i,j,k,l]=A[i,j,k]*B[i,l]
This works as intended, but is very slow. What would be best practice for such operation in pytorch?
Thank you.

A.reshape(a, b, c, 1) * B.reshape(a, 1, 1, d)
will do the trick.

Related

Expand a dimension of 3-dimensional array into a diagonal matrix with vectorized computations

I have np.ndarray A of shape (N, M, D).
I'd like to create np.ndarray B of shape (N, M, D, D) such that for every pair of fixed indices n, m along axes 0 and 1
B[n, m] = np.eye(A[n, m])
I understand how to solve this problem using cycles, yet I'd like to write code performing this in vectorized manner. How can this be done using numpy?
import numpy as np
A = ... # Your array here
n, m, d = A.shape
indices = np.arange(d)
B = np.zeros((n, m, d, d))
B[:, :, indices, indices] = A

how to vectorize this in tensorflow?

Let's day A is a M x J matrix and B is a N x J matrix.
I would like to generate a M x N matrix S where:
S_ij = w^t[A_i;B_j;A_i o B_j)
Basically each element of the result matrix S is some vector w (a row of a matrix W) dot product with: col A_j concat with col B_j and concat with the element-wise product of each A_i and B_j for all i and j.
Ideally i would like to vectorize the operation and only use matrix form S, A and B instead of slicing and doing for loops. However I am new to tensorflow and can't seem to figure out how to do the code in matrix form as A_i o B_j seems to result in a 2d matrix and it needs to be concat with vector A_i and B_j.
Thanks

How to create a new array of tensors from old one

I have a tensor [a, b, c, d, e, f, g, h, i] with dimension 9 X 1536. I need to create a new tensor which is like [(a,b), (a,c), (a,d), (a,e),(a,f),(a,g), (a,h), (a,i)] with dimension [8 x 2 x 1536]. How can I do it with tensorflow ?
I tried like this
x = tf.zeros((9x1536))
x_new = tf.stack([(x[0],x[1]),
(x[0], x[2]),
(x[0], x[3]),
(x[0], x[4]),
(x[0], x[5]),
(x[0], x[6]),
(x[0], x[7]),
(x[0], x[8])])
This seems to work but I would like to know if there is a better solution or approach which can be used instead of this
You can obtain the desired output with a combination of tf.concat, tf.tile and tf.expand_dims:
import tensorflow as tf
import numpy as np
_in = tf.constant(np.random.randint(0,10,(9,1536)))
tile_shape = [(_in.shape[0]-1).value] + [1]*len(_in.shape[1:].as_list())
_out = tf.concat([
tf.expand_dims(
tf.tile(
[_in[0]],
tile_shape
)
,
1),
tf.expand_dims(_in[1:], 1)
],
1
)
tf.tile repeats the first element of _in creating a tensor of length len(_in)-1 (I compute separately the shape of the tile because we want to tile only on the first dimension).
tf.expand_dims adds a dimension we can then concat on
Finally, tf.concat stitches together the two tensors giving the desired result.
EDIT: Rewrote to fit the OP's actual use-case with multidimensional tensors.

Evaluating the pairwise euclidean distance between multi-dimensional inputs in TensorFlow

I have two 2-D tensors of shape say m X d and n X d. What is the optimized(i.e. without for loops) or the tensorflow way of evaluating the pairwise euclidean distance between these two tensors so that I get an output tensor of shape m X n. I need it for creating the squared term of a Gaussian kernel for ultimately having a covariance matrix of size m x n.
The equivalent unoptimized numpy code would look like this
difference_squared = np.zeros((x.shape[0], x_.shape[0]))
for row_iterator in range(difference_squared.shape[0]):
for column_iterator in range(difference_squared.shape[1]):
difference_squared[row_iterator, column_iterator] = np.sum(np.power(x[row_iterator]-x_[column_iterator], 2))
I found the answer by taking help from here. Assuming the two tensors are x1 and x2, and their dimensions are m X d and n X d, their pair-wise Euclidean distance is given by
tile_1 = tf.tile(tf.expand_dims(x1, 0), [n, 1, 1])
tile_2 = tf.tile(tf.expand_dims(x2, 1), [1, m, 1])
pairwise_euclidean_distance = tf.reduce_sum(tf.square(tf.subtract(tile_1, tile_2)), 2))

What is the efficient way of multiplying chain of tensors in tensorflow

I have 3 sparse tensors of dimensions A = P*N, B = Q*N and C = R*N. What is the efficient way to compute the product matrix A*B*C such that dimension of the product matrix is P*Q*R in tensorflow.?
I have tried with tf.matmul and followed by tf.reshape but it won't give the product matrix with the dimension as specified above.
Thanks.
tf.einsum Should help you. Though I'm not really sure what you mean by A*B*C since dimensions are incompatible for matrix multiplication. Probably something like this:
R = tf.einsum('il,jl,kl->ijk', A, B, C)