[PYTHON] numpy memorandum 2 / transpose doesn't just swap rows and columns

1.First of all

I didn't understand how to use transepose in detail, so I will leave the result of my investigation as a memorandum.

2.2 dimensional array

import numpy as np

img = np.array([[ 0,  1],
                [ 2,  3]])

img = img.transpose(1,0)
print(img)

# [[0 2]
#  [1 3]]

No conversion is transpose (0, 1) and the axis numbers are ** x-axis (0), y-axis (1) **. With transpose (1, 0), the x-axis (0) and y-axis (1) are swapped, resulting in a so-called transpose matrix.

3.3 dimensional array

img = np.array([[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]])

img = img.transpose(0, 2, 1)
print(img)

# [[[ 0  3  6]
#   [ 1  4  7]
#   [ 2  5  8]]

#  [[ 9 12 15]
#   [10 13 16]
#   [11 14 17]]]

No conversion is transpose (0, 1, 2), and the axis numbers are ** channel axis (0), x axis (1), y axis (2) ** (channel axis is a name given appropriately). is). Note that the x-axis and y-axis axis numbers change according to the number of dimensions.

transpose (0, 2, 1) swaps the x-axis (1) and y-axis (2).

img = np.array([[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]])

img = img.transpose(1, 0, 2)
print(img)

# [[[ 0  1  2]
#   [ 9 10 11]]

#  [[ 3  4  5]
#   [12 13 14]]

#  [[ 6  7  8]
#   [15 16 17]]]

Bringing transpose (1, 0, 2) and the x-axis (1) in front of the channel axis (0), it used to be ** processing in each matrix **, but ** matrix Processing between **. Make one matrix in the 0th row, 1 matrix in the 1st row, and 1 matrix in the 2nd row of 2 matrices.

img = np.array([[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]])

img = img.transpose(2, 0, 1)
print(img)

# [[[ 0  3  6]
#   [ 9 12 15]]

#  [[ 1  4  7]
#   [10 13 16]]

#  [[ 2  5  8]
#   [11 14 17]]]

Bringing transpose (2, 0, 1) and the y-axis (2) in front of the channel axis (0) will result in inter-matrix processing as before. This time, make one matrix in the 0th column of the two matrices, 1 matrix in the 1st column, and 1 matrix in the 2nd column.

img = np.array([[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]])

img = img.transpose(1, 2, 0)
print(img)

# [[[ 0  9]
#   [ 1 10]
#   [ 2 11]]

#  [[ 3 12]
#   [ 4 13]
#   [ 5 14]]

#  [[ 6 15]
#   [ 7 16]
#   [ 8 17]]]

Now, what if we bring both transpose (1, 2, 0) and x-axis (1), y-axis (2) in front of channel axis (0)? ** Skewer the values of the same coordinates in each matrix **.

This time, the x-axis (0) is the first (priority), so the 0th row is skewered to make one matrix, the 1st row is skewered to make one matrix, and the 2nd row is skewered to make one matrix. Make a line.

img = np.array([[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]])

img = img.transpose(2, 1, 0)
print(img)

# [[[ 0  9]
#   [ 3 12]
#   [ 6 15]]

#  [[ 1 10]
#   [ 4 13]
#   [ 7 16]]

#  [[ 2 11]
#   [ 5 14]
#   [ 8 17]]]

This time, if you bring transpose (2, 1, 0) and the y-axis (2) to the beginning, the y-axis (2) will take precedence, and the 0th column will be skewered to make one matrix. The first row is skewered to make one matrix, and the second row is skewered to make one matrix.

4D array

It's finally 4 dimensions. I will explain only one notable example.

img = np.array([
               [[[ 0, 1, 2],
                 [ 3, 4, 5],
                 [ 6, 7, 8]],
    
                [[ 9,10,11],
                 [12,13,14],
                 [15,16,17]]],
               
               [[[18,19,20],
                 [21,22,23],
                 [24,25,26]],
    
                [[27,28,29],
                 [30,31,32],
                 [33,34,35]]]
                ])

img = img.transpose(2, 3, 0, 1)
print(img)

# [[[[ 0  9]
#    [18 27]]

#   [[ 1 10]
#    [19 28]]

#   [[ 2 11]
#    [20 29]]]

#  [[[ 3 12]
#    [21 30]]

#   [[ 4 13]
#    [22 31]]

#   [[ 5 14]
#   [23 32]]]

#  [[[ 6 15]
#    [24 33]]

#   [[ 7 16]
#    [25 34]]

#   [[ 8 17]
#    [26 35]]]]

No conversion is transpose (0, 1, 2, 3) and the axis numbers are ** batch axis (0), channel axis (1), x axis (2), y axis (3) ** ( The batch axis and channel axis are named appropriately).

If you do transpose (2, 3, 0, 1) in a 4-dimensional array, the same coordinates of each matrix are skewered in the same way as in a 3-dimensional array, but the unit of aggregation is not a row but a coordinate unit. It becomes. Then, the coordinates are 0 rows and 0 columns, 0 rows and 1 column, 0 rows and 2 columns, 1 row and 0 columns, and so on.

In the case of transpose (3, 2, 0, 1), the order in which the coordinates advance is changed to 0 row 0 column, 1 row 0 column, 2 row 0 column, 0 row 1 column, ... Is the same.

4. Actual usage example

A simple sample will explain an example in which transpose is used in an algorithm called im2col that performs convolution operations at high speed. スクリーンショット 2020-02-08 11.32.22.png How can I convert from the four matrices on the left to the matrix on the right?

img = np.array([
               [[[ 0, 1, 2],
                 [ 4, 5, 6],
                 [ 8, 9, 0]],
    
                [[ 1, 2, 3],
                 [ 5, 6, 7],
                 [ 9, 0, 1]]],
               
               [[[ 4, 5, 6],
                 [ 8, 9, 0],
                 [ 2, 3, 4]],
    
                [[ 5, 6, 7],
                 [ 9, 0, 1],
                 [ 3, 4, 5]]]
                ])

print('img.shape = ',img.shape)
img = img.transpose(2, 3, 0, 1)
print(img)

# img.shape =  (2, 2, 3, 3)

# [[[[0 1]
#    [4 5]]

#   [[1 2]
#    [5 6]]

#   [[2 3]
#    [6 7]]]

#  [[[4 5]
#    [8 9]]

#  [[5 6]
#    [9 0]]

#   [[6 7]
#    [0 1]]]

#  [[[8 9]
#    [2 3]]

#   [[9 0]
#    [3 4]]

#   [[0 1]
#   [4 5]]]]

That's right. If you use transpose (2, 3, 0, 1) earlier, you can skewer each coordinate and group it in coordinate units. After that, if you apply a reshape,

img = img.reshape(9, -1)
print(img)

# [[ 0  9 18 27]
#  [ 3 12 21 30]
#  [ 6 15 24 33]
#  [ 1 10 19 28]
#  [ 4 13 22 31]
#  [ 7 16 25 34]
#  [ 2 11 20 29]
#  [ 5 14 23 32]
#  [ 8 17 26 35]]

It's done! Reshape (9, -1) is a way of writing in a format that decides only 9 lines and then automatically reshapes (useful when the array is very large), and of course reshape (9, 4) is also OK.

After all, the previous process can be represented by just one line, ** transpose (2, 3, 0, 1) .reshape (9, -1) **. As expected, numpy.

Recommended Posts

numpy memorandum 2 / transpose doesn't just swap rows and columns
[Python] Swapping rows and columns in Numpy data
Add totals to rows and columns in pandas