2.5 KiB
2.5 KiB
Day 1 Deep Dive: MiniMind 模型结构拆解
深挖问题 1:MiniMind 的最小 forward 路径是什么?
打开 model/model_minimind.py:
MiniMindForCausalLM.forwardMiniMindModel.forwardMiniMindBlock.forwardAttention.forwardFeedForward.forward
你要能追踪:
input_ids
-> embed_tokens
-> dropout
-> N x MiniMindBlock
-> RMSNorm
-> lm_head
-> logits
-> cross_entropy loss
重点观察:
input_ids.shape == [batch, seq_len]hidden_states.shape == [batch, seq_len, hidden_size]logits.shape == [batch, seq_len, vocab_size]
深挖问题 2:为什么 forward 里是这样算 loss?
代码位置:MiniMindForCausalLM.forward
核心逻辑:
x = logits[..., :-1, :]
y = labels[..., 1:]
loss = F.cross_entropy(x.view(-1, x.size(-1)), y.view(-1), ignore_index=-100)
理解方式:
- 位置 0 的 logits 预测 token 1。
- 位置 1 的 logits 预测 token 2。
- 最后一个位置没有下一个 token,所以丢掉。
- label 的第一个 token 没有被任何上文预测,所以丢掉。
ignore_index=-100 是训练中最重要的 mask 约定之一。pretrain 用它忽略 padding;SFT 用它忽略 user/system/prompt 部分。
深挖问题 3:Attention 里 GQA 是怎么实现的?
看 Attention.__init__:
num_attention_headsnum_key_value_headsn_rep = q_heads // kv_heads
看 repeat_kv:
- K/V heads 先少算。
- attention 前把 K/V 复制到和 Q heads 对齐。
工业理解:
- 训练时省一部分参数和计算。
- 推理时 KV cache 更小。
- 对小模型通常是合理取舍。
深挖问题 4:MoE 为什么有 aux loss?
看 MOEFeedForward.forward:
- gate 给每个 token 分配 expert。
topk_idx决定 token 去哪个 expert。aux_loss鼓励 expert 负载更均衡。
工业风险:
- 没有负载均衡,部分 expert 可能被过度使用。
- 原生 PyTorch MoE 训练不一定快,因为 expert 分派有额外调度开销。
今日小实验
写一个临时 Python 片段,不修改项目文件:
python - <<'PY'
import torch
from model.model_minimind import MiniMindConfig, MiniMindForCausalLM
config = MiniMindConfig(hidden_size=128, num_hidden_layers=2)
model = MiniMindForCausalLM(config)
input_ids = torch.randint(0, config.vocab_size, (2, 16))
labels = input_ids.clone()
out = model(input_ids, labels=labels)
print(out.logits.shape)
print(out.loss.item())
PY
你要解释:
- 为什么随机模型也有 loss?
- loss 大概应接近
log(vocab_size),为什么?