The use of meshgrid in pytorch/numpy - numpy

Below code is a snippet taken from https://blog.paperspace.com/how-to-implement-a-yolo-v3-object-detector-from-scratch-in-pytorch-part-3/, and I am confused as to what it is trying to achieve.
grid = np.arange(grid_size)
a,b = np.meshgrid(grid, grid)
x_offset = torch.FloatTensor(a).view(-1,1)
y_offset = torch.FloatTensor(b).view(-1,1)
if CUDA:
x_offset = x_offset.cuda()
y_offset = y_offset.cuda()
x_y_offset = torch.cat((x_offset, y_offset), 1).repeat(1,num_anchors).view(-1,2).unsqueeze(0)
I tried the case when grid_size = 3, and it outputed:
tensor([[0., 1.],
[2., 0.],
[1., 2.],
[0., 1.],
[2., 0.],
[0., 0.],
[1., 1.],
[1., 2.],
[2., 2.],
[0., 1.],
[2., 0.],
[1., 2.],
[0., 1.],
[2., 0.],
[0., 0.],
[1., 1.],
[1., 2.],
[2., 2.],
[0., 1.],
[2., 0.],
[1., 2.],
[0., 1.],
[2., 0.],
[0., 0.],
[1., 1.],
[1., 2.],
[2., 2.]])
I cannot quite see what is the pattern here. According to the description in the given link I think I should really expect something like:
tensor([[0,0],
[0,0],
[0,0],
[0,1],
[0,1],
[0,1],
[0,2],
[0,2],
...]])

If you are expecting the second output you show, simply change
x_y_offset = (
torch.cat((x_offset, y_offset), 1).repeat(1, num_anchors).view(-1, 2).unsqueeze(0)
)
to
x_y_offset = (
torch.cat((y_offset, x_offset), 1).repeat(1, num_anchors).view(-1, 2).unsqueeze(0)
)
It just has to do with the ordering of the output of meshgrid.

Related

Repeat along given axis with as_strided

I have a numpy array:
a = array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]])
which i replicate with np.repeat like that:
np.repeat(a, 3, axis=0)
with the result:
array([[0., 1., 2.],
[0., 1., 2.],
[0., 1., 2.],
[3., 4., 5.],
[3., 4., 5.],
[3., 4., 5.],
[6., 7., 8.],
[6., 7., 8.],
[6., 7., 8.]])
Can i achieve the same with np.lib.stride_tricks.as_strided to avoid copying data? I need something like that also for multidimensional arrays, but i always repeat along 0-th axis...
I don't think this is possible. You can get close:
n=3
out = np.lib.stride_tricks.as_strided(a,
shape = (n,) + a.shape,
strides = (0,) + a.strides
)
np.shares_memory(a, out)
Out[]: True
out
Out[]:
array([[[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]],
[[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]],
[[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]]])
But that's not repeating in dimension 0, it's repeating everything in a new dimension 0. And reshaping creates a copy:
out.reshape(-1, 3)
Out[]:
array([[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.],
[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.],
[0., 1., 2.],
[3., 4., 5.],
[6., 7., 8.]])
np.shares_memory(a, out.reshape(-1, 3))
Out[]: False
You'll generally be better off using broadcasting instead, going from something like:
op(a_repeated, b)
to:
op(a[None, ...], b.reshape((-1, a.shape[0]) + b.shape[1:])) )
But that depends a lot on what op is (and whether it is vectorized and/or vectorizable).

Is there a Numpy pad equivalent which lets you specify desired size?

numpy.pad wants me to specify the amount of padding, but what if I just want to specify the total desired size in each dimension then have my array symmetrically padded to achieve that?
I'm not looking for someone to write a function for me. Instead, I'd like to know if there's anything that does it out of the box.
Here's an example of how numpy.pad would work:
>>> arr = np.ones(shape=(4,4))
>>> arr
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> arr = np.pad(arr, [(1,1),(1,1)])
>>> arr
array([[0., 0., 0., 0., 0., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.]])
>>>
And now what I wish I had
>>> arr = np.ones(shape=(4,4))
>>> arr
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> arr = np.magic_pad(arr, (6,6))
>>> arr
array([[0., 0., 0., 0., 0., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.]])
>>>
There's no builtin to achieve that exact functionality. But there are always alternatives. So, here's one with array-assignment -
def pad_to_shape(arr, out_shape):
m,n = out_shape
x,y = arr.shape
out = np.zeros(out_shape, dtype=arr.dtype)
mx,my = (m-x)//2, (n-y)//2
out[mx:mx+x, my:my+y] = arr
return out
Sample runs -
In [76]: arr
Out[76]:
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
In [77]: pad_to_shape(arr, (8,6))
Out[77]:
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
In [78]: pad_to_shape(arr, (4,6))
Out[78]:
array([[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.],
[0., 1., 1., 1., 1., 0.]])
Here is one in which you can specify the amount of padding you want on each side:
# Value to pad by (on both sides)
pad_width_left = 5 # Padding on lefthand side
pad_width_right = 3 # Padding on righthand side
# Now pad vector
arr_padded_left = np.pad(arr, pad_width_left)[:-pad_width_left]
arr_padded_right = np.pad(arr_padded_left, pad_width_right)[pad_width_right:]

Numpy arange a diagonal array

I would like to create a square numpy array such that it starts counting from the diagonal.
Do you know a one-liner for that?
Example with 5x5:
array([[ 1., 2., 3., 4., 5.],
[ 0., 1., 2., 3., 4.],
[ 0., 0., 1., 2., 3.],
[ 0., 0., 0., 1., 2.],
[ 0., 0., 0., 0., 1.]])
In [49]: np.identity(5).cumsum(axis=1).cumsum(axis=1)
Out[49]:
array([[ 1., 2., 3., 4., 5.],
[ 0., 1., 2., 3., 4.],
[ 0., 0., 1., 2., 3.],
[ 0., 0., 0., 1., 2.],
[ 0., 0., 0., 0., 1.]]
>>> mat = np.vstack((np.concatenate((np.zeros(i),np.arange(1,5-i+1))) for i in range(0,5)))
>>> mat
array([[1., 2., 3., 4., 5.],
[0., 1., 2., 3., 4.],
[0., 0., 1., 2., 3.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 0., 1.]])

Splitting numpy array into different parts and summing each part rowwise

I have a list of arrays say
k=[array([0, 2], dtype=int64),
array([1], dtype=int64),
array([3, 4], dtype=int64)]
There is also an array
e=array([[0., 4., 0., 0.],
[1., 2., 2., 0.],
[0., 0., 2., 4.],
[0., 0., 0., 0.],
[0., 0., 0., 3.]])
I want to get an array x as follows
array([[0,4,2,4],
[1,2,2,0],
[0,0,0,3]])
Here
x[0] = e[0]+e[2]
x[1] = e[1]
x[2] = e[3]+e[4]
I want this in a vectorized fashion(without loops).Is this possible?
If the input arrays are all the same size, a full numpy solution is possible:
k = np.array([[0, 2], [1, 1], [3, 4]], dtype=int)
e = np.array([[0., 4., 0., 0.],
[1., 2., 2., 0.],
[0., 0., 2., 4.],
[0., 0., 0., 0.],
[0., 0., 0., 3.]])
e[k].sum(axis=1)
If not, using a loop is I think necessary:
import numpy as np
k = [np.array([0, 2], dtype=int),
np.array([1], dtype=int),
np.array([3, 4], dtype=int)]
e = np.array([[0., 4., 0., 0.],
[1., 2., 2., 0.],
[0., 0., 2., 4.],
[0., 0., 0., 0.],
[0., 0., 0., 3.]])
np.array([ e[ki, :].sum(axis=0) for ki in k ])

Tensorflow: batching labels with tf.train.batch

i have a piece of code
la=[0,0,0,0,0,0,1,1,1,1]
onehot = tf.one_hot(la, depth=2) #[[1,0],[1,0],[1,0],[1,0],[1,0],[1,0],[0,1],[0,1],[0,1],[0,1]]
image_batch,labels_batch=tf.train.batch([resized_image,onehot],batch_size=2,num_threads=1)
when i run
print(s.run([tf.shape(image_batch),labels_batch]))
it is batching all labes at a time,like
[array([ 2, 50, 50, 3]), array([[[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.]],
[[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 1., 0.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.]]], dtype=float32)]
it should output something like
[array([ 2, 50, 50, 3]), array([[[ 1., 0.],
[[ 1., 0.]]], dtype=float32)]
doesn't it? as batch size is 2 and taking 2 images and it's corresponding labels at a time.
i'm new to CNN and machine learning.thanks beforehand.
According to the Tensorflow documentation of tf.train.batch (https://www.tensorflow.org/api_docs/python/tf/train/batch),
Since the enqueue_many=False by default and your input onehot have the shape of [10, 2], then the output (here labels_batch) shape become [batch_size, 10, 2].
if the enqueue_many=True, then only the output (here labels_batch) will become [batch_size,2].
Hope this helps.