tensor数据类型

Tensor在使用时可以有不同的数据类型,官方给出了 7种CPU Tensor类型与8种GPU Tensor类型。16位半精度浮点是专为GPU模型设计的,以尽可能地节省GPU显存占用,但这种节省显存空间的方式也缩小了所能表达数据的大小。PyTorch中默认的数据类型是 torch.FloatTensor,即torch.Tensor等同于torch.FloatTensor。

ShuffleAttention的pytorch代码 pytorch floattensor_深度学习


PyTorch可以通过set_default_tensor_type函数设置默认使用的Tensor 类型,在局部使用完后如果需要其他类型,则还需要重新设置回所需的 类型。

torch.set_default_tensor_type('torch.DoubleTensor')

类型转换

对于Tensor之间的类型转换,可以通过type(new_type)、type_as()、 int()等多种方式进行操作,尤其是type_as()函数,在后续的模型学习中 可以看到,我们想保持Tensor之间的类型一致,只需要使用type_as()即 可,并不需要明确具体是哪种类型。下面分别举例讲解这几种方法的使 用方式。

# 创建新Tensor,默认类型为torch.FloatTensor 
>>> a = torch.Tensor(2, 2) 
>>> a tensor(1.00000e-36 * 
		[[-4.0315, 0.0000], 
		[ 0.0700, 0.0000]]) 
# 使用int()、float()、double()等直接进行数据类型转换 
>>> b = a.double() 
>>> b tensor(1.00000e-36 * 
		[[-4.0315, 0.0000], 
		[ 0.0700, 0.0000]], dtype=torch.float64) 
# 使用type()函数 >>> c = a.type(torch.DoubleTensor) 
>>> c 
tensor(1.00000e-36 * 
				[[-4.0315, 0.0000], 
				[ 0.0700, 0.0000]], dtype=torch.float64) 
# 使用type_as()函数 
>>> d = a.type_as(b)
>>> d
 tensor(1.00000e-36 *
   [[-4.0315, 0.0000],
    [ 0.0700, 0.0000]], dtype=torch.float64)

Tensor的创建与维度查看

Tensor有多种创建方法,如基础的构造函数Tensor(),还有多种与 NumPy十分类似的方法,如ones()、eye()、zeros()和randn()等,图2.1列 举了常见的Tensor创建方法。

ShuffleAttention的pytorch代码 pytorch floattensor_java_02

# 最基础的Tensor()函数创建方法,参数为Tensor的每一维大小 
>>> a=torch.Tensor(2,2) 
>>> a 
tensor(1.00000e-18 *
				 [[-8.2390, 0.0000],
				[ 0.0000, 0.0000]])
>>> b = torch.DoubleTensor(2,2) 
>>> b 
tensor(1.00000e-310 *
		[[ 0.0000, 0.0000], 
		[ 6.9452, 0.0000]], dtype=torch.float64)
# 使用Python的list序列进行创建 
>>> c = torch.Tensor([[1, 2], [3, 4]]) 
>>> c 
tensor([[ 1., 2.], [ 3., 4.]]) 
# 使用zeros()函数,所有元素均为0 
>>> d = torch.zeros(2, 2) 
>>> d
tensor([[ 0., 0.], [ 0., 0.]]) 
# 使用ones()函数,所有元素均为1 >>> e = torch.ones(2, 2) 
>>> e 
tensor([[ 1., 1.], [ 1., 1.]]) 
# 使用eye()函数,对角线元素为1,不要求行列数相同,生成二维矩阵 

>>> f = torch.eye(2, 2) 
>>> f
 tensor([[ 1., 0.], [ 0., 1.]]) 
# 使用randn()函数,生成随机数矩阵
>>> g = torch.randn(2, 2)
>>> g
 tensor([[-0.3979, 0.2728], [ 1.4558, -0.4451]])
# 使用arange(start, end, step)函数,表示从start到end,间距为step,一维向量 
>>> h = torch.arange(1, 6, 2) 
>>> h
 tensor([ 1., 3., 5.]) 
# 使用linspace(start, end, steps)函数,表示从start到end,一共steps份,一维向量 
>>> i = torch.linspace(1, 6, 2) 
>>> i
 tensor([ 1., 6.]) .
# 使用randperm(num)函数,生成长度为num的随机排列向量
>>> j = torch.randperm(4) 
>>> j 
tensor([ 1, 2, 0, 3]) 
# PyTorch 0.4中增加了torch.tensor()方法,参数可以为Python的list、NumPy的ndarray等 
>>> k = torch.tensor([1, 2, 3]) 
			tensor([ 1, 2, 3])

对于Tensor的维度,可使用Tensor.shape或者size()函数查看每一维 的大小,两者等价。

>>> a=torch.randn(2,2)
# 使用shape查看Tensor维度 
>>> a.shape
torch.Size([2, 2]) 
# 使用size()函数查看Tensor维度 torch.Size([2, 2])
 >>> a.size() 
 torch.Size([2, 2])

查看Tensor中的元素总个数,可使用Tensor.numel()或者 Tensor.nelement()函数,两者等价。

# 查看Tensor中总的元素个数 
>> a.numel() 
4
>>> a.nelement() 
4

Tensor的组合与分块

组合与分块是将Tensor相互叠加或者分开,是十分常用的两个功 能,PyTorch提供了多种操作函数,如图2.2所示。

ShuffleAttention的pytorch代码 pytorch floattensor_java_03


组合操作是指将不同的Tensor叠加起来,主要有torch.cat()和 torch.stack()两个函数。cat即concatenate的意思,是指沿着已有的数据的 某一维度进行拼接,操作后数据的总维数不变,在进行拼接时,除了拼 接的维度之外,其他维度必须相同。而torch.stack()函数指新增维度,并 按照指定的维度进行叠加,具体示例如下:

# 创建两个2×2的Tensor
>>> a=torch.Tensor([[1,2],[3,4]]) 
>>> a tensor([[ 1., 2.], [ 3., 4.]]) 
>>> b = torch.Tensor([[5,6], [7,8]]) 
>>> b
 tensor([[ 5., 6.], [ 7., 8.]]) 
# 以第一维进行拼接,则变成4×2的矩阵 
>>> torch.cat([a,b], 0) 
tensor([[ 1., 2.], [ 3., 4.], [ 5., 6.], [ 7., 8.]]) 

# 以第二维进行拼接,则变成24的矩阵 
>>> torch.cat([a,b], 1) 
tensor([[ 1., 2., 5., 6.], [ 3., 4., 7., 8.]]) 
# 以第0维进行stack,叠加的基本单位为序列本身,即a与b,因此输出[a, b],输出维度为2×2×2 
>>> torch.stack([a,b], 0) 
tensor([[[ 1., 2.], [ 3., 4.]], [[ 5., 6.], [ 7., 8.]]]) 

# 以第1维进行stack,叠加的基本单位为每一行,输出维度为2×2×2
>>> torch.stack([a,b], 1) 
tensor([[[ 1., 2.], [ 5., 6.]], [[ 3., 4.], [ 7., 8.]]]) 

# 以第2维进行stack,叠加的基本单位为每一行的每一个元素,输出维度为2×2×2 
>>> torch.stack([a,b], 2) 
tensor([[[ 1., 5.], [ 2., 6.]], [[ 3., 7.], [ 4., 8.]]])

分块则是与组合相反的操作,指将Tensor分割成不同的子Tensor, 主要有torch.chunk()与torch.split()两个函数,前者需要指定分块的数量, 而后者则需要指定每一块的大小,以整型或者list来表示。具体示例如 下:

>>> a=torch.Tensor([[1,2,3],[4,5,6]]) 
>>> a tensor([[ 1., 2., 3.], [ 4., 5., 6.]]) 
# 使用chunk,沿着第0维进行分块,一共分两块,因此分割成两个1×3的Tensor 

>>> torch.chunk(a, 2, 0) 
(tensor([[ 1., 2., 3.]]), tensor([[ 4., 5., 6.]])) 
# 沿着第1维进行分块,因此分割成两个Tensor,当不能整除时,最后一个的维数会小于前面的因此第一个Tensor为2×2,第二个为2×1 

>>> torch.chunk(a, 2, 1) 
(tensor([[ 1., 2.], [ 4., 5.]]), tensor([[ 3.], [ 6.]])) # 使用split,沿着第0维分块,每一块维度为2,由于第一维维度总共为2,因此相当于没有分割 
>>> torch.split(a, 2, 0) 
(tensor([[ 1., 2., 3.], [ 4., 5., 6.]]),) 
# 沿着第1维分块,每一块维度为2,因此第一个Tensor为2×2,第二个为2×1 
>>>> torch.split(a, 2, 1) 
(tensor([[ 1., 2.], [ 4., 5.]]), tensor([[ 3.], [ 6.]])) 
# split也可以根据输入的list进行自动分块,list中的元素代表了每一个块占的维度 
>>> torch.split(a, [1,2], 1) 
(tensor([[ 1.], [ 4.]]), tensor([[ 2., 3.], [ 5., 6.]]))