文章目录
什么是张量?
张量(Tensors)是 PyTorch 中的核心数据结构,类似于数组和矩阵,但具有更强大的功能。在深度学习中,我们使用张量来表示:
- 模型的输入和输出数据
- 模型的参数(权重和偏置)
- 中间计算过程中的数据
张量与 NumPy 的 ndarrays 类似,但有两大关键优势:
- GPU 加速:可在 GPU 或其他硬件加速器上运行
- 自动微分:支持自动求导,这对深度学习至关重要
import torch
import numpy as np
张量初始化方法
1. 直接从数据创建
data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)
2. 从 NumPy 数组转换
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
3. 基于现有张量创建
x_ones = torch.ones_like(x_data) # 保留原始张量属性
x_rand = torch.rand_like(x_data, dtype=torch.float) # 覆盖数据类型
print(f"Ones Tensor:\n{x_ones}")
print(f"Random Tensor:\n{x_rand}")
4. 使用随机值或常量
shape = (2, 3)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)
print(f"Random Tensor:\n{rand_tensor}")
print(f"Ones Tensor:\n{ones_tensor}")
print(f"Zeros Tensor:\n{zeros_tensor}")
张量属性
每个张量都有三个关键属性:
tensor = torch.rand(3, 4)
print(f"Shape: {tensor.shape}") # 形状
print(f"Datatype: {tensor.dtype}") # 数据类型
print(f"Device: {tensor.device}") # 存储设备 (CPU/GPU)
张量操作
设备转移
# 转移到GPU(如果可用)
device = "cuda" if torch.cuda.is_available() else "cpu"
tensor = tensor.to(device)
print(f"Device after transfer: {tensor.device}")
索引和切片
tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:, 1] = 0 # 修改第二列
print(tensor)
连接张量
t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(f"Concatenated tensor:\n{t1}")
算术运算
# 矩阵乘法(三种等效方式)
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)
y3 = torch.rand_like(y1)
torch.matmul(tensor, tensor.T, out=y3)
# 逐元素乘法(三种等效方式)
z1 = tensor * tensor
z2 = tensor.mul(tensor)
z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)
单元素张量转换
agg = tensor.sum()
agg_item = agg.item() # 转换为Python标量
print(f"Sum value: {agg_item}, Type: {type(agg_item)}")
原地操作(In-place Operations)
原地操作直接修改张量内容,使用 _
后缀表示:
print("Original tensor:")
print(tensor)
tensor.add_(5) # 原地加5
print("\nAfter in-place addition:")
print(tensor)
注意:虽然原地操作节省内存,但在自动微分中可能导致梯度计算问题,应谨慎使用。
PyTorch 与 NumPy 互操作
张量转 NumPy 数组
t = torch.ones(5)
n = t.numpy()
print(f"Tensor: {t}\nNumPy: {n}")
# 修改张量会影响NumPy数组
t.add_(1)
print(f"\nAfter modification:\nTensor: {t}\nNumPy: {n}")
NumPy 数组转张量
n = np.ones(5)
t = torch.from_numpy(n)
print(f"NumPy: {n}\nTensor: {t}")
# 修改NumPy数组会影响张量
np.add(n, 1, out=n)
print(f"\nAfter modification:\nNumPy: {n}\nTensor: {t}")
张量操作总结表
操作类型 | 方法示例 | 说明 |
---|---|---|
创建 | torch.tensor() , torch.rand() , torch.zeros() |
多种初始化方式 |
属性 | .shape , .dtype , .device |
获取张量元数据 |
索引 | tensor[0] , tensor[:, 1] |
类似NumPy的索引 |
运算 | torch.matmul() , tensor.sum() |
矩阵运算和归约 |
连接 | torch.cat() , torch.stack() |
合并多个张量 |
转换 | .numpy() , torch.from_numpy() |
与NumPy互转 |
最佳实践与注意事项
- 设备管理:明确张量所在的设备(CPU/GPU),避免不必要的设备间传输
- 数据类型:注意操作中的数据类型一致性,使用
.dtype
检查 - 内存共享:PyTorch 和 NumPy 数组共享内存,修改一个会影响另一个
- 自动微分:避免在需要梯度的计算图中使用原地操作
- 性能优化:对大规模数据使用 GPU 加速,对小规模操作可能 CPU 更高效
# 高效设备转移示例
if torch.cuda.is_available():
tensor = tensor.to('cuda')
# 保持数据类型一致
float_tensor = torch.rand(3, dtype=torch.float32)
int_tensor = torch.tensor([1, 2, 3], dtype=torch.int32)
result = float_tensor + int_tensor.float() # 显式转换
掌握张量操作是使用 PyTorch 进行深度学习的基础。通过本文介绍的各种方法,您可以高效地创建、操作和转换张量,为构建复杂模型奠定坚实基础!
官方文档:https://docs.pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html