赞
踩
数学中有标量、向量和矩阵的概念,它们的维度分别是0、1、2。也就是说,标量中元素的位置固定,向量中元素的位置需要通过其索引确定,矩阵中的元素位置需要通过其行号和列号确定。张量可以视为矩阵的扩展,可以用于表示无穷维度的数据。
张量(Tensor)是Pytorch库中的基本数据类型,Pytorch中各种基本数字类型都有其对应的Tensor类型,但是在Pytorch中没有内嵌的字符串类型。
常用的Pytorch数值型数据类型:
由于Pytorch库中没有布尔类型,因此常常使用字节整型张量来表示布尔值。
上面的类型都是针对CPU而言的,对于在GPU上的数据类型,还需要添加一个cuda,也就是下面这些形式:
将一个普通张量类型转化为GPU张量类型的方法:普通张量变量名.cuda()
。该函数返回一个GPU张量的引用。
查看张量数据类型的方法:直接使用Python自带的type函数查看Tensor的具体类型是不行的,这样返回的类型值始终是“torch.Tensor"。因此需要使用到下面的两种方法。
张量名.type()
的方式可以查看张量的具体类型。isinstance(张量名,类型名)
,返回值是一个布尔值。譬如下面的这个例子:isinstance(torch.randn(2,3),torch.FloatTensor)
张量的形状确定:
张量中元素个数确定:张量名.numel()
。
张量的维度确定:张量名.dim()
。
测试样例:
import torch
# 创建一个3行3列的张量
a=torch.ones((3,3))
print(a.numel()) # 输出9
print(a.dim()) # 输出2
将不同类型的数据转化为张量:可以通过已有的单个数值、Python列表、Numpy数组等方式来生成张量。也可以先不指定所生成的张量的元素值,而只生成指定元素个数的张量。
torch.tensor(标量值)
。标量也就是一个数字。torch.tensor(列表)
。备注:在使用tensor函数创建tensor张量对象时还可以使用dtype参数指定数据类型,使用device参数指定运算设备是CPU还是GPU,此处不再赘述。
torch.from_numpy(numpy数组)
。同时,也可以直接使用torch.tensor(numpy数组)
的形式来生成张量。备注1:可以通过使用Python的list()函数将张量转化为Python列表。
# 浮点型张量
tensor.FloatTensor(标量/列表/numpy数组) # 生成元素均为单精度浮点型的张量
tensor.DoubleTensor(标量/列表/numpy数组) # 生成元素均为双精度浮点型的张量
tensor.HalfTensor(标量/列表/numpy数组) # 生成元素均为半精度浮点型的张量
# 整型张量
tensor.IntTensor(标量/列表/numpy数组) # 生成元素均为基本整型的张量
tensor.ShortTensor(标量/列表/numpy数组) # 生成元素均为短整型的张量
tensor.LongTensor(标量/列表/numpy数组) # 生成元素均为长整型的张量
# 布尔型张量
tensor.BoolTensor(标量/列表/numpy数组) # 生成元素均为布尔类型的张量
设置所有生成的张量的默认元素类型:torch.set_default_tensor_type(类型名)
。Pytorch的默认张量类型是torch.FloatTensor。增强学习中使用DoubleTensor的使用会更多。
将张量转换为其他数据类型:
张量名.numpy()
;张量名.item()
。生成指定形状的随机张量:
torch.empty(维度1长度,维度2长度...)
。备注:为什么有能够进行初始化生成张量的函数还要考虑empty函数呢?这是因为empty函数由于没有进行内存初始化的过程,因此执行效率会比需要初始化的ones和zeros等函数更高。当在后续操作过程中会对张量中的元素进行手动初始化时,更加推荐使用empty函数。
生成元素服从0到1均匀分布的指定形状的张量:torch.rand(维度1长度,维度2长度...)
。
生成与指定张量形状相同的元素服从0到1均匀分布的张量:torch.rand_like(张量名)
。
生成元素为指定区间均匀分布整数的指定形状的张量:torch.randint(最小值,最大值,形状列表)
。注意该区间不包括右端点(最大值)。
生成元素服从标准正态分布的指定形状的张量:torch.randn(维度1长度,维度2长度...)
。
生成元素服从指定均值和标准差的正态分布的一维张量:torch.normal(表示均值的张量,表示标准差的张量)
。torch.normal
函数返回张量的形状与与均值和标准差张量的形状相同。
生成全部元素为1的指定形状的张量:torch.ones(形状元组)
。
生成全部元素为0的指定形状的张量:torch.zeros(形状元组)
。
生成指定填充值的指定形状的张量:torch.full(形状列表,填充值)
。
生成元素满足对角矩阵的指定形状的张量:torch.eye(行数,列数)
。
生成等差张量和等比张量(一维):
torch.arange(起始值,终止值,steps=步长)
。生成数字的区间不包括终止值。torch.linspace(起始值,终止值,steps=生成元素个数)
。注意,生成的元素包括终止值。torch.logspace(起始值,终止值,steps=元素个数,base=底数)
。生成的每一个元素都是对当前值求log10对数的结果。生成随机打散的整数张量:
tensor.randperm(n)
:返回一个含有n个元素的一维张量,张量中的元素位置随机,但是都是从0到n-1之间的不重复的整数。
根据一个已知张量复制一个新张量:张量名.clone()
。
张量名[维度1,维度2...]
。张量名[维度1起始位置:维度1终止位置,维度2起始位置:维度2终止位置...]
。备注:
①如果需要对整个维度进行切片,则直接使用冒号“:
”表示整个维度即可。
②切片区间是左闭右开的,也就是不包含终止位置的元素。
③和Python中的列表相同,张量的索引和切片也可以用负数形式的反向索引和切片。
④进行切片时还可以指定步长,其语法形式为起始位置:终止位置:步长
。
张量名.index_select(维度,位置)
。注意位置需要用一个一维张量来进行表示。# 取0维度上的1、5、6号对象
TestTensor.index_select(0,torch.tensor([1,5,6]))
masked_select 是 Pytorch 库中的一个函数,可以用来从输入张量中按照给定的掩码(mask)选取元素。掩码是一个布尔类型的张量,其形状和输入张量相同,掩码中每个元素的值决定了是否选取输入张量中对应位置的元素。
masked_select(input, mask)
函数接受两个参数:
input:要从中选取元素的输入张量,可以是任意形状的张量。
mask:用来控制选取哪些元素的掩码,必须是一个形状和 input 相同的布尔类型张量。
函数返回一个一维张量,其中包含了所有符合条件的元素。
以下是一个示例:
import torch
# 创建一个 2x3 的张量
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 创建一个与 x 相同形状的掩码
mask = torch.tensor([[True, False, True], [False, True, False]])
# 使用掩码从 x 中选取符合条件的元素
result = torch.masked_select(x, mask)
print(result) # 输出 tensor([1, 3, 5])
注意事项:对张量进行维度变换并不改变张量本身的存储方式,只是对原本存储的内容换了一种方法进行解释。
张量名.reshape(新维度1,新维度2...)
。备注:使用reshape操作一定要确保变换前后的张量具有相同数量的元素。同时,使用reshape操作会使得原始张量的维度信息丢失,因此使用时一定要谨慎。
张量名.unsqueeze(插入索引)
。插入索引表示在当前哪一个维度的索引前插入新的维度。索引可以用正向索引和可以用负向索引,但是不建议负向索引,因为容易混淆。张量名.squeeze(删除位置索引)
。删除位置表示删除哪一个维度的索引。只有长度为1的维度才能进行挤压,否则原始张量不会发生变化。张量名.expand(维度1长度,维度2长度...)
。
-1
表示。因此,输入参数时可以只输入扩展后的张量的最高几个维度即可。contiguous()
函数。expand()
函数作用在张量最高维度的前一个维度上,可以实现原始张量的升维。张量名.repeat(维度1拷贝次数,维度2拷贝次数...)
。
repeat()
函数实现的是将整个张量视为一个元素,构造一个指定大小的张量。repeat()
函数会真正实现对数据的复制,这一点与expand()函数不同。二维张量名.t()
。也可以通过二维张量名.T
的方式进行矩阵转置。张量名.transpose(维度1,维度2)
。output_tensor = input_tensor.permute(*dims)
其中,input_tensor
是要进行维度重排的张量,dims
是一个整数序列,表示新的维度顺序。output_tensor
是维度重排后得到的新张量。
例如,假设有一个大小为(3, 4, 5)的张量x,要将维度顺序变为(4, 5, 3),可以使用如下代码:
import torch
x = torch.randn(3, 4, 5)
y = x.permute(1, 2, 0)
将张量进行连续存储:张量名.contiguous()
。
contiguous()
函数的作用就是确保一个张量是连续存储的。如果这个张量已经是连续存储的,那么就不进行任何操作;否则会创建一个新的连续存储的张量并将原始张量中的数据复制到新的张量中。这个操作通常在需要进行连续存储的操作之前使用,用来避免额外的时间空间开销。Broadcasting机制的作用:在 Pytorch 中,Broadcasting (广播)是一种自动扩展张量形状的机制,使得不同形状的张量可以进行算术运算。其实现方式是在需要进行运算的张量上自动添加维度,使其形状能够匹配另一个张量的形状,而不需要手动对参与运算的张量进行扩展或者重复。
Broadcasting机制是如何进行的:
例如,如果有一个形状为 (3, 1) 的张量 a 和一个形状为 (1, 4) 的张量 b,那么在对它们进行加法运算时,PyTorch 会自动地将它们扩展为形状分别为 (3, 4) 的张量,然后进行加法运算。
备注:这种自动扩展张量形状的机制可以大大简化代码的书写,提高程序的可读性和可维护性。但是在使用时,需要注意张量形状的匹配关系,以免出现意外的错误。
torch.cat([张量1,张量2...],dim=拼接维度下标)
。使用该函数要求所拼接的张量除了需要进行拼接的维度的值不同外,维度相同且其他维度的数值都相同。torch.stack([张量1,张量2...],dim=新创建维度)
。要求进行拼接的两个张量的形状必须完全相同。torch.split([张量1长度,张量2长度...],dim=被拆分的维度)
。被拆分得到的多个张量以一个元组的形式作为返回值返回。torch.chunk(拆分个数,dim=被拆分的维度)
。四则运算函数:除了直接使用运算符外,也可以使用对应的函数进行运算。加减乘除的对应函数分别为torch.add()、torch.sub()、torch.mul()、torch.div(),传入的参数是进行运算的两个张量。
torch.matmul(张量1,张量2)
。这个函数也可以对更高维度的张量进行运算,具体结果形式此处不再解释。备注:在pytorch中,运算符@也是表示两个矩阵相乘。
张量名.pow(次数)
。张量名.sqrt()
。torch.exp(张量名)
。具体来说,就是以张量的元素为指数,求出自然对数e的幂。torch.log(张量名)
。如果需要以2为底数或以10为底数,可以分别使用torch.log2()
和torch.log10()
两个函数。张量名.ceil()
/张量名.floor()
。张量名.round()
。张量名.trunc()
/张量名.frac()
。张量名.clamp(最小值,最大值)
。使用该函数后,张量中本来比最小值还要小的元素将被修改为最小值,比最大值还要大的元素将被修改为最大值。torch.all(张量名)
。该函数返回一个零维张量,如果元素为1表示所有元素都是True,否则返回0。torch.eq(张量1,张量2)
。该函数返回一个布尔类型的张量。torch.ge(张量1,张量2)
。torch.gt(张量1,张量2)
。torch.le(张量1,张量2)
。torch.lt(张量1,张量2)
。torch.norm(张量名,p=范数类型,dim=求范数维度)
。
fro
(Frobenius范数),float类型数值
(表示求几阶范数),nuc
(核范数)。张量名.max(dim=需要求最大值的维度)
和张量名.min(dim=需要求最小值的维度)
。张量名.mean()
。张量名.sum()
和张量名.prod()
。张量名.argmax(dim=求解维度)
和张量名.argmin(dim=求解维度)
。张量名.topk(元素个数,dim=求最值的维度,largest=最大/最小)
。
largest
为True
表示求最大的几个元素;largest
为False
表示求最小的几个元素。张量名.kthvalue(K,dim=求最值的维度)
。该方法也会像topk方法一样返回两个张量。where函数的使用方法:
在 Pytorch 中,torch.where() 函数的作用是根据条件选择输入张量的元素,并返回一个新的张量。
函数的使用方法如下:
torch.where(condition, x, y)
其中,condition 是一个布尔类型的张量,x 和 y 分别是两个张量,它们的形状可以不相同,但是必须有相同的维度。函数返回一个新的张量,其形状与 condition 张量相同,其元素根据 condition 张量中的值选择自 x 或 y 中的相应元素。
具体地说,当 condition[i] 为 True 时,新张量的第 i 个元素将等于 x[i],否则为 y[i]。
下面是一个简单的示例,说明如何使用 torch.where() 函数:
import torch
x = torch.randn(3, 3)
y = torch.ones(3, 3)
result = torch.where(x > 0, x, y)
print(result)
在上面的例子中,我们首先创建了两个 3x3 的张量 x 和 y,其中 x 中的元素是随机的,y 中的元素都是 1。然后,我们使用 torch.where() 函数根据 x > 0 的条件选择 x 或 y 中的元素,将结果保存到 result 张量中,并打印输出。
gather函数的使用方法:
在 Pytorch 中,gather() 函数用于按索引从输入张量中收集元素,并将它们组成一个新的张量返回。
函数的使用方法如下:
torch.gather(input, dim, index, out=None)
其中,input 是输入张量,dim 是指定的维度,index 是索引张量,out 是输出张量(可选参数)。函数返回一个新的张量,其形状与 index 张量相同。
具体地说,对于 2D 张量 input,dim 可以是 0 或 1,分别表示在行或列上进行索引。而对于多维张量 input,dim 则可以是任意维度。
下面是一个简单的示例,说明如何使用 gather() 函数:
import torch
input = torch.tensor([[10, 20], [30, 40], [50, 60]])
index = torch.tensor([[0, 1], [1, 0], [0, 1]])
output = torch.gather(input, 1, index)
print(output)
在上面的例子中,我们首先创建了一个 3x2 的张量 input,其中包含了一些元素。然后,我们创建了一个与 input 相同大小的索引张量 index,用于按行收集元素。最后,我们使用 gather() 函数按行从 input 张量中收集元素,并将结果保存到 output 张量中,并打印输出。
输出结果为:
tensor([[10, 20],
[40, 30],
[50, 60]])
可以看到,输出张量中的每个元素都是从 input 张量中按照相应的索引收集而来的。例如,第一个元素 10 是来自 input[0, 0],第二个元素 20 是来自 input[0, 1],以此类推。
在运行一些张量操作时可以需要为新的结果重新分配内存,例如,如果我们使用Y=Y+X,那么我们将取消Y指向的张量,而是指向新分配的内存处的张量。
Python中可以通过id函数查看某个变量的具体地址:
id_number=id(变量名)
通过id()
函数我们即可看出一个变量的存储位置是否发生了改变。
下面给出一个浪费内存空间的例子:
before = id(Y)
Y = Y + X
id(Y) == before
在机器学习和深度学习任务中要避免重新分配内存,原因如下:
可以通过切片操作将用新的张量覆盖已有的不用的张量来实现节约内存。
before=id(Y)
Y[:]=Y+X
id(Y)==before
torch.save(张量名,保存文件名)
。torch.load(保存文件名)
。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。