看视频版《动手学深度学习》第二课的时候,我一度以为是自己漏看了一节:没有模型,没有损失函数,整节都在讲怎么对张量做切片、reshape、拼接、广播。但这些看似基础的“数据基本操作”,后来几乎构成了我写所有训练代码的地基。尤其是当你在真实项目里处理图像、文本、表格数据,而不是教材里现成的 mnist 时,才会发现数据如果不整理成模型能吃的形状,后面再花哨的网络结构都跑不起来。
这门课的定位很清楚,适合刚入门深度学习、想系统搭起知识框架的人。数据基本操作就是那个最先要过的坎。不管是 PyTorch、TensorFlow 还是 Paddle,核心的数据结构都是张量(Tensor),围绕张量的创建、访问、变换、组合、批量装载,就是第二课真正想让你掌握的“肌肉记忆”。这篇笔记我会以 PyTorch 为例,把第二课的要点串成一条完整的数据处理链路,把我自己踩过的坑、查阅过的底层逻辑一并放进去,尽量把每一步“为什么要这么做”也讲明白。
1. 数据操作:深度学习里最先要过的坎
1.1 为什么第二课就把数据操作摆在模型前面
很多初学者会觉得,深度学习入门不都应该从“神经网络长什么样”开始吗?我一开始也有这个错觉。但真按课程顺序走下来就会明白,所有深度学习框架的底层计算,都不是对着原始图片、文本字符串做的,而是统一交给一种叫“张量”的多维数组。你输入一张 224x224 的彩色图片,对框架来说就是一个形状为 [3, 224, 224] 的张量;你输入一句长度为 20 的话,token 化之后就变成 [1, 20] 甚至 [batch, 20, hidden] 的张量。
如果连张量都操作不熟练,后面写数据管道会非常痛苦。课程把这个内容排在第二课,相当于先修一条路,后面模型训练、反向传播都是在这条路上跑车。我个人还会额外把它看作“从数学符号过渡到编程实现”的桥梁:数学课上我们说矩阵相乘,代码里就要做张量乘法;数学上说“把这个矩阵转置”,代码里就要做 .T 或 .permute。你越早把这两套语言对应起来,后面读论文复现代码就越顺。
1.2 一次数据操作到底在做什么
用大白话描述,数据进入模型前要经历五个环节:读取、清洗、格式化、张量化、按批供给。前两件事取决于具体业务,图像要解码、文本要去噪、表格要补缺失值;格式化与张量化则相对通用,就是把数据变成统一尺寸、统一数值类型、统一排布规则的多维数组;按批供给则是训练时用 DataLoader 不停地把数据一小块一小块喂给模型。
很多人会忽略格式化这个环节。比如图像数据有的项目是 [高,宽,通道],有的框架期望 [通道,高,宽];同一个数据,排布顺序不同,模型看到的“语义”完全不同。第二课里练的 reshape、permute、transpose,本质上都在解决这类维度约定问题。学的时候不是背几个 API,而是要建立起“数据形状就是我对框架说的话”这种意识。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 张量基础操作,先把手感和维度感练出来
2.1 从创建张量到看懂 shape:先学会“查形状”
我不建议一上来就死磕 torch 的全部初始化方式,先把最常用的几个记熟就够了。torch.arange(12) 会生成从 0 到 11 的一维张量,torch.zeros((2,3)) 和 torch.ones((2,3)) 初始化全 0、全 1 张量,torch.randn((3,4)) 生成标准正态分布的随机张量。实际写代码时,随机初始化常用来模拟输入、验证网络前向能不能通;全 0、全 1 张量则常用于初始化掩码或某些中间变量。
python复制import torch
x = torch.arange(12)
print(x.shape) # torch.Size([12])
print(x.numel()) # 12,元素个数
print(x.reshape(3, 4)) # 变成 3 行 4 列
y = torch.randn(3, 4)
print(y.shape) # torch.Size([3, 4])
这里最容易被忽略的是 reshape 的底层逻辑。它把原张量按“行优先”顺序拉平,再重新切成目标形状,所以元素总量必须一致。换句话说,reshape(3,4) 不是简单地对半裁,而是把 0 到 11 这 12 个数按顺序填成三行四列。很多新手会忽略的一件事是:reshape 可能返回原数据的视图,也可能触发拷贝,取决于内存是否连续。如果你之后对 reshape 后的结果做原地修改,又把它当成原数据的副本,容易出隐蔽 bug。我的习惯是:不确定会不会影响原数据时,优先用 .clone() .reshape(),或者直接用 .view() 前先确认内存连续。课程里只讲了 API,但这一条经验是我在实际项目里吃过亏后才记住的。
2.2 索引、切片与拼接:像操作列表一样操作张量
张量支持类似 Python 列表的索引方式,但维度更多,规则也更强。要练出手感,核心是记住:X[-1] 取最后一行,X[1:3] 取第 2 行到第 3 行,左闭右开,和 Python 原生切片一致。多维索引时每个维度依次写,比如取一张图片张量 img 的 R 通道就是 img[0],如果图片张量形状是 [3, H, W],还可以用 img[0, :, :] 来强调维度语义。
拼接在数据准备中非常常用。torch.cat 沿已有维度拼接,不新增维度;
