目录
前言
张量 Tensor
PyTorch 中的 张量(Tensor) 是多维数组的核心数据结构,类似于 NumPy 的 ndarray
,但具备 GPU 加速计算和自动微分(Autograd)的能力。
1. 张量的基本概念
- 定义:张量是 PyTorch 中表示多维数据的容器,可以看作是多维数组。
- 0维张量:标量(Scalar),如
tensor(3.14)
- 1维张量:向量(Vector),如
tensor([1, 2, 3])
- 2维张量:矩阵(Matrix),如
tensor([[1, 2], [3, 4]])
- 3维及以上:高维张量,如
tensor([[[1, 2], [3, 4]]])
- 0维张量:标量(Scalar),如
2. 创建张量
PyTorch 提供了多种创建张量的方式:
从 Python 列表或 NumPy 数组
import torch
import numpy as np
# 从列表创建
a = torch.tensor([1, 2, 3]) # 1维张量
b = torch.tensor([[1, 2], [3, 4]]) # 2维张量
# 从 NumPy 数组创建
np_array = np.array([1, 2, 3])
c = torch.from_numpy(np_array) # 共享内存(修改一个会影响另一个)
生成特定形状的张量
# 全零张量
zeros = torch.zeros(2, 3) # 2行3列的全零矩阵
# 全一张量
ones = torch.ones(2, 3) # 2行3列的全一矩阵
# 随机张量(均匀分布)
rand = torch.rand(2, 3) # 0~1之间的随机数
# 随机张量(正态分布)
randn = torch.randn(2, 3) # 均值为0,标准差为1
# 等差序列
arange = torch.arange(0, 10, 2) # tensor([0, 2, 4, 6, 8])
指定设备(CPU/GPU)
# 将张量放在 GPU 上(需有可用 GPU)
if torch.cuda.is_available():
gpu_tensor = torch.tensor([1, 2, 3], device="cuda:0")
指定数据类型(dtype)
# 指定数据类型为 float32
float_tensor = torch.tensor([1, 2, 3], dtype=torch.float32)
3. 张量的属性
每个张量有三个核心属性:
shape
:张量的维度形状。x = torch.rand(2, 3) print(x.shape) # 输出 torch.Size([2, 3])
dtype
:张量的数据类型(如float32
,int64
等)。print(x.dtype) # 输出 torch.float32
device
:张量所在的设备(CPU 或 GPU)。print(x.device) # 输出 cpu 或 cuda:0
4. 张量的操作
数学运算
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])
# 加法
c = a + b # 或 torch.add(a, b)
# 乘法(逐元素相乘)
d = a * b # tensor([4, 10, 18])
# 矩阵乘法
mat1 = torch.rand(2, 3)
mat2 = torch.rand(3, 2)
matmul = torch.matmul(mat1, mat2) # 或 mat1 @ mat2
形状操作
x = torch.rand(2, 3)
# 改变形状(不改变数据)
y = x.view(3, 2) # 变为3行2列(需保证元素总数一致)
# 转置
z = x.T # 行变列,列变行
# 增加/减少维度
x = torch.unsqueeze(x, dim=0) # 在第0维增加一维,形状变为 [1, 2, 3]
x = torch.squeeze(x) # 删除所有长度为1的维度
索引与切片
与 NumPy 类似:
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
print(x[0, 1]) # 输出 2(第0行第1列)
print(x[:, 1:3]) # 输出所有行的第1到2列
广播机制(Broadcasting)
PyTorch 支持自动广播,允许不同形状的张量进行运算:
a = torch.tensor([[1, 2, 3]]) # 形状 [1, 3]
b = torch.tensor([4, 5, 6]) # 形状 [3]
c = a + b # 自动广播为 [1,3] + [3] → [1,3] + [1,3]
5. 自动微分(Autograd)
PyTorch 张量支持自动微分(通过 requires_grad=True
):
x = torch.tensor([2.0], requires_grad=True)
y = x ** 2 + 3 * x + 1
y.backward() # 计算梯度
print(x.grad) # 输出导数 dy/dx = 2x + 3 → 7.0
6. 与 NumPy 的互操作
张量和 NumPy 数组可以互相转换:
# 张量 → NumPy 数组
tensor = torch.tensor([1, 2, 3])
numpy_array = tensor.numpy() # 共享内存
# NumPy 数组 → 张量
new_tensor = torch.from_numpy(numpy_array)
7. 张量的存储
张量的底层数据存储在连续的内存块中,可以通过 storage()
访问:
x = torch.tensor([[1, 2], [3, 4]])
print(x.storage()) # 输出底层存储的1D数组 [1, 2, 3, 4]
你提到的 .item()
和 .tolist()
是 PyTorch 张量中常用的方法,用于将张量转换为 Python 原生的数据类型(如标量或列表)。以下是它们的详细说明和典型应用场景:
8. 其他方法
1. .item()
方法
-
作用:
将 单元素张量(即形状为[]
或[1]
的张量)转换为 Python 的标量(int
,float
,bool
等)。 -
适用场景:
当张量中只包含一个数值时,提取该数值(例如计算损失值后提取标量结果)。 -
示例:
import torch # 标量张量(0维) x = torch.tensor(3.14) print(x.item()) # 输出 3.14(Python float) # 单元素张量(1维) y = torch.tensor([5]) print(y.item()) # 输出 5(Python int)
-
注意事项:
- 如果张量包含多个元素,调用
.item()
会报错:z = torch.tensor([1, 2]) # z.item() # 报错:ValueError: only one element tensors can be converted to Python scalars
- 如果张量包含多个元素,调用
2. .tolist()
方法
-
作用:
将张量转换为 Python 列表(多维张量会转换为嵌套列表)。
所有元素会被转换为 Python 的原生数据类型(如int
,float
)。 -
适用场景:
需要将张量数据导出为 Python 原生结构(例如保存到 JSON 文件,或与其他非 PyTorch 库交互)。 -
示例:
# 1维张量 → 列表 a = torch.tensor([1, 2, 3]) print(a.tolist()) # 输出 [1, 2, 3] # 2维张量 → 嵌套列表 b = torch.tensor([[1, 2], [3, 4]]) print(b.tolist()) # 输出 [[1, 2], [3, 4]] # 包含浮点数的张量 c = torch.tensor([1.5, 2.7]) print(c.tolist()) # 输出 [1.5, 2.7]
-
注意事项:
- 转换后的列表与原张量 不共享内存。
- 支持任意维度的张量(会生成嵌套列表)。
.numpy()
方法
- 作用:将张量转换为 NumPy 数组(与原张量共享内存)。
- 示例:
x = torch.tensor([1, 2, 3]) np_array = x.numpy() # 转换为 NumPy 数组
- 注意:如果张量在 GPU 上,需要先移动到 CPU:
x = x.cpu().numpy()
.data
属性
- 作用:获取张量的数据(返回一个无梯度的新张量)。
- 示例:
x = torch.tensor([1.0], requires_grad=True) y = x.data # y 是普通张量,无梯度信息