【pytorch】一文读懂tensor张量(官方教程)
文章目录
1. 简介
Tensor(张量)是一种特殊的数据结构,与数组和矩阵非常相似。在PyTorch中,我们使用Tensor对模型的输入和输出以及模型的参数进行编码。Tensor与NumPy的ndarray非常相似,只是张量可以在GPU或其他专用硬件上运行以加速计算。如果您熟悉ndarray的话,Tensor的API对你来说也不会陌生,因为它们真的很像,几乎完全一样。如果不熟悉的话也没关系,请按照下面的快速演练进行操作。
2. 张量初始化
Tensor可以通过多种方式初始化。 看看下面的例子。
2.1. 直接从数据中创建
张量可以直接从数据创建。数据类型将自动推断。
>>> import torch
>>> data = [[1, 2], [3, 4]]
>>> tensor = torch.tensor(data)
>>> tensor.dtype
torch.int64
2.2. 从NumPy的array创建
张量也可以从NumPy的array创建。
>>> import torch
>>> import numpy as np
>>> np_array = np.array([[1, 2], [3, 4]])
>>> torch.from_numpy(np_array)
tensor([[1, 2],
[3, 4]], dtype=torch.int32)
2.3. 从另一个张量创建
除非显式重写,否则新的张量将包含参数张量的属性(形状,数据类型)。
>>> import torch
>>> x_data = torch.tensor([[1, 2], [3, 4]])
>>> torch.ones_like(x_data)
tensor([[1, 1],
[1, 1]])
>>> torch.rand_like(x_data, dtype=torch.float)
tensor([[0.5592, 0.7087],
[0.2888, 0.3338]])
2.4. 用随机或常量值初始化
shape
是一个表示张量维度的元组。在下面的函数中,它决定了输出张量的维度。
>>> import torch
>>> shape = (2, 3)
>>> torch.rand(shape)
tensor([[0.6550, 0.9232, 0.0042],
[0.0289, 0.8122, 0.1064]])
>>> torch.ones(shape)
tensor([[1., 1., 1.],
[1., 1., 1.]])
>>> torch.zeros(shape)
tensor([[0., 0., 0.],
[0., 0., 0.]])
3. 张量属性
张量属性描述了它们的形状,数据类型以及存储它们的设备。
>>> import torch
>>> tensor = torch.rand(2, 3)
>>> tensor
tensor([[0.3751, 0.4458, 0.7898],
[0.5268, 0.3546, 0.4721]])
>>> tensor.shape
torch.Size([2, 3])
>>> tensor.dtype
torch.float32
>>> tensor.device
device(type='cpu')
4. 张量运算
这里全面介绍了100多种张量运算方法,包括转置、索引、切片、数学运算、线性代数、随机抽样等。
它们每个都可以在GPU上运行(通常比在CPU上具有更高的速度)。 如果您使用的是Colab,请通过转到编辑>Notebook设置来分配GPU。
# 如果GPU可用,可以将张量移动到GPU上
if torch.cuda.is_available():
tensor = tensor.to('cuda')
尝试从列表中进行一些操作。 如果您熟悉NumPy API,则可以轻松使用Tensor API。
4.1. 索引切片
>>> import torch
>>> tensor = torch.ones(4, 4)
>>> tensor
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> tensor[:, 1] = 0
>>> tensor
tensor([[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.],
[1., 0., 1., 1.]])
4.2. 张量连接
您可以使用torch.cat
沿给定维度连接一系列张量。另请参阅torch.stack,这是另一个与torch.cat
稍有不同的张量连接操作。
>>> import torch
>>> a = torch.tensor([[1], [2]])
>>> b = torch.tensor([[3], [4]])
>>> torch.cat([a, b], dim=0)
tensor([[1],
[2],
[3],
[4]])
>>> torch.cat([a, b], dim=1)
tensor([[1, 3],
[2, 4]])
4.3. 张量乘法
简介也提到过:张量与数组和矩阵非常相似,数组可以理解为一维张量,矩阵可以理解为二维张量。因此,矩阵的一些乘法操作在二维张量里面也适用。
4.3.1. 矩阵数乘
数与矩相乘。
>>> import torch
>>> tensor = torch.tensor([[1, 2, 3],
... [4, 5, 6]])
>>>
>>> tensor.mul(2)
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
或者:
>>> import torch
>>> tensor = torch.tensor([[1, 2, 3],
... [4, 5, 6]])
>>>
>>> tensor*2
tensor([[ 2, 4, 6],
[ 8, 10, 12]])
4.3.2. 哈达马积
矩阵对应的元素相乘。要满足两个矩阵的大小相同才有意义,比如都是 M M M行 N N N列。
>>> import torch
>>> tensor = torch.tensor([[1, 2],
... [3, 4]])
>>>
>>> tensor.mul(tensor)
tensor([[ 1, 4],
[ 9, 16]])
或者:
>>> import torch
>>> tensor = torch.tensor([[1, 2],
... [3, 4]])
>>>
>>> tensor*tensor
tensor([[ 1, 4],
[ 9, 16]])
4.3.3. 矩阵乘法
矩阵与矩阵相乘,要满足第一个矩阵的列数和第二个矩阵的行数相等时才有意义。其次,你得了解矩阵乘法计算公式,如下:
A
=
[
a
11
a
12
a
13
a
21
a
22
a
23
]
A = \begin{bmatrix} a_{11} \quad a_{12} \quad a_{13} \\ a_{21} \quad a_{22} \quad a_{23} \end{bmatrix}
A=[a11a12a13a21a22a23]
B
=
[
b
11
b
12
b
21
b
22
b
31
b
32
]
B= \begin{bmatrix} b_{11} \quad b_{12} \\ b_{21} \quad b_{22} \\ b_{31} \quad b_{32} \\ \end{bmatrix}
B=⎣⎡b11b12b21b22b31b32⎦⎤
C
=
A
B
=
[
a
11
b
11
+
a
12
b
21
+
a
13
b
31
,
a
11
b
12
+
a
12
b
22
+
a
13
b
32
a
21
b
11
+
a
22
b
21
+
a
23
b
31
,
a
21
b
12
+
a
22
b
22
+
a
23
b
32
]
C=AB= \begin{bmatrix} a_{11}b_{11}+a_{12}b_{21}+a_{13}b_{31}, \quad a_{11}b_{12}+a_{12}b_{22}+a_{13}b_{32}\\ a_{21}b_{11}+a_{22}b_{21}+a_{23}b_{31}, \quad a_{21}b_{12}+a_{22}b_{22}+a_{23}b_{32} \end{bmatrix}
C=AB=[a11b11+a12b21+a13b31,a11b12+a12b22+a13b32a21b11+a22b21+a23b31,a21b12+a22b22+a23b32]
>>> import torch
>>> tensor = torch.tensor([[1, 2],
... [3, 4]])
>>>
>>> tensor.matmul(tensor)
tensor([[ 7, 10],
[15, 22]])
或者
>>> import torch
>>> tensor = torch.tensor([[1, 2],
... [3, 4]])
>>>
>>> tensor@tensor
tensor([[ 7, 10],
[15, 22]])
5. In-place
翻译过来就是就地操作。什么是就地操作呢?就是在原张量上直接更改,后缀为_
的操作就是就地操作。例如:x.copy_(y)
, x.t_()
,都将更改x
的值。
>>> import torch
>>> tensor = torch.ones(3, 3)
>>> tensor.add(1)
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
>>> tensor
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
>>> tensor.add_(1)
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
>>> tensor
tensor([[2., 2., 2.],
[2., 2., 2.],
[2., 2., 2.]])
可以看到,直接使用torch.add(1)
函数,张量的值会加1,但张量本身不会发生改变。而使用torch.add_(1)
是直接在张量上进行加1操作,会改变张量的值。
注意:
就地操作可以节省一些内存,但是在计算导数时可能会因为立即丢失历史记录而出现问题。 因此,不鼓励使用它们。
6. 与NumPy桥接
在CPU上的张量和NumPy数组可以共享其基础内存地址,更改一个将改变另一个。
6.1. Tensor转NumPy array
>>> import torch
>>> t = torch.ones(5)
>>> t
tensor([1., 1., 1., 1., 1.])
>>> n = t.numpy()
>>> n
array([1., 1., 1., 1., 1.], dtype=float32)
张量的变化也将反映在NumPy数组中。
>>> import torch
>>> t = torch.ones(5)
>>> t.add_(1)
tensor([2., 2., 2., 2., 2.])
>>> n = t.numpy()
>>> n
array([2., 2., 2., 2., 2.], dtype=float32)
6.2. NumPy array转Tensor
>>> import torch
>>> import numpy as np
>>> n = np.ones(5)
>>> n
array([1., 1., 1., 1., 1.])
>>> t = torch.from_numpy(n)
>>> t
tensor([1., 1., 1., 1., 1.], dtype=torch.float64)
NumPy数组的变化也将反映在张量中。
>>> import torch
>>> import numpy as np
>>> n = np.ones(5)
>>> np.add(n, 1, out=n)
array([2., 2., 2., 2., 2.])
>>> t = torch.from_numpy(n)
>>> t
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
7. 原文
https://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html