Tensor,又名张量,是pytorch、tensorflow、Theano等深度学习框架中重要的数据结构。关于张量的本质,我们可以简单的认为就是一个数组,它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)、多维数组…,pytorch的tensor支持GPU加速。
在ipython或者notebook中,使用function?方法或者help(function)方法可以查看一个函数的帮助文档,比如构造参数等等,以torch的save方法为例:
(1)function?方法
输入torch.save?
,shift+enter即可得到它的帮助文档
Docstring:
ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
Returns a tensor filled with the scalar value `1`, with the shape defined
by the variable argument :attr:`size`.
Args:
size (int...): a sequence of integers defining the shape of the output tensor.
Can be a variable number of arguments or a collection like a list or tuple.
out (Tensor, optional): the output tensor.
dtype (:class:`torch.dtype`, optional): the desired data type of returned tensor.
Default: if ``None``, uses a global default (see :func:`torch.set_default_tensor_type`).
layout (:class:`torch.layout`, optional): the desired layout of returned Tensor.
Default: ``torch.strided``.
device (:class:`torch.device`, optional): the desired device of returned tensor.
Default: if ``None``, uses the current device for the default tensor type
(see :func:`torch.set_default_tensor_type`). :attr:`device` will be the CPU
for CPU tensor types and the current CUDA device for CUDA tensor types.
requires_grad (bool, optional): If autograd should record operations on the
returned tensor. Default: ``False``.
Example::
>>> torch.ones(2, 3)
tensor([[ 1., 1., 1.],
[ 1., 1., 1.]])
>>> torch.ones(5)
tensor([ 1., 1., 1., 1., 1.])
Type: builtin_function_or_method
(2)help(function)方法
help(torch.save)
,enter+shift也可得到其帮助文档
需要注意的是,在使用上述两种方法的时候,一定要加上模块名,比如torch.save
,若只输入save?或help(save)则会提示NameError: name 'save' is not defined
。
对tensor的操作常分为两类:
(1)通过torch对tensor进行操作,即torch.function , 如torch.save
等。
(2)直接对tensor操作,即tensor.function,如tensor.view
等。
实际上torch提供的绝大多数的方法同时支持这两种接口,比如torch.sum(a,b)
(a,b均为tensor类型),与a.sum(b)是等同的。
在另外一方面,对tensor的操作即可以改变自身的值,也可以不改变自身的值。区别在于函数名以_结尾的都会改变自身的值,使用时要加以区分。
(1)不改变自身的值:如a.add(b)
,处理后的结果存储在一个新的tensor中
(2)改变自身的值:如a.add_(b
),处理完的结果存储在a中,也就是说,a被修改了。
需要注意的是,在使用下述第一种方法创建tensor时,系统不会马上分配空间,只会计算剩余的内存是否足够使用,使用到tensor时才会分配。而其他几种操作都会在创建完tensor后马上分配空间。
tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False) -> Tensor
参数:
data:Tensor的初始数据,可以是列表、元组、numpy、ndarray、scalar等等
dtype:所需的返回张量的类型,从data可以推断,默认为None
device:所需的返回张量的设备,默认为tensor类型对应的当前设备。如果是cpu类型的tensor,device为cpu,而如果是cuda类型的张量,则device是cuda设备
requires_grad:说明当前张量是否需要在计算中保留对应的梯度信息,默认为False
pin_memory:表示是否属于锁页内存,锁页内存存放的内容在任何情况下都不会与主机的虚拟内存进行交换(注:虚拟内存就是硬盘)默认为False。一般来说,若计算机内存充足,可以设置pin_memory=True。
>>> torch.tensor([[0.11111, 0.222222, 0.3333333]],
dtype=torch.float64,
device=torch.device('cuda:0')) # creates a torch.cuda.DoubleTensor
tensor([[ 0.1111, 0.2222, 0.3333]], dtype=torch.float64, device='cuda:0')
ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数:
size:定义输出张量形状的整数序列。可以是可变数目的参数,也可以是像列表或元组这样的集合。
out:输出的结果张量。可以看到把张量a作为out参数,新创建的全为1的张量覆盖了a的原来的值。
In [7]: a=torch.tensor([1,2])
In [8]: print(a)
tensor([1, 2])
In [9]: b=torch.ones([3,5],out=a)
In [10]: print(b)
tensor([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]])
In [11]: print(a)
tensor([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]])
例:
>>> torch.ones(2, 3)
tensor([[ 1., 1., 1.],
[ 1., 1., 1.]])
>>> torch.ones(5)
tensor([ 1., 1., 1., 1., 1.])
layout:返回张量的所需布局。默认值:torch.strided
至于dtype和device以及requires_grad三个参数请参见torch.tensor()函数。
zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数请参见torch.ones()函数
>>> torch.zeros(2, 3)
tensor([[ 0., 0., 0.],
[ 0., 0., 0.]])
>>> torch.zeros(5)
tensor([ 0., 0., 0., 0., 0.])
eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数:
n:整数,矩阵行数
m:整数,表示矩阵列数,默认为n
其余参数与前几种方法类似。
例:
>>> torch.eye(3)
tensor([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数:
start:tensor的起始数据,默认为0
end:tensor的终点数据
step:步长值,默认为1
其余参数与上述类似。
需要注意的是,在start与end构成的区间里通过步长值取值是左闭右开的,比如说start=0,end=2,那么得到的tensor为[0,1],end的2是取不到的。
例:
>>> torch.arange(5)
tensor([ 0, 1, 2, 3, 4])
>>> torch.arange(1, 4)
tensor([ 1, 2, 3])
>>> torch.arange(1, 2.5, 0.5)
tensor([ 1.0000, 1.5000, 2.0000])
linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数:
steps:在start与end构成的区间均匀划分的份数,默认为100.
其余参数与上述类似。但与arange()方法不同的是,该方法start与end形成的区间两个端点都要取到。
Example::
>>> torch.linspace(3, 10, steps=5)
tensor([ 3.0000, 4.7500, 6.5000, 8.2500, 10.0000])
>>> torch.linspace(-10, 10, steps=5)
tensor([-10., -5., 0., 5., 10.])
>>> torch.linspace(start=-10, end=10, steps=5)
tensor([-10., -5., 0., 5., 10.])
>>> torch.linspace(start=-10, end=10, steps=1)
tensor([-10.])
rand: 返回由区间[0,1)
上均匀分布的随机数填充的张量
rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
randn:返回由正态分布中的随机数填充的张量均值为“0”,方差为“1”(也称为标准正态分配)
randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
参数:
size: 返回张量的形状,可以是数,元组或者列表
其余参数请参见上述函数
>>> torch.rand(2, 3)
tensor([[ 0.8237, 0.5781, 0.6879],
[ 0.3816, 0.7249, 0.0998]])
>>> torch.randn(2, 3)
tensor([[ 1.5954, 2.8929, -1.0923],
[ 1.1719, -0.4709, -0.1996]])
normal:返回随机数的张量,所述随机数取自独立的正态分布,其均值和标准差均已给定。
normal(mean, std, out=None) -> Tensor
参数:
mean:各输出元素正态分布的均值
std:各输出元素正态分布的标准差
Example::
>>> torch.normal(mean=torch.arange(1., 11.), std=torch.arange(1, 0, -0.1))
tensor([ 1.0425, 3.5672, 2.7969, 4.2925, 4.7229, 6.2134,
8.0505, 8.1408, 9.0563, 10.0566])
uniform:将tensor用从区间[from,to]均匀分布中抽样得到的值填充。
uniform_(from=0, to=1) → Tensor
example:
In [26]: a=torch.Tensor(2,3).uniform_(-1,1)
In [27]: print(a)
tensor([[ 0.4314, -0.5970, 0.1675],
[-0.5439, 0.9027, 0.1656]])
0
到n-1
的整数的随机排列。randperm(n, out=None, dtype=torch.int64, layout=torch.strided, device=None, requires_grad=False) -> LongTensor
参数:
n:上限(不含)
Example::
>>> torch.randperm(4)
tensor([2, 1, 0, 3])
list -->tensor,把list作为tensor的data参数即可
In [3]: a=[[1,2],[3,4]]
In [4]: b=torch.tensor(a)
In [5]: print(b)
tensor([[1, 2],
[3, 4]])
tensor–>list,使用tolist()方法
In [6]: print(b.tolist())
[[1, 2], [3, 4]]
tensor.size()返回torch.Size对象,它是tuple的子类。
In [7]: b_size=b.size()
In [8]: b_size
Out[8]: torch.Size([2, 2])
我们可以使用得到的b_size构建一个新的tensor,它的形状和b的形状一致
In [12]: c=torch.Tensor(b_size)
In [13]: c
Out[13]:
tensor([[0., 0.],
[0., 0.]])
另外,tensor.numel()和tensor.nelement()可以计算tensor中元素总个数
至于tensor.shape(),它其实就等价于tensor.size()
通过tensor.view()方法可以调整tensor的形状,但必须保证调整前后元素总数一致。view不会修改自身的数据,返回的新的tensor共享内存,即更改其中一个,另一个也随之改变。
In [16]: b.view(1,4)
Out[16]: tensor([[1, 2, 3, 4]])
squeeze和unsqueeze方法则可以添加或减少某一维度。
unsqueeze:增加维度,参数表示增加的位置,若为负数,表示倒数的位置,比如说unsqueeze(-1),表示在倒数第一个维度增加“1”
In [27]: b.unsqueeze(2).size()
Out[27]: torch.Size([2, 2, 1])
In [28]: b.unsqueeze(0).size()
Out[28]: torch.Size([1, 2, 2])
squeeze();减少维度
参数意义与unsqueeze类似。而tensor.qqueeze则表示把所有维度为‘1’的压缩。
resize是另一种可以调整size的方法,但与view不同,它可以修改tensor的尺寸,如果新尺寸超过了原尺寸,会自动分配新的内存空间,而如果新尺寸小于原尺寸,则之前的数据依旧会被保存。
In [65]: a
Out[65]:
tensor([[1, 2],
[3, 4]])
In [66]: a.resize_(3,3)
Out[66]:
tensor([[1, 2, 3],
[4, 0, 0],
[0, 0, 0]])
tensor索引操作得到的结果一般情况下与原tensor共享内存,也就是说,修改一个另一个会随之改变。
通用表达式:a[m:n,i:j]
其中‘,’之前的m、n表示行索引,i、j表示列索引,若没有逗号后面的列索引,则表示取从m到n(不含)行,比如a[:2]
,表示取前两行,但实际上我们可以注意到,在a[:2]
这个表达式中m也被省略了,事实上m,i的默认值都为0,那么我们如何取某几列呢,同样的,把m和n省去即可,但这时应注意,‘,’和m、n之间的‘:’不可省去。
In [67]: a=torch.randn(3,4)
In [68]: a
Out[68]:
tensor([[-0.2629, -0.0373, 0.7344, 0.6874],
[ 0.2065, -1.5565, -0.8811, -0.2437],
[-0.7666, 0.4774, -0.8461, -1.3079]])
In [69]: a[0]
Out[69]: tensor([-0.2629, -0.0373, 0.7344, 0.6874])
In [70]: a[:,1:2]
Out[70]:
tensor([[-0.0373],
[-1.5565],
[ 0.4774]])
(1)index_select(input,dim,index) 在指定维度dim上选取,例如选取某些行,某些列input即为输入的要操作的tensor,dim指定操作的维度,若dim=0,则选取行,若dim=1,则选取列,而index规定了选取范围。
Example::
>>> x = torch.randn(3, 4)
>>> x
tensor([[ 0.1427, 0.0231, -0.5414, -1.0009],
[-0.4664, 0.2647, -0.1228, -1.1068],
[-1.1734, -0.6571, 0.7230, -0.6004]])
>>> indices = torch.tensor([0, 2])
>>> torch.index_select(x, 0, indices)
tensor([[ 0.1427, 0.0231, -0.5414, -1.0009],
[-1.1734, -0.6571, 0.7230, -0.6004]])
>>> torch.index_select(x, 1, indices)
tensor([[ 0.1427, -0.5414],
[-0.4664, -0.1228],
[-1.1734, 0.7230]])
(2)masked_select(input,mask)
masked_select(input, mask, out=None) -> Tensor
根据掩码张量mask中的二元值,取输入张量中的指定项( mask为一个 ByteTensor),将取值返回到一个新的1维张量(张量 mask须跟input张量有相同数量的元素数目,但形状或维度不需要相同。)
(3)nonzero(input),返回非零元素的下标
Example::
>>> torch.nonzero(torch.tensor([1, 1, 1, 0, 1]))
tensor([[ 0],
[ 1],
[ 2],
[ 4]])