张量

数据操作

在深度学习中,我们通常会频繁的去对数据进行操作。

创建Tensor(张量)

1)先介绍一下Tensor的最基本的功能,即Tensor的创建。

首先就是导入PyTorch:

1
2
3
# 创建一个5x3的未初始化的 Tensor
x = torch.empty(5, 3)
print(x)
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
1
2
3
# 创建一个5x3的随机初始化的Tensor
x = torch.rand(5, 3)
print(x)
tensor([[0.7852, 0.0743, 0.0271],
        [0.6014, 0.5902, 0.8844],
        [0.0410, 0.6901, 0.8871],
        [0.0437, 0.0626, 0.5687],
        [0.9419, 0.7970, 0.9925]])
1
2
3
# 创建一个5x3的long型全0的Tensor
x = torch.zeros(5, 3, dtype = torch.long)
print(x)
tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
1
2
3
# 还可以直接根据数据来创建
x = torch.tensor([4.5, 3])
print(x)
tensor([4.5000, 3.0000])
1
2
3
4
5
6
7
# 还可以通过现有的Tensor来创建,此方法会默认重用输入Tensor的一些属性,
# 例如 数据类型,除非自定义数据类型
x = x.new_ones(5, 3, dtype = torch.float64)
print(x)

x = torch.randn_like(x, dtype = torch.float)
print(x)
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
tensor([[ 0.5578, -0.0502,  2.0930],
        [-0.9528, -0.6031, -0.0405],
        [ 0.1853, -0.7159, -1.0291],
        [ 1.0159, -0.3431, -0.3712],
        [-0.1306,  0.7387, -0.6336]])
1
2
3
4
5
# 我们还可以通过 shape 或者size() 来获取Tensor的形状
print(x.size())
print(x.shape)
# 注意:返回的torch.Size其实就是一个tuple(元组), 支持所有tuple的操作
# 在 Python 中,tuple(元组)是一种不可变的序列数据类型。
torch.Size([5, 3])
torch.Size([5, 3])

还有很多函数可以创建Tensor,去翻翻官方API就知道了,下表给了一些常用的作参考。

函数 功能
Tensor(*sizes) 基础构造函数
tensor(data,) 类似np.array的构造函数
ones(*sizes) 全1Tensor
zeros(*sizes) 全0Tensor
eye(*sizes) 对角线为1,其他为0
arange(s,e,step) 从s到e,步长为step
linspace(s,e,steps) 从s到e,均匀切分成steps份
rand/randn(*sizes) 均匀/标准分布
normal(mean,std)/uniform(from,to) 正态分布/均匀分布
randperm(m) 随机排列

操作

这里学习Tensor的各种操作

算术操作

在PyTorch中,同一种操作可能有很多形式,下面使用加法作为例子。

1
y = torch.rand(5, 3)
  • 加法形式1
1
print(x + y)
  • 加法形式2
1
print(torch.add(x, y))
  • 加法形式3
1
2
3
result = torch.empty(5, 3)
torch.add(x, y, out = result)
print(result)
  • 加法形式4
1
2
y.add_(x)
print(y)

索引

1)我们还可以使用类似NumPy的索引来操作访问Tensor的一部分,需要注意的是:索引出来的结果与元数据共享内存,也即修改一个,另一个也会跟着改变。

1
2
3
4
y = x[0, :]
y += 1
print(y)
print(x[0, :])

2)处理常用的索引选择数据之外,PyTorch还提供了一些高级的选择函数:

函数 功能
index_select(input, dim, index) 在指定维度dim上选取,比如选取某些行、某些列
masked_select(input, mask) 例子如上,a[a>0],使用ByteTensor进行选取
nonzero(input) 非0元素的下标
gather(input, dim, index) 根据index,在dim维度上选取数据,输出的size与index一样

这里不详细介绍,用到了再查官方文档。

改变形状

用view()来改变Tensor的形状

1
2
3
y = x.view(15)
z = x.view(-1, 5) # -1所指的维度可以根据其他维度的值推出来
print(x.size(), y.size(), z.size())

注意view(),返回的新的Tensor与源Tensor虽然可能有些不同的size,但是是共享data的,也就是说,改变其中一个,另一个也会跟着改变。**(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)**

1
2
3
x += 1
print(x)
print(y) # 也加了1

所以如果我们想返回一个真正新的副本(即不共享data内存)该怎么办呢?Pytorch还提供了一个reshape()可以改变形状,但是此函数并不能保证返回的是其拷贝,所以不推荐使用。推荐先用clone创造一个副本然后再使用view

1
2
3
4
x_cp = x.clone().view(15)
x -= 1
print(x)
print(x_cp)

张量
http://example.com/2024/09/02/深度学习/张量/
作者
JcenLeung
发布于
2024年9月2日
许可协议