numpy的reshape和transpose机制解释
文章目录
- ndarray的base和strides属性
- base
- strides
- reshape
- transpose
- 总结
reshape和transpose都是非常高效的算子,究其原因,是因为二者均没有在内存中重新排列数据,只是对数据的shape或strides等信息进行了改变。下面分别简介。
ndarray的base和strides属性
为了更好地理解reshape和transpose算子,需要对ndarray的shape, base, strides
三个属性有所了解,其中shape很容易理解,就不多说了,下面简单介绍一下base和strides。
base
base参考:https://numpy.org/doc/stable/reference/generated/numpy.ndarray.base.html
如果一个ndarray是通过其他ndarray经过某种操作创建出来的,那么其base就会指向最初的源头。
比如下面例子中,a
是b, c
的源头,所以b.base 和 c.base
都等于a
,而a
本身没有base,所以是None。
import numpy as npa = np.array([0, 1, 2, 3, 4, 5])
print(a) # ==> [0 1 2 3 4 5]
print(a.base) # ==> Noneb = a.reshape([2, 3])
print(b) # ==>
# [[0 1 2]
# [3 4 5]]
print(b.base) # ==> [0 1 2 3 4 5]c = b.transpose([1, 0])
print(c) # ==>
# [[0 3]
# [1 4]
# [2 5]]
print(c.base) # ==> [0 1 2 3 4 5]
strides
strides参考:https://numpy.org/doc/stable/reference/generated/numpy.ndarray.strides.html
ndarray的每一个维度(axis)都有一个strides,表示从数组在某个维度进行遍历的内存偏移量
。
比如在下面的例子中,数组a
三个维度的strides分别是(48, 16, 4)
,意思是:
- 从
a[0, 0, 0]
到a[0, 0, 1] = 1
的内存偏移量是4字节,1个int型数字是4字节 - 从
a[0, 0, 0]
到a[0, 1, 0] = 4
的内存偏移量是16字节,因为需要偏移4个int型数字 - 从
a[0, 0, 0]
到a[1, 0, 0] = 12
的内存偏移量是48字节,因为需要偏移12个int型数字
import numpy as npa = np.arange(24).reshape([2, 3, 4])print(a.strides) # ==> (48, 16, 4)
print(a) # ==>
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]
reshape
reshape仅仅只是改变了数组的shape属性,比如把shape从(4,)(4,)(4,)改成(2,2)(2,2)(2,2)。通过下面的测试代码,可以明白reshape的下列性质:
- 如果我们从最后一个维度开始,依次向前循环打印数组的话,会发现无论怎么样reshape,数组打印的顺序不会发生任何变化。也就是说无论reshape多少次,数组打印顺序不变。
- 类似于python的浅拷贝,reshape之后,尽管变量发生了变化,但是变量内的数据体却未被碰过。下面列子中,改变reshape后的
b
的第一个值,发现所有相关的变量的第一个值都发生了变化,所以就可以知道,经reshape后,变量用于保存数据的那块内存没有被碰过。
import numpy as npa = np.arange(4) # a = torch.arange(4)
print(a) # ==> [0 1 2 3]
print(a.shape) # ==> (4,)b = a.reshape([2, 2]) # b = a.reshape([2, 2])
print(b) # ==> [[0 1], [2 3]]
print(b.shape) # ==> (2, 2)c = b.reshape([-1]) # c = torch.reshape(b, [-1])
print(c) # ==> [0 1 2 3]b[0, 0] = 100
print(a) # ==> [100 1 2 3]
print(b) # ==> [[100 1], [2 3]]
print(c) # ==> [100 1 2 3]
transpose
transpose改变了数组的维度(axis)排列顺序。比如对于二维数组,如果我们把两个维度的顺序互换,那就是我们很熟悉的矩阵转置。而transpose可以在更多维度的情况下生效。transpose的入参是输出数组的维度排列顺序,序号从0开始计数。
下面例子中我们改变了transpose后的b
的第一个元素的值,发现a
也随之改变,说明transpose也没有去碰数组的内存。那么问题来了,既然数组没有在内存中重新排列,那么打印顺序是受什么影响而发生了改变呢?是strides。
import numpy as npa = np.arange(24).reshape([2, 3, 4])
print(a.base) # ==>
# [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]print(a.shape) # ==> (2, 3, 4)
print(a.strides) # ==> (48, 16, 4)
print(a) # ==>
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]b = a.transpose([1, 2, 0])
print(b.shape) # ==>(3, 4, 2)
print(b.strides) # ==> (16, 4, 48)
print(b) # ==>
# [[[ 0 12]
# [ 1 13]
# [ 2 14]
# [ 3 15]]
#
# [[ 4 16]
# [ 5 17]
# [ 6 18]
# [ 7 19]]
#
# [[ 8 20]
# [ 9 21]
# [10 22]
# [11 23]]]b[0, 0, 0] = 100
print(a) # ==>
# [[[100 1 2 3]
# [ 4 5 6 7]
# ...]]]print(b) # ==>
# [[[100 12]
# [ 1 13]
# ...]]]
下面图示一下strides的含义。
首先明确一个很重要的概念,strides都是相对于base数组而言进行遍历的,所以无论是a
还是b
,遍历时需要参考的源头都是a.base / b.base
,也就是最上面的一维数组。
数组a
的strides情况我们前面已经讲过了,接下来主要看看b
。
- 由于b.strides最后一个维度的值是48,所以
b[0, 0, 1]
是b[0, 0, 0]
在b.base
中偏移48字节后的数字,也就是12
。 - b.strides中间维度的值是4,所以
b[0, 1, 0]
是b[0, 0, 0]
在b.base
中偏移4字节后的数字,也就是1
。 - b.strides第一个维度的值是16,所以
b[1, 0, 0]
是b[0, 0, 0]
在b.base
中偏移16字节后的数字,也就是4
。
所以ranspose操作只是改变了strides的顺序,没有重新排列内存中的数据。
总结
前面我们在解释reshape和transpose的机制时,分别从ndarray的shape和strides属性进行了侧重解释。实际上reshape既改变shape也改变strides,而transpose也可能会改变shape。
但这两个算子均不会在内存中重新排列数据。
numpy的reshape和transpose机制解释相关推荐
- numpy reshape和transpose的使用
numpy reshape和transpose的使用 不熟悉numpy的时候,看到别人代码中的reshape和transpose不太懂,这里转载一下别人的解释,很强! Python numpy.tra ...
- Numpy和Opencv中的reshape 和 transpose的区别
Numpy和Opencv中的reshape 和 transpose的区别 在Numpy和Opencv中,都有两个函数:reshape 和 transpose. 该两个函数都具有改变维度的作用,在使用中 ...
- Python精讲Numpy基础,大牛笔记详细解释
https://www.toutiao.com/a6664936105076326920/ 总认为Numpy是渣渣,直到深入接触以后才知道功能这么强大.堪比Matlab啊.果然是人生苦短,我用Pyth ...
- numpy中的转置Transpose和.T以及轴对换swapaxis
简 介: 本文对于 numpy中的转置Transpose和.T以及轴对换swapaxis 中关于numpy矩阵的轴交换函数进行了测试.并对于深度学习中的图像数据进行处理. 参考文章:https://b ...
- matlab imcrop 对应python函数_Python精讲Numpy基础,大牛笔记详细解释
总认为Numpy是渣渣,直到深入接触以后才知道功能这么强大.堪比Matlab啊.果然是人生苦短,我用Python.所以本文作为一个记录&笔记,文章内容大多数取自网络以&官网快速入门等, ...
- pythonnumpy详解_Python精讲Numpy基础,大牛笔记详细解释
以前总认为Numpy是渣渣,直到深入接触以后才知道功能这么强大.堪比Matlab啊.果然是人生苦短,我用Python.所以本文作为一个记录&笔记,文章内容大多数取自网络以&官网快速入门 ...
- 利用Python中的numpy.ndarray.reshape()对阵列形状进行调整
我们在进行阵列运算的时候,常常要根据需要调整阵列的形状,numpy库中的函数reshape()可以方便地实现对阵列形状进行调整. 其函数原型如下: dst = numpy.ndarray.reshap ...
- numpy中reshape方法详解
numpy中reshape方法详解_zhanggonglalala的博客-CSDN博客_reshape
- pythonreshape函数三个参数_Python Numpy中reshape函数参数-1的含义
python numpy中reshape函数参数-1的含义,新数组的shape属性应该要与原来数组的一致,即新数组元素数量与原数组元素数量要相等.一个参数为-1时,那么reshape函数会根据另一个参 ...
最新文章
- 链接1: 学习Python以及SQL的好去处----仅链接
- 【每日一算法】买卖股票的最佳时机
- 整个世界都是你的绿幕:这个视频抠图换背景的方法着实真假难辨
- 如何快速成长为技术大牛?
- tinycore php,tinycore中文支持
- html中.inner样式,JavaScript-DOM动态控制Html标签对象样式和innerHTML、className属性
- 删除同目录下面txt文件(利用os,fnmacth模块)
- 域做文件服务器,linux 做域文件服务器
- Android 代码关于重构的一点体会
- 继承与data member之多重继承
- 中国大学MOOC伦理学试题题库及答案
- hashmap java 排序_Java HashMap 默认排序
- 有效地报告自动测试结果
- 3月4日 与柳传志面对面(谁是这个时代的思想家)
- 哪一款蓝牙耳机音质最好?2023发烧级音质蓝牙耳机推荐
- linux gic驱动
- Colab 上使用shutil.copytree()复制整个文件夹到另一个文件夹
- Qt实现天气信息显示和温度曲线绘制
- 安装python3.10.1教程
- linux内net.ipv4.tcp_tw_recycle参数一定不要启用