【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

posted @ 2021-01-06 14:44  XavierJ  阅读(729)  评论(0编辑  收藏  举报