- 开篇 — 不谈大模型,亲手跑小模型
- 第 0 部 — 第一个教训:没有预热的基准测试会撒 38 倍的谎
- 第 1 部 — microGPT:把 GPT 从零训练,只要 28 秒
- 第 2 部 — OCR 对决:专用模型 vs 通用 VLM
- 第 3 部 — 音乐生成:8 秒的音乐,1.9 秒生成
- 结语 — 小模型的时代,一张 GPU 就够了
- 参考资料
开篇 — 不谈大模型,亲手跑小模型
如今的话题清一色都是 700B 参数、成千上万张 GPU。但要学习计算机科学,反过来才更好 — 把巴掌大的模型放在一张 GPU 上亲手训练、拆开来看、撞上它的极限。刚好有一张 RTX 5090(Blackwell,32GB)就在 SSH 的另一头,于是我直接跑了三个小模型:从零训练的 char-level GPT、专用 OCR vs 小型 VLM 的对决,以及文本转音乐(text-to-music)。所有数字都是实测。而这一路上遇到的那些诚实的陷阱,其实比结果本身更是好教材。
第 0 部 — 第一个教训:没有预热的基准测试会撒 38 倍的谎
在跑模型之前,我先用 bf16 矩阵乘法确认 GPU 是否正常工作。第一个测量值是 6.1 TFLOP/s。5090 不该是这个数啊…… 于是加了一个预热循环重新测。
First (no warmup) Measured properly
bf16 matmul 6.1 TFLOP/s 231.8 TFLOP/s ← 38x difference
罪魁祸首是 第一次调用把 cuBLAS 初始化、内核自动调优整个都算了进去。GPU 基准测试的铁律 — 先预热(warmup)几次,用 torch.cuda.synchronize() 等内核真正结束之后再测。231.8 TFLOP/s 和 5090 的 bf16 dense 规格(约 210 TFLOPS)也正好对得上。本文所有的延迟(latency)测量里,都包含了这次预热。
顺带一提,为了用上这台服务器,之前也折腾了一番:5090 是 Blackwell sm_120 架构,旧版本的 PyTorch 会嘴上说着"CUDA 可用",却因为没有内核而悄无声息地失败。直到 torch 2.10.0+cu128(CUDA 12.8 构建)才终于把 sm_120 纳入架构列表。用最新的 GPU 时,有一半的功夫都花在和环境较劲上。
第 1 部 — microGPT:把 GPT 从零训练,只要 28 秒
首先沿着 Karpathy 的 nanoGPT 一脉,用纯 PyTorch 从零训练一个 char-level GPT。把 1MB 的莎士比亚文本按字符切分(vocab 65 个)喂进去,让一个 6 层、6 头、384 维的 Transformer(约 10.75M 参数)跑了 2000 步。
iter 1 | train 3.7921 | val 3.8103 | 10.0k tok/s
iter 500 | train 1.5798 | val 1.7738 | 1006.2k tok/s
iter 1000 | train 1.2769 | val 1.5302 | 1119.1k tok/s
iter 1750 | train 1.1221 | val 1.4425 | 1174.8k tok/s ← val minimum
iter 2000 | train 1.1150 | val 1.4552 | 1184.7k tok/s ← val rebounds (overfitting begins)
trained 2000 iters in 28.0s | peak VRAM 1.73 GB | 1.17M tokens/s
28 秒,VRAM 1.73GB。 loss 从 3.79 降到 1.12,生成的样本是这样的莎士比亚风格:
The people, could be speak'd of this course,
Who shall be at bold well away and a chief.
Second Citizen:
This in the morniest hour of Turningh; down princ
语法虽然粗糙,但能看出它以字符为单位学到了台词的格式、人物名字、古体的措辞。这里还藏着一个教训 — val loss 从 1750 步的 1.4425 反弹到了 2000 步的 1.4552。train loss 一直在降,val 却在升,这是教科书式的 过拟合的开端。1MB 的数据配 10M 参数,很快就会开始死记硬背。这正是亲眼看到早停(early stopping)的时刻。如果想在更大的图景里看 Transformer 结构,可以搭配 AI 模型开发生命周期篇 一起读。
核心代码很有当下 PyTorch 的味道,很简洁 — 注意力不用手动做掩码,而是交给 flash attention 内核:
# 因果自注意力: is_causal=True 代替了三角掩码
y = F.scaled_dot_product_attention(q, k, v, is_causal=True)
第 2 部 — OCR 对决:专用模型 vs 通用 VLM
这是最有意思的一个实验。在同一张图上,让 专用 OCR(Microsoft TrOCR) 和 小型视觉-语言模型(Qwen2-VL-2B) 正面对决。指标是 CER(Character Error Rate,越低越好)。测试图片是英文一行、韩文一行,还有一张韩·英·数字混排的收据。
Model Image Latency CER Read result
──────────────────── ──────── ─────── ────── ──────────────────────────────
TrOCR-printed English 69ms 0.791 THE QUICK BROWN FOX ... LAY DOG
TrOCR-printed Korean 40ms 1.429 CHANGE @ SUBJECT EXCLIP
TrOCR-handwritten English 44ms 0.000 The quick brown fox ... lazy dog
Qwen2-VL-2B (VLM) English 90ms 0.000 The quick brown fox ... lazy dog
Qwen2-VL-2B (VLM) Korean 143ms 0.071 다람쥐 헌 챗바퀴에 타고파
Qwen2-VL-2B (VLM) Receipt 453ms — (KR/EN/num multi-line nearly perfect)
这里引出三个话题。
第一,别把指标照单全收。 TrOCR-printed 的英文 CER 是 0.791,若就此断定它"很糟",那就错了。实际输出是 THE QUICK BROWN FOX JUMPS OVER THE LAY DOG — 几乎全读对了,只是 全部输出成了大写(而且漏掉了 lazy 里的一个 z)。CER 把大写和小写当成不同的字符来数,所以仅仅一次大写化就把分数灌水到了 0.79。忽略大小写的话,CER 只有 0.05 上下。指标差不等于模型差,你得知道这个指标到底在数什么。
第二,专用模型很窄。 TrOCR 只用拉丁字符训练,所以面对韩文图片会输出 CHANGE @ SUBJECT EXCLIP 这种彻头彻尾的胡话(CER 1.429 — 因为插入错误而超过了 1)。模型说不出"我不知道",只能硬塞进它认识的字符,这是域外输入的典型失败。
第三,有意思的反转 — "手写体用"的 TrOCR-handwritten 竟然把印刷体英文读得 CER 0.000,堪称完美,连大小写都读对了。"印刷体用"的模型压成了大写,"手写体用"的反而精准命中。名牌(模型的名字)并不保证性能 — 在用真实数据测过之前,谁也不知道。
然后是通用 VLM 的完胜:Qwen2-VL-2B 英文完美,韩文只错了一个字(챗/쳇),最重要的是 把韩·英·数字混排的收据连换行都保留下来,几乎原样誊了出来。而且它能听懂"把这张收据原样抄下来"这样的 自然语言指令 — 这是专用 OCR 做不到的。
归纳起来,就是 专用 vs 通用的经典权衡:
Dedicated OCR (TrOCR) General-purpose VLM (Qwen2-VL-2B)
────────── ─────────────────────── ─────────────────────────────
Speed 40~69ms (fast) 90~453ms (slow)
VRAM 1.39 GB (small) 4.49 GB (3x)
Language Latin only Multilingual
Layout Single line only Multi-line, tables, mixed
Instruction Not possible Instructable in natural language
如果要以超低延迟、低成本大批量处理单行拉丁文档,就用专用 OCR;如果需要多语言、复杂排版、灵活性,就用 VLM — 大致的感觉就是这样。
第 3 部 — 音乐生成:8 秒的音乐,1.9 秒生成
最后是文本转音乐(text-to-music)。给 Meta 的 MusicGen-small(587M)扔了两个提示词。
Prompt Gen time Music len Real-time factor
──────────────────────────────────────────────── ──────── ──────── ──────────
"upbeat lofi hip hop beat, warm piano, relaxing" 1.90s 7.9s 4.19x
"epic orchestral cinematic trailer, drums, brass" 1.85s 7.9s 4.30x
peak VRAM 1.37 GB
8 秒的音乐,用 1.9 秒生成 — 也就是实时的 4.2 倍速度。MusicGen 把音频转成 EnCodec token(每秒约 50 个),像语言模型一样自回归地吐出来,最后再解码回波形。就像 LLM 吐出文本 token 那样把音乐当作"token"吐出来 — 生成式 AI 的语法在这里同样适用。产物以 32kHz 单声道 WAV 保存,实际播放时会按提示词放出 lo-fi 节拍和管弦乐。
结语 — 小模型的时代,一张 GPU 就够了
三个实验的共同点:全都在不到 5GB 的 VRAM 里、以秒为单位就跑完了。
Experiment Parameters VRAM Key figure
──────────── ───────── ───────── ────────────────────────
microGPT 10.75M 1.73 GB 2000-step training in 28s
TrOCR 334M 1.39 GB single line read 40~69ms
Qwen2-VL-2B 2B 4.49 GB receipt transcription 453ms
MusicGen 587M 1.37 GB 8s of music in 1.9s
大模型抢走了头条,但 真正适合学习和做实验的地方,是这些小模型。从零训练 GPT,亲眼看到过拟合;用 OCR 对决,亲身体会"专用 vs 通用"和"指标的陷阱";用音乐生成,印证生成式 AI 的 token 语法 — 这一切,不是靠一台笔记本电脑,而是 30 秒、一张 GPU 就能搞定。如果你好奇迈向多 GPU 的下一步,分布式训练平台篇 就是接下来的故事。而只有亲手跑过的模型,才会成为真正的直觉留下来 — 毕竟哪怕只是一个基准测试数字,没有预热也会撒 38 倍的谎。
参考资料
현재 단락 (1/64)
如今的话题清一色都是 700B 参数、成千上万张 GPU。但要*学习*计算机科学,反过来才更好 — 把巴掌大的模型放在一张 GPU 上亲手训练、拆开来看、撞上它的极限。刚好有一张 RTX 5090(B...