放弃 API 调用,我用 PyTorch 亲手撸了一个 640 万参数的 Transformer 模型
最近我意识到,如果每天的工作只是在写 Prompt 和调用 API,本质上是在做一种“黑盒工程”。虽然效率很高,但你永远无法真正感知模型内部的权重是如何流动的。为了彻底搞清楚 Transformer 的运转机制,我在给自己的食谱应用做后端时,做了一个大胆的决定:砍掉所有外部 API,尝试用 PyTorch 从零开始训练一个 Decoder-only 的小模型。
这个模型我给它起名叫 RasavedaGPT。在大多数人的认知里,现在的 LLM 动辄百亿、千亿参数,但实际上,如果任务场景足够垂直,一个参数量在百万级别的模型完全可以跑通。经过实际测试,这个模型的总参数量精确控制在 6,392,320 个。虽然规模极小,但它在处理食谱这类结构化强、领域集中的文本时,表现出了惊人的实用性。
在具体的架构配置上,我为了在 Colab T4 这种基础环境下保证训练速度,选择了比较克制的参数组合:词表大小设定为 6,000(采用了自定义的 BPE 分词),上下文长度为 512 tokens,Embedding 维度 256,注意力头数 8 个,Transformer 层数 6 层,FFN 维度则设为 1,024。
在实际开发过程中,我踩到了一个非常关键的坑,这对于想尝试小模型训练的人来说很有参考价值。起初我尝试直接用随机初始化的模型去跑食谱数据集,结果发现模型陷入了困境:它要么能勉强学会食谱的格式,但语言完全不通顺;要么语言流畅,但完全不理解食谱的领域知识。
为了解决这个问题,我将训练策略改成了两阶段走:
第一阶段是基础预训练。我使用了 WikiText-2 数据集跑了 3 个 Epoch。这个阶段的目标不是让模型学会做菜,而是让它先学会“说人话”。在这个过程中,我密切关注 Perplexity(困惑度)的变化,直到它从最初的 345 降低到 114 左右,这意味着模型已经掌握了基础的语言概率分布。
第二阶段才是真正的领域微调。我在 2,139 个精选的食谱样本上跑了 12 个 Epoch。由于第一阶段已经打好了语言底子,第二阶段的收敛速度非常快,模型迅速习得了食谱特有的词汇分布和逻辑结构。
最让我兴奋的是部署阶段。因为模型只有 6.4M 参数,我直接将其部署在 FastAPI 后端,采用进程内运行的方式。这意味着它完全不需要 GPU 支撑,也没有任何 Token 计费,更不用担心 API 限流导致的服务中断。这种极致的掌控感是调用 Claude 或 GPT-4 无法提供的。
这次实战给我最大的体感是:当你盯着那个不肯下降的 Loss 曲线死磕,或者在调试位置编码(Positional Encoding)导致模型输出乱码时,你对 Attention 机制的理解会比读十遍论文还要深刻。对于想要从 Prompt 工程师进阶到模型开发者的开发者来说,与其在巨大的模型面前感到渺小,不如尝试在小规模的实战中构建一个属于自己的“微型大脑”。
Tokenizer要是没对齐,分词乱套了整个模型基本就废了
640万参数要是用BPE分词估计得直接内存溢出,求推荐个轻量级的库!