Get shape of both tensor and np array - numpy

Tensor and numpy arrays are pretty similar in use. I'm writing a function that can except either but I need to find a way to get the shape of both a tensor and a np array with the same call. Is that possible?

I found you can use '.shape' for both:
myNpArray = np.zeros((1,10,256))
print(myNpArray.shape)
myTensor = torch.zeros((1, 10, 256))
print(myTensor.shape)
prints
(1, 10, 256)
torch.Size([1, 10, 256])
Both can be accessed element wise

Related

Trouble Understanding broadcasting behavior for tensors

I am trying to do element-wise multiplication of two tensors of dimensions (1,5,64) and (1,5). As far as I know, in spite of their dimension mismatch, broadcasting should allow this to work. So, I use this code:
x = tf.range(0,64*5)
x = tf.reshape(x, [1,5, 64])
y = tf.range(0,5)
y = tf.reshape(y, [1, 5])
prodct = x*y
This causes this error:
InvalidArgumentError: Incompatible shapes: [1,5,64] vs. [1,5] [Op:Mul]
However If i reshape first tensor to dimension (1,64,5), then it works. Code:
x = tf.range(0,64*5)
x = tf.reshape(x, [1,64, 5])
y = tf.range(0,5)
y = tf.reshape(y, [1, 5])
prodct = x*y
I do not understand why the first code does not work.
The General Broadcasting Rules, when operating on two arrays, numpy compares their shapes element-wise. It starts with the trailing (i.e. rightmost) dimensions and works its way left. Two dimensions are compatible when
they are equal, or
one of them is 1
If these conditions are not met, a ValueError: operands could not be broadcast together exception is thrown, indicating that the arrays have incompatible shapes. The size of the resulting array is the size that is not 1 along each axis of the inputs.
tensorflow also follows the same spirit. Check the documentation for more examples and details. For your case, the rightmost dimension doesn't follow the rules and throws an error.
1, 5, 64
1, 5
But this would work as it obeys the rules.
1, 64, 5
1, 5
Code
In numpy, and in tensorflow for reference.
import numpy as np
a = np.arange(64*5).reshape(1, 64, 5)
b = np.arange(5).reshape(1,5)
(a*b).shape
(1, 64, 5)
import tensorflow as tf
x = tf.reshape(tf.range(0,64*5), [1, 64, 5])
y = tf.reshape(tf.range(0,5), [1, 5])
(x*y).shape
TensorShape([1, 64, 5])

Passing x_train as a list of numpy arrays to tf.data.Dataset is not working

My problem is that x_train in tf.data.Dataset.from_tensor_slices(x_train, y_train) needs to be a list. When I use the following lines to pass [x1_train,x2_train] to tensorflow.data.Dataset.from_tensor_slices, then I get error (x1_train, x2_train and y_train are numpy arrays):
Train=tensorflow.data.Dataset.from_tensor_slices(([x1_train,x2_train], y_train)).batch(batch_size)
Error:
Train=tensorflow.data.Dataset.from_tensor_slices(([x1_train,x2_train], y_train)).batch(batch_size)
return ops.EagerTensor(value, ctx.device_name, dtype)
ValueError: Can't convert non-rectangular Python sequence to Tensor.
What should I do?
If the main goal is to feed data to a model having multiple input layers then the following might be helpful:
import tensorflow as tf
from tensorflow import keras
import numpy as np
def _input_fn(n):
x1_train = np.array([1, 2, 3, 4, 5, 6, 7, 8], dtype=np.int64)
x2_train = np.array([15, 25, 35, 45, 55, 65, 75, 85], dtype=np.int64)
labels = np.array([40, 30, 20, 10, 80, 70, 50, 60], dtype=np.int64)
dataset = tf.data.Dataset.from_tensor_slices(({"input_1": x1_train, "input_2": x2_train}, labels))
dataset = dataset.batch(2, drop_remainder=True)
dataset = dataset.repeat(n)
return dataset
input1 = keras.layers.Input(shape=(1,), name='input_1')
input2 = keras.layers.Input(shape=(1,), name='input_2')
model = keras.models.Model(inputs=[input_1, input_2], outputs=output)
basically instead of passing a python list, pass a dictionary where the key indicates the layer's name to which the array will be fed to.
like in the above array x1_train will be fed to tensor input1 whose name is input_1. Refered from here
If you have a dataframe with different types (float32, int and str) you have to create it manually.
Following the Pratik's syntax:
tf.data.Dataset.from_tensor_slices(({"input_1": np.asarray(var_float).astype(np.float32), "imput_2": np.asarray(var_int).astype(np.int), ...}, labels))

Understanding INDArray dimension reshaping for Tensorflow Object detection models

Trying to load Tensorflow trained model into Deeplearning4J with following error:
IllegalStateException: Invalid array shape: cannot associate an array with shape [38880] with a placeholder of shape [-1, -1, -1, 3]:shape is wrong rank or does not match on one or more dimensions
var arr: INDArray = Nd4j.create(data) //.reshape(1, -1, -1, 3);
arr = Nd4j.pile(arr, arr)
sd.associateArrayWithVariable(arr, sd.variables.get(0))
Python model was loaded like that:
# Load image using OpenCV and
# expand image dimensions to have shape: [1, None, None, 3]
# i.e. a single-column array, where each item in the column has the pixel RGB value
image = cv2.imread(PATH_TO_IMAGE)
image_expanded = np.expand_dims(image, axis=0)
Please explain any question if you know:
1) What means [1, None, None, 3] in terms of Python arrays
2) What means np.expand_dims(image, axis=0) in Python
3) Deeplearning4J reshape(1, -1, -1, 3);
You're mixing two different concepts here, TF placeholders, and imperative numpy-like reshape.
In your case, model expects 4D input tensor, with shape [-1, -1, -1, 3]. For human it can be translated to [Any, Any, Any, 3]. But you're trying to feed it with tensor with shape [38880], rank 1.
Now to your questions.
1) See above. -1 is treated as "Any".
2) This function adds 1 as dimension. i.e. if you have [38880], expand_dims at axis=0 will make it [1, 38880]
3) Nope, that's wrong. You should not use that as your shape. You have some image there, so you should specify proper dimensions your image has, i.e. [1, 800, 600, 3].

Tensorflow landmark heatmap

I am trying to draw landmark heatmaps with tensorflow.
My current approach is using tf.scatter_nd like this:
def draw_lmarks(x):
def draw_lmarks_inner(x2):
return tf.scatter_nd(x2[0], x2[1], shape=(IMGSIZE, IMGSIZE))
ret = tf.map_fn(draw_lmarks_inner, x, dtype="float32")
return tf.reshape(tf.reduce_max(ret, axis=0), [IMGSIZE, IMGSIZE, 1])
return tf.map_fn(draw_lmarks, [locations, vals], dtype="float32")
But this is quite slow as i have to create an IMAGESIZE*IMAGESIZE image for each batch times landmarks.
So i poked around and found tf.tensor_scatter_nd_update which i could use like:
img = tf.zeros((IMGSIZE,IMGSIZE), dtype="float32")
def draw_lmarks(x):
return tf.tensor_scatter_nd_update(img, x[0], x[1])
imgs = tf.map_fn(draw_lmarks, [locations, vals], dtype="float32")
Which allows me to only generate batch_size images which runs considerably faster.
... BUT, this doesn't use the highest values at one point but instead simply overwrites.
There is the tf.scatter_max function which sounds like what i need but this seems to expect different shaped inputs.
Is there a way to use the second approach but instead of overwriting values takes the maximum value at one point ?
Shapes:
location = (-1, 68, 16, 16, 2)
vals = (-1, 68, 16, 16)
To visualize:
This is what the second (faster) function returns:
while i need something like
I think you will be much better off by first setting the seeds of your landmarks and then convolve the result with your heatmap template. Something like
import tensorflow as tf
num_loc = 10
im_dim = 32
locations = tf.random.uniform((num_loc, 2), maxval=im_dim, dtype=tf.int32)
centers = tf.scatter_nd(locations, [1]*num_loc, (im_dim, im_dim))
heatmap = tf.nn.conv2d(centers[None, :, :, None], heatmap_template[:, :, None, None], (1, 1, 1, 1), 'SAME')[0, :, :, 0]

How to feed a placeholder tensor without fixed shape?

After some work, the question becomes: how to feed a placeholder tensor without fixed shape? The code is as follows. Note that tensor 'x' has shape [?, 32, 32, 64]. Obviously, the shape of 'ini_obj' is wrong. So, how can I feed tensor 'x' in 'eval()' method.
ini_obj = np.random.random((None, 32, 32, 64)) # numpy array
sess = tf.Session()
sess.run(x)
x.eval(feed_dict={x: ini_obj}, session=sess)
To convert a tensor to numpy array, you have to run eval() function in keras.