How to permute "dimensions" along a single axis of a tensor?
Something akin to tf.transpose, but at the level of "dimensions" along an axis, instead of at the level of axes.
To permute them randomly (along the first axis), there it tf.random.shuffle, and to shift them, there is tf.roll. But I can't find a more general function that would apply any given permutation.
tf.gather can be used to that end. In fact, it is even more general, as the indices it takes as one of its inputs don't need to represent a permutation.
Related
I have a 3d numpy array (nx5x5). I want to sum each of the n slices together. So the new shape will be (nx1x1), where each n is just the sum of an individual 5x5 array. Can I do this in numpy without using a loop? np.sum has its axis arguments, but they reshape the array into the wrong shape. I think I may need to call np.sum twice? But I'm having trouble thinking about how to do this. Anybody know the answer?
Here are three different ways of doing it:
Use a tuple for axis:
a.sum(axis=(1, 2))
Reshape properly to merge the axes you want to sum over:
a.reshape(a.shape[0], -1).sum(axis=1)
Use multiple sums:
a.sum(-1).sum(-1)
OR
a.sum(1).sum(-1)
etc.
np.sum has its axis arguments, but they reshape the array into the wrong shape
Summing is a reduction operation and it makes sense that after reducing in a specific axis (by summing all elements in that axis) that particular dimension is removed. If you don't want that you can pass the optional keepdims argument.
values = np.random.randn(3,5,5)
values.sum(axis=(1,2), keepdims=True)
Think I figured this out, for anyone who is running into the same issue. It turns out you can select two axes from np.sum, making a plane instead of a line. So:
np.sum(a, (1,2)
Does the trick.
lower_bounds = torch.max(set_1[:, :2].unsqueeze(1),
set_2[:, :2].unsqueeze(0)) #(n1, n2, 2)
This code snippet uses unsqueeze(1) for one tensor, but unsqeeze(0) for another. What is the difference between them?
unsqueeze turns an n-dimensionsal tensor into an n+1-dimensional one, by adding an extra dimension of zero depth. However, since it is ambiguous which axis the new dimension should lie across (i.e. in which direction it should be "unsqueezed"), this needs to be specified by the dim argument.
Hence the resulting unsqueezed tensors have the same information, but the indices used to access them are different.
Here is a visual representation of what squeeze/unsqueeze do for an effectively 2d matrix, where it is going from a 2d tensor to a 3d one, and hence there are 3 choices for the new dimension's position:
I have a tensor ,model with shape (5,100,200). Its like a (100x200) image with 5 channels. I am trying to achieve the following two things without using for loops:
Replacing
I have another image I of shape (100,200). I want to replace the smallest pixel value across the channel for every pixel of model with the pixel of I.Eg:
For pixel (3,5)
model(0,3,5)=128
model(1,3,5)=64
model(2,3,5)=256
model(3,3,5)=0
model(4,3,5)=32
and
I(3,5)=69
The smallest value is in 3rd channel so I want to replace model(3,3,5)(i.e. 0) with I(3,5)(i.e. 69). I use
minargs=np.argmin(model,axis=0)
to get a matrix of shape (100,200) having channel indices {0,1,2,3,4} of channels having minimum value for each pixel. I just don't know how to use this matrix to achieve the replacement(without for loop).
Sorting
I have another model matrix,kmodel, of size (5,100,200) and I want to sort pixel values across/through channels of model but by using the values in kmodel as the key. Suppose
kmodel(0,3,4)=5
kmodel(1,3,4)=1
kmodel(2,3,4)=3
kmodel(3,3,4)=2
kmodel(4,3,4)=6
and
model(0,3,4)=9
model(1,3,4)=8
model(2,3,4)=7
model(3,3,4)=6
model(4,3,4)=5
So after sorting I should have model as:
model(0,3,4)=8 (8 was the value at model(**1**,3,4)and kmodel has the minimum value ,*1* at channel **1**)
model(1,3,4)=6
model(2,3,4)=7
model(3,3,4)=9
model(4,3,4)=5
I use
numpy.argsort(kmodel,axis=0)
to get the arguments in a tensor (5,100,200) but again I don't know how to use them to achieve the sort(without for loops).
What is the fastest way of achieving the above goals. I am also frequently using operation of these tensors (5,100,200) like addition and exp. Also providing links to sources containing good tutorials on various ways to specify index of numpy arrays would be appreciated.
I have a numpy array of shape (3,12,7,5). I would like to have the sum of all slices along the first axis of this array.
data = np.random.randint(low=0, high=8000, size=3*12*7*5).reshape(3,12,7,5)
data[0,...].sum()
data[1,...].sum()
data[2,...].sum()
np.array((data[0,...].sum(), data[1,...].sum(), data[2,...].sum()))
First, I thought this should be possible using np.sum(data, axis=...) but it is not.
How do I perform this calculation in a single shot. What is the numpy magic?
For a generic ndarray, you could reshape into a 2D array, keeping the number of elements along the first axis same and merging all of the remaining axes as the second axis and finally sum along that axis, like so -
data.reshape(data.shape[0],-1).sum(axis=1)
For a 4D array, you could include the axes along which the summation is to be performed. So, to solve our case, we would have -
data.sum(axis=(1,2,3))
This could be extended to make it work for generic ndarrays by creating a tuple of appropriate axis IDs and thus avoid reshaping, like so -
data.sum(axis=tuple(np.arange(1,data.ndim)))
I used opencv to do some image processing. I tried to then plot the image on my plotter (origin at lower left), however the image is flipped. opencv's origin is in the upper left, and so the y coordinates of the image are flipped.
What function should I apply to my points such that it will plot properly in the new origin system (lower left)?
EDIT:
I am not concerned with changing the plot display, I actually need the points' coordinates flipped.
Using np.flipud did not change the points at all since the point are displayed by a N X 2 matrix.
The problem does not lie in numpy but in matplotlib way of displaying data. In order to produce valid visualization you should flip y-axis on the image generation level, not numpy analysis. It can be easily done through matplitlib API to the axes object:
plt.gca().invert_yaxis()
Are you asking how to flip a numpy array or how to display it?
If you're asking how to flip the array, have a look at np.flipud or equivalently your_data[::-1, ...]
numpy.flipud is a function that uses the exact slicing shown above. However, it's more readable if you're not familiar with numpy slicing.
To explain why data[::-1, ...] will flip the array vertically, you need to understand a bit about how indexing works.
In general, indexing in python works by specifying start:stop:step. Each of these may be None (e.g. :-10 specifies start=None, stop=-10, step=None).
Therefore, ::-1 specifies start=None, stop=None, step=-1 -- in other words, go over the full sequence, but increment with a negative step, effectively reversing the sequence.
... is an Ellipsis. In numpy, this is used to indicate including all other dimensions.
The ellipsis avoids the need to special case your array being 2D or 3D (or 27-dimensional, for that matter). If it's a 2D array, then x[::-1, ...] is equivalent to x[::-1, :]. If it's a 3D array, it's equivalent to x[::-1, :, :], etc.
In numpy, the first axis is rows. Therefore, x[::-1, ...] says "reverse the rows and leave all other dimensions alone. This will create a view, so the memory wont' be duplicated and no copy will be created.
In the specific case of rows, you could leave the ellipsis out. However, it's useful to think about for the general case. For example, flipping left-right would be x[:, ::-1, ...] (or np.fliplr).