Is there a function in Tensorflow can do the following math? - python

I have two tensors, x and y, of shape [B, D]. I want to do something like the following code
B, D = x.shape
x = tf.expand_dims(x, 1) # [B, 1, D]
y = tf.expand_dims(y, -1) # [B, D, 1]
z = x * y # [B, D, D]
z = tf.reshape(z, (B, D**2))
Is there a function in Tensorflow that already does this?

Related

Pytorch tensor multi-dimensional selection

i have a question regarding the efficient operation of the pytorch tensor multidimensional selection.
Assuming i have a tensor a, with
# B=2, V=20000, d=64
a = torch.rand(B, V, d)
and a tensor b, with
# B=2, N=30000, k=10; k is the index inside of [0, V]
b = torch.randint(0, V, (B, N, k))
The target is to construct a selected tensor from a, namely
help_1 = a[:, None, :, :].repeat(1, N, 1, 1) # [B, N, V, d]
help_2 = b[:, :, :, None].expand(-1,-1,-1,d) # [B, N, k, d]
c = torch.gather(help_1, dim=2, index=help_2)
this operation can indeed output the desired results, but is not very efficient since i created a very large help_1 matrix, which has size [2, 30000, 20000, 64]. I wonder if anyone has idea about doing this without creating such a large helper tensor for selection? Thank you!
You could use broadcasting with the indexing to save memory. Something like the following would work.
idx0 = torch.arange(B, device=b.device).reshape(-1, 1, 1, 1) # [B, 1, 1, 1]
idx1 = b[..., None] # [B, N, k, 1]
idx2 = torch.arange(d, device=b.device).reshape(1, 1, 1, -1) # [1, 1, 1, d]
c = a[idx0, idx1, idx2] # [B, N, k, d]

What are some of the most efficient ways to make a list of homogeneous transformation matrices?

I want a list of 4X4 matrices that follow this form:
a # An array of shape [n,3]
[[cos(a[0]),-sin(a[0]),0,a[1]],
[sin(a[0]),cos(a[0]),0,a[2]],
[0,0,1,0],
[0,0,0,1]])
How about:
import numpy as np
n = 1000000
a = np.random.rand(n, 3)
c = np.cos(a[:, 0])
s = np.sin(a[:, 0])
dx = a[:, 1]
dy = a[:, 2]
z = np.zeros(n)
o = np.ones(n)
out = np.array([
[c, -s, z, dx],
[s, c, z, dy],
[z, z, o, z],
[z, z, z, o],
]).transpose(2, 0, 1)

Index pytorch 4d tensor by values in 2d tensor

I have two pytorch tensors:
X with shape (A, B, C, D)
I with shape (A, B)
Values in I are integers in range [0, C).
What is the most efficient way to get tensor Y with shape (A, B, D), such that:
Y[i][j][k] = X[i][j][ I[i][j] ][k]
You probably want to use torch.gather for the indexing and expand to adjust I to the required size:
eI = I[..., None, None].expand(-1, -1, 1, X.size(3)) # make eI the same for the last dimension
Y = torch.gather(X, dim=2, index=eI).squeeze()
testing the code:
A = 3
B = 4
C = 5
D = 7
X = torch.rand(A, B, C, D)
I = torch.randint(0, C, (A, B), dtype=torch.long)
eI = I[..., None, None].expand(-1, -1, 1, X.size(3))
Y = torch.gather(X, dim=2, index=eI).squeeze()
# manually gather
refY = torch.empty(A, B, D)
for i in range(A):
for j in range(B):
refY[i, j, :] = X[i, j, I[i,j], :]
(refY == Y).all()
# Out[]: tensor(1, dtype=torch.uint8)

Combination with multiple criteria

I have the following three lists of unequal lengths:
a = [2.13, 5.48,-0.58]
b = [4.17, 1.12, 2.13, 3.48,-1.01,-1.17]
c = [6.73, 8, 12]
d = [(2.13,2.13),(5.48,-1.17),(-0.58,4.17)]
e = [(4.17,12),(2.13,6.73)]
I need to create a combination_abc = [ (x,y,z) for x in a
for y in b
for z in c] such that (x,y) is not equal to d and (y,z) is not equal to e
If I understood you correct, just add if-statement into your list comprehension:
[(x, y, z) for x in a for y in b for z in c if (x, y) not in d and (y, z) not in e]
Also you can use itertools.product for simplicity:
from itertools import product
[(x, y, z) for x, y, z in product(a, b, c) if (x, y) not in d and (y, z) not in e]

How to construct the following matrix elegantly in numpy?

Suppose I have a 5 dimensional matrix v and now I want a new matrix D fulfilling
D[a, b, n, m, d] = v[a, b, n, n, d]-v[a, b, m, m, d].
How do I elegantly do this in numpy?
How do you want to change the dimensionality? You can reshape it like this
import numpy as np
a, b, n, d = 2, 3, 4, 5
v = np.zeros((a, b, n, n, d))
D = v.reshape((a, b, n*n, d))
I found einsum can do this:
D = np.einsum('abiic->abic', v)[..., None, :] - np.einsum('abiic->abic', v)[:, :, None, ...]

Categories