创建Tensor的四种方式

dqn 数据特征 pytorch代码 pytorch tensor.data_数据

这四种方式的区别:

首先看torch.Tensor(data)torch.tensor(data)torch.Tensor(data)表示的是类构造函数,而torch.tensor(data)表示的是工厂函数,我们可以将工厂函数看作是接收参数输入并返回特定类型对象的函数,在这个例子中是张量对象,使用工厂函数的目的是可以创建更多的动态对象。

事实上另外两个函数torch.as_tensortorch.from_numpy也是工厂函数。

dqn 数据特征 pytorch代码 pytorch tensor.data_python_02


可以看出他们之间的差异存在于数据类型不同,因为构造函数在构造一个张量时使用全局缺省值,而工厂函数则根据输入推断数据类型。我们可以根据get_default_dtype方法来验证,看看dtype的全局缺省值是否确实是float32

dqn 数据特征 pytorch代码 pytorch tensor.data_pytorch_03


我们确实看到,float32是默认的dtype。另一方面,工厂函数是根据传入的数据选择一个dtype,这就是所谓的类型判断,dtype是根据传入的数据推断出来的:

dqn 数据特征 pytorch代码 pytorch tensor.data_dqn 数据特征 pytorch代码_04

我们也可以显式地设置数据类型:

dqn 数据特征 pytorch代码 pytorch tensor.data_python_05


可以看出,我们这里的dtype是float64的,即使传入的数据是int类型。

所有的工厂函数都允许我们显式地设置像这样的数据类型,但是构造函数没有这样的功能。

torch.Tensor、torch.tensor、torch.as_tensor、torch.from_numpy区别

dqn 数据特征 pytorch代码 pytorch tensor.data_深度学习_06


dqn 数据特征 pytorch代码 pytorch tensor.data_数据_07


可以看出来t1,t2在改变数组后并不影响张量数据,然而,第二组两个张量t3,t4包含了更改之后的数组中的相同数据,这种差异是由于在每个创建选项中分配内存的方式造成的。

t1,t2在内存中创建一个额外的输入数据副本,而t3,t4在内存中共享数据。

所以,torch.as_tensor()torch.from_numpy()可以共享数据,而torch.tensor()torch.Tensor()是拷贝数据。

共享数据比复制数据更有效,使用更少的内存,因为数据内有写到内存中的两个位置,而是只有一个位置。这就证明了torch.as_tensortorch.from_numpy的输入数据共享了内存。

那么我们应该用哪一个呢?
最好的选择是torch.tensor(),这个方法经常使用;如果我们要对性能进行呢调优,我们还需要使用第二种方法,就是内存共享,最好的方式就是torch.as_tensor(),为什么这个比torch.from_numpy()要好呢?原因很简单,torch.as_tensor()函数可以接受任何像Python数据结构这样的数据,而torch.from_numpy调用只接受numpy数组

从numpy中引入数据

a = numpy.array([2,3.3])
torch.from_numpy(a) # tensor([2.0000, 3.3000], dtype=torch.float64)

a = numpy.ones([2,3])
torch.from_numpy(a)
# tensor([[1., 1., 1.],
#        [1., 1., 1.]], dtype=torch.float64)

从list中引入数据

torch.tensor([2, 3.2]) # tensor([2.0000, 3.2000])
torch.FloatTensor([2, 3.2]) # tensor([2.0000, 3.2000])
torch.FloatTensor(2, 3) # 随机生成两行三列的数据,注意与FloatTensor([2, 3.2])的区别

细节

在PyTorch中可以使用FloatTensorTensor来创建张量,那么Tensor代表的是什么类型呢?在PyTorch中有一个默认的类型FloatTensor,可以通过自定义进行修改:torch.set_default_tensor_type(torch.DoubleTensor)

torch.tensor([1.2, 3]).type() # 'torch.FloatTensor'
torch.set_default_tensor_type(torch.DoubleTensor)
torch.tensor([1.2, 3]).type() # 'torch.DoubleTensor'

在增强学习中使用DoubleTensor比较多。

rand随机初始化

rand会随机产生0~1之间的数值,不包括1

torch.rand(3,3) # 会随机产生0~1之间的数值,不包括1
# tensor([[0.1549, 0.0633, 0.9588],
#        [0.8376, 0.4593, 0.7707],
#        [0.1973, 0.0879, 0.7441]])
torch.randint(1, 10, [3,3]) # 第一个参数是最小值(包括),第二个参数是最大值(不包括),第三个参数是shape
#tensor([[9, 3, 1],
#        [7, 6, 3],
#        [9, 9, 9]])

产生正态分布N(0,1)表示均值为0,方差为1:

torch.randn(3,3)
#tensor([[ 0.4423, -0.1191,  0.5476],
#        [-1.0675, -1.2120, -0.5078],
#        [ 1.0311,  0.5760, -1.5498]])

full赋值

torch.full([2,3],7) # 创建2*3的矩阵,并每个数据都赋值为7
#tensor([[7, 7, 7],
#        [7, 7, 7]])

torch.full([],7.1) # 生成一个标量,值为tensor(7.1000)
torch.full([2],7.1) # tensor([7.1000, 7.1000])

递增/递减

torch.arange(0,10) # tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
torch.arange(0,10,2) # tensor([0, 2, 4, 6, 8])
torch.range(0,10) # 不推荐使用,tensor([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.])

torch.linspace(0,10, steps=4) # tensor([ 0.0000,  3.3333,  6.6667, 10.0000]) 平均切割为4份

torch.logspace(0,-1,steps=10) # 以10位底的log,参数从0到-1分割为10份
#tensor([1.0000, 0.7743, 0.5995, 0.4642, 0.3594, 0.2783, 0.2154, 0.1668, 0.1292,
#        0.1000])

全0,全1,单位矩阵

torch.ones(3,3) # 全1
#tensor([[1., 1., 1.],
#        [1., 1., 1.],
#        [1., 1., 1.]])

torch.zeros(3,3) # 全0
#tensor([[0., 0., 0.],
#        [0., 0., 0.],
#        [0., 0., 0.]])

torch.eye(3,4) # 单位矩阵
#tensor([[1., 0., 0., 0.],
#        [0., 1., 0., 0.],
#        [0., 0., 1., 0.]])

randperm随机生成10个索引

torch.randperm(10) #tensor([6, 4, 7, 3, 1, 5, 2, 8, 9, 0])
a=torch.randn(3,3)
b=torch.randn(2,2)
idx=torch.randperm(2)
a[idx]
b[idx]