PyTorch张量(Tensor)操作手册:多维数据容器深度解析(二)

一、张量核心概念解析

1.1 张量本质剖析

张量是PyTorch的核心数据结构,是具有统一数据类型(dtype)的多维矩阵,其数学定义可表示为:
T ∈ R d 1 × d 2 × ⋯ × d n T \in \mathbb{R}^{d_1 \times d_2 \times \cdots \times d_n} TRd1×d2××dn
其中 d i d_i di 表示第i个维度的长度。与NumPy数组相比,张量具有两大核心优势:

  1. GPU加速计算能力
  2. 自动微分支持(Autograd)

1.2 张量元信息三要素

t = torch.randn(3, 4, 5)
print(f"形状: {
      
      t.shape}")      # torch.Size([3, 4, 5])
print(f"数据类型: {
      
      t.dtype}")  # torch.float32
print(f"存储设备: {
      
      t.device}")  # cpu/cuda:0

二、张量创建全方法详解

2.1 直接构造法

# 从Python列表创建(自动推断类型)
t1 = torch.tensor([[1., 2], [3, 4]]) 

# 显式指定参数创建
t2 = torch.tensor([1, 2, 3], 
                 dtype=torch.float64,
                 device='cuda',
                 requires_grad=True)

# 特殊矩阵生成
diag_tensor = torch.diag(torch.tensor([1,2,3]))  # 对角矩阵
linspace_t = torch.linspace(0, 10, 5)  # 线性空间采样

2.2 工厂函数创建法

函数 功能描述 数学原理
torch.empty(3,3) 未初始化矩阵 分配内存但不设置初始值
torch.zeros_like(x) 创建与x同形的全0张量 T i j = 0 T_{ij} = 0 Tij=0
torch.randperm(10) 生成随机排列 Fisher-Yates洗牌算法
torch.logspace() 对数均分采样 1 0 s t a r t ∼ 1 0 e n d 10^{start} \sim 10^{end} 10start10end

2.3 NumPy互操作进阶

# 内存共享验证实验
np_arr = np.array([1, 2, 3])
t = torch.from_numpy(np_arr)
np_arr[0] = 999
print(t)  # 输出tensor([999, 2, 3])

# 阻断内存共享的方法
t_independent = torch.tensor(np_arr)  # 数据拷贝

三、数学运算深度解析

3.1 逐元素运算

a = torch.tensor([1, 2, 3], dtype=torch.float32)
b = torch.tensor([4, 5, 6], dtype=torch.float32)

# 基本运算
add = a + b          # tensor([5., 7., 9.]) 
mul = a * b          # tensor([4., 10., 18.])
pow = a ** 2         # tensor([1., 4., 9.])

# 超越函数
sin_a = torch.sin(a) # 计算正弦
log_b = torch.log(b) # 自然对数

3.2 矩阵运算专题

3.2.1 矩阵乘法家族
mat1 = torch.randn(2, 3)
mat2 = torch.randn(3, 4)

# 标准矩阵乘法
mm_result = torch.mm(mat1, mat2)  # 2x4

# 批量矩阵乘法(支持广播)
batch1 = torch.randn(5, 2, 3)
batch2 = torch.randn(5, 3, 4)
bmm_result = torch.bmm(batch1, batch2)  # 5x2x4

# 向量内积
vec1 = torch.randn(3)
vec2 = torch.randn(3)
dot_product = torch.dot(vec1, vec2)  # 标量结果
3.2.2 矩阵分解操作
# 特征分解
A = torch.randn(3, 3)
eigenvals, eigenvecs = torch.linalg.eig(A)

# SVD分解
U, S, V = torch.svd(A)

3.3 广播机制全规则

广播三定律

  1. 维度对齐:从右向左对齐
  2. 维度扩展:缺失维度视为1
  3. 单维度扩展:将size=1的维度复制扩展

复杂案例解析

A = torch.rand(3, 1, 4, 1)  # shape (3,1,4,1)
B = torch.rand(   2, 1, 5)  # shape (  2,1,5)

# 广播过程:
# Step1: 对齐维度 → (3,1,4,1) vs (1,2,1,5)
# Step2: 扩展维度 → (3,2,4,5)
result = A + B  # 最终形状 (3,2,4,5)

四、形状变换高阶技巧

4.1 维度操作大全

t = torch.arange(24).reshape(2,3,4)

# 转置操作
t1 = t.permute(2,0,1)  # 维度顺序变为(4,2,3)

# 轴交换
t2 = t.transpose(1, 2)  # 交换1、2轴 → (2,4,3)

# 拼接与分割
cat_t = torch.cat([t, t], dim=0)  # 沿dim=0拼接
split_list = torch.split(t, 2, dim=1)  # 沿dim=1分割

4.2 内存连续性原理

original = torch.randn(2,3).t()  # 转置后不连续
print(original.is_contiguous())  # False

# 恢复连续性方法
contiguous_tensor = original.contiguous() 

内存布局对比

原始存储(2x3):
[[0, 1, 2],
 [3, 4, 5]]
 
转置后(3x2)内存布局:
[0, 3, 1, 4, 2, 5]

4.3 高级索引技巧

t = torch.arange(12).view(3,4)

# 布尔掩码索引
mask = t > 5
print(t[mask])  # tensor([6,7,8,9,10,11])

# 多维索引
indices = torch.tensor([0, 2])
print(t[:, indices])  # 选取第0列和第2列

五、设备管理指南

5.1 多设备协同计算

# 多GPU环境操作
if torch.cuda.device_count() > 1:
    # 数据并行
    tensor = tensor.to('cuda:0')
    model = nn.DataParallel(model)

# 设备间数据传输
cpu_tensor = tensor.cpu()
gpu_tensor = cpu_tensor.to('cuda', non_blocking=True)  # 异步传输

5.2 设备选择策略

场景 推荐方案 原理说明
小规模数据 CPU计算 避免GPU内存传输开销
大规模矩阵运算 GPU计算 利用并行计算优势
多设备流水线 使用pin_memory 加速CPU到GPU的数据传输

六、性能优化实战

6.1 原地操作加速

x = torch.randn(3,3)
y = torch.randn(3,3)

# 非原地操作(内存开销大)
x = x + y  # 分配新内存

# 原地操作(节省内存)
x.add_(y)  # 后缀_表示原地操作

6.2 自动混合精度

scaler = torch.cuda.amp.GradScaler()

with torch.cuda.amp.autocast():
    output = model(input)
    loss = loss_fn(output, target)
    
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()

七、综合应用案例

7.1 图像处理流水线

# 加载图像为NumPy数组
image_np = np.random.rand(256,256,3) 

# 转换为张量并预处理
image_tensor = torch.from_numpy(image_np).permute(2,0,1)  # HWC→CHW
image_tensor = image_tensor.unsqueeze(0)  # 添加batch维度
image_tensor = image_tensor.to('cuda')

# 应用卷积滤波器
conv = torch.nn.Conv2d(3, 16, kernel_size=3)
output = conv(image_tensor)

7.2 神经网络计算示例

# 定义全连接层
W = torch.randn(784, 256, requires_grad=True)
b = torch.zeros(256, requires_grad=True)

# 前向传播
x = torch.randn(32, 784)  # batch_size=32
z = torch.matmul(x, W) + b  
a = torch.relu(z)

# 计算损失
loss = a.sum()
loss.backward()  # 自动计算梯度

八、调试与错误排查

8.1 常见错误类型

  1. 形状不匹配:矩阵乘法时维度未对齐

    # 错误案例
    torch.mm(torch.randn(2,3), torch.randn(2,3))  # 应改为3x2
    
  2. 设备不一致:张量位于不同设备

    # 解决方案
    tensor = tensor.to('cuda')
    
  3. 梯度丢失:未设置requires_grad=True

    param = torch.randn(3,3, requires_grad=True)
    

8.2 调试工具推荐

# 梯度检查
print(tensor.requires_grad)  # 查看梯度状态

# 设备检查
print(tensor.device)  # 确认设备位置

# 数值分析
print(tensor.mean(), tensor.std())  # 统计数值特征