8. 理解 Dataset
理解 LLM 的数据加载流水线模型结构决定能力上限数据流水线决定训练效率和最终效果。在工业界大模型训练中花时间最多的往往不是模型而是数据。可以把整个训练过程想象成一家大型食品工厂原始数据 ↓ 清洗 ↓ 切块(Tokenize) ↓ 装箱(Padding) ↓ 打包(Batch) ↓ 送入模型 ↓ 计算Loss ↓ 反向传播一、数据是怎么进入模型的假设你有一条训练数据我喜欢学习人工智能模型根本看不懂中文。它只能看数字。所以第一步文本 ↓ Tokenizer ↓ Token ID例如我 喜 欢 学 习 人 工 智 能 ↓ [35, 88, 29, 63, 91, 17, 45, 73, 12]这时模型终于能处理了。二、Dataset仓库管理员Dataset 本质上就是告诉 PyTorch 去哪里拿数据。例如classMyDataset(Dataset):def__getitem__(self,idx):returnself.data[idx]def__len__(self):returnlen(self.data)作用数据文件 ↓ Dataset ↓ 一条一条样本像仓库管理员用户 给我第100条数据 Dataset 好的拿去例如dataset[0]返回{text:我喜欢AI}三、DataLoader流水线工人Dataset 一次只能取一个样本。训练时需要一次喂几十条 甚至几百条所以需要DataLoader负责Dataset ↓ 组装 Batch ↓ 送给 GPU例如loaderDataLoader(dataset,batch_size32,shuffleTrue)含义每次拿32条数据 随机打乱顺序 送入模型流程Dataset 样本1 样本2 样本3 ... 样本10000 ↓ DataLoader Batch1: 样本1~32 Batch2: 样本33~64 Batch3: 样本65~96四、为什么需要 Padding这是很多新人第一次接触训练时最困惑的地方。假设样本1: 我喜欢AI 长度4样本2: 今天天气不错 长度5样本3: 深度学习改变世界 长度8GPU 最喜欢矩形矩阵例如3 × 8而不是4 5 8这种参差不齐的长度。所以需要补齐。Padding 之前[我 喜 欢 AI] [今 天 天 气 不 错] [深 度 学 习 改 变 世 界]Padding 之后PAD 特殊填充符[我 喜 欢 AI PAD PAD PAD PAD] [今 天 天 气 不 错 PAD PAD] [深 度 学 习 改 变 世 界]这样长度统一8 8 8GPU 就能并行计算。五、为什么需要 Truncation有些文章特别长。例如长度 5000 Token而模型最大长度max_seq_len 2048怎么办只能砍掉。tokenstokens[:2048]变成前2048个保留 后2952个丢弃这就叫Truncation截断六、max_seq_len 到底是什么很多人误解max_seq_len 训练时随便设置的数字其实不是。它决定模型一次最多能看到多少Token例如max_seq_len 4096表示模型视野长度 ≈ 4096 Token类似人眼视野太短 看不见上下文 太长 显存爆炸因为 AttentionO(n2) O(n^2)O(n2)长度翻倍4096 → 8192 计算量 ≈ 4倍七、真正重要的Loss Mask这是 SFT 和预训练最大的区别之一。很多面试都会问。预训练数据我 喜 欢 学 习 AI训练目标预测下一个词例如我 → 喜 我 喜 → 欢 我 喜 欢 → 学因此每个Token都有价值Loss Mask[1 1 1 1 1]除了 PAD[1 1 1 1 1 0 0]SFT 为什么不同假设训练样本User: 什么是AI Assistant: AI是人工智能。拼接后User 什么是AI Assistant AI是人工智能。模型输入全部输入进去但是监督目标不是全部。我们只关心什么只关心Assistant 怎么回答不关心User 怎么提问所以User部分 不计算LossLoss MaskUser 什么是AI Assistant AI是人工智能。对应0 0 0 0 0 0 1 1 1 1 1 1图示Prompt ↓↓↓↓↓↓↓ 什么是AI 000000000 Assistant回答 ↓↓↓↓↓↓↓ AI是人工智能 111111111为什么必须这样做假设不 Mask。模型会同时学习如何提问 如何回答梯度目标混在一起。结果可能变成用户什么是AI 模型 什么是AI因为模型发现训练数据里 用户说的话也算Loss于是它会模仿用户。这显然不是我们想要的。八、Loss 是怎么计算的假设Loss [2.1, 1.5, 3.0, 0.8]对应 Mask[0, 0, 1, 1]那么实际计算0×2.1 0×1.5 1×3.0 1×0.8只保留3.0 0.8最后平均(3.0 0.8) / 2九、Batch Size 是什么假设10万条训练数据不可能一次全塞GPU所以分批例如batch_size 32表示一次训练32条数据流程Batch1 → 更新参数 Batch2 → 更新参数 Batch3 → 更新参数十、为什么还要梯度累积假设你希望batch_size 256训练更稳定。但是显存只能放32怎么办拆开。原本256条 一起算变成32 32 32 32 32 32 32 32共8次每次loss.backward()只累计梯度。不更新参数。最后一次optimizer.step()更新一次。效果近似真正 batch_size256公式Effective Batch Sizebatch size×gradient accumulation×GPU 数 \text{Effective Batch Size} \text{batch size} \times \text{gradient accumulation} \times \text{GPU 数}Effective Batch Sizebatch size×gradient accumulation×GPU数例如batch_size 32 grad_acc 8 gpu 4则有效Batch 32 × 8 × 4 1024十一、完整训练流水线把所有东西串起来如果只记住一句话Dataset 负责“取数据”Tokenizer 负责“切词变数字”Padding 负责“补齐长度”Loss Mask 负责“告诉模型哪些地方该学习”DataLoader 负责“打包成 Batch 送进 GPU”。这五个环节组成了 LLM 训练的数据处理流水线。