PyTorch|Tensor的创建

01 | 什么是Tensor(张量)?

Tensor是PyTorch中的基础数据概念,直译过来为“张量”。那么什么是张量呢?

我们知道,数学是研究世间数量和空间关系的学科,“张量”作为一种特殊的数量形式,自然也来自于数学领域。

最原始的数量就是标量,因为其只有“数量”而没有变化方向,如数字“1”。

若将标量沿着某个方向进行数据扩展,就会得到一个1维数组,也称为1维张量(通俗理解是沿着某个方向“扩张”)。

若在1维数组的基础上再添加一个方向,则容易变成2维数组,即2维张量。

类似地,如果对一个二维数组进行第三个维度的“扩张”,那么可以得到一个3维数组,即3维张量;因此,从数学角度来看,Tensor(张量)本质是一个多维数组,它是标量、向量、矩阵的高维扩展。

下图中展示了从“标量”→“1维张量”→“2维张量”→“3维张量”的演化过程。需要注意的是,Tensor可以无穷维度扩张下去,因此理论上可以得到N维张量。

在这里插入图片描述
张量的应用源于现实应用需要,如早期的数字图像使用灰度值表示像素颜色,即每个像素中标记有0~255的数值,表示从白到黑的不同程度,图像整体由不同的像素灰度值组合而成,此时可以将灰度图像看作是一个二维矩阵。

若采用RGB三原色分别建立三个二维矩阵,那么采用一组颜色数组(R,G,B)来表示图像一个像素的颜色,即可得到一副RGB彩色图像。

在这里插入图片描述在这里插入图片描述

02 | Tensor数据结构

PyTorch的Tensor是一种源于数学高维数组的数据结构,其中不仅包含原始的data部分,而补充了用于数学说明与梯度求解相关的数据属性。其中:

  • data部分表示数学上的数据张量

  • dtype表示高维数组的数据类型,通常默认使用64float类型

  • shape表示张量的形状,如(64,3,224,224),显然此时张量达到了四维度

  • device表示张量所在的设备,通常分为GPU和CPU,而能否存在GPU是借助GPU加速的关键

  • grad表示data部分的梯度

  • grad_fn表示创建Tensor的Function,是自动求导的关键

  • requires_grad表示是否需要梯度,因为计算梯度需要消耗时间和资源,因此取消本项可以节省时间

  • is_leaf表示是否是叶子节点,主要用于图模型中使用

在这里插入图片描述

03 | Tensor创建:直接创建

PyTorch中提供了直接创建Tensor的方法,一种方式为使用“torch.tensor()”直接创建,但是需指定相应的参数:

  • data:数据,可以是list和numpy

  • dtype:数据类型,默认与data一致

  • device:所在设备,选择cuda/cpu

  • requires_grad:是否需要计算梯度

  • pin_memory:是否存于锁页内存,默认False即可

在这里插入图片描述
我们尝试在PyCharm上运行代码,可以发现:1)新建tensor的数据类型默认继承了list/numpy数据类型;2)设置device参数后可以将其tensor存储在cuda上加速运算,默认在CPU上。

import torch 
import numpy as np 
# **************************** example 1 **************************** 
# 通过torch.tensor()直接创建张量 
flag = True 
if flag:  
	# 创建一个3×3的单位矩阵 arr = np.ones((3,3))        
	print("ndarray的数据类型是: ", arr.dtype)        
	# 在CPU上基于numpy数据创建tensor     
	t1 = torch.tensor(arr)        
	print(t1)        
	# 在GPU上基于numpy数据创建tensor     
	t2 = torch.tensor(arr, device='cuda')        
	print(t2)

在这里插入图片描述
除去torch.tensor()之外,还可以直接从numpy的ndarray数据类型中创建tensor,j即“torch.from_numpy()”。但是需要注意的是,此时创建的tensor与原始的ndarray共享内存,当修改其中一个数据时,另外一个也会改动。

运行下述代码,可以发现ndarray数据arr与张量t的第[0,0]元素同时发生改变。

# **************************** example 2 **************************** 
# 通过torch.from_numpy()创建共享张量 
flag = True 
if flag:    
	arr = np.array([[1,2,3], [1,2,3]])        
	t = torch.from_numpy(arr)        
	print("numpy array: ", arr)        
	print("tensor: ", t)        
	# 修改numpy的ndarray        
	arr[0,0] = 0        
	print("numpy array: ", arr)        
	print("tensor: ", t)

在这里插入图片描述

04 | Tensor创建:依据数值创建

041 | 创建等数值张量

第二种创建Tensor的方式是基于数值创建,此时常见于创建全0或全1的张量。

第一个介绍的方法是“torch.zeros()”,顾名思义,创建一个元素全0张量,大小形状基于size确定。其中的参数为:

  • size:表示张量的形状,如(3,3)或(3,224,224)

  • out:输出的张量

  • layout:内存中布局形式,有strided和sparse_coo等,后者用于稀疏矩阵提升处理效率,默认使用strided即可

  • device:表示张量所在设备,gpu/cpu

  • requires_grad:表示是否需要计算梯度

![在这里插入图片描述](https://img-blog.csdnimg.cn/32a36b9c6aa6440fad015079e2836a9b.jpeg#pic_center

此时可以在PyCharm中运行代码,检验效果。可见其中“out”参数的作用为将张量输出到另外一个变量,从而替代掉原始的ndarray数据。

# **************************** example 3 **************************** 
# 通过torch.zeros创建全0张量 
flag = True 
if flag:     
	# torch.tensor()可以接受list或numpy数据 
	out_t = torch.tensor([1])        
	print(out_t)        
	# 新建全0张量并输出到已有的out_t     
	t = torch.zeros((4,4), out=out_t)        
	print(t)        
	print(out_t)

在这里插入图片描述
类似地,大家可以理解同样新建全1张量的命令“torch.ones()”,其用法基本相同。如果想自定义全X张量,那么可以采用升级版命令“torch.full()”来创建任意数值的命令,其重要参数有两个:

  • size:表示张量的形状,如(9,9)
  • fill_value:表示张量的元素值

在这里插入图片描述

042 | 创建等差变化张量

借助torch.full()可以创建等数值张量,同时也可以借助“torch.arange()”创建等差张量,注意这里的意思是“a range”而非“arrangement”的意思。此时有三个重要参数:

  • start:表示数列起始值

  • end:表示数列结束值,非闭合区间

  • step:数列公差,默认为1

此外还可以使用“torch.linspace”均分数列张量,这里的“linspace”表示“linear space”的意思。其主要参数如下:

  • start:表示数列起始值

  • end:数列结束值

  • steps:数列长度(或通俗理解为均分线段后的端点总数)

需要注意的是,不同于torch.arange(),torch.linspace()需要均分[end - start]之间的数列,因此需要完全闭合区间,即选取数列范围时包含start和end两个端点。

有趣的是,当我们按照“steps=5”等分[2,10]时,会发现间隔为2得到[2,4,6,8,10],即得到“5”个元素;而使用“steps=6”等分[2,10]时,考虑到“爬楼梯”问题中,所在楼层减一恰好等于实际爬过的层数,因而实际将闭合区间五等分后输出得到的6个端点。

# **************************** example 4 **************************** 
# 通过torch.arange()创建等差张量,利用torch.linspace()均分数列创建张量 
flag = True 
if flag:   
	# 等差张量下,起始为闭开半闭区间        
	t1 = torch.arange(2,10,2)       
	print(t1)        
	# 均分数列张量下,起始均为闭合区间        
	t2 = torch.linspace(2,10,5)        
	t3 = torch.linspace(2,10,6)        
	print(t2)        
	print(t3)

在这里插入图片描述
此外,PyTorch中也提供了基于对数均分创建张量的方法,即“torch_logspace()”,其最大的不同就是添加了对数函数的底作为“base”参数。

在这里插入图片描述
另外我们还可以使用“torch.eye()”创建对角矩阵(2维张量),注意所得结果默认为方针,因此一般只提供行/列参数即可。

在这里插入图片描述

05 | Tensor创建:依据概率分布创建张量

上面我们介绍了张量的直接创建、从数值创建两类方法,还有一类方法十分常用,如初始化权值参数的时候往往选择某种概率分布。

我们可以使用“torch.normal()”建立符合正态分布/高斯分布的张量,对于正态分布而言,只需要指定均值和标准差即可。需要注意的是,由于均值和标准差分别可以选择标量和张量(一维数组),因而实际中共有四种组合。

这里需要注意的是,当mean与std均为标量时,需要指定size以确定张量大小,且张量中每个元素都是从同一个正态分布中采样所得;当mean或std为张量时,则采用一一对应的原则,即mean第一个元素与std第一个元素确定第一个正态分布,并采样获得目标张量的第一个元素数值,以此类推。

# **************************** example 5 **************************** 
# 通过torch.normal()创建符合正态分布张量 
flag = True 
if flag:    
		# mean张量,std张量        
		mean = torch.arange(1, 5, dtype=torch.float)        
		std = torch.arange(1, 5, dtype=torch.float)        
		t_normal = torch.normal(mean, std)        
		print("mean:{}\nstd:{}".format(mean, std))        
		print(t_normal)            
	
		# mean标量,std标量        
		# 由于mean与std都是标量,无法确定张量大小,故需指定size=()        
		# 分别从指定正态分布中采样4次和采样10次创建张量        
		t_normal_0 = torch.normal(1, 0, size=(4,))        
		t_normal_1 = torch.normal(1, 1, size=(10,))        
		print("mean标量,std标量:", t_normal_0)        
		print("mean标量,std标量:", t_normal_1)            

		# mean张量,std标量        
		# 此时所得张量的元素来自与张量mean与标量std的组合所得的4个正态分布采样        
		mean = torch.arange(1, 5, dtype=torch.float)        
		std = 1        
		t_normal_0 = torch.normal(mean, std)        
		t_normal_1 = torch.normal(mean, std)        
		print("第1次采样:", t_normal_0)    
		print("第2次采样:", t_normal_1)

运行结果如下:

在这里插入图片描述此外,我们还可以使用“torch.randn()”生成标准分布采样的张量,或采用“torch.rand()”在(0,1]上生成均匀分布。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值