【阅读笔记(一)】Numpy与Tensor

学习前言

相关知识框架的搭建首先是根据《深度学习入门之基于Python的理论与实现》这本书的指引形成的,作者斋藤康毅,该书深入浅出地剖析了深度学习的原理与相关技术,书中使用Python3,没有涉及相关框架,尽量不依赖外部库或工具,从理论的理解到代码的实践。同时与Pytorch框架对比学习,理解更加容易。

该书PDF链接:https://pan.baidu.com/s/1-hzaHbKwO0mg_VmO-D-aBw
提取码:bi1j

Numpy

Numpy是什么

Numpy是Python的一个科学计算库,支持大型多维数组对象和各种工具,数组是某类型元素的集合,可以有一个或多个维度。数学上一维数组称为向量,二维数组称为矩阵,将三维数组及三位以上的数组称为张量。且矩阵两个轴索引,行为0,列为1。

  1. Numpy的核心数据结构,就叫做array/数组,array对象可以是一维数组,也可以是多维数组;
  2. Python的List也可以实现相同的功能,但是array比List的优点在于性能好、包含数组元数据信息、大量的便捷函数
  3. Numpy的array存储相同类型和大小的元素,这也是Numpy高性能的一个原因,而Python的List可以放任何数据类型。

array的属性

shape:维度
ndim:维度的数目
size:该array中数据元素的数目
dtype:array中元素的数据类型
在这里插入图片描述

创建array的方法

arange、ones、ones_like、zeros、zeros_like、empty、empty_like、full、full_like、random

对array索引查询

三种索引方法:
基础索引:使用单个数字或切片,对一维或二维数组进行索引。

单个字符则单个数字,多行多列则切片。

神奇索引:使用列表直接指定对行和列进行查询。

筛选多行,列可以省略;筛选多列,行不能省略。

布尔索引:通过条件判断查询出符合条件的行列,并以此进行索引。

Pytorch中的张量Tensor

Tensor与Numpy的ndarrays非常类似,相互之间也可以相互转换。
Tensor有多种创建方法,如基础的构造函数Tensor(),还有多种与NumPy十分类似的方法,如ones()、eye()、zeros()和randn()等。
Tensor的多种创建方法

扫描二维码关注公众号,回复: 12664697 查看本文章
  1. 对于Tensor的维度,可使用Tensor.shape或者size()函数查看每一维的大小,两者等价。
  2. 查看Tensor中的元素总个数,可使用Tensor.numel()或者Tensor.nelement()函数,两者等价。

Tensor的组合与分块

组合操作是指将不同的Tensor叠加起来,主要有torch.cat()和torch.stack()两个函数。

cat是指沿着已有的数据的某一维度进行拼接,操作后数据的总维数不变,在进行拼接时,除了拼接的维度之外,其他维度必须相同。而torch.stack()函数指新增维度,并按照指定的维度进行叠加。

分块则是与组合相反的操作,指将Tensor分割成不同的子Tensor,主要有torch.chunk()与torch.split()两个函数。

前者需要指定分块的数量,而后者则需要指定每一块的大小,以整型或者list来表示。

Tensor的索引与变形

索引操作与NumPy非常类似,主要包含下标索引(相当于Numpy中的基础索引)、表达式索引(相当于Numpy中的布尔索引)、使用torch.where()与Tensor.clamp()的选择性索引。

变形操作则是指改变Tensor的维度,以适应在深度学习的计算中,数据维度经常变换的需求,是一种十分重要的操作。在PyTorch中主要有4类不同的变形方法。
在这里插入图片描述

  1. view()、resize()和reshape()函数(resize已弃用)
    view()、resize()和reshape()函数可以在不改变Tensor数据的前提下任意改变Tensor的形状,必须保证调整前后的元素总数相同,并且调整前后共享内存,三者的作用基本相同。
    如果想要直接改变Tensor的尺寸,可以使用resize_()的原地操作(即直接对当前Tensor进行操作)函数。在resize_()函数中,如果超过了原Tensor的大小则重新分配内存,多出部分置0,如果小于原Tensor大小则剩余的部分仍然会隐藏保留。

  2. transpose()和permute()函数
    transpose()函数可以将指定的两个维度的元素进行转置,而permute()函数则可以按照给定的维度进行维度变换,比如规定按照第0、2、1的维度顺序重新进行元素排列。

  3. squeeze()和unsqueeze()函数
    在实际的应用中,经常需要增加或减少Tensor的维度,尤其是维度为1的情况,这时候可以使用squeeze()与unsqueeze()函数,前者用于去除size为1的维度,而后者则是将指定的维度的size变为1。

  4. expand()和expand_as()函数
    有时需要采用复制元素的形式来扩展Tensor的维度,这时expand就派上用场了。expand()函数将size为1的维度复制扩展为指定大小,也可以使用expand_as()函数指定为示例Tensor的维度。

注意:在进行Tensor操作时,有些操作如transpose()、permute()等可能会把Tensor在内存中变得不连续,而有些操作如view()等是需要Tensor内存连续的,这种情况下需要使用contiguous()操作先将内存变为连续的。

Tensor的排序与取极值

比较重要的是排序函数sort(),选择沿着指定维度进行排序,返回排序后的Tensor及对应的索引位置。max()与min()函数则是沿着指定维度选择最大与最小元素,返回该元素及对应的索引位置。

eg:按第0维即按行排序,则每一列进行比较

对于Tensor的单元素数学运算,如abs()、sqrt()、log()、pow()和三角函数等,都是逐元素操作(element-wise),输出的Tensor形状与原始Tensor形状一致。

对于类似求和、求均值、求方差、求距离等需要多个元素完成的操作,往往需要沿着某个维度进行计算,在Tensor中属于归并操作,输出形状小于输入形状。与NumPy极为相似。

Tensor的自动广播机制与向量化

自动广播语义,即不同形状的Tensor进行计算时,可自动扩展到较大的相同形状,再进行计算,这与Numpy也是相同的,在《深度学习入门之基于Python的理论与实现》的1.5.5章节也有详细说明。广播机制的前提是任一个Tensor至少有一个维度,且从尾部遍历Tensor维度时,两者维度必须相等,其中一个要么是1要么不存在。

向量化操作是指可以在同一时间进行批量地并行计算,例如矩阵运算,以达到更好的计算效率的一种方式。在实际使用时,应尽量使用向量化直接对Tensor操作,避免低效率的for循环对元素逐个操作,尤其是在训练网络模型时,如果有大量的for循环,会极大地影响训练的速度。

Tensor的内存共享

为了实现高效计算,PyTorch提供了一些原地操作运算,即in-place operation,不经过复制,直接在原来的内存上进行计算。对于内存的共享,主要有如下3种情况。
在这里插入图片描述

  1. 通过Tensor初始化Tensor
    直接通过Tensor来初始化另一个Tensor,或者通过Tensor的组合、分块、索引、变形操作来初始化另一个Tensor,则这两个Tensor共享内存。

  2. 原地操作符
    PyTorch对于一些操作通过加后缀“”实现了原地操作,如add()和resize_()等,这种操作只要被执行,本身的Tensor则会被改变。

  3. Tensor与NumPy转换
    Tensor与NumPy可以高效地进行转换,并且转换前后的变量共享内存。在进行PyTorch不支持的操作时,甚至可以曲线救国,将Tensor转换为NumPy类型,操作后再转为Tensor。

总结

Numpy和Tensor有许多相似,对于Tensor的求导等问题将结合其原理总结。

参考

《深度学习入门之基于Python的理论与实现》 斋藤康毅
《深度学习之Pytorch物体检测实战》 董洪义

猜你喜欢

转载自blog.csdn.net/weixin_44164333/article/details/114287349
今日推荐