Pytorch 张量创建详解

张量

张量可以理解为向量,在python中的编程中可以联想至列表和numpy的ndarray数据类型,具体包括了一维张量和高维矩阵,pytorch和numpy有很多相似之处,比如都具有广播机制和向量化操作,并且pytorch的张量和numpy的ndarray可以较为方便的进行转换。不同的是张量支持gpu运算

基本创建方式

torch.tensor()

torch.tensor()是pytorch中最为基础和常用的张量创建方式,以下为tensor()函数的参数设置

def tensor(data: Any, dtype: Optional[_dtype] = None, device: Device = None, requires_grad: _bool = False) -> Tensor:

可以看到有四个参数可以进行设置,分别是data(用于转换的值),dtype(指定数据类型),device(计算设备选择cpu/gpu),requires_grad(是否参与梯度计算),而函数的返回类型就是Tensor(张量)。这四个参数中必不可少的就是data,这里的data可以传入基本的数值类型如整形和浮点型,也可传入列表和元组(注意,这里不支持传入集合),并且也可传入ndarray类型。

data参数

若传入浮点型或整形数据

import torch

data1 = torch.tensor(10)
print(data1, data1.dtype)
data2 = torch.tensor(10.0)
print(data2, data2.dtype)
# tensor(10) torch.int64
# tensor(10.) torch.float32

由上可见,这里分别创建了两个标量张量,并且可以看到pytorch对整形和浮点数据的转换默认的数据类型分别为int64和float32

若传入容器类型数据或ndarray

import torch
import numpy as np

data1 = torch.tensor([1, 2, 3])
print(data1, data1.dtype)
data2 = torch.tensor((1, 2, 3))
print(data2, data2.dtype)
data3 = torch.tensor(np.array([1, 2, 3]))
print(data3, data3.dtype)
data4 = torch.tensor(np.array([1.0, 2.0, 3.0]))
print(data4, data4.dtype)
# tensor([1, 2, 3]) torch.int64
# tensor([1, 2, 3]) torch.int64
# tensor([1, 2, 3], dtype=torch.int32) torch.int32
# tensor([1., 2., 3.], dtype=torch.float64) torch.float64

由上述代码可以看出,若传入的是ndarrary数据类型,由于其底层默认整形数据为int32,浮点型数据为float64,所以在转换后,张量的精度也与其一样。

dtype参数

若要对创建张量的数据类型进行转换,只需指定dtype参数即可

import torch
import numpy as np

data1 = torch.tensor([1, 2, 3], dtype=torch.float32)
print(data1, data1.dtype)
data2 = torch.tensor((1, 2, 3), dtype=torch.float32)
print(data2, data2.dtype)
data3 = torch.tensor(np.array([1, 2, 3]), dtype=torch.float32)
print(data3, data3.dtype)
data4 = torch.tensor(np.array([1.0, 2.0, 3.0]), dtype=torch.float32)
print(data4, data4.dtype)
# tensor([1., 2., 3.]) torch.float32
# tensor([1., 2., 3.]) torch.float32
# tensor([1., 2., 3.]) torch.float32
# tensor([1., 2., 3.]) torch.float32
device参数 

对于device参数,参数设置一般为'cpu','cuda','cuda:0','cuda:1'...分别代指将张量放入cpu进行计算或放入gpu进行计算,而'cuda:0'表示第一块gpu,以此类推':1'表示第二块,如有多块gpu可以分别调用,注意,不在同一块设备上的张量不能参与运算

import torch

data1 = torch.tensor([1.0, 2.0, 3.0], device="cuda")
print(data1, data1.device)
data2 = torch.tensor((1.0, 2.0, 3.0), device="cuda")
print(data2, data2.device)
# tensor([1., 2., 3.], device='cuda:0') cuda:0
# tensor([1., 2., 3.], device='cuda:0') cuda:0

注意这里若只有一块gpu,则device参数使用'cuda'和'cuda:0'是等效的

在张量定义之后,也可以对张量的运算设备进行转换如使用cpu(),cuda(),to()函数

import torch

data1 = torch.tensor([1.0, 2.0, 3.0], device="cuda:0")
print(data1, data1.device)
data1 = data1.cpu()
print(data1, data1.device)
data1 = data1.cuda()
print(data1, data1.device)
data1 = data1.to("cpu")
print(data1, data1.device)
data1 = data1.to("cuda")
print(data1, data1.device)
# tensor([1., 2., 3.], device='cuda:0') cuda:0
# tensor([1., 2., 3.]) cpu
# tensor([1., 2., 3.], device='cuda:0') cuda:0
# tensor([1., 2., 3.]) cpu
# tensor([1., 2., 3.], device='cuda:0') cuda:0

注意,这里在设备切换后,需要重新赋值,切换函数本身不会修改并覆盖原本数据

一般在开源项目中都可以看到这样一行代码 

import torch

device = "cuda:0" if torch.cuda.is_available() else "cpu"
data1 = torch.tensor([1.0, 2.0, 3.0], device=device)
print(data1)
# tensor([1., 2., 3.], device='cuda:0')

这里为了在不同设备上运行项目,使用了三目运算符进行判定本地设备是否支持cuda,用于判断是否支持的函数就是torch.cuda.is_available(),支持返回True,否则返回False,那么这个三目运算符的作用就是在cuda支持的情况下使用'cuda:0'否则调用'cpu',关于三目运算符的详解可以参考我的另一篇博客CSDN

requires_grad参数

requires_grad参数的作用是设置创建的张量是否需要参与梯度计算,默认为False,也可以手动设置为True,注意,整形张量不支持求梯度。

import torch
import numpy as np

data1 = torch.tensor([1, 2, 3], requires_grad=True)
print(data1)
# Traceback (most recent call last):
#   File "D:\Pythonproject\teach_day_01\demo01.py", line 4, in <module>
#     data1 = torch.tensor([1,2,3],requires_grad=True)
#             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# RuntimeError: Only Tensors of floating point and complex dtype can require gradients
import torch

data1 = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
print(data1, data1.requires_grad)
data2 = torch.tensor([1.0, 2.0, 3.0])
print(data2, data2.requires_grad)
# tensor([1., 2., 3.], requires_grad=True) True
# tensor([1., 2., 3.]) False
torch.Tensor()

关于torch.Tensor()函数,现在一般很少使用,或者说并不建议使用,其相对于torch.tensor()的优势在于可以指定张量形状进行创建

import torch

data1 = torch.Tensor(2, 3)
print(data1)
# tensor([[-2.1118e+14,  1.5905e-42,  0.0000e+00],
#         [ 0.0000e+00,  0.0000e+00,  0.0000e+00]])

可以看到上述代码创建了一个两行三列的随机张量,这里的随机并不符合均匀分布或者正态分布,而是其内存位置上的原本任意值。

同样torch.Tensor()也支持传入数据进行张量转换,但是要注意,这里并不支持传入整形或者浮点型数据,只能传入列表、元组或者ndarray类型数据

import torch

data1 = torch.Tensor(3)
print(data1)
data2 = torch.Tensor(2.0)
print(data2)
# tensor([-1.4512e+25,  2.1398e-42,  0.0000e+00])
# Traceback (most recent call last):
#   File "D:\Pythonproject\teach_day_01\demo01.py", line 5, in <module>
#     data2 = torch.Tensor(2.)
#             ^^^^^^^^^^^^^^^^
# TypeError: new(): data must be a sequence (got float)

由上述代码可以看出data1在创建的时候参数3被识别为了要创建一个一维随机张量,长度为3,而data2在创建的时候可以看到报错中要求data要为一个序列,所以并不支持单数值作为参数使用

import torch
import numpy as np

data1 = torch.Tensor([1, 2, 3])
print(data1, data1.dtype)
data2 = torch.Tensor((1, 2, 3))
print(data2, data2.dtype)
data3 = torch.Tensor(np.array([1, 2, 3]))
print(data3, data3.dtype)
# tensor([1., 2., 3.]) torch.float32
# tensor([1., 2., 3.]) torch.float32
# tensor([1., 2., 3.]) torch.float32

上述代码演示了由列表、元组和ndarray作为参数的时候的情况,可以注意到的一点是,torch.Tensor()不会主动识别参数的数据类型,并且没有dtype参数设置来改变数据类型,所有数据最后都会变成float32数据类型,这也是目前不推荐使用Tensor()创建张量的原因

指定数据类型创建张量

张量的基本数据类型基本包括如下几种数据类型

ShortTensor

IntTensor

LongTensor

FloatTensor

DoubleTensor

上面五种类型分别对应torch.int16,torch.int32,torch.int64,torch.float32,torch.float64。

我们可以使用这几种类型进行指定进行张量的实例化

import torch

data1 = torch.ShortTensor([1.2, 2.3, 3.4])
data2 = torch.IntTensor([1.2, 2.3, 3.4])
data3 = torch.LongTensor([1.2, 2.3, 3.4])
data4 = torch.FloatTensor([1, 2, 3])
data5 = torch.DoubleTensor([1, 2, 3])
print(data1)
print(data2)
print(data3)
print(data4)
print(data5)
# tensor([1, 2, 3], dtype=torch.int16)
# tensor([1, 2, 3], dtype=torch.int32)
# tensor([1, 2, 3])
# tensor([1., 2., 3.])
# tensor([1., 2., 3.], dtype=torch.float64)

注意,上述的五个张量创建函数,都不支持在定义的时候设置requires_grad,都需要在定义完张量后再设置

import torch

data1 = torch.FloatTensor([1, 2, 3])
data1.requires_grad = True

print(data1)
# tensor([1., 2., 3.], requires_grad=True)

张量数据类型转换

张量在创建之后也是支持元素类型的转换的,具体的方法会short(),int(),long(),float(),double(),分别对应torch.int16,torch.int32,torch.int64,torch.float32,torch.float64的转换,要注意,该方法不会修改并覆盖原数据,需要重新赋值

import torch

data1 = torch.tensor([1, 2, 3])
data1 = data1.float()
print(data1, data1.dtype)

data1 = data1.short()
print(data1, data1.dtype)

data1 = data1.int()
print(data1, data1.dtype)

data1 = data1.double()
print(data1, data1.dtype)

data1 = data1.long()
print(data1, data1.dtype)
# tensor([1., 2., 3.]) torch.float32
# tensor([1, 2, 3], dtype=torch.int16) torch.int16
# tensor([1, 2, 3], dtype=torch.int32) torch.int32
# tensor([1., 2., 3.], dtype=torch.float64) torch.float64
# tensor([1, 2, 3]) torch.int64

创建全0、全1和全指定值张量

全0张量
torch.zeros()

torch.zeros()的作用是创建指定形状的全0张量,参数为创建张量的形状以及包括tensor()中的device,dtype,requires_grad参数

import torch

data1 = torch.zeros([2, 3])
print(data1)
data2 = torch.zeros(2, 3)
print(data2)
# tensor([[0., 0., 0.],
#         [0., 0., 0.]])
# tensor([[0., 0., 0.],
#         [0., 0., 0.]])

注意形状参数如为高维可以使用元组或者列表的形式,也可以不加括号

import torch

data1 = torch.zeros(2, 3, device="cuda", requires_grad=True, dtype=torch.float64)
print(data1)
# tensor([[0., 0., 0.],
#         [0., 0., 0.]], device='cuda:0', dtype=torch.float64,
#        requires_grad=True)
torch.zeros_like()

torch.zeros_like()的作用区别于torch.zeros()在于第一个参数,zeros()是形状,zeros_like()的第一个参数是另一个张量,作用是创建与其形状相同的全0张量,其余参数设置与zeros()相同

import torch

data1 = torch.tensor([1, 2, 3])
data2 = torch.zeros_like(data1, dtype=torch.float32, device="cuda", requires_grad=True)
print(data1)
print(data2)
# tensor([1, 2, 3])
# tensor([0., 0., 0.], device='cuda:0', requires_grad=True)
全1张量
torch.ones()

详情与torch.zeros()类似,区别为创建的是全1张量

import torch

data1 = torch.ones(2, 3, requires_grad=True, dtype=torch.float32, device="cuda")
print(data1)
# tensor([[1., 1., 1.],
#         [1., 1., 1.]], device='cuda:0', requires_grad=True)
torch.ones_like()

详情与torch.zeros_like()类似,区别为创建的是全1张量

import torch

data1 = torch.tensor([1, 2, 3])
data2 = torch.ones_like(data1, requires_grad=True, dtype=torch.float32, device="cuda")
print(data2)
# tensor([1., 1., 1.], device='cuda:0', requires_grad=True)
全指定值张量
torch.full()

torch.full()用于创建全指定值元素的张量,注意函数前两个参数分别为size和fill_value,所以这里的size若为高维需要使用元组或列表的形式,否则可能造成参数错位。其余参数也包括了device,dtype,requires_grad参数可以设置

import torch

data1 = torch.full((2, 3), 10, device="cuda", dtype=torch.float32, requires_grad=True)
print(data1)
# tensor([[10., 10., 10.],
#         [10., 10., 10.]], device='cuda:0', requires_grad=True)
torch.full_like()

torch.full_like()用于创建与另一张量相同形状的全指定值张量,与full()的区别在于第一个参数需要设置为用于模仿形状的张量

import torch

data1 = torch.tensor([1, 2, 3])
data2 = torch.full_like(
    data1, 10, device="cuda", dtype=torch.float32, requires_grad=True
)
print(data2)
# tensor([10., 10., 10.], device='cuda:0', requires_grad=True)

创建随机张量

torch.rand()

torch,rand()的作用是创建0-1区间内均匀分布的随机值,第一个参数为形状,高维可以使用列表或元组形式,也可不使用括号其余参数还包括device,dtype,requires_grad。

import torch

data1 = torch.rand(2, 3, device="cuda", dtype=torch.float64, requires_grad=True)
print(data1)
# tensor([[0.1615, 0.7415, 0.6346],
#         [0.3183, 0.6323, 0.9578]], device='cuda:0', dtype=torch.float64,
#        requires_grad=True)
torch.randn()

torch.randn()与torch.rand()的唯一区别为生成的是正态分布的0-1区间随机值

import torch

data1 = torch.randn(2, 3, device="cuda", dtype=torch.float64, requires_grad=True)
print(data1)
# tensor([[-1.1177, -0.6240, -1.4654],
#         [-0.6016,  0.1243, -0.2280]], device='cuda:0', dtype=torch.float64,
#        requires_grad=True)
torch.randint()

torch.randint()主要用于生成指定范围指定形状的随机整形张量,设计的主要参数包括low,high,size,分布对应了生成数值的下限,上限,和形状,注意,这里的生成范围为[low,high)也就是不包括上限的,并且生成的数据符合均匀分布

import torch

data1 = torch.randint(0, 10, (2, 3), device="cuda")
print(data1)
# tensor([[9, 0, 0],
#         [6, 4, 2]], device='cuda:0')
torch.empty()

torch.empty()的作用是生成指定形状的未初始化的随机张量,其值取决于先前内存中存储的随机值

import torch

data1 = torch.empty(2, 3, requires_grad=True)
print(data1)
# tensor([[0., 0., 0.],
#         [0., 0., 0.]], requires_grad=True)

其它常用的函数

uniform_()

uniform_()函数的作用是填充指定区间的符合均匀分布的随机数,参数未from,to分别代指生成随机数的左区间和右区间,生成的范围是[from,to),一般会跟在使用empty()创建的张量后进行数值填充

import torch

data1 = torch.tensor([1.0, 2.0, 3.0]).uniform_(0, 10)
print(data1)
data2 = torch.empty(2, 3).uniform_(0, 10)
print(data2)
# tensor([8.4342, 0.5614, 3.8917])
# tensor([[0.8433, 2.9977, 7.3362],
#         [5.8126, 3.4763, 0.8273]])

注意如果在张量定义时设置了requires_grad为True,我们不能直接使用uniform_进行赋值,需要使用detach()将节点从计算图中剥离再赋值,具体如下所示,可以注意到张量在detach()后会默认将requires_grad设置为False,这是因为detach()在剥离节点后返回的张量是不在计算图上的副本,但数值是与原张量共享内存的,关于detach()的详解后续会更新博客说明。

import torch

data1 = torch.tensor([1.0, 2.0, 3.0], requires_grad=True).detach().uniform_(0, 10)
print(data1)
data2 = torch.empty(2, 3, requires_grad=True).detach().uniform_(0, 10)
print(data2)
# tensor([4.7236, 4.9742, 4.2246])
# tensor([[2.0460, 9.2987, 8.7641],
#         [1.2816, 1.2288, 6.4062]])
normal_()

normal_()函数的作用是给张量填充符合特定正态分布的数值,参数有两个,mean和std,分别代表均值和标准差,用法和uniform_()类似,以下样例均以均值为1,标准差为10为例

import torch

data1 = torch.tensor([1.0, 2.0, 3.0]).normal_(1, 10)
print(data1)
data2 = torch.empty(2, 3).normal_(1, 10)
print(data2)
# tensor([ 14.6649,  -2.3475, -13.1385])
# tensor([[-2.9050,  7.1260,  6.4159],
#         [ 0.3098,  3.1476, -0.3499]])
import torch

data1 = torch.tensor([1.0, 2.0, 3.0], requires_grad=True).detach().normal_(1, 10)
print(data1)
data2 = torch.empty(2, 3, requires_grad=True).detach().normal_(1, 10)
print(data2)
# tensor([-0.1726, 21.7300, 12.0811])
# tensor([[ 5.9375, 14.9223, 18.2401],
#         [ 5.1840,  3.2753, -1.3274]])
torch.arange()

torch.arange()的作用就是类似与range()和np.arange(),用于生成一个能指定start,end,step也就是起点,终点,步长,范围为[start,end)

import torch

data1 = torch.arange(0, 10, 2)
print(data1)
# tensor([0, 2, 4, 6, 8])
torch.linspace()

torch.linspace()的作用就是生成一个符合等差数列的张量,lin为linear的缩写,也就是线性的,同样也是包括三个参数start,end,step也就是起点,终点,步长,范围为[start,end],但是这里的步长与arange()不同,这里的步长指的是等差数列中的元素个数

import torch

data1 = torch.linspace(0, 10, 8)
print(data1)
# tensor([ 0.0000,  1.4286,  2.8571,  4.2857,  5.7143,  7.1429,  8.5714, 10.0000])
torch.logspace()

torch.logspace()的作用是生成一个符合等比数列的张量,log为logarithmic的缩写,也就是对数的,同样也是包括三个参数start,end,step,base也就是起点,终点,步长,底数,范围为[base^start,base^end],如果不设置底数的话,base默认为10

import torch

data1 = torch.logspace(0, 10, 8)
data2 = torch.logspace(0, 10, 8, base=2)
print(data1)
print(data2)

# tensor([1.0000e+00, 2.6827e+01, 7.1969e+02, 1.9307e+04, 5.1795e+05, 1.3895e+07,
#         3.7276e+08, 1.0000e+10])
# tensor([1.0000e+00, 2.6918e+00, 7.2458e+00, 1.9504e+01, 5.2501e+01, 1.4132e+02,
#         3.8041e+02, 1.0240e+03])

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值