数学中有标量、向量和矩阵的概念,它们的维度分别是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的使用会更多。
生成指定形状的随机张量:
torch.empty(维度1长度,维度2长度...)
。备注:不推荐使用empty函数来生成张量,因为如果忘记对张量中的元素进行初始化则可能产生相当麻烦的错误。
torch.rand(维度1长度,维度2长度...)
。torch.rand_like(张量名)
。torch.randint(最小值,最大值,形状列表)
。注意该区间不包括右端点(最大值)。torch.randn(维度1长度,维度2长度...)
。torch.normal(表示均值的一维张量,表示标准差的一维张量)
。备注:randn方法和normal方法在返回值上的最大区别在于,normal方法返回的仍然是一个一维张量,如果想要得到其他形状和维度的张量,则需要对张量进行维度变换。
torch.ones(形状元组)
。torch.zeros(形状元组)
。torch.full(形状列表,填充值)
。torch.eye(行数,列数)
。生成等差张量和等比张量(一维):
torch.arange(起始值,终止值,steps=步长)
。生成数字的区间不包括终止值。torch.linspace(起始值,终止值,steps=生成元素个数)
。同样,生成的数字的区间不包括终止值。torch.logspace(起始值,终止值,steps=元素个数)
。生成的每一个元素都是对当前值求log10对数的结果。生成随机打散的整数张量:
tensor.randperm(n)
:返回一个含有n个元素的一维张量,张量中的元素位置随机,但是都是从0到n-1之间的不重复的整数。
张量名[维度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。expand方法执行速度快,但是并不会对扩展部分的数据进行初始化,因此需要程序员对扩展部分的数据进行手动初始化。张量名.repeat(维度1拷贝次数,维度2拷贝次数...)
。和expand方法不同的是,repeat方法在进行形状扩展的同时还会进行数据的复制过程,因此其相应地也比expand执行速率更低。二维张量名.t()
。张量名.transpose(维度1,维度2)
。output_tensor = input_tensor.permute(*dims)
其中,input_tensor是要进行维度重排的张量,dims是一个整数序列,表示新的维度顺序。*dims表示将序列解包成独立的参数。output_tensor是维度重排后得到的新张量。
例如,假设有一个大小为(3, 4, 5)的张量x,要将维度顺序变为(4, 5, 3),可以使用如下代码:
import torchx = torch.randn(3, 4, 5)
y = x.permute(1, 2, 0)
在某些情况下,Pytorch 要求 tensor 的数据必须是连续的,否则会抛出运行时错误。这种情况通常涉及到 tensor 之间的操作,如矩阵乘法等。当 tensor 不是连续的时候,我们可以使用 contiguous() 函数来将其转换为连续的 tensor。
将张量进行连续存储:张量名.contiguous()
。
broadcasting机制的作用:在 Pytorch 中,broadcasting 是一种自动扩展张量形状的机制,使得不同形状的张量可以进行算术运算。其实现方式是在需要进行运算的张量上自动添加维度,使其形状能够匹配另一个张量的形状。
Broadcasting机制是如何进行的:如果两个张量在某个维度上的形状不同,而这个维度的长度为 1,那么 Pytorch 会自动地沿着这个维度进行复制,使得两个张量在这个维度上的长度相同,从而能够进行算术运算。这个过程会一直持续到两个张量在所有维度上的形状都相同为止。
例如,如果有一个形状为 (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)
。张量名.norm(范数阶数,dim=需要求范数的维度)
。张量名.max(dim=需要求最大值的维度)
和张量名.min(dim=需要求最小值的维度)
。keepdim参数:对于max函数和min函数,有一个可选参数keepdim,该参数是一个布尔值。如果为了保留原始的维度信息,就可以将该keepdim参数设置为True。
张量名.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 torchx = 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 torchinput = 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],以此类推。
上一篇:RESTful API接口
下一篇:IO流之 File 类和字节流