Tensor
Tensor又名张量是PyTorch中重要的数据结构,可认为是一个高维数组。它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)或更高维的数组。Tensor和numpy的ndarrays类似,但Tensor可以使用GPU加速。下面通过几个例子了解Tensor的基本用法:
from __future__ import print_function
import torch as t
x=t.rand(5,3)
print(x)
#输出为
tensor([[0.2413, 0.3471, 0.0982],
[0.5920, 0.7532, 0.4236],
[0.5827, 0.9651, 0.7479],
[0.5994, 0.1697, 0.8942],
[0.2575, 0.9214, 0.8885]])
若要查看x的形状可通过以下两种方式:
1.print(x.size())
2.x.size()[0],x.size()[1]
#第一种方法
print(x.size())
#第二种方法
x.size()[0],x.size()[1]
#输出分别为:
torch.Size([5, 3])
(5, 3)
下面给出一个例子:
print('最初y')
print(y)
print('第一种加法,y的结果')
y.add(x)#普通加法不改变y的内容
print(y)
print('第二种加法,y的结果')
y.add_(x)#y改变了
print(y)
#其运行结果为:
最初y
tensor([[0.0494, 0.5277, 0.6374],
[0.0373, 0.8295, 0.9684],
[0.6179, 0.1679, 0.6150],
[0.0594, 0.8679, 0.8903],
[0.2588, 0.2327, 0.4701]])
第一种加法,y的结果
tensor([[0.0494, 0.5277, 0.6374],
[0.0373, 0.8295, 0.9684],
[0.6179, 0.1679, 0.6150],
[0.0594, 0.8679, 0.8903],
[0.2588, 0.2327, 0.4701]])
第二种加法,y的结果
tensor([[0.2908, 0.8747, 0.7355],
[0.6293, 1.5827, 1.3920],
[1.2006, 1.1330, 1.3629],
[0.6588, 1.0375, 1.7846],
[0.5163, 1.1541, 1.3586]])
由上述例子可以发现:函数名后边带下划线_的函数会修改Tensor本身。例如:x.add_(y)和x.t_()会改变x的值,但x.add(y)和x.t()会返回一个新的Tensor,而x不变。
另外Tensor和numpy的数组间的互操作非常容易且快速。Tensor不支持的操作,可以先转为numpy数组处理,之后再转回Tensor。
常用Tensor操作:
通过tensor.view方法可以调整tensor的形状,但必须保证调整前后元素总数一致。view不会修改自身的数据,返回的新tensor和源tensor共享内存,即更改其中一个,另一个也会跟着改变。在实际应用中可能经常需要添加或者减少某一维度,这时squeeze和unsqueeze两个函数就派上了用场。
a=t.arange(0,6)
a.view(2,3)
b=a.view(-1,3)
b
#其输出分别为
tensor([[0, 1, 2],
[3, 4, 5]])
tensor([[0, 1, 2],
[3, 4, 5]])
其中,b=a.view(-1,3)表示将张量‘a’改变为一个包含3列的的二维张量,而行数会根据原始张量的大小自动计算。具体而言,‘-1’表示自动计算该维度的大小,以使得其他维度的元素总数保持不变。在这个例子中,‘a’张量的元素总数是6,因此‘-1’被解释为‘6/3=2’,即将b变为一个2行3列的二维张量。
b.unsqueeze(1)
b.unsqueeze(-2)
#其输出分别为
tensor([[[0, 1, 2]],
[[3, 4, 5]]])
tensor([[[0, 1, 2]],
[[3, 4, 5]]])
在pytorch中,‘unsqueeze’方法用于在张量的指定位置插入一个新的维度。在本例中,b.unsqueeze(1)将在‘b’张量的第一维度(索引为1的维度,从0开始)上插入一个新的维度。具体而言,如果‘b’的形状为(2,3),那么b.unsqueeze(1)将在维度1上插入一个新维度,形状将变为(2,1,3)。
resize是另外一种可用来调整size的方法,但与view不同,它可以修改Tensor的尺寸。如果新尺寸超过了原尺寸,会自动分配新的内存空间,而如果新尺寸小于原尺寸,则之前的数据依旧会被保存:
b.resize_(1,3)
b.resize_(3,3)
#其结果分别为
tensor([[0, 1, 2]])
tensor([[ 0, 1, 2],
[ 3, 4, 5],
[2914514450426197026, 2318281922439043931, 2314885866833337650]])
索引操作
Tensor支持与numpy.ndarray类似的索引操作,语法上也类似。下边通过一些例子展现常用的索引操作。如无特殊说明,索引出来的结果与原tensor共享内存,即修改一个另一个也会跟着改变。
a=t.randn(3,4)
a
#其输出结果为
tensor([[-0.9061, -0.0364, 1.8696, -0.7673],
[ 1.6485, 0.0897, -0.0847, -1.9825],
[ 0.0994, -1.4814, -0.0781, 0.1053]])
#进行索引操作
a[0]#第0行,下标从0开始
#其输出为
tensor([-0.9061, -0.0364, 1.8696, -0.7673])
a[:,0]#第0列
#其输出为
tensor([-0.9061, 1.6485, 0.0994])
a[0][2]#第0行第3个元素,等价于a[0,2]
#其输出为
tensor(1.8696)
a[:2]#前两行
#其输出为
tensor([[-0.9061, -0.0364, 1.8696, -0.7673],
[ 1.6485, 0.0897, -0.0847, -1.9825]])
a[:2,0:2]#前两行,0,1列
#其输出为
tensor([[-0.9061, -0.0364],
[ 1.6485, 0.0897]])