I have tensor named "k1" which is in shape 3,1,1,9 and also have p1 tensor in shape of 3,7,9,9 and I wanna know what does the line below do?
p1 = p1 .masked_fill(k1== 0, float("-1e30"))
As the documentation page describes it:
Tensor.masked_fill(mask, value)
Fills elements of self tensor with value where mask is True. The shape of mask must be broadcastable with the shape of the underlying tensor.
In your case it will place in p1 the value of float("-1e30") at the positions where k1 is equal to zero. Since k1 has singleton dimensions its shape will be broadcasted to the shape of p1.
Related
There is a 5-dimensional tensor dense_volume1 and I have many 4-dimensional index tensors coord inside of 'coords'.
How can I index the original value tensor efficiently?
The code below seems too slow:
for coord in coords:
feats.append(dense_volume1[coord[3], :, coord[0], coord[1], coord[2]])
Programmatically indexing with coord
You can permute the axes of dense_volume1 such that you are able to index with sequential dimensions from coord. In other words, by building a tensor dv such that:
dense_volume1[coord[3], :, coord[0], coord[1], coord[2]]
Is equal to
dv[coord[0], coord[1], coord[2], coord[3], :] # trailing ':' is not necessary
You can do so with torch.permute:
>>> dv = dense_volume1.permute(2,3,4,0,1) # the returned tensor is a view
Then you can simply index with coord by splitting its first axis:
>>> for coord in coords:
... feats.append(dv[tuple(coord)])
I am reading the code for the spatial-temporal graph convolution operation here:
https://github.com/yysijie/st-gcn/blob/master/net/utils/tgcn.py and I'm having some difficulty understanding what is happening with an einsum operation. In particular
For x a tensor of shape (N, kernel_size, kc//kernel_size, t, v), where
kernel_size is typically 3, and lets say kc=64*kernel_size, t is the number of frames, say 64, and v the number of vertices, say 25. N is the batch size.
Now for a tensor A of shape (3, 25, 25) where each dimension is a filtering op on the graph vertices, an einsum is computed as:
x = torch.einsum('nkctv,kvw->nctw', (x, A))
I'm not sure how to interpret this expression. What I think it's saying is that for each batch element, for each channel c_i out of 64, sum each of the three matrices obtained by matrix multiplication of the (64, 25) feature map at that channel with the value of A[i]. Do I have this correct? The expression is a bit of a mouthful, and notation wise there seems to be a bit of a strange usage of kc as one variable name, but then decomposition of k as kernel size and c as the number of channels (192//3 = 64) in the expression for the einsum. Any insights appreciated.
Helps when you look closely at the notation:
nkctv for left side
kvw on the right side
nctw being the result
Missing from the result are:
k
v
These elements are summed together into a single value and squeezed, leaving us the resulting shape.
Something along the lines of (expanded shapes (added 1s) are broadcasted and sum per element):
left: (n, k, c, t, v, 1)
right: (1, k, 1, 1, v, w)
Now it goes (l, r for left and right):
torch.mul(l, r)
torch.sum(l, r, dim=(1, 4))
squeeze any singular dimensions
It is pretty hard to get, hence Einstein's summation helps in terms of thinking about resulting shapes “mixed” with each other, at least for me.
Y = torch.einsum('nkctv,kvw->nctw', (x, A)) means:
einsum interpretation on graph
For better understanding, I have replaced the x in left hand side with Y
The following is my Code. The "sequences" are my training data in the form [139 rows x 4 columns], 0) where the 139x4 are my signals and the 0 is my encoded label.
def __getitem__(self, idx):
sequence, label = self.sequences[idx]
#converting sequence and label to tensors
sequence = torch.Tensor(sequence.to_numpy())
print("label before tensor", label)
label = torch.Tensor(label).long()
print("numel() labels :", label.numel())
print("label shape :", shape(label))
return (sequence, label)
The Code output is:
>>label bevore tensor 0 (This is my encoded label)
>>numel() labels : 0
>>label shape : torch.Size([0])
Why is my label tensor empty?
Because torch.Tensor expects either an array (in which case this array becomes the underlying values) or several ints which will be the size of the tensor. Hence torch.Tensor(0) instantiates a tensor of size 0.
Either you use torch.Tensor([0]) or torch.tensor(0). Why these two objects behave in a different manner I don't know, but I'd recommend using the tensor (not capitalized) since it's better documented (the Tensor one seems to be part of the C port)
edit : found this useful thread about their difference
Below is the function that I am passing to a keras Lambda layer.
I am getting a problem with the output of tf.cond(). It returns a shape of <unknown>. The input tensor (t) and the constant weight tensor have shapes of (None,6) and (6,), respectively. When I add these two outside of tf.cond() then I get a tensor of shape (None,6), which is what I need it to be. However, when the same add operation is returned from within tf.cond(), I get a tensor of shape <unknown>.
What changes when this operation goes via tf.cond().
def class_segmentation(t):
class_segments = tf.constant([0,0,1,1,2,2])
a = tf.math.segment_mean(t, class_segments, name=None)
b = tf.math.argmax(a)
left_weights = tf.constant([1.0,1.0,0.0,0.0,0.0,0.0])
middle_weights = tf.constant([0.0,0.0,1.0,1.0,0.0,0.0])
right_weights = tf.constant([0.0,0.0,0.0,0.0,1.0,1.0])
zero_weights = tf.constant([0.0,0.0,0.0,0.0,0.0,0.0])
c = tf.cond(tf.math.equal(b,0), lambda: tf.math.add(t, left_weights), lambda: zero_weights)
d = tf.cond(tf.math.equal(b,1), lambda: tf.math.add(t, middle_weights ), lambda: zero_weights)
e = tf.cond(tf.math.equal(b,2), lambda: tf.math.add(t, right_weights), lambda: zero_weights)
f = tf.math.add_n([c,d,e])
print("Tensor shape: ", f.shape) # returns "Unknown"
return f
You have a few problems in your code.
tf.math.segment_mean() expects class_segments to have the same shape as first dimension of your input t. So None must be equal 6 in order for your code to run. This is most likely cause of you getting the unknown shape - because the shape of your tensors depends on None which is determined on runtime. You could apply transformation for your code to run (not sure if that is what you are trying to achieve), eg.
a = tf.math.segment_mean(tf.transpose(t), class_segments)
In tf.cond() true_fn and false_fn must return tensors of same shape. In your case true_fn returns (None, 6) because of broadcasting and false_fn returns tensor of shape (6,).
The predicate in tf.cond() must be reduced to a rank 0. For example, if you were to apply
b = tf.math.argmax(tf.math.segment_mean(tf.transpose(t), class_segments), 0)
then the shape of b would be (None) and the predicate pred in tf.cond() will be broadcasted to the same shape (which will raise an error).
Without knowing what are you trying to achieve further help is impossible.
I have a 2-d placeholder tensor with dimensions of (2,2). How can I expand the columns (same number dimensions) so that the new tensor is (2,3) and assign a constant value to the new column?
For example, the current data may look like
[[2,2], [2,2]]
And I want to transform through tensorflow to (prepending a constant of 1):
[[1,2,2], [1,2,2]]
You can use the tf.concat() op to concatenate a constant with your placeholder:
placeholder = tf.placeholder(tf.int32, shape=[2, 2])
prefix_column = tf.constant([[1], [1]])
expanded_placeholder = tf.concat([prefix_column, placeholder], axis=1)