How does NumPy's transpose() method permute the axes of an array?

别说谁变了你拦得住时间么 提交于 2019-11-26 08:45:46

问题


In [28]: arr = np.arange(16).reshape((2, 2, 4))

In [29]: arr
Out[29]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])


In [32]: arr.transpose((1, 0, 2))
Out[32]: 
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

When we pass a tuple of integers to the transpose() function, what happens?

To be specific, this is a 3D array: how does NumPy transform the array when I pass the tuple of axes (1, 0 ,2)? Can you explain which row or column these integers refer to? And what are axis numbers in the context of NumPy?


回答1:


To transpose an array, NumPy just swaps the shape and stride information for each axis. Here are the strides:

>>> arr.strides
(64, 32, 8)

>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)

Notice that the transpose operation swapped the strides for axis 0 and axis 1. The lengths of these axes were also swapped (both lengths are 2 in this example).

No data needs to be copied for this to happen; NumPy can simply change how it looks at the underlying memory to construct the new array.


Visualising strides

The stride value represents the number of bytes that must be travelled in memory in order to reach the next value of an axis of an array.

Now, our 3D array arr looks this (with labelled axes):

This array is stored in a contiguous block of memory; essentially it is one-dimensional. To interpret it as a 3D object, NumPy must jump over a certain constant number of bytes in order to move along one of the three axes:

Since each integer takes up 8 bytes of memory (we're using the int64 dtype), the stride value for each dimension is 8 times the number of values that we need to jump. For instance, to move along axis 1, four values (32 bytes) are jumped, and to move along axis 0, eight values (64 bytes) need to be jumped.

When we write arr.transpose(1, 0, 2) we are swapping axes 0 and 1. The transposed array looks like this:

All that NumPy needs to do is to swap the stride information for axis 0 and axis 1 (axis 2 is unchanged). Now we must jump further to move along axis 1 than axis 0:

This basic concept works for any permutation of an array's axes. The actual code that handles the transpose is written in C and can be found here.




回答2:


As explained in the documentation:

By default, reverse the dimensions, otherwise permute the axes according to the values given.

So you can pass an optional parameter axes defining the new order of dimensions.

E.g. transposing the first two dimensions of an RGB VGA pixel array:

 >>> x = np.ones((480, 640, 3))
 >>> np.transpose(x, (1, 0, 2)).shape
 (640, 480, 3)



回答3:


In C notation, your array would be:

int arr[2][2][4]

which is an 3D array having 2 2D arrays. Each of those 2D arrays has 2 1D array, each of those 1D arrays has 4 elements.

So you have three dimensions. The axes are 0, 1, 2, with sizes 2, 2, 4. This is exactly how numpy treats the axes of an N-dimensional array.

So, arr.transpose((1, 0, 2)) would take axis 1 and put it in position 0, axis 0 and put it in position 1, and axis 2 and leave it in position 2. You are effectively permuting the axes:

0 -\/-> 0
1 -/\-> 1
2 ----> 2

In other words, 1 -> 0, 0 -> 1, 2 -> 2. The destination axes are always in order, so all you need is to specify the source axes. Read off the tuple in that order: (1, 0, 2).

In this case your new array dimensions are again [2][2][4], only because axes 0 and 1 had the same size (2).

More interesting is a transpose by (2, 1, 0) which gives you an array of [4][2][2].

0 -\ /--> 0
1 --X---> 1
2 -/ \--> 2

In other words, 2 -> 0, 1 -> 1, 0 -> 2. Read off the tuple in that order: (2, 1, 0).

>>> arr.transpose((2,1,0))
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])

You ended up with an int[4][2][2].

You'll probably get better understanding if all dimensions were of different size, so you could see where each axis went.

Why is the first inner element [0, 8]? Because if you visualize your 3D array as two sheets of paper, 0 and 8 are lined up, one on one paper and one on the other paper, both in the upper left. By transposing (2, 1, 0) you're saying that you want the direction of paper-to-paper to now march along the paper from left to right, and the direction of left to right to now go from paper to paper. You had 4 elements going from left to right, so now you have four pieces of paper instead. And you had 2 papers, so now you have 2 elements going from left to right.

Sorry for the terrible ASCII art. ¯\_(ツ)_/¯




回答4:


To summarise a.transpose()[i,j,k] = a[k,j,i]

a = np.array( range(24), int).reshape((2,3,4))
a.shape gives (2,3,4)
a.transpose().shape gives (4,3,2)  shape tuple is reversed.

when is a tuple parameter is passed axes are permuted according to the tuple. For example

a = np.array( range(24), int).reshape((2,3,4))

a[i,j,k] equals a.transpose((2,0,1))[k,i,j]

axis 0 takes 2nd place

axis 1 takes 3rd place

axis 2 tales 1st place

of course we need to take care that values in tuple parameter passed to transpose are unique and in range(number of axis)



来源:https://stackoverflow.com/questions/32034237/how-does-numpys-transpose-method-permute-the-axes-of-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!