Python/numpy issue with array/vector with empty second dimension - python

I have what seems to be an easy question.
Observe the code:
In : x=np.array([0, 6])
Out: array([0, 6])
In : x.shape
Out: (2L,)
Which shows that the array has no second dimension, and therefore x is no differnet from x.T.
How can I make x have dimension (2L,1L)? The real motivation for this question is that I have an array y of shape [3L,4L], and I want y.sum(1) to be a vector that can be transposed, etc.

While you can reshape arrays, and add dimensions with [:,np.newaxis], you should be familiar with the most basic nested brackets, or list, notation. Note how it matches the display.
In [230]: np.array([[0],[6]])
Out[230]:
array([[0],
[6]])
In [231]: _.shape
Out[231]: (2, 1)
np.array also takes a ndmin parameter, though it add extra dimensions at the start (the default location for numpy.)
In [232]: np.array([0,6],ndmin=2)
Out[232]: array([[0, 6]])
In [233]: _.shape
Out[233]: (1, 2)
A classic way of making something 2d - reshape:
In [234]: y=np.arange(12).reshape(3,4)
In [235]: y
Out[235]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
sum (and related functions) has a keepdims parameter. Read the docs.
In [236]: y.sum(axis=1,keepdims=True)
Out[236]:
array([[ 6],
[22],
[38]])
In [237]: _.shape
Out[237]: (3, 1)
empty 2nd dimension isn't quite the terminology. More like a nonexistent 2nd dimension.
A dimension can have 0 terms:
In [238]: np.ones((2,0))
Out[238]: array([], shape=(2, 0), dtype=float64)
If you are more familiar with MATLAB, which has a minimum of 2d, you might like the np.matrix subclass. It takes steps to ensure that most operations return another 2d matrix:
In [247]: ym=np.matrix(y)
In [248]: ym.sum(axis=1)
Out[248]:
matrix([[ 6],
[22],
[38]])
The matrix sum does:
np.ndarray.sum(self, axis, dtype, out, keepdims=True)._collapse(axis)
The _collapse bit lets it return a scalar for ym.sum().

There is another point to keep dimension info:
In [42]: X
Out[42]:
array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
In [43]: X[1].shape
Out[43]: (2,)
In [44]: X[1:2].shape
Out[44]: (1, 2)
In [45]: X[1]
Out[45]: array([0, 1])
In [46]: X[1:2] # this way will keep dimension
Out[46]: array([[0, 1]])

Related

every element is 1x1 matrix in python, How do i make it so that every element is not seperate?

print(s0[3][0][0]) gives me 1
but print(s0[3][0]) gives me [1]
how do i make it so that print(s0[3][0]) gives me 1?
S0 is a numpy matrix of 100 rows
S0 =
[[[ 1. ]
[-0.91903376]
[ 0.18724527]]
[[ 1. ]
[ 0.87834638]
[-0.88794145]]
[[ 1. ]
[-0.75320818]
[ 0.59000726]]]
small sample ^
Take some time to read numpy basics. The key here is shape. You have a 3d array:
In [122]: arr = np.arange(9).reshape(3,3,1)
In [123]: arr
Out[123]:
array([[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[6],
[7],
[8]]])
In [124]: arr.shape
Out[124]: (3, 3, 1)
You can index such an array with
In [125]: arr[:,:,0]
Out[125]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [126]: _.shape
Out[126]: (3, 3)
arr[0][0][0] works, but arr[0,0,0] is clearer.
You can also get a 2d array from this with reshape (note that I used reshape to create the original array from the 1d arange array.
In [127]: arr.reshape(3,3)
Out[127]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
The display (and input) with all the [] and commas is nice for viewing arrays, but the sooner you become familiar with shape (and reshape) your numpy coding will be easier.
As mentioned above, the array S0 is a 3-d array. To get one value from this 3-d array you need to have three indices. In order to get value using two indices (S0[i][j]) you have to convert this to a 2-d array.
eg-
S1 =[[1.0, -0.91903376, 0.18724527],
[1.0, 0.87834638, -0.88794145],
[1.0, -0.75320818, 0.59000726]]
S1[0][0] now will give 1.0

Numpy: for each element in one dimension, find coordinates of maximum of sub-array

I've seen variations of this question asked a few times but so far haven't seen any answers that get to the heart of this general case. I have an n-dimensional array of shape [a, b, c, ...] . For some dimension x, I want to look at each sub-array and find the coordinates of the maximum.
For example, say b = 2, and that's the dimension I'm interested in. I want the coordinates of the maximum of [:, 0, :, ...] and [:, 1, :, ...] in the form a_max = [a_max_b0, a_max_b1], c_max = [c_max_b0, c_max_b1], etc.
I've tried to do this by reshaping my input matrix to a 2d array [b, a*c*d*...], using argmax along axis 0, and unraveling the indices, but the output coordinates don't wind up giving the maxima in my dataset. In this case, n = 3 and I'm interested in axis 1.
shape = gains_3d.shape
idx = gains_3d.reshape(shape[1], -1)
idx = idx.argmax(axis = 1)
a1, a2 = np.unravel_index(idx, [shape[0], shape[2]])
Obviously I could use a loop, but that's not very pythonic.
For a concrete example, I randomly generated a 4x2x3 array. I'm interested in axis 1, so the output should be two arrays of length 2.
testarray = np.array([[[0.17028444, 0.38504759, 0.64852725],
[0.8344524 , 0.54964746, 0.86628204]],
[[0.77089997, 0.25876277, 0.45092835],
[0.6119848 , 0.10096425, 0.627054 ]],
[[0.8466859 , 0.82011746, 0.51123959],
[0.26681694, 0.12952723, 0.94956865]],
[[0.28123628, 0.30465068, 0.29498136],
[0.6624998 , 0.42748154, 0.83362323]]])
testarray[:,0,:] is
array([[0.17028444, 0.38504759, 0.64852725],
[0.77089997, 0.25876277, 0.45092835],
[0.8466859 , 0.82011746, 0.51123959],
[0.28123628, 0.30465068, 0.29498136]])
, so the first element of the first output array will be 2, and the first element of the other will be 0, pointing to 0.8466859. The second elements of the two matrices will be 2 and 2, pointing to 0.94956865 of testarray[:,1,:]
Let's first try to get a clear idea of what you are trying to do:
Sample 3d array:
In [136]: arr = np.random.randint(0,10,(2,3,4))
In [137]: arr
Out[137]:
array([[[1, 7, 6, 2],
[1, 5, 7, 1],
[2, 2, 5, *6*]],
[[*9*, 1, 2, 9],
[2, *9*, 3, 9],
[0, 2, 0, 6]]])
After fiddling around a bit I came up with this iteration, showing the coordinates for each middle dimension, and the max value
In [151]: [(i,np.unravel_index(np.argmax(arr[:,i,:]),(2,4)),np.max(arr[:,i,:])) for i in range
...: (3)]
Out[151]: [(0, (1, 0), 9), (1, (1, 1), 9), (2, (0, 3), 6)]
I can move the unravel outside the iteration:
In [153]: np.unravel_index([np.argmax(arr[:,i,:]) for i in range(3)],(2,4))
Out[153]: (array([1, 1, 0]), array([0, 1, 3]))
Your reshape approach does avoid this loop:
In [154]: arr1 = arr.transpose(1,0,2) # move our axis first
In [155]: arr1 = arr1.reshape(3,-1)
In [156]: arr1
Out[156]:
array([[1, 7, 6, 2, 9, 1, 2, 9],
[1, 5, 7, 1, 2, 9, 3, 9],
[2, 2, 5, 6, 0, 2, 0, 6]])
In [158]: np.argmax(arr1,axis=1)
Out[158]: array([4, 5, 3])
In [159]: np.unravel_index(_,(2,4))
Out[159]: (array([1, 1, 0]), array([0, 1, 3]))
max and argmax take only one axis value, where as you want the equivalent of taking the max along all but one axis. Some ufunc takes a axis tuple, but these do not. The transpose and reshape may be the only way.
In [163]: np.max(arr1,axis=1)
Out[163]: array([9, 9, 6])

Is it bad to use numpy arrays in this way?

Main Question:
Is it bad (perhaps in terms of computation time or memory) to using np.array([[1, 2, 3]]) everywhere instead of np.array([1, 2, 3])?
Motivation:
I come form a math background, so I like to think of things in terms of vectors and matrices. For example, I think of y = np.array([1, 2, 3]) as a row vector, or as a 1 X 3 matrix. However, numpy doesn't treat y quite like a 1 X 3 matrix. For instance, if we take a 2 X 3 matrix A = np.array([[1, 2, 3], [4, 5, 6]]) numpy will allow us to do the matrix multiplicationA # y even though the dimensions are (2 X 3) times (1 X 3) don't make sense mathematically.
On the other hand, y # A.T gives an error even though the dimensions (1 X 3) times (3 X 2) make sense.
So in conclusion np.array([1, 2, 3]) does not behave exactly as a matrix. However, from my experiments it seems that numpy does treat np.array([[1, 2, 3]]) as a bona fide 1 X 3 matrix. So if there are no downsides, I would prefer to use this version.
numpy has an old subclass np.matrix that makes sure everything has exactly 2 dimensions. But it is no longer recommended.
numpy tries to work equally well with 0,1,2, and more dimensions.
In [69]: A = np.array([[1,2,3],[4,5,6]])
In [70]: x = np.array([1,2,3])
In [71]: y = np.array([[1,2,3]])
In [72]: A.shape
Out[72]: (2, 3)
Matrix product of a (2,3) with (3,) resulting a (2,). It's docs say it expands the (3,) to (3,1), getting a (2,1) result, and then squeezing out that 1:
In [73]: A#x
Out[73]: array([14, 32])
The (2,3) with (1,3) transposed produces (2,1):
In [74]: A#y.T
Out[74]:
array([[14],
[32]])
(3,) with (3,2) => (2,):
In [78]: x#A.T
Out[78]: array([14, 32])
(1,3) with (3,2) => (1,3):
In [79]: y#A.T
Out[79]: array([[14, 32]])
How does your math intuition handle 3d or higher arrays? matmul/# handles them nicely. np.einsum does even better.
While you can create a (1,n) arrays, if it makes you more comfortable. But beware that you'll still end up with 1 or even 0d results.
For example with indexing:
In [80]: A
Out[80]:
array([[1, 2, 3],
[4, 5, 6]])
In [81]: A[1,:]
Out[81]: array([4, 5, 6])
In [82]: A[:,1]
Out[82]: array([2, 5])
In [83]: A[1,1]
Out[83]: 5
In [84]: A[1,1].shape
Out[84]: ()
In [85]: A[1,1].ndim
Out[85]: 0
or reduction along an axis:
In [86]: A.sum(axis=1)
Out[86]: array([ 6, 15])
though it's possible to retain dimensions:
In [87]: A.sum(axis=1, keepdims=True)
Out[87]:
array([[ 6],
[15]])
In [88]: A[[1],:]
Out[88]: array([[4, 5, 6]])
In [89]: A[:,[1]]
Out[89]:
array([[2],
[5]])
Another to keep in mind is that numpy operators most operation element-wise. The main exception being #. Where as in MATLAB A*B is matrix multiplication, and A.*B is element-wise. Add to that broadcasting, which allows us to add a (2,3) and (3,) array:
In [90]: A+x
Out[90]:
array([[2, 4, 6],
[5, 7, 9]])
Here (2,3) + (3,) => (2,3) + (1,3) => (2,3). The (3,) 1d array often behaves as a (1,3) or even (1,1,3) if needed. But expansion in the other direction has to be explicit.
In [92]: A / A.sum(axis=1) # (2,3) with (2,) error
Traceback (most recent call last):
File "<ipython-input-92-fec3395556f9>", line 1, in <module>
A / A.sum(axis=1)
ValueError: operands could not be broadcast together with shapes (2,3) (2,)
In [93]: A / A.sum(axis=1, keepdims=True) # (2,3) with (2,1) ok
Out[93]:
array([[0.16666667, 0.33333333, 0.5 ],
[0.26666667, 0.33333333, 0.4 ]])
In [94]: A / A.sum(axis=1)[:,None]
Out[94]:
array([[0.16666667, 0.33333333, 0.5 ],
[0.26666667, 0.33333333, 0.4 ]])

Numpy indexing broadcasting introduces new dimension

I have an array I wan to use for mapping. Let's call it my_map ,type float shape (m,c).
I have a second array with indexes, lest call it my_indexes, type int size (n,c), every value is between 0 and m.
Trying to index my_map doing my_ans = my_map[my_indexes] I get an array of shape (n,c,c), when I was expecting (n,c). What would be the proper way to do it?
Just to be clear, what I am trying to do is something equivalent to:
my_ans = np.empty_like(touch_probability)
for i in range(c):
my_ans[:,i] = my_map[:,i][my_indexes[:,i]]
To illustrate and test your problem, define simple, real arrays:
In [44]: arr = np.arange(12).reshape(3,4)
In [45]: idx = np.array([[0,2,1,0],[2,2,1,0]])
In [46]: arr.shape
Out[46]: (3, 4)
In [47]: idx.shape
Out[47]: (2, 4)
Your desired calculation:
In [48]: res = np.zeros((2,4), int)
In [49]: for i in range(4):
...: res[:,i] = arr[:,i][idx[:,i]] # same as arr[idx[:,i], i]
...:
In [50]: res
Out[50]:
array([[0, 9, 6, 3],
[8, 9, 6, 3]])
Doing the same with one indexing step:
In [51]: arr[idx, np.arange(4)]
Out[51]:
array([[0, 9, 6, 3],
[8, 9, 6, 3]])
This is broadcasting the two indexing arrays against each other, and then picking points:
In [52]: np.broadcast_arrays(idx, np.arange(4))
Out[52]:
[array([[0, 2, 1, 0],
[2, 2, 1, 0]]),
array([[0, 1, 2, 3],
[0, 1, 2, 3]])]
So we are indexing the (m,c) array with 2 (n,c) arrays
The following are the same:
arr[idx]
arr[idx, :]
It is using idx to select whole rows from arr, so the result is shape of idx plus the last dimension of arr. Where as what you want is just the ith element of the idx[j,i] row.

Difference between tensor.permute and tensor.view in PyTorch?

What is the difference between tensor.permute() and tensor.view()?
They seem to do the same thing.
Input
In [12]: aten = torch.tensor([[1, 2, 3], [4, 5, 6]])
In [13]: aten
Out[13]:
tensor([[ 1, 2, 3],
[ 4, 5, 6]])
In [14]: aten.shape
Out[14]: torch.Size([2, 3])
torch.view() reshapes the tensor to a different but compatible shape. For example, our input tensor aten has the shape (2, 3). This can be viewed as tensors of shapes (6, 1), (1, 6) etc.,
# reshaping (or viewing) 2x3 matrix as a column vector of shape 6x1
In [15]: aten.view(6, -1)
Out[15]:
tensor([[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6]])
In [16]: aten.view(6, -1).shape
Out[16]: torch.Size([6, 1])
Alternatively, it can also be reshaped or viewed as a row vector of shape (1, 6) as in:
In [19]: aten.view(-1, 6)
Out[19]: tensor([[ 1, 2, 3, 4, 5, 6]])
In [20]: aten.view(-1, 6).shape
Out[20]: torch.Size([1, 6])
Whereas tensor.permute() is only used to swap the axes. The below example will make things clear:
In [39]: aten
Out[39]:
tensor([[ 1, 2, 3],
[ 4, 5, 6]])
In [40]: aten.shape
Out[40]: torch.Size([2, 3])
# swapping the axes/dimensions 0 and 1
In [41]: aten.permute(1, 0)
Out[41]:
tensor([[ 1, 4],
[ 2, 5],
[ 3, 6]])
# since we permute the axes/dims, the shape changed from (2, 3) => (3, 2)
In [42]: aten.permute(1, 0).shape
Out[42]: torch.Size([3, 2])
You can also use negative indexing to do the same thing as in:
In [45]: aten.permute(-1, 0)
Out[45]:
tensor([[ 1, 4],
[ 2, 5],
[ 3, 6]])
In [46]: aten.permute(-1, 0).shape
Out[46]: torch.Size([3, 2])
View changes how the tensor is represented. For ex: a tensor with 4 elements can be represented as 4X1 or 2X2 or 1X4 but permute changes the axes. While permuting the data is moved but with view data is not moved but just reinterpreted.
Below code examples may help you. a is 2x2 tensor/matrix. With the use of view you can read a as a column or row vector (tensor). But you can't transpose it. To transpose you need permute. Transpose is achieved by swapping/permuting axes.
In [7]: import torch
In [8]: a = torch.tensor([[1,2],[3,4]])
In [9]: a
Out[9]:
tensor([[ 1, 2],
[ 3, 4]])
In [11]: a.permute(1,0)
Out[11]:
tensor([[ 1, 3],
[ 2, 4]])
In [12]: a.view(4,1)
Out[12]:
tensor([[ 1],
[ 2],
[ 3],
[ 4]])
In [13]:
Bonus: See https://twitter.com/karpathy/status/1013322763790999552
tensor.permute() permutes the order of the axes of a tensor.
tensor.view() reshapes the tensor (analogous to numpy.reshape) by reducing/expanding the size of each dimension (if one increases, the others must decrease).
The link gives a clear explanation about view, reshape, and permute:
view works on contiguous tensors.
reshape works on non-contigous tensors.
permute returns a view of the original tensor input with its dimensions permuted. It is quite different to view and reshape.

Categories

Resources