1. PyTorch张量的核心概念张量Tensor是PyTorch中最基本的数据结构你可以把它理解为一个多维数组。就像我们生活中用数字表示温度、用列表表示购物清单、用表格表示成绩单一样PyTorch用张量来表示各种维度的数据。举个例子当你用手机拍一张照片时如果照片是黑白的它就是一个二维张量高度×宽度如果是彩色照片就变成三维张量高度×宽度×3个颜色通道如果你处理的是视频那就是四维张量帧数×高度×宽度×通道在PyTorch中创建张量非常简单import torch # 创建标量0维张量 scalar torch.tensor(3.14) # 创建向量1维张量 vector torch.tensor([1, 2, 3]) # 创建矩阵2维张量 matrix torch.tensor([[1, 2], [3, 4]]) # 创建3维张量 cube torch.rand(2, 3, 4) # 2个3×4的矩阵2. 张量的维度操作2.1 查看和改变张量形状张量的形状shape可能是深度学习中最常操作的属性之一。PyTorch提供了几种方法来查看和改变张量形状x torch.rand(4, 3) # 4行3列的矩阵 print(x.shape) # 输出torch.Size([4, 3]) print(x.size()) # 与shape相同 print(x.dim()) # 输出维度数2改变形状最常用的方法是view()和reshape()# 将4×3的矩阵改为6×2 y x.view(6, 2) # 自动计算某一维度大小 z x.view(-1, 6) # -1表示自动计算这里会变成2×62.2 增加和减少维度在实际项目中我们经常需要调整张量的维度# 增加维度 x torch.tensor([1, 2, 3]) print(x.unsqueeze(0).shape) # 在最前面加维度(1, 3) print(x.unsqueeze(1).shape) # 在中间加维度(3, 1) # 减少维度 y torch.rand(1, 3, 1, 4) print(y.squeeze().shape) # 去掉所有大小为1的维度(3, 4) print(y.squeeze(0).shape) # 只去掉第0维(3, 1, 4)2.3 张量拼接和分割处理数据时经常需要合并或拆分张量a torch.rand(2, 3) b torch.rand(2, 3) # 沿第0维拼接垂直方向 c torch.cat([a, b], dim0) # 形状变为(4, 3) # 沿第1维拼接水平方向 d torch.cat([a, b], dim1) # 形状变为(2, 6) # 分割张量 chunks torch.chunk(c, 2, dim0) # 分成2块每块(2,3)3. 张量的内存布局3.1 连续性与步长stride张量在内存中的存储方式直接影响计算效率。PyTorch用两个关键属性来描述内存布局stride表示在每个维度上移动一个元素需要跨越的内存位置数is_contiguous()检查张量在内存中是否是连续存储的x torch.rand(3, 4) print(x.stride()) # 输出(4, 1) print(x.is_contiguous()) # 通常为True3.2 视图view与复制copy理解视图和复制的区别非常重要x torch.arange(12).view(3, 4) y x.view(4, 3) # 创建视图不复制数据 z x.clone() # 创建真正的副本 # 修改原始张量会影响视图但不会影响副本 x[0, 0] 100 print(y[0, 0]) # 输出100 print(z[0, 0]) # 输出03.3 转置与内存连续性转置操作会改变张量的stride可能导致内存不连续x torch.rand(3, 4) y x.t() # 转置 print(x.is_contiguous()) # True print(y.is_contiguous()) # False # 不连续的张量不能直接使用view() # 需要先调用contiguous() z y.contiguous().view(12)4. 高效维度变换技巧4.1 选择合适的形状变换方法PyTorch提供了多种形状变换方法各有特点view()要求张量是连续的否则会报错reshape()自动处理连续性问题但可能产生内存复制permute()重新排列维度顺序transpose()交换两个维度x torch.rand(2, 3, 4) # 改变维度顺序 y x.permute(2, 0, 1) # 新形状(4, 2, 3) # 交换两个维度 z x.transpose(1, 2) # 交换第1和第2维(2, 4, 3)4.2 避免不必要的内存复制不当的形状变换可能导致性能问题# 不推荐的写法可能产生内存复制 x torch.rand(10000, 10000) y x.t().contiguous().view(-1) # 推荐的写法 x torch.rand(10000, 10000) y x.reshape(-1) # 或者x.view(-1)如果x是连续的4.3 实际应用示例在图像处理中经常需要在不同格式间转换# 假设有一批RGB图像形状为(批量大小, 高度, 宽度, 通道) images torch.rand(32, 256, 256, 3) # 转换为PyTorch常用格式(批量大小, 通道, 高度, 宽度) images images.permute(0, 3, 1, 2) # 处理后再转回原格式 output model(images) output output.permute(0, 2, 3, 1)5. 常见问题与解决方案5.1 形状不匹配错误这是最常见的错误之一。例如x torch.rand(3, 4) y torch.rand(4, 3) try: z x y # 会报错 except RuntimeError as e: print(e) # 形状不匹配解决方案是使用广播机制或调整形状# 方法1转置其中一个张量 z x y.t() # 方法2使用广播 a torch.rand(3, 1) b torch.rand(1, 3) c a b # 自动广播为(3,3)5.2 内存不连续问题当遇到view()操作需要连续张量的错误时x torch.rand(3, 4).t() # 转置后不连续 try: y x.view(12) # 会报错 except RuntimeError as e: print(e) # 解决方案 y x.contiguous().view(12)5.3 高效处理高维数据处理高维数据时合理使用einops库可以简化代码from einops import rearrange # 将(batch, seq_len, features)转为(batch, features, seq_len) x torch.rand(32, 100, 768) y rearrange(x, b s f - b f s) # 合并多个维度 z rearrange(y, b f (s1 s2) - b f s1 s2, s110, s210)6. 性能优化建议6.1 选择合适的操作顺序某些操作的顺序会影响性能# 不推荐的顺序 x torch.rand(1000, 1000) y x.t().contiguous().view(-1) # 两次内存重排 # 推荐的顺序 x torch.rand(1000, 1000) y x.reshape(-1) # 一步完成6.2 利用原地操作原地操作可以节省内存x torch.rand(1000, 1000) # 普通操作会创建新张量 y x 1 # 新内存分配 # 原地操作 x.add_(1) # 修改原始张量6.3 批处理技巧合理利用批处理可以提高效率# 低效的逐样本处理 for sample in dataset: process(sample) # 高效的批处理 loader DataLoader(dataset, batch_size32) for batch in loader: process_batch(batch)在实际项目中我发现合理使用张量操作可以显著提升模型训练和推理速度。特别是在处理大规模数据时理解内存布局和选择高效的操作方式往往能带来意想不到的性能提升。