一、记忆敲门
先说最简单的结论:
1维,只有W(width)
2维,先H(height),后W,即HW
3维,先C(channel),后HW,即CHW
4维,先B(batch),后CHW,即BCHW
更多维,依然理解维先大后小
二、代码表示
2维张量示例,形状3x5,(h=3,w=5)
>>> torch.arange(15).reshape([3,5])
tensor([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
可以看到果然最里面横着的部分的数量是5,竖着的部分数量是3。可以看出二维张量,这种高和宽的特性,与书写是有对应关系的。
然后再看3维张量
>>> torch.arange(30).reshape([2,3,5])
tensor([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]],
[[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29]]])
可以看到,虽然无法通过多维数组显示立体的东西,但依然可以看出,“里面”依然保留了“先大后小”的规律。
以下是让大模型帮做的一个总结,更为详细(虽然理解上依然有些绕)
核心记忆规律:从外到内,从大到小;
# 最通用的记忆顺序:[Batch, Channel, Height, Width]
# 可以记成:BCHW 或者 "批通高宽"
tensor_4d = torch.randn(8, 3, 224, 224)
# 维度0: Batch Size (8) - 一次处理几张图
# 维度1: Channels (3) - 每张图有几个通道
# 维度2: Height (224) - 图片高度
# 维度3: Width (224) - 图片宽度
具体对应关系和记忆技巧:
import torch
# 1D张量 - 向量
vector = torch.randn(100)
print(f"1D: {vector.shape}")
# 只有长度,像一条线
# 2D张量 - 矩阵/灰度图
matrix = torch.randn(28, 28)
print(f"2D: {matrix.shape}")
# [高度, 宽度] - 像一张灰度照片
# 记忆:行列,先说行(高)再说列(宽)
# 3D张量 - 彩色图/视频帧
image_3d = torch.randn(3, 224, 224)
print(f"3D: {image_3d.shape}")
# [通道数, 高度, 宽度] - RGB三层叠起来
# 记忆:CHW (Channel-Height-Width)
# 4D张量 - 批量图像 (最常见)
batch_images = torch.randn(32, 3, 224, 224)
print(f"4D: {batch_images.shape}")
# [批次, 通道, 高度, 宽度] - 一摞彩色照片
# 记忆:BCHW (Batch-Channel-Height-Width)
# 5D张量 - 视频/3D数据
video = torch.randn(16, 3, 10, 224, 224)
print(f"5D: {video.shape}")
# [批次, 通道, 时间/深度, 高度, 宽度]
# 记忆:BCTHW 或 BCDHW
记忆口诀和可视化:
def visualize_dimensions():
"""
维度记忆法:像俄罗斯套娃,从外到内
"""
print("=== 维度记忆口诀 ===")
print("1D: 一条线 [长度]")
print("2D: 一张纸 [高, 宽] - 想象一张纸的长宽")
print("3D: 一本书 [页数, 高, 宽] - 想象书的厚度、长、宽")
print("4D: 一摞书 [摞数, 页数, 高, 宽] - 想象书架上一摞摞书")
print("5D: 一排书架 [排数, 摞数, 页数, 高, 宽]")
print("\n=== 图像数据的具体对应 ===")
print("2D图像: [H, W] - 灰度图")
print("3D图像: [C, H, W] - 彩色图")
print("4D批次: [B, C, H, W] - 一批彩色图")
print("5D视频: [B, C, T, H, W] - 一批视频")
visualize_dimensions()
# 实际例子对比
print("\n=== 实际数据例子 ===")
# 单张灰度图 MNIST
mnist_single = torch.randn(28, 28)
print(f"单张MNIST: {mnist_single.shape} [H, W]")
# 单张彩色图
cifar_single = torch.randn(3, 32, 32)
print(f"单张CIFAR: {cifar_single.shape} [C, H, W]")
# 一批训练图像
batch_cifar = torch.randn(128, 3, 32, 32)
print(f"一批CIFAR: {batch_cifar.shape} [B, C, H, W]")
# 一个视频片段
video_clip = torch.randn(1, 3, 16, 224, 224)
print(f"视频片段: {video_clip.shape} [B, C, T, H, W]")
不同框架的差异要注意:
# PyTorch: BCHW (Channel First)
pytorch_tensor = torch.randn(8, 3, 224, 224)
print(f"PyTorch格式: {pytorch_tensor.shape} [B, C, H, W]")
# TensorFlow: BHWC (Channel Last)
# tensorflow_tensor = tf.random.normal([8, 224, 224, 3])
# print(f"TensorFlow格式: [B, H, W, C]")
# 转换方法
# BCHW -> BHWC
pytorch_to_tf = pytorch_tensor.permute(0, 2, 3, 1)
print(f"转换后: {pytorch_to_tf.shape} [B, H, W, C]")
记忆技巧总结:
-
层次思维:从整体到局部
- Batch → Channel → Height → Width
- 整批 → 通道 → 行 → 列
-
物理类比:
- 1D: 一条线
- 2D: 一张纸
- 3D: 一本书(多页)
- 4D: 一摞书
- 5D: 一排书架
HW永远在最后:高度和宽度总是最后两个维度
-
Channel的位置:
- PyTorch: Channel在HW前面
- TensorFlow: Channel在HW后面
口诀:"批通高宽" (BCHW) - 最常用的4D格式