首页 > 其他分享 >Pytorch学习笔记(一)

Pytorch学习笔记(一)

时间:2024-03-22 15:58:45浏览次数:31  
标签:dim 元素 tensor torch 笔记 学习 Pytorch 构建 Tensor

一、Tensor

1.1 基本概念

Tensor,又名张量,是pytorch中重要的一种数据结构,从工程的角度上来说,可以很简单将其认为是与numpy的nadarray类似的数组,用来保存数据支持高效的科学计算。但是PyTorch中的Tensor支持cuda用GPU加速。

1.2基本操作

从接口的角度来说,对tensor的操作可以分为两类:

(1)torch.function,如torch.save等。

(2)tensor.function,如tensor.view等。

实际上,这两种操作大部分时候等价,只是调用的API不同,做为初学者一般可以不予区分。

从储存的角度来说,对tensor的操作也可以分为两类:

(1)不修改自身的数据,如a.add(b),该操作不会修改a中数据,而是将加法结果返回一个新的tensor。

(2)修改自身的数据,如a.add_(b),该操作会将加法结果储存在a当中,将a原本的数据修改为加法的结果。

实际上,可观察到函数尾有_后缀的都是会修改自身的数据,应用时注意加以区分。

1.3创建Tensor

表1-1 新建tensor的常见方式
Tensor(*sizes)基础构建函数

ones(*sizes)

构建一个全为1的Tensor
zeros(*sizes)构建一个全为0的Tensor
eye(*sizes)构建一个对角矩阵Tensor
arange(s, e, step)构建一个从s到e,步长为step的Tensor
linspace(s ,e, steps)从s到e,均匀切成steps份
rand/randn(*sizes)构建一个均匀/标准分布Tensor
normal(mean, std)/uniform(from, to)构建一个正态/均匀分布Tensor
randperm(m)构建一个随机排列Tensor

下面举几个构建Tensor的例子:

#指定tensor的形状
a = torch.Tensor(2, 3)
#数值决定于当前内存空间的状态,会生成一个2x3大小的Tensor

#用list的数据创建tensor
b = torch.Tensor([1, 2, 3], [4, 5, 6])
#会生成一个2x3大小的Tensor,其中数据按照123456排序

如果要查看tensor的size,使用tensor.size()函数,如:

b = torch.tensor(2, 3)
b_size = b.size()#此函数返回torch.Size([2, 3])其中list[2, 3]表示b为2x3的Tensor
#注:虽然b.size()返回tuple子类数据,但是对其的操作方式与tuple有所区别
b_all_number = b.numel()#此函数可以统计b中所有元素的个数,相当于b.nelement()

 下面说明torch.Size对象与tuple的不同。

#要创建一个大小与b相同的数组c
c = torch.Tensor(b.size())
#若使用tuple
d = torch.Tensor((2, 3))

#查看c,d的结果可以看到c是一个2x3大小的Tensor,而d会生成一个元素为2和3的2大小的Tensor

当然除了tensor.size()函数,tensor.shape()函数也可以直接查看torch的形状大小。

其他构建tensor的方法:

#构建大小为2x3,元素全为1的tensor
a = torch.ones(2, 3)

#构建大小为2x3,元素全为0的tensor
b = torch.zeros(2, 3)

#构建从1到6,步长为2的tensor
c = torch.arrage(1, 6, 2)

#将1到10分割平均分割成3份,得到size是3,元素为1.0000, 5.0000, 10.0000的tensor
d = torch.linspace(1, 10, 3)

#构建大小为2x3,元素为标准分布的tensor
e = torch.randn(2, 3)

#构建长度为5的随机排列tensor
f = torch.randperm(5)

#构建大小为2x3,对角线元素为1,其他全为0的tensor
g = torch.eyes(2, 3)

1.4常见tensor操作

1.4.1变形操作

通过tensor.view可以改变tenosr的形状,但是必须保证调整前后元素总数一致,如2x3只能变成1x6或者6x1或者3x2。同时veiw不会改变自身的数据,返回的新的tensor与原来的tensor共享内存。

#构建一个2x3的tensor
a = torch.arrange(0, 6).view(2, 3)

#当某一维是-1时,自动计算其大小
b = a.view(-1, 3)

#如果要再增加一维,使用unsqueeze()函数,如unsqueeze(1)在第一维(下标从0开始)上增加“1”
c = b.unqueeze(1)

在jupyter-notebook上运行unsqueeze()结果如下:

b.unsqueeze(0)表示在第0维上增加一维。

b.unsqueeze(1)表示在第1维上增加一维。

b.unsqueeze(2)表示在第2维上增加一维。

下面展示squeeze()的用法

#设置一个1x1x1x2x3形状的tensor
d = torch.arange(0, 6).view(1, 1, 1, 2, 3)

#压缩第0维的“1”
d.squeeze(0)

#压缩所有维度的“1”
d.squeeze()

在jupyter-notebook上运行结果如下图:

同时由于b由a.view(-1, 3)构建,二者共享内存,当改变a内元素时,b内元素随之改变:

a[1] = 100
#由于a,b共享内存,此时b[1]也应该等于100

在jupyter中查看结果:

可见尽管他们形状不同,但是由于b由a.view()生成,他们依旧共享内存。

另一种resize_()函数同样可以修改tensor的形状尺寸,但是前后的元素总量可变,当新尺寸大于旧尺寸的时候,会自动分配新的内存空间,如果小于,之前的数据依旧会被保存。

如下:

#将b变为1x3的tensor
b.resize_(1, 3)

#将b变为3x3的tensor
b.resize_(3, 3)

1.4.2索引操作

pytorch中对tensor的索引操作在语法上与numpy对ndarry类似。一般情况下,对tensor索引出来的结果与原tensor共享内存。基本操作可见numpy对索引的操作,下面将举例一些常用的选择函数:

表1-2 常用的选择函数
index_select(input, dim, index)在指定维度dim上选取,例如选取某些行、某些列
masked_select(input, mask)使用ByteTensor进行选取,与a[a>1]类似
non_zero(input)选取非0元素的下标
gather(input, dim, index)根据index,在dim维度上选取数据,输出的size与index一致

其中gather操作是一个比较复杂的操作,对于一个Tensor,其输入如下所示: 

#生成一个4x4的Tensor
a = torch.arange(0, 16).view(4, 4)

#生成一个1x1的LongTensor保存索引
index = torch.LongTensor([[0, 1, 2, 3]])
a.gather(0, index)

得到:

若要求反对角线的元素:

index_reverse = torch.LongTensor([[3, 2, 1, 0]]).torch()
a.gather(0, index_reverse).view(1, 4)

当然,如果想要两条对角线上面的元素,如下:

#选取正对角线的元素
a = torch.arange(0, 16).view(4, 4)
index = torch.LongTensor([[0, 1, 2, 3], [3, 2, 1, 0]])
a.gather(0, index)

如果不想要索引与原Tensor共享内存,使用Pytorch 0.2以上版本更新的高级索引操作,高级索引是Numpy风格,例:

#构建一个3x3x3的Tensor
a = torch().arange(0, 27).view(3, 3, 3)
#取出a[1, 1, 2]和a[2, 2, 0],即14和24
a[[1, 2], [1, 2], [2, 0]]
#取出a[2, 0, 1],a[1, 0, 1],a[0, 0, 1],即19,10,1
a[[2, 1, 0], [0], [1]]
#取出a[0],a[2],即第一维的第一个以及第三个
a[[0, 2]]

此时改变其中的元素:

#取出a[0, 0, 0]为100,如果共享内存,则原Tensor第一维第一行第一列那个元素为100
b = a[[0], [0], [0]]
b = 100
#查看a[0]
print(a[[0], [0], [0]])

可见不共享内存

1.5 Tensor的类型

Tensor有不同的类型,绝大多数类型都拥有CPU版本和GPU版本。默认的Tensor类型是FloatTensor, 可以通过torch.set_default_tensor_type修改默认的Tensor类型,但是此方法在pytorch更新之后仅支持设置默认类型为浮点类型。

以下是tensor的数据类型

表1-3 Tensor的数据类型
数据类型CPU TensorGPU Tensor
32bit浮点torch.FloatTensortorch.cuda.FloatTensor
64bit浮点torch.DoubleTensortorch.cuda.DoubleTensor
16bit半精度浮点N/Atorch.cuda.HalfTensor
8bit无符号整型(0~255)torch.ByteTensortorch.cuda.ByteTensor
8bit有符号整型(-128~127)torch.CharTensortorch.cuda.CharTensor
16bit有符号整型torch.ShortTensortorch.cuda.ShortTensor
32bit有符号整型torch.IntTensortorch.cuda.IntTenso
64bit有符号整型torch.LongTensortorch.cuda.LongTensor

要进行类型的转化,type(new_type)是通用的做法,同时可以直接使用long,float,int等类numpy快捷方法。而CPU与GPU之间的转化,使用torch.cuda和torch.cpu来实现。

Tensor中还有一个new方法,用法与torch.Tensor一致。

同时还有type_as函数,用法如下:

1.6逐元素操作

该操作会对tensor中每个元素进行操作,输入与输出的形状一致。常见的操作如下:

表1-4 常见的逐元素操作
abs/sqrt/div/exp/fmod/log/pow绝对值/平方根/除法/指数/求余/求对数/求幂
cos/sin/tan/asin/atan2/cosh三角函数
ceil/round/floor/trunc上取整/四舍五入/下取整/只保留整数部分
clamp(input, min , max)超出min和max的部分截断
sigmod/tanh激活函数

对于一般运算可以直接使用运算符来替代,如torch.pow(a, 2) == a ** 2,而对于clamp如下图:

如图,clamp用在比较大小的地方,取tensor中每一个元素与另一个数的最大值或最小值。

#构建一个2x3的Tensor
a = torch.arange(0, 6).view(2, 3)
#使用clamp函数找大的值
b = torch.clamp(a, max = 3)
print(b)

1.7归并操作

归并操作会使两个tensor合并,使得输出比输入小,也可以沿着某一维度单独操作。

表1-5 常见的归并操作
mean/sum/median/mode均值/和/中位数/众数
norm/dist

范数/距离

std/var标准差/方差
cumsum/cumprod累加/累乘

以上大多数函数都只有一个参数dim,用来指定这些操作是在哪个维度上执行。假设输入的形状是(m, n, k):

1.如果dim = 0,输出(1, n, k);

2.如果dim = 1,输出(m, 1, k);

3.如果dim = 2,输出(m, n, 1);

是否保留原维度1,取决于keepdim,keepdim = True会保留维度1,默认keepdim = Flase(一般情况)

#构建一个2x3的元素全是1的tensor
b = torch.ones(2, 3)
b.sum(dim = 0, keepdim = True)

#不保留维度“1”, 注意形状
b.sum(dim = 0, keepdim = False)

#对第二维度求和
b.sum(dim = 1)

#沿行累加
a = torch.arange(0, 6).view(2, 3)
a.cumsum(dim = 1)

1.8比较

比较函数中有一些是逐元素比较,操作类似于逐元素操作。

表1-6 常用的比较函数
gt/lt/le/eq/ne大于/小于/大于等于/小于等于/等于/不等于
topk

最大的k个数

sort排序
max/min比较两个tensor的最大值和最小值

以上几种函数,第一行的函数可以使用运算符来替代,返回ByteTensor,max/min操作比较特殊,有三种使用情况:

1.torch.max(tensor):返回tensor中最大的一个数;

2.torch.max(tensor, dim):指定维上的最大的数,返回tensor以及下标;

3.torch.max(tensor_1, tensor_2):比较两个tensor中较大的元素。

1.9线性代数

pytorch的线性函数中主要封装了Blas以及Lapack,常用线性代数函数如下:

表1-7 常用的线性代数函数
trace对角线元素之和(矩阵的迹)
diag对角线元素
triu/tril矩阵的上三角/下三角,可指定偏移量
mm/bmm矩阵乘法,batch的矩阵乘法
addmm/addbmm/addmv矩阵运算
t转置
dot/cross内积/外积
inverse求逆矩阵
svd奇异值分解

注:矩阵转置时可能会导致存储空间的不同,需要调用.contigous方法将其转为连续。

1.10Tensor与Numpy

Tensor与Numpy有极高的相似性,彼此之间可以简单高效的转化。当Tensor遇到不支持的操作时,可以转为numpy进行操作。

将numpy中的元素进行传入tensor时,可以使用torch.from_numpy函数进行操作,也可以直接使用torch.Tensor传入。由于是Tensor与Numpy的转化,所以在传入时Tensor和Numpy共享内存。

注:广播法则是科学运算中经常使用的一种技巧,可以快速实现向量化运算,有以下法则:

1.让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分通过在前面加1补齐。

2.两个数组要么在某一个维度的长度一致,要么其中一个为1,否则不能计算。

3.当输入数组的某个维度的长度为1时,计算时沿此维度复制扩充成一样的形状。

#构建3x2的元素全为“1”的tensor,构建2x3x1的元素全是“0”的tensor
a = torch.ones(3, 2)
b = torch.zeros(2, 3, 1)

#自动广播法则
#第一步:a是二维,b是三维,所以先在较小的a前面补1
#即:a.unqueeze(0),a的形状变为(1, 3, 2), b的形状是(2, 3, 1)
#第二步:a和b在第一维和第三维的形状不一样,其中一个为1
#可以利用广播法则扩展,两个形状都变成了(2, 3, 2)
a + b

#手动广播法则
#或者a.view(1, 3, 2).expend(2, 3, 2) + b.expand(2, 3, 2)
a.unqueeze(0).expand(2, 3, 2) + b.expand(2, 3, 2)

#使用expand不会占用额外空间,只会在需要时才扩充,可极大地节省内存

1.11内部结构

tensor的数据结构如上图所示,分为头信息区(Tensor)和存储区(storage),头信息区主要保存数据的形状,步长,数据类型等信息,真正的数据储存在存储区,由于头信息区只存储tensor的性质等信息,而存储区存有大量数据,所以tensor的内存占用取决于tensor中元素的数目。

一般来说,一个tensor有相对应的storage,storage是在data上封装的接口,不同的tensor头信息不同但是可以使用相同的storage。

接下来给出部分函数(可用于查看地址等信息):

#一个对象的id值可以看作它在内存中的地址
id(a.storage())
#data_ptr返回tensor首元素的内存地址
a.data_ptr()
#storage_offset返回tensor中的第一个元素于storage中第一个元素的偏移量
a.storage_offset()
#stride()是在指定维度dim中从一个元素跳到下一个元素所必需的步长。当没有参数传入时,返回所有步长的元组。否则,将返回一个整数值作为特定维度dim中的步长。
a.stride()
#is_contiguous()是判断tensor存储是否连续
a.iscontiguous()

1.12Tensor的保存于加载

torch.save和torch.load时可以指定使用的pickle模块,在加载时还可以把GPU tensor映射到CPU或者其他GPU上

#保存与加载
if torch.cuda.is_available():
    a = a.cuda(1) # 把a转为GPU1上的tensor
    torch.save(a, 'a.pth')

    #加载为b,存储于GPU1上(因为保存时tensor就在GPU1上)
    b = torch.load('a.pth')

    #加载为c,存储于CPU
    c = torch.load('a.pth', map_location = lambda storage, loc: storage)

    #加载为d,存储于GPU0上
    d = torch.load('a.pth', map_location = {'cuda:1' : 'cuda:0'})

*1.13向量化计算

向量化是一种特殊的并行计算方式,可以在同一时间执行多个操作,极大地提高科学运算的效率。

使用pytorch中需要注意以下几点:

        1.大多数torch.function都有一个参数out,此时结果将保存在out指定的tensor中;

        2.torch.set_num_threads可以设置Pytorch进行CPU多线程并行计算时所占用的线程数;

        3.torch.set_printoptions(precision = )可以用来设置打印tensor时的数值精度和格式,precision可以设置精度。

标签:dim,元素,tensor,torch,笔记,学习,Pytorch,构建,Tensor
From: https://blog.csdn.net/AsukaRanyo/article/details/136819389

相关文章

  • CentOS学习笔记-离线环境下禁止yum命令从repo中下载软件
    CentOS学习笔记-离线环境下禁止yum命令从repo中下载软件CentOSLinuxyum离线环境下使用yuminstall安装rpm时,还是会试图联网从系统的repo中去寻找和下载依赖。使用下面的配置来禁止这个功能。使用yum-config-manager--disable*可以禁用所有的repo,使用yum-config-manager--ena......
  • 无计算机基础想进AI方向,可以通过以下几个阶段学习AI,具体建议如下:
    无计算机基础想进AI方向,可以通过以下几个阶段学习AI,具体建议如下:阶段一:数学与编程基础构建在这个阶段,学员将专注于夯实数学基础,涵盖统计学、线性代数和微积分等核心数学知识,确保对机器学习和深度学习算法背后的数学原理有深入理解。同时,系统学习Python语言,包括语法结构、数据类......
  • 【刷题笔记】回溯算法 - ⭐去重问题
    代码随想录讲解:代码随想录(programmercarl.com)只是在刷题过程中记录一下自己的想法,因为总是记不住去重逻辑。回溯算法:回溯法,一般可以解决如下几种问题:组合问题:N个数里面按一定规则找出k个数的集合切割问题:一个字符串按一定规则有几种切割方式子集问题:一个N个数的集合里有......
  • CentOS学习笔记-设置yum保存软件包并指明保存位置
    CentOS学习笔记-设置yum保存软件包并指明保存位置CentOSLinuxyum在联网的环境中使用yum下载软件或者更新软件之后,希望把软件包保存下来,以便以后在离线机器上进行配置修改配置文件vi/etc/yum.confenterdescriptionhere这里要修改两地方,一是cachedir,表示要存放的位置,自己创......
  • 机器学习-05-回归算法
    总结本系列是机器学习课程的系列课程,主要介绍机器学习中回归算法,包括线性回归,岭回归,逻辑回归等部分。参考fit_transform,fit,transform区别和作用详解!!!!!!机器学习入门(七):多项式回归,PolynomialFeatures详解“L1和L2正则化”直观理解解读正则化LASSO回归岭回归python学......
  • 软件测试的学习随笔001
    T01:我理解的软件测试流程:1.需求分析阶段:测试团队与业务团队和开发团队合作,了解需求与功能,确定测试范围与重点,分配好产品计划的排期。2.测试计划阶段:制定测试计划,包括测试目标、测试策略、资源需求、进度安排等等。3.测试设计阶段:根据需求和设计文档编写测试用例,设计测试数据。......
  • 【折腾笔记】兰空图床数据迁移
    【折腾笔记】兰空图床数据迁移前言源数据环境:基于绿联私有云NASDX4600Pro的Docker功能安装LskyProVer2.1MySQLVer8.3.0目标数据环境:基于群晖NASDS423+的Docker功能安装LskyProVer2.1MySQLVer5.7.44目标数据环境是我迁移后的新的环境,仅供参考。迁移......
  • Python实战:爬取小红书-采集笔记详情
    上一篇文章发出后,有读者问能不能爬到小红书笔记详情数据,今天他来了。一、先看效果程序输入:在一个txt文件内粘贴要爬取的笔记链接,每行放1个链接。程序输出:输出是一个所有笔记详情数据的excel表格,包含”采集日期、作者、笔记标题、发布日期、IP属地、点赞数、收藏数、......
  • Vue学习笔记56--vue常用Ajax库(axios)
    vue常用Ajax库:1.vue-resource插件库npmivue-resource使用方式略,不建议使用,vue1.x使用广泛,官方已不维护2.axios通用的Ajax请求库,官方推荐,使用广泛axios在Vue项目中可以用来向后台发送请求(调接口API),获取响应信息的一个方法。Axios 是一个基于 promise 的 HTTP 库,可以......
  • PyTorch张量
    目录基本创建方式  创建线性和随机张量张量元素类型转换 阿达玛积张量数值计算 ......