Keras backend switch combined with tf.where not working as intended - python

I have a custom loss function where I want to change values from a one-hot based encoding to values in a certain range to calculate an IOU.
Part of this code is to look at where I have a one in a tensor that has zeros otherwise. For this I am using tf.where which returns me the location. I have a vector of shape [batch_size,S1,S2,12] where I only care for the last dimension, thats why I take [...,2] of tf.where.
Now it often happens that my prediction is all zeros because I have background events without any values in them and also my network will predict an all zero vector every now and then. This means tf.where will return an empty tensor.
Thats why I want to use K.switch to check if the tensor is empty, because if it is I would like to have zeros returned.
The problem is now that K.switch expects the shape of the then else options to have the same shape but I need my output to have shape [batch_size,S1,S2,1]. I have tried different things but I cant get this to work.
I need to get zeros of shape [batch_size,S1,S2,1] or I need where_box1 to have [batch_size,S1,S2,1] with floats.
The way its implemented now, K.switch returns an empty vector of zeros when where_box1_temp is empty, which is not what I want.
When I use tf.zeros([batch_size,S1,S2,1]) instead it will complain that the conditions are of different shape when where_box1_temp is empty....
where_box1_temp = tf.where(y_pred[...,C+1:C+13])[...,2]
where_box1 = K.switch(tf.equal(tf.size(where_box1_temp),0) ,
tf.zeros_like(where_box1_temp) , where_box1_temp)

So I found a workaround, maybe this is helpful for someone else:
where_box1_temp = tf.where(y_pred[...,C+1:C+13],[1,2,3,4,5,6,7,8,9,10,11,12],0)
where_box1 = tf.reshape(K.sum(where_box1_temp,axis=3),[batch_size,5,5])
This allows me to have a tensor of my desired shape where all background/zero prediction values are 0 without having to use k.switch and having trouble with any empty dimensions or something like that.

Related

Are several subsequent `reshape` operations equivalent to only one?

In Pytorch,
I recently stumbled onto code that looks like this.
# initially, my_tensor is one_dimensional, of length b*x*y
my_tensor = my_tensor.reshape(b, x, y)
my_tensor = my_tensor.reshape(b, x*y)
Is it equivalent to only writing the second line?
my_tensor = my_tensor.reshape(b, x*y)
And in general, is doing several reshape operations always equivalent to only doing the last one?
Intuitively, I think so, but the documentation for reshape doesn’t really mention any invariant, and I couldn’t find information for the inner representation of tensors and how reshape changed that
The reshape operation does not (need to) touch the underlying data. It simply adjusts the "meta-data" about the dimensions. So a series of reshape operations (without any operations in between!!) is equal to a single reshape operation.

Getting the value at the intersection of a row and column in a pytorch tensor matrix

I am new to pytorch and am looking to get a value at an index from a matrix. There is a matrix called psfm_s that has been initialized with
psfm_s=Var(torch.randn(12,20),requires_grad=True) For example, I would like to to get the number in the first column (out of 12 columns) and the number in the first row (out of 20 rows).
I have tried doing something like index=torch.tensor([0,0])
num_at_index=psfm_s[index] to get the desired number but that just gets me a tensor with a bunch of numbers in it, I'm not really sure what happens with this method.
I just want the one number at the desired index, how can I go about doing this if it's even possible? Thanks for the help!
To reproduce the described code in its completeness (for future reference, please provide a [mcve] in your question), and taking the already correct solution from #jodag in the comments, consider this code snippet:
from torch.autograd import Variable
import torch
psfm_s = Variable(torch.randn(12,20), requires_grad=True)
single_value = psfm_s[0,0].item()
print(single_value) # prints a single random number from your tensor
For some background information, consider the official docs:
Returns the value of this tensor as a standard Python number. This
only works for tensors with one element. For other cases, see tolist().
This operation is not differentiable.
Consequently, getting a complete row (or column), would look like this:
from torch.autograd import Variable
import torch
psfm_s = Variable(torch.randn(12,20), requires_grad=True)
single_row_tensor = psfm_s[0,:]
single_row_list = single_row_tensor.tolist()
single_row_numpy_1 = single_row_tensor.data.numpy()
single_row_numpy_2 = single_row_tensor.detach().numpy()
# the following doesn't work, as it is a torch.Variable with gradient history:
single_row_fail = single_row_tensor.numpy()
In the case you want to get a NumPy array, you have to be careful not to directly cast it to .numpy(), as this causes issues with the gradient history of the Variable. You can either use .data.numpy(), or .detach().numpy().
There seems to be some discussion as to which one is preferred, but both should work for your case.

Trying to get Convolution of Single Image

I am trying to get the result of a single convolution over an image using tf.keras.backend.conv2d.
The specifications of the input are 227 pixels by 227 pixels, with a channel size of 3 (RGB image.)
The filter size I would like to use is 11x11 and a stride of 4. There is no zero padding included.
I am not married to the idea of using tf.keras.backend.conv2d. I am willing to change methods/packages, just as long as I get a convolved image with the specified requirements above.
Here is the chunk of code I'm trying to make work:
import tensorflow as tf
from tensorflow import keras
import cv2
image = cv2.imread('pic.jpg')
tf.keras.backend.conv2d(image,11,strides=4,data_format="channels_last",dilation_rate=(1))
I get this error message
InvalidArgumentError: cannot compute Conv2D as input #1(zero-based) was expected to be a double tensor but is a int32 tensor [Op:Conv2D] name: convolution/
If there is anything I can add to clarify, please let me know. I can post the entirety of the code, but most of it is irrelevant, at least in my opinion.
Thank you to whoever takes their time to help me!
You are using the wrong function. What you are using is the convolution op, which takes an input and a filter tensor and performs the convolution. As such, the second argument should be the filter tensor itself. You are trying to pass 11 as the filter tensor which obviously doesn't make sense. What I suspect you want to use is tf.keras.layers.Conv2D which takes care of creating the filter according to some specification and then wraps the convolution op as well. Try this:
conv_layer = tf.layers.Conv2D(1, 11, 4)
result = conv_layer(image)
This creates an 11x11 filter and a convolution op with stride 4; the second line then calls the op. I put 1 as the number of filters (first argument) since I don't know what exactly you are trying to do.

How to update a sub-tensor inside a tensor in tensorflow?

I'm working with MNIST and I have a tensor of gradients with size [?,28,28,1] and I want to zero out a few of the [28,28,1] sub-tensors inside it, how should I accomplish this?
I know the indices (as a list) where I need to zero out the sub-tensors. I tried doing something like this (given below) but, scatter.update can only change variables not tensors. I also tried stacking up the required sub-tensors of zeroes and ones but couldn't build up the required result.
dy_dx, = tf.gradients(loss, x_adv)
zeroes = tf.zeros(dy_dx[0].get_shape(), tf.float32)
dy_dx = tf.scatter_update(dy_dx, indices, zeroes)
Thanks!
I'd suggest creating a TensorFlow constant with zeros at the locations you want to zero out and ones everywhere else. Then you could create an op that uses tf.multiply to do elementwise multiplication of the constant and dy_dx. Depending on the structure of your graph, you might need to feed the result to dy_dx in your next call to session.run; you can replace any Tensor with feed data, including variables and constants.
Incidentally, if you just want to apply dropout to the input layer you can use tf.layers.dropout

Select which tensor to use in middle of TensorFlow graph

In Tensorflow, how would I go about selecting between a python list of Tensors in the middle of my graph as an input to the rest of the graph?
Basically, I have a python list of Tensors that are candidates to be used as inputs in the rest of the graph. I want to select from one of them without adding extra dependencies that require all of the Tensors in the list to be computed (I think that would happen if I used tf.cond). How can I select one of them? I can't do it at the python level because I choose the tensor based on a value computed from a placeholder. So for example:'
x = tf.placeholder(tf.int32, shape=(num_steps, None))
y = tf.placeholder(tf.int32, shape=(None,))
lengths = tf.placeholder(tf.int32, shape=(None,))
# Pretend there is a bunch of lines of code here
output_index = max_sequence_length = tf.reduce_max(lengths)
final_output = potential_outputs[output_index] # won't work, output_index is Tensor
# Pretend the rest of the model uses final_output
More info if you want it:
I am unrolling an RNN and I want to only unroll to the maximum length of the sequence. When this is less then the number of unrolling steps, there is a lot of wasted computation. Dynamic_rnn and static_rnn do not meet my needs, so I am trying to come up with my own custom method of unrolling the graph.
To index in tensorflow use tf.slice.
It should be noted that based on the code you provided, I don't think you are indexing the outputs correctly using tf.reduce_max function since this is providing the actual maximum value across a given axis which may not be an integer (but I'm not sure how your network works). You may be looking for tf.argmax that returns to index for the maximum value. The issue with this however is that tensorflow does not a have a gradient defined for tf.argmax so that function cannot be a learned part of your network.

Categories