minimind/learning/day01/04_qa_notes.md

9.6 KiB
Raw Blame History

Day 1 问答笔记(实操记录)

本文件记录第一天实际操作中遇到的、有价值的问题与结论。区别于 01_prereading/02_deep_dive(课程材料),这里是「踩坑 + 解决」的真实记录。


Q1. 没有写权限装不了包:EnvironmentNotWritableError

现象: conda install torch 报 current user does not have write permissions to /opt/anaconda3。

笔记: 系统级 base 环境(/opt/anaconda3)通常没有写权限,不要往 base 里装包。正确做法是建自己的虚拟环境(装在用户目录,有写权限)。

Q2. 虚拟环境是什么?python -m venv .venv 在干嘛?

笔记: 虚拟环境 = 一个「隔离的小盒子」,里面有独立的 python 和 pip,装的包只属于这个项目,不污染系统、不和别的项目冲突。

  • python -m venv 名字 → 创建(只需一次)。.venv 是惯例名(开头 . 会隐藏)。
  • 环境名可自定义,用英文/数字/-/_,别用空格中文。

Q3. venv 和 conda 的区别?怎么激活/退出?

笔记: 两种建环境方式,激活命令不同:

方式 创建 激活 退出
venv python -m venv minimind-env source minimind-env/bin/activate deactivate
conda conda create -n minimind python=3.10 conda activate minimind conda deactivate

退出命令是 deactivate(不是 inactivate)。conda 新建的环境默认装到 ~/.conda/envs(用户目录,有写权限),所以能绕开 base 没权限的问题。

Q4. 怎么判断包装进了虚拟环境,还是误装到 home?

笔记:核心判断方法——看路径,不要凭感觉。

which python   # 带 .venv/bin/ 才对;显示 /opt/anaconda3/bin 说明没激活
which pip      # 同上
pip show 包名   # 看 Location 字段在不在 .venv 里

关键习惯: 每次新开终端,venv 都不会自动激活,必须先 source .venv/bin/activate,看到命令行前面有 (.venv) 再操作。没激活就 pip install,包会装到 ~/.local(用户级),不在虚拟环境里。

Q5. pip install requirements 报错?

笔记: 装依赖文件要加 -r 和完整文件名:pip install -r requirements.txt。 不加 -r 时,pip 以为你要装一个名叫 requirements 的包,报 No matching distribution。 minimind 的 requirements.txt 里 torch/torchvision 被注释掉了,要单独装 GPU 版: pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121

Q6. modelscope 数据集下到哪了?怎么下对地方?

笔记:

  • 默认下到缓存 ~/.cache/modelscope(和 Python 环境无关,是缓存目录)。
  • 下载中断时,大文件会卡在 ._____temp 临时目录里(没下完)。
  • 下对地方的技巧: 用 --local_dir 直接下到项目的 dataset 目录:
    modelscope download --dataset gongjy/minimind_dataset pretrain_t2t_mini.jsonl --local_dir ./dataset
    
  • 只想快速跑通,下 mini 版即可(pretrain_t2t_mini + sft_t2t_mini),不用下全量(pretrain_t2t 10GB / sft_t2t 14GB)。

Q7. 项目的数据流是怎么走的?怎么「打点」调试?

预训练数据流路线图:

jsonl ({"text":...})
  → PretrainDataset.__getitem__   [dataset/lm_dataset.py:47]  文字→编码→加bos/eos→pad
  → DataLoader                    [train_pretrain.py:162]      拼成batch input_ids[B,L]
  → .to(device)                   [train_pretrain.py:28]
  → model.forward(input_ids,labels) [model_minimind.py:443]
        embed → Transformer → hidden[B,L,768] → lm_head → logits[B,L,6400]
        → logits[:-1] 预测 labels[1:] → cross_entropy → loss
  → backward + optimizer.step     [train_pretrain.py:37-49]
  → 日志/保存                      [train_pretrain.py:51-69]

笔记:打点 = 在关键位置加 print 看数据 shape 和内容。 推荐顺序:

  1. 先单独验证数据(不启动训练):写个 debug_data.py,建 Dataset → 取 ds[0] 看单条 → 取一个 batch 看 shape。
  2. 再在训练里打点:__getitem__ 里看编码对不对(解码回去对比原文 + labels 里 -100 是不是 pad 位);batch 处看 input_ids.shape;forward 后看 logits.shape 和 loss。
  3. 打点加 if index < 2 / if step <= 2 限制,避免刷屏。 labels 里 -100 = 该位置不计算 loss(pad 位置)。

Q8. 现代大模型的数据是怎么处理和清洗的?

笔记:分两大阶段,逻辑完全不同。

预训练数据(海量、求量和广,TB~PB 级,全自动清洗)经典流水线:

  1. 抽取:从网页 HTML 抽正文(trafilatura),去标签/广告。
  2. 语种过滤:fastText 识别语言,留目标语言。
  3. 质量过滤(核心):启发式规则(Gopher/C4:太短、符号比例异常、重复行多→删)+ 模型打分(拿维基当正例训分类器打分)。
  4. 去重(关键!):精确去重(哈希)+ 近似去重——MinHash+LSH(datasketch 库) 估 Jaccard 相似度删相似文档;SimHash(simhash 库) 指纹+汉明距离。⚠️ 这两个库就在 minimind 的 requirements.txt 里。去重防止模型死记重复内容、浪费算力。
  5. 去隐私(PII)/有害内容:去邮箱手机号、过滤色情暴力。
  6. 去污染(Decontamination):把评测题(MMLU/CEval)从训练集删掉,否则评分虚高=作弊。
  7. 格式统一:→ {"text": "干净文字"}。

后训练数据(少量、求质和准):

  • SFT(sft_t2t.jsonl):构造/筛选高质量问答对,来源含人工标注、公开数据、模型蒸馏合成(作者用 qwen3-4b 合成约10w条tool call)。筛选靠 LLM-as-a-judge 打分 + 多样性去重。格式 {"conversations":[{role,content}]}。
  • RL/DPO(dpo.jsonl):每条是「同一问题的好/坏回答对」(chosen/rejected),用于偏好对齐。

一句话总结: 预训练清洗重在「质量过滤+去重+去污染」,SFT 重在「高质量问答对+格式统一」,DPO 重在「构造好坏对比对」。

minimind 的数据集是作者已清洗好的成品,直接训练即可。


Q9. 怎么看 GPU 利用率?nvidia-smi 表盘完整解读

命令: nvidia-smi(看一次);watch -n 1 nvidia-smi(每秒刷新实时盯,Ctrl+C 退出,不影响训练)。

表盘第一区(整卡状态):

| 59%  83C  P1  300W / 300W |  7807MiB / 97887MiB |  97%  Default |
   ↑     ↑   ↑      ↑              ↑                   ↑
  风扇  温度 性能 功耗/上限      显存用量/总量        算力利用率

笔记:关键看两个数,且它俩是两回事:

  • Memory-Usage(显存用量):7807/97887 MiB = 用了 7.8G / 共 96G。显存够不够「装得下」。
  • GPU-Util(算力利用率):97% = 计算单元忙不忙。卡「算得快不快/有没有闲」。
  • 其他:风扇% / 温度(83℃偏高但安全) / Perf状态(P0最高~P8最低) / 功耗(300W已拉满=Max-Q功耗墙)。
  • ECC、MIG 一般用不到。

表盘第二区(进程):

PID 42514   C   python   7284MiB   ← 你的训练进程占了 7.3G
PID  2898   G   Xorg      175MiB   ← 桌面系统占的,忽略

笔记: Type 列 C=计算进程(你的训练),G=图形进程(桌面)。能看出显存被谁吃了。

Q10. 加大 batch_size 为什么没更快?为什么要同步调大学习率?

笔记:踩坑认知——「显存没满 ≠ 可以无脑加 batch 提速」。 判断卡有没有「吃饱」要看 GPU-Util,不是显存:

  • 显存 8% 但 GPU-Util 已 97% → 算力已满载,加大 batch 不会提速(吞吐量/每秒token数已固定)。
  • 只有 GPU-Util 偏低(卡在等数据/batch太小喂不饱)时,加 batch 才提速。

实测: batch 32(39695步/epoch) → 128(9924步/epoch),总时间基本不变甚至略增。因为每步算4倍活、总步数变1/4,乘起来≈不变。早期 epoch_time(ETA) 偏高是因为启动开销摊在少量步数上,不准,跑久了会降。

大 batch 的真正收益是「训练质量」不是「速度」: 梯度噪声更小、更稳,可配更大LR、用更少epoch收敛。

为什么 batch 和 LR 要一起放大:

  1. batch 大 → 梯度估计更准 → 敢迈更大步(大LR),不怕走偏。
  2. batch 大 → 总步数变少 → 每步不迈大点会欠训练,需大LR补偿。

缩放法则(batch 放大 k 倍):

法则 LR 调整 适用
线性缩放 ×k SGD
平方根缩放 ×√k Adam/AdamW(minimind用这个)
batch 32→128(×4):AdamW 推荐 √4=×2,即 5e-4 → 1e-3。

真正提速的手段(不是加batch): --use_compile 1(torch.compile) / 减少 --epochs。


今日待办状态

  • 建立 .venv 虚拟环境(~/Project/minimind/.venv)
  • modelscope 装进 .venv
  • 清理误装到 home 的包和缓存
  • 下载数据集(全量已下到 ~/.cache,再 mv 进 ./dataset/;下载时漏了 --local_dir 是坑)
  • 安装 PyTorch GPU 版(torch 2.11.0+cu128,Blackwell 必须 cu128)+ requirements.txt
  • 成功跑通第一次预训练(loss 从 ~7.3 正常下降)✅
  • 配置 VSCode 调试(已建 .vscode/launch.json,需装 Python 扩展,用 F5 而非 python xxx.py)
  • 跑完预训练 → 用 eval_llm.py 测试生成效果