使用Pytorch操作张量(多维数组)
初始化
Pythorch对应的包是torch,在使用前需要安装torch包。
python
import torch
我们可以通过 arange 函数来快速初始化一个 0~n 的一维数组:
python
x=torch.arange(12)
print(x)
# tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
然后通过 reshape 函数来重新构建一个数组的形状:
python
x=torch.arange(12)
print("x= ",x)
# 也可以通过 x.reshape(3,4) 来实现,'-1'表示自动计算
y=x.reshape(3,-1)
print("y= ",y)
print("x= ",x)
# x= tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# y= tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
# x= tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
对于一个数组,我们可以通过 shape 函数来获取其形状:
python
print("x.shape= ",x.shape)
print("y.shape= ",y.shape)
# x.shape= torch.Size([12])
# y.shape= torch.Size([3, 4])
可以通过 numel 函数来获取一个数组的元素数量:
python
print("x.numel= ",x.numel())
print("y.numel= ",y.numel())
# x.numel= 12
# y.numel= 12
如果想要快速构建一个元素全为0或元素全为1的数组,可以通过 zeros 或 ones 函数:
python
# 注意这是一个3维数组
x=torch.zeros(2,3,4)
print("x= ",x)
# x= tensor([[[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]],
#
# [[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]]])
y=torch.ones(2,3,4)
print("y= ",y)
# y= tensor([[[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]],
#
# [[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]]])
我们也可以通过 randn 函数,来构建一个数组,其元素随机取自 均值为0、标准差为1 的高斯分布:
均值为0、标准差为1 的高斯分布,也就是标准正态分布。
python
x=torch.randn(3,4)
print("x= ",x)
# x= tensor([[ 1.6662, 1.0917, 0.5183, 0.7725],
# [-0.3504, -0.3056, 1.4037, -0.5792],
# [-0.4681, 0.1452, 0.9675, 0.8223]])
当然,你也可以自己指定一个数组,通过 tensor :
python
x=torch.tensor([[1,1,1],[2,2,2]])
print("x= ",x)
# x= tensor([[1, 1, 1],
# [2, 2, 2]])
运算
对于常见运算:加(+)、减(-)、乘(*)、除(/)、幂(**),必需要两个形状相同的数组进行运算,其运算过程就是将两个数组对应位置上的元素进行运算:
python
x=torch.tensor([[1,1,1],[2,2,2]])
y=torch.tensor([[2,2,2],[3,3,3]])
print(x+y)
# tensor([[3, 3, 3],
# [5, 5, 5]])
print(x-y)
# tensor([[-1, -1, -1],
# [-1, -1, -1]])
print(x*y)
# tensor([[2, 2, 2],
# [6, 6, 6]])
print(x/y)
# tensor([[0.5000, 0.5000, 0.5000],
# [0.6667, 0.6667, 0.6667]])
print(x**y)
# tensor([[1, 1, 1],
# [8, 8, 8]])
其实参与运算的两个数组也不一定要完全形状相同,这里有一个 广播 机制。可以理解为,对于两个形状相同的数组,如果某个数组缺失了某一维度,可以直接将该数组另一个维度复制过来,补充上缺失的维度:
python
x=torch.tensor([1,1,1])
y=torch.tensor([[2,2,2],[3,3,3]])
print(x+y)
# tensor([[3, 3, 3],
# [4, 4, 4]])
# 可以看到,这里的数组x,本来(相对于数组y)缺失了一个维度,但在计算过程中通过复制,补充成了:[[1,1,1],[1,1,1]]
# 但对于这种情况,就会报错
x=torch.tensor([[1,1,1],[3,3,3]])
y=torch.tensor([[2,2,2],[3,3,3],[4,4,4]])
print(x+y)
# 因为广播机制只会对长度为1的维度进行补充。上面的数组x的维度0的长度为2,估不适用广播机制
我们也可以对两个数据进行拼接,通过 cat 函数:
python
# dim=0 表示拼接第0轴(第0维)
print(torch.cat((x,y),dim=0))
# tensor([[1, 1, 1],
# [2, 2, 2],
# [2, 2, 2],
# [3, 3, 3]])
# dim=1 表示拼接第1轴(第1维)
print(torch.cat((x,y),dim=1))
# tensor([[1, 1, 1, 2, 2, 2],
# [2, 2, 2, 3, 3, 3]])
我们当然也可以对两个数组进行比较:
python
x=torch.tensor([[1,1,1],[2,2,2]])
y=torch.tensor([[2,1,2],[3,2,3]])
# 分别比较每个元素
print(x==y)
# tensor([[False, True, False],
# [False, True, False]])
print(x>y)
# tensor([[False, False, False],
# [False, False, False]])
print(x<y)
# tensor([[ True, False, True],
# [ True, False, True]])
对一个数组调用 sum 函数,可以得到该数组的所有元素之和:
python
x=torch.tensor([[1,1,1],[2,2,2]])
print(x.sum())
# tensor(9)
索引
我们可以像索引一维数组一样,索引多维数组:
python
x=torch.arange(12).reshape(-1,4)
print(x)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
# 取最后一个元素
print(x[-1])
# tensor([ 8, 9, 10, 11])
print(x[-1][-1])
# tensor(11)
# 取从 索引1到索引2的元素(后面是开区间:[1,2))
print(x[1:2])
# tensor([[4, 5, 6, 7]])
# 取第0维的索引0到索引2的元素,然后取第1维的全部元素
print(x[0:2][:])
# tensor([[0, 1, 2, 3],
# [4, 5, 6, 7]])
当然也可以像赋值一维数组一样,赋值多维数组:
python
x=torch.arange(12).reshape(-1,4)
print(x)
# tensor([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
# 最后一个元素
x[-1]=9
print(x)
# tensor([[0, 1, 2, 3],
# [4, 5, 6, 7],
# [9, 9, 9, 9]])
x[-1][-1]=0
print(x)
# tensor([[0, 1, 2, 3],
# [4, 5, 6, 7],
# [9, 9, 9, 0]])
# 索引1到索引2的元素(后面是开区间:[1,2))
x[1:2]=0
print(x)
# tensor([[0, 1, 2, 3],
# [0, 0, 0, 0],
# [9, 9, 9, 0]])
# 第0维的索引0到索引2的元素,然后是第1维的全部元素
x[0:2][:]=-1
print(x)
# tensor([[-1, -1, -1, -1],
# [-1, -1, -1, -1],
# [ 9, 9, 9, 0]])