I have a multidimensional array with the last two dimensions corresponding a "window". For each "window" in the array my goal is to set the first max value in the window to 1 and the rest of the values to 0. For example, for one window, we have this assignment:
[[0., 0., 0.], [[0., 0., 0.],
[0., 1., 1.], -> [0., 1., 0.],
[0., 1., 1.]], [0., 0., 0.]]
Now, i want to do this for all windows, where each window is on the last two dimensions, i.e. axis=(-1,-2). This is what I have tried so far:
# windows
x = np.array([[[[[[0., 0., 0.],
[0., 1., 1.],
[0., 1., 1.]],
[[0., 0., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 1.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 0.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 0., 1.]]]]]])
max_indices = np.argwhere(x == x.max()) # all indicies of max values in x
mask = np.zeros_like(x) # start of with everything set to 0
# I can set the first window by doing the following
mask[tuple(max_indices[0])] = 1.0
How can i do the same for all other windows? Preferably without looping.
My idea was to find unique values in max_indices where the last two dimensions are not taken into account, but i am not sure how to go about this.
EDIT
I have a case where x in the scenario above is taken from another
array using np.lib.stride_tricks.as_strided, which means that the strides will differ.
Here is the case:
# The image or whatever i want to modify
x = np.array([[[[0., 0., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 0., 1.]]]])
# the windows of that image
x = np.lib.stride_tricks.as_strided(x, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))
Using the solution given by Felipe:
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
# plug it back
x[0][0] = y
x
array([[[[[[0., 0., 0.],
[0., 1., 0.],
[0., 1., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[1., 0., 0.]]],
[[[0., 1., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]]]])
The shape is the same but with different strides in x and y it seems as if "plugging it back" causes x and y to not be identical, which I would expect.
Here's one way using np.put_along_axis (though this is really just a somewhat faster loop).
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
Output:
array([[[[0., 0., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]])
EDIT
Not the brightest idea but what I meant is you could reassign it first to a copy of it and then get your strided view again, something like:
x0 = x.copy() # Get a normal view
# [ Run the previous snippet ]
x0[0][0] = y # Assign the modified version
# Then if you really want another strided view you can recreate it
x0 = x0.reshape(saved_x.shape) # Reshape it to the original version pre-stride
x = np.lib.stride_tricks.as_strided(x0, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))
Related
This creates an identity matrix.
np.identity(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
But what if I want to multiply with 3I like this?
array([[3., 0., 0.],
[0., 3., 0.],
[0., 0., 3.]])
I have following multi-dimensional array:
windows = array([[[[[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]]],
[[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[1., 0.],
[0., 0.]]],
[[[1., 0.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]]]]]])
print(windows.shape)
(1, 1, 3, 3, 2, 2) # (n, d, a, b, c, c) w = a * (c*c), h = b * (c*c)
I want to get next resulting array:
mask = array([[
[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]
]], dtype=np.float32)
print(mask.shape)
(1, 1, 6, 6) # (n, d, w, h)
Basically, I want to squeeze last 4 dimensions into 2-d matrix so the final shape become (n, d, w, h), in this case (1, 1, 6, 6).
I tried np.concatenate(windows, axis = 2), but it didnt concatenate along 2nd dimension and reduced for some reason first(although I set axis = 2) 'n' dimension.
Additional information:
windows is a result of following code snippet
windows = np.lib.stride_tricks.sliding_window_view(arr, (c, c), axis (-2,-1), writeable = True) # arr.shape == mask.shape
windows = windows[:, :, ::c, ::c] # these are non-overlapping windows of arr with size (c,c)
windows = ... # some modifications of windows
Now I want to build from these windows array with shape of arr.shape, this array called mask in example above. Simple reshape doesn't work because it returns elements in wrong order.
IIUC, you want to merge dimensions 2+4 and 3+5, an easy way would be to swapaxes 4 and 5 (or -3 and -2), and reshape to (1,1,6,6):
windows.swapaxes(-2,-3).reshape(1,1,6,6)
output:
array([[[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]]])
This is my predictions outcome
array([[1., 0., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 1., 0.],
[0., 0., 1.],
[0., 1., 0.],
[0., 0., 1.],
[1., 0., 0.],
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[1., 0., 0.],
[0., 0., 1.],
[1., 0., 0.],
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 0., 1.],
[1., 0., 0.]], dtype=float32)
and this is the confusion_matrix() function
cm = confusion_matrix(test_labels, predictions[:,0])
My query is how this confusion_matrix() functions works and how to solve this issue?
As I am a novice it will be really helpful if anyone can give me a little explanation.
Thank you.
This is primarily due to the shape of the arrays not being similar. Please check the arrays with test_labels.shape etc. Then use the reshape method or split them properly so that the shapes match.
let's assume that i have array called A
A = np.zeros((4, 3, 2))
array([[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
and another array called B
B = np.arange(4)
array([0, 1, 2, 3])
and i want to do something like concatenation in the third dimension to got this result:
array([[[0., 0., 0.0],
[0., 0., 0.0],
[0., 0., 0.0]],
[[0., 0., 1.0],
[0., 0., 1.0],
[0., 0., 1.0]],
[[0., 0., 2.0],
[0., 0., 2.0],
[0., 0., 2.0]],
[[0., 0., 3.0],
[0., 0., 3.0],
[0., 0., 3.0]]])
i tried serval ways to do that but i didn't succeed.
who i can do that in good way not loops?
To add the extra dimension you can use np.append. You just have to get the shape correct. You can use np.repeat() to make the repeating elements:
A = np.zeros((4, 3, 2))
h, w, d = A.shape
B = np.repeat(np.arange(h), w).reshape([h, w, 1])
np.append(A, B, axis=2)
Output:
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])
We could broadcast B to the corresponding shape and use advanced indexing here and assign B broadcasted across the corresponding axes:
np.concatenate([A, np.broadcast_to(B[:,None,None], A[...,-1:].shape)], -1)
print(A)
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])
I have some 2d arrays using numpy, and I want to copy subregions from one into another. For example, if I start with:
dest = numpy.zeros((4, 4))
# array([[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]])
src = numpy.ones((4, 4))
# array([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
I want to somehow say that the src should be copied into dest at (2,1), such that source would then look like:
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Or if (-3, 0), then:
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
I can do the good old fashioned double index loop to do this, but I was hoping numpy had some clever magic that did it. I looked at take, but couldn't see how to make that the tool for this job.
Both of these can be accomplished with numpy indexing. To understand how this works, the documentation is always your friend.
Your first case:
dest[1: ,2:] = src[1: ,2:]
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Your second case: (You indicated column -3 but your results indicate -4)
dest[:, -4] = src[:, -4]
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])