张量的创建及常用操作

创建tensor

几何代数中定义的张量是基于向量和矩阵的推广,比如可以将标量视为零阶张量,矢量可以视为一阶张量,矩阵就是二阶张量

使用torch.rand构造一个随机初始化的矩阵

import torch

x = torch.rand(4, 3)
print(x)
tensor([[0.9090, 0.0717, 0.6515],
        [0.5202, 0.4521, 0.5968],
        [0.2457, 0.9790, 0.5771],
        [0.3811, 0.2427, 0.6869]])

构造全零矩阵

x = torch.zeros(4, 3, dtype=torch.long)
print(x)
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])

将list转化为tensor

x = torch.tensor([5.5, 3])
print(x)
print(x.shape, x.size())
tensor([5.5000, 3.0000])
torch.Size([2]) torch.Size([2])

构造形状相同的矩阵

y = torch.ones_like(x)
y
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

张量的操作

加法操作

y = torch.rand(4, 3)
x = torch.ones_like(y)
# 方法一
print(x + y)

# 方法二
print(torch.add(x, y))

# 方法三, out-place
result = torch.empty_like(x)
print(torch.add(x, y, out=result))

# 方法四, in-place
y.add_(x)
print(y)
tensor([[1.7305, 1.0857, 1.2853],
        [1.8159, 1.0455, 1.8792],
        [1.8721, 1.7205, 1.7788],
        [1.5893, 1.9778, 1.6206]])
tensor([[1.7305, 1.0857, 1.2853],
        [1.8159, 1.0455, 1.8792],
        [1.8721, 1.7205, 1.7788],
        [1.5893, 1.9778, 1.6206]])
tensor([[1.7305, 1.0857, 1.2853],
        [1.8159, 1.0455, 1.8792],
        [1.8721, 1.7205, 1.7788],
        [1.5893, 1.9778, 1.6206]])
tensor([[1.7305, 1.0857, 1.2853],
        [1.8159, 1.0455, 1.8792],
        [1.8721, 1.7205, 1.7788],
        [1.5893, 1.9778, 1.6206]])

索引操作

需要注意的是:索引出来的结果与原数据共享内存,修改一个,另一个也会接着修改,如果不想修改,可以使用copy()等方法

x = torch.rand(3, 4)
x
tensor([[0.4065, 0.7128, 0.6444, 0.0308],
        [0.4295, 0.9147, 0.7969, 0.4274],
        [0.5885, 0.1450, 0.0452, 0.6621]])

取第二列

print(x[:, 1])
tensor([0.7128, 0.9147, 0.1450])

修改切片数据源数据也会被改

y = x[0, :]
y += 1
print(y)
print(x)
tensor([2.4065, 2.7128, 2.6444, 2.0308])
tensor([[2.4065, 2.7128, 2.6444, 2.0308],
        [0.4295, 0.9147, 0.7969, 0.4274],
        [0.5885, 0.1450, 0.0452, 0.6621]])

如果想改变一个tensor的大小或者形状,可以使用torch.view

x = torch.rand(4, 4)
y = x.view(16)
z = x.view(-1, 8)
print(x.shape, y.shape, z.shape)
torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])

注意view()返回的新tensor和源tensor是共享内存的,即改变了其中的一个,另外一个也会发生变化

x += 1  # 对x的所有数据都加1,观察y发现y的所有数据也都增加了一
print(x)
print(y)
tensor([[2.6332, 2.9636, 2.7696, 2.0887],
        [2.2007, 2.0402, 2.2890, 2.3280],
        [2.8369, 2.8077, 2.2749, 2.1647],
        [2.5960, 2.1254, 2.9193, 2.0021]])
tensor([2.6332, 2.9636, 2.7696, 2.0887, 2.2007, 2.0402, 2.2890, 2.3280, 2.8369,
        2.8077, 2.2749, 2.1647, 2.5960, 2.1254, 2.9193, 2.0021])

如果想直接返回一个真正的副本(即不共享内存),可以先使用clone()创造一个副本然后再使用view改变形状
使用clone的时候还有一个好处是会被记录在计算图中,即梯度回传到副本的时候也会被回传到源tensor

x = torch.rand(3, 3)
y = x.clone().view(-1)
y += 1
print(x, y)
tensor([[0.9508, 0.8564, 0.1388],
        [0.1186, 0.9064, 0.5860],
        [0.6449, 0.1584, 0.1335]]) tensor([1.9508, 1.8564, 1.1388, 1.1186, 1.9064, 1.5860, 1.6449, 1.1584, 1.1335])
# 对于只有一个值的tensor来说还可以使用.item()方法来获得tensor的value
x = torch.rand(1)
print(type(x))
print(type(x.item()))

# 对于有多个值的tensor来说可以使用.tolist()方法来获得tensor的value
x = torch.rand(3, 3)
print(type(x))
print(type(x.tolist()))
<class 'torch.Tensor'>
<class 'float'>
<class 'torch.Tensor'>
<class 'list'>

广播机制

当两个形状不同的Tensor按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使得两个Tensor有相同的形状之后再按元素运算

x = torch.arange(1, 3).view(1, 2)
y = torch.arange(1, 4).view(3, 1)
print(x)
print(y)
print(x + y)
tensor([[1, 2]])
tensor([[1],
        [2],
        [3]])
tensor([[2, 3],
        [3, 4],
        [4, 5]])

版权声明:本文为qq_46311811原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。