Tensors
Tensors (opens new window)
Tensor 中文为张量。张量的意思是一个多维数组,它是标量、向量、矩阵的高维扩展。
标量可以称为 0 维张量,向量可以称为 1 维张量,矩阵可以称为 2 维张量,RGB 图像可以表示 3 维张量。你可以把张量看作多维数组。

Tensor 与 Variable
在 PyTorch 0.4.0 之前,torch.autograd 包中存在 Variable 这种数据类型,主要是用于封装 Tensor,进行自动求导。Variable 主要包含下面几种属性。
data: 被包装的 Tensor。
grad: data 的梯度。
grad_fn: 创建 Tensor 所使用的 Function,是自动求导的关键,因为根据所记录的函数才能计算出导数。
requires_grad: 指示是否需要梯度,并不是所有的张量都需要计算梯度。
is_leaf: 指示是否叶子节点(张量),叶子节点的概念在计算图中会用到,后面详细介绍。

在 PyTorch 0.4.0 之后,Variable 并入了 Tensor。在之后版本的 Tensor 中,除了具有上面 Variable 的 5 个属性,还有另外 3 个属性。
- dtype: 张量的数据类型,如 torch.FloatTensor,torch.cuda.FloatTensor。
- shape: 张量的形状。如 (64, 3, 224, 224)
- device: 张量所在设备 (CPU/GPU),GPU 是加速计算的关键

关于 dtype,PyTorch 提供了 9 种数据类型,共分为 3 大类:float (16-bit, 32-bit, 64-bit)、integer (unsigned-8-bit ,8-bit, 16-bit, 32-bit, 64-bit)、Boolean。模型参数和数据用的最多的类型是 float-32-bit。label 常用的类型是 integer-64-bit。

tensor 创建方法
函数 | 功能 |
---|---|
Tensor(sizes) | 基础构造函数 |
tensor(data) | 类似于 np.array |
ones(sizes) | 全 1 |
zeros(sizes) | 全 0 |
eye(sizes) | 对角为 1,其余为 0 |
arange(s,e,step) | 从 s 到 e,步长为 step |
linspace(s,e,steps) | 从 s 到 e,均匀分成 step 份 |
rand/randn(sizes) | rand 是[0,1)均匀分布;randn 是服从 N(0,1)的正态分布 |
normal(mean,std) | 正态分布(均值为 mean,标准差是 std) |
randperm(m) | 随机排列 |
直接创建
torch.tensor()
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
data:
数据,可以是 list,numpy
dtype:
数据类型,默认与 data 的一致
device:
所在设备,cuda/cpu
requires_grad:
是否需要梯度
pin_memory:
是否存于锁页内存
代码示例:
ndarray = np.ones((3, 3))
print("ndarray的数据类型:", ndarray.dtype)
# 创建存放在 GPU 的数据
# t = torch.tensor(ndarray, device='cuda')
t= torch.tensor(ndarray)
print(t)
2
3
4
5
6
输出为:
ndarray的数据类型: float64
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]], device='cuda:0', dtype=torch.float64)
2
3
4
指定类型函数随机创建
out_a = torch.FloatTensor(2,3)
out_b = torch.IntTensor(2)
out_c = torch.IntTensor([1,2,3,4])
print(out_a,'\n',out_b,'\n',out_c)
2
3
4
输出为:
tensor([[1.9964e-16, 4.5898e-41, 2.0081e-32],
[0.0000e+00, 0.0000e+00, 0.0000e+00]])
tensor([627453024, 32754], dtype=torch.int32)
tensor([1, 2, 3, 4], dtype=torch.int32)
2
3
4
tensor 和 numpy array 之间的相互转换
torch.from_numpy(ndarray)
从 numpy 创建 tensor。利用这个方法创建的 tensor 和原来的 ndarray 共享内存,当修改其中一个数据,另外一个也会被改动。

代码示例:
arr = np.array([[1, 2, 3], [4, 5, 6]])
t = torch.from_numpy(arr)
# 修改 array,tensor 也会被修改
# print("\n修改arr")
# arr[0, 0] = 0
# print("numpy array: ", arr)
# print("tensor : ", t)
# 修改 tensor,array 也会被修改
print("\n修改tensor")
t[0, 0] = -1
print("numpy array: ", arr)
print("tensor : ", t)
2
3
4
5
6
7
8
9
10
11
12
13
14
输出为:
修改tensor
numpy array: [[-1 2 3]
[ 4 5 6]]
tensor : tensor([[-1, 2, 3],
[ 4, 5, 6]], dtype=torch.int32)
2
3
4
5
根据数值创建
torch.zeros()
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:根据 size 创建全 0 张量
- size: 张量的形状
- out: 输出的张量,如果指定了 out,那么
torch.zeros()
返回的张量和 out 指向的是同一个地址 - layout: 内存中布局形式,有 strided,sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用。
- device: 所在设备,cuda/cpu
- requires_grad: 是否需要梯度
代码示例:
out_t = torch.tensor([1])
# 这里制定了 out
t = torch.zeros((3, 3), out=out_t)
print(t, '\n', out_t)
# id 是取内存地址。最终 t 和 out_t 是同一个内存地址
print(id(t), id(out_t), id(t) == id(out_t))
2
3
4
5
6
输出是:
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
2984903203072 2984903203072 True
2
3
4
5
6
7
torch.zeros_like()
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False, memory_format=torch.preserve_format)
功能:根据 input 形状创建全 0 张量
- input: 创建与 input 同形状的全 0 张量
- dtype: 数据类型
- layout: 内存中布局形式,有 strided,sparse_coo 等。当是稀疏矩阵时,设置为 sparse_coo 可以减少内存占用。
同理还有全 1 张量的创建方法:torch.ones()
,torch.ones_like()
。
torch.full() | torch.full_like()
torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建自定义数值的张量
- size: 张量的形状,如 (3,3)
- fill_value: 张量中每一个元素的值
代码示例:
t = torch.full((3, 3), 1)
print(t)
2
输出为:
tensor([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
2
3
torch.arange()
torch.arange(start=0, end, step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建等差的 1 维张量。注意区间为[start, end)。
- start: 数列起始值
- end: 数列结束值,开区间,取不到结束值
- step: 数列公差,默认为 1
代码示例:
t = torch.arange(2, 10, 2)
print(t)
2
输出为:
tensor([2, 4, 6, 8])
torch.rand()
torch.rand
是 PyTorch 中用于生成具有均匀分布随机数的函数。这个函数返回一个填充了从区间 [0, 1) 中均匀抽取的随机数的张量。
torch.rand(*size, *, generator=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False, pin_memory=False) → Tensor
torch.rand
的参数说明如下:
- sizes (int...): 这是一个整数序列,用于定义输出张量的形状。例如,
torch.rand(3, 4)
会返回一个形状为 3x4 的张量,其中每个元素都是 [0, 1) 区间内的随机数。 - out (Tensor, optional): 如果提供了这个参数,那么生成的随机数会被存放在提供的张量
out
中。如果out
已有内容,则会被新生成的随机数覆盖。 - dtype (torch.dtype, optional): 期望的输出张量的数据类型。如果没有提供,则使用默认的浮点数据类型(通常是
torch.float32
)。 - layout (torch.layout, optional): 期望的输出张量的内存布局。默认是
torch.strided
。 - device (torch.device, optional): 期望的输出张量所在的设备。可以是 CPU 或 GPU。如果没有提供,则使用当前默认的张量设备。
- requires_grad (bool, optional): 如果设置为
True
,则生成的张量将需要计算梯度,这在自动微分中是必要的。默认为False
。
下面是一个简单的示例,演示了如何使用 torch.rand
:
import torch
# 生成一个形状为 (2, 3) 的张量,其中的元素是从 [0, 1) 区间内均匀抽取的随机数
tensor = torch.rand(2, 3)
print(tensor)
2
3
4
5
输出可能类似于:
tensor([[0.1234, 0.5678, 0.9012],
[0.3456, 0.7890, 0.2345]])
2
每次调用 torch.rand
时,即使使用相同的形状和参数,得到的张量中的值也可能会有所不同,因为这些值是随机生成的。
torch.linspace()
torch.linspace(start, end, steps=100, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建均分的 1 维张量。数值区间为 [start, end]
- start: 数列起始值
- end: 数列结束值
- steps: 数列长度 (元素个数)
代码示例:
# t = torch.linspace(2, 10, 5)
t = torch.linspace(2, 10, 6)
print(t)
2
3
输出为:
tensor([ 2.0000, 3.6000, 5.2000, 6.8000, 8.4000, 10.0000])
torch.logspace()
torch.logspace(start, end, steps=100, base=10.0, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建对数均分的 1 维张量。数值区间为 [start, end],底为 base。
- start: 数列起始值
- end: 数列结束值
- steps: 数列长度 (元素个数)
- base: 对数函数的底,默认为 10
代码示例:
# t = torch.logspace(2, 10, 5)
t = torch.logspace(2, 10, 6)
print(t)
2
3
输出为:
tensor([ 2.0000, 3.6000, 5.2000, 6.8000, 8.4000, 10.0000])
torch.eye()
torch.eye(n, m=None, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
功能:创建单位对角矩阵( 2 维张量),默认为方阵
- n: 矩阵行数。通常只设置 n,为方阵。
- m: 矩阵列数
根据概率创建
torch.randn
torch.randn([3,4])
创建 3 行 4 列的随机数的 tensor,随机值的分布式均值为 0,方差为 1
torch.randn(*size, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
返回一个张量,包含了从标准正态分布(均值为 0,方差为 1,即高斯白噪声)中抽取一组随机数,形状由可变参数sizes
定义。 参数:
- sizes (int...) – 整数序列,定义了输出形状
- out (Tensor (opens new window), optinal) - 结果张量
>>> torch.randn(2, 3)
1.4339 0.3351 -1.0999
1.5458 -0.9643 -0.3558
[torch.FloatTensor of size 2x3]
2
3
4
5
PyTorch 中 tensor 的常用方法
查看 tensor 维度信息
out = torch.randn(2, 3)
print(out.size())
print(out.shape)
2
3
输出为:
torch.Size([2, 3])
torch.Size([2, 3])
2
tensor.size()
广播机制
当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。
x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
2
3
4
5
tensor([[1, 2]])
tensor([[1],
[2],
[3]])
tensor([[2, 3],
[3, 4],
[4, 5]])
2
3
4
5
6
7
tensor([[1, 2]])
tensor([[1],
[2],
[3]])
tensor([[2, 3],
[3, 4],
[4, 5]])
2
3
4
5
6
7
由于 x 和 y 分别是 1 行 2 列和 3 行 1 列的矩阵,如果要计算 x+y,那么 x 中第一行的 2 个元素被广播 (复制)到了第二行和第三行,⽽ y 中第⼀列的 3 个元素被广播(复制)到了第二列。如此,就可以对 2 个 3 行 2 列的矩阵按元素相加。
CUDA 中的 tensor
CUDA(Compute Unified Device Architecture),是 NVIDIA 推出的运算平台。 CUDA™ 是一种由 NVIDIA 推出的通用并行计算架构,该架构使 GPU 能够解决复杂的计算问题。
torch.cuda
这个模块增加了对 CUDA tensor 的支持,能够在 cpu 和 gpu 上使用相同的方法操作 tensor
通过.to
方法能够把一个 tensor 转移到另外一个设备(比如从 CPU 转到 GPU)
x = torch.randn(1,2)
if torch.cuda.is_available():
device = torch.device("cuda") # cuda device对象
y = torch.ones_like(x, device=device) # 创建一个在cuda上的tensor
x = x.to(device) # 使用方法把x转为cuda 的tensor
z = x + y
print(z)
print(z.to("cpu", torch.double)) # .to方法也能够同时设置类型
2
3
4
5
6
7
8
输出为:
tensor([[ 1.9796, -0.8879]], device='cuda:0')
tensor([[ 1.9796, -0.8879]], dtype=torch.float64)
2
torch.numel()
torch.numel()
是 PyTorch 中用于计算张量(tensor)中元素总数的函数。它不接受任何参数,因为它直接作用于调用它的张量。
import torch
# 创建一个张量
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 使用 torch.numel() 计算张量中的元素总数
num_elements = tensor.numel()
print(num_elements) # 输出:6
2
3
4
5
6
7
8
9
注意事项
torch.numel()
是张量的一个方法,而不是一个独立的函数。因此,你需要先有一个张量对象,然后才能调用这个方法。torch.numel()
返回一个整数,表示张量中的元素总数。- 与
torch.size()
或tensor.shape
不同,torch.numel()
返回的是张量中所有维度的元素总数,而不是各维度的大小。例如,对于一个形状为[a, b, c]
的三维张量,torch.numel()
将返回a * b * c
。