关于NumPy中tanspose函数的理解
tanspose函数高维数组的转置,有时候比较费脑子,这里对于三维转置,想了一种取巧的快捷理解和推导方式,仅供参考。
In [2]: import numpy as np
In [3]: arr = np.arange(16).reshape((2,2,4))
In [4]: arrr
Out[4]:array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
以上可以理解成什么呢?
这个图可以辅助想象下,.reshape(2,2,4)函数的在0轴上切成两片(数值小于7.5的那些方格,和数值大于7.7的一部分),1轴上分成两列,每列再2轴上按次序排了四个。上面是由外向内的理解
那么由内向外写上面的代码的结果,就是先写最内层为2轴的,那么就是
[0,1,2,3]
然后2轴是在1轴上扩展的,我们把扩展的第二部分[4,5,6,7]加上
他们构成0轴上的第一部分:
[[0,1,2,3],[4,5,6,7]]
同理,0轴上第二部分
[[8,9,10,11],[12,13,14,15]]
最后将0轴两部分组合一下:
[[[0,1,2,3],[4,5,6,7]],
[[8,9,10,11],[12,13,14,15]]]
这么从内向外来写出来就比较明了。
那么我们按照上面的方法看下下面这个代码:
In [6]: arr.transpose((1,0,2))
Out[6]:array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
这个函数
.transpose((1,0,2))
就是把0和1轴上转置了,2轴不动。
画出图来如下:仅仅0,1互换
同样按照上面的次序,先写最里层的2轴的
还是第一组
[0,1,2,3]
接下来有点变化了,因为我们要写在1轴上的扩展,这个时候不是4567了,因为那是在0轴上了,这个时候1轴上扩展的是
[8,9,10,11]
他们组成一个大组:
[[0,1,2,3],[8,9,10,11]]
同样的这个大组会最后在0轴上扩展:
[[4,5,6,7],[12,13,14,15]]
最后两个大组合起来:
[[[0,1,2,3],[8,9,10,11]],
[[4,5,6,7],[12,13,14,15]]]
形象地可以理解成一个三维的豆腐大块,切三刀,按照2轴,1轴,0轴的次序,由内往外拿出来。
那么有人可能想,不是每次都要这么画个三维图来推导结果吧?
熟练了可以直接看着初始的模样直接写转置的模样:
我们还是先看下这个初始样子
Out[4]:array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
就是下面这张图片:
那么如果我们写一个
arr.transpose((2,1,0))
的结果呢?那就是把2,0轴对调下:
先写2轴:
[0,8]
在1轴上的扩展后:
[[0,8],[4,12]]
再在0轴扩展:
[
[[0,8],[4,12]],
[[1,9],[5,13]],
[[2,10],[6,,14]],
[[3,11],[7,15]]
]
看下代码执行出来的结果:
In [7]: arr.transpose((2,1,0))
Out[7]:array([[[ 0, 8],
[ 4, 12]],
[[ 1, 9],
[ 5, 13]],
[[ 2, 10],
[ 6, 14]],
[[ 3, 11],
[ 7, 15]]])
同样地,你也按照上面的方式试下推导下下面的结果呢?
arr.transpose((0,2,1))
结果是不是和下面的一样呢?
In [8]: arr.transpose((0,2,1))
Out[8]:array([[[ 0, 4],[ 1, 5],[ 2, 6],[ 3, 7]],[[ 8, 12],[ 9, 13],[10, 14],[11, 15]]])
最后,也看到有人是按照空间坐标系的方式,把每个位置的转成轴的元组值,轴转置后,对应换掉元组值,然后找寻对应的最开始的数值,最后再按照转置后的shape,来码出来结构。
这样也是理解的一种方式,可能思维理解上更为准确。
只是个人觉得那样不够直观,不够快捷。
这里想的豆腐块理论,2轴1轴0轴从内往外拿取的思路和方法可能不够严谨,或者思维方式上走了偏锋,走了治标的路子,但是多少也是一种理解,如果不习惯,还是按照自己原本的理解就好。