上次我们分析了数据准备(数据预处理)在大模型中如何实现的,也就是encoding的过程,这次我们继续讲解一下第二个文件夹,config/中配置了哪些参数,都代表什么含义。

有关配置的内容在项目中有两个,它们都属于训练工程配置,不是模型算法本身,分别是configurator文件config/文件夹,我们来分别理解一下。

一、configurator.py-参数的读取和覆盖规则

它本身不配置“训练参数内容”,而是配置了参数如何被读取和覆盖的规则。

核心做了两件事:

1. 读取配置文件

如果命令行参数里有一个不带 = 的字符串,当你运行:

python train.py config/train_shakespeare_char.py

程序会发现第二个参数 config/train_shakespeare_char.py 不是像 --lr=0.001 这种带 = 的“参数赋值”,于是把它当作一个 Python 配置文件去执行。执行后,配置文件里定义的变量会覆盖主程序中的默认变量。关于这个文件涉及以下几个知识点,是理解它的前提:

(1)sys.argv

Python命令行参数 sys.argv 是 Python 用来拿“命令行输入内容”的列表。它本质上就是一个列表(List),里面装着你在命令行里输入的所有内容。

  • sys: 是一个 Python 内置的模块,提供了与 Python 解释器交互的功能。

  • argv: 是 sys 模块里的一个属性,全称是 "argument vector"(参数向量),你可以理解为“装着所有参数的列表”。

sys.argv 的作用就是:

  1. 接收外部指令:让你在运行脚本时,可以从外部给它传递信息(比如文件名、用户名、配置选项等)。

  2. 以列表形式存储:所有信息(包括脚本名)都被放进一个列表里,方便你通过索引(sys.argv[0], sys.argv[1]...)来取用。

  3. 实现脚本灵活性:同一个脚本,因为接收到的参数不同,可以执行不同的操作,变得非常灵活。

运行命令

python train.py config/train_shakespeare_char.py --batch_size=64

那么:

sys.argv[0] # train.py

sys.argv[1] # config/train_shakespeare_char.py

sys.argv[2] # --batch_size=64

也就是说,程序就是靠 sys.argv 知道你在命令行里传了什么。

(2)配置管理

配置管理:把训练参数单独放到配置文件里,而不是全写死在代码里。

比如这些都属于配置:

batch_size

learning_rate

dropout

n_layer

好处是:不同实验可以用不同配置文件,不用每次改主代码,更方便复现实验。

所以 config/train_shakespeare_char.py 本质上就是一个“配置文件”。

(3)exec、globals()

可以把它想成变量仓库,globals() 就像一个仓库:

变量名是标签,比如 "batch_size"

变量值是仓库里的东西,比如 32

你做:globals()["batch_size"] = 64

就是把仓库里 "batch_size" 对应的值,从 32 换成 64。

globals() 本质上就是:当前文件全局变量名 -> 变量值 的映射表(字典)

所以配置文件执行时,只要它在这个全局表里运行,就能改掉主程序原来的默认变量。

exec(..., globals()) 连起来看

比如:

batch_size = 32

code ="batch_size = 64"

exec(code, globals())

print(batch_size)

输出:64

意思是:code 里面有一段代码 "batch_size = 64",exec(..., globals()) 让这段代码在“当前全局变量表”里执行,所以把原来的 batch_size = 32 改成了 64。

(4)读取命令行覆盖项

如果命令行里有:--batch_size=32

它就把这个参数解析成:key: batch_size、value: 32,然后覆盖当前变量。

这属于的知识类:CLI 参数解析,配置优先级设计

串起来看,比如命令行输入:python train.py config.py --batch_size=32 --dropout=0.2

程序大概会这样做:先读默认值,再执行 config.py,覆盖默认值,再解析 --batch_size=32

用字符串处理拆出:

key: batch_size

value: "32"

再用 literal_eval("32") 变成整数 32,最后把当前配置里的 batch_size 改成 32

所以连起来就是:

CLI 参数解析:从命令行读参数

字符串处理:把 --batch_size=32 拆成 key/value

literal_eval:把 "32" 变成整数 32

配置优先级设计:让命令行参数覆盖配置文件和默认值

(5)防呆设计、配置校验、工程可维护性

此外,还做了简单校验,它还检查:参数名是否存在、类型是否匹配,这种防呆设计,提前防止用户犯错,或者让错误尽早暴露。

比如命令行里写:--batc_size=32

你本来想写 batch_size,结果拼错了。如果程序完全不检查,这个参数可能根本没生效,但你自己还不知道,后面训练结果就不对了。

所以程序会做防呆:检查这个参数名存不存在、不存在就直接报错、不让错误悄悄混过去

再比如:

--batch_size=abc

batch_size 应该是整数,不应该是字符串 abc,这时也应该马上报错。

所以“防呆设计”本质上就是:通过限制、检查、报错,减少低级误操作。

“配置校验”就是:检查你传进来的配置是不是合法。

比如校验两类东西:参数名是否存在

例如程序只允许这些参数:

batch_size

learning_rate

dropout

如果你传:--hello=123,那就是非法参数,因为程序根本没有这个配置项。

类型是否匹配,比如:

batch_size 应该是 int

learning_rate 应该是 float

compile 应该是 bool

如果你传:--batch_size="abc",或者:--compile=[1,2,3],这就类型不对。

所以“配置校验”就是:确保配置项名字对、值的类型对、必要时范围也对。

更完整一点还可以检查:数值范围,比如 dropout 必须在 0~1,是否为空,参数组合是否冲突

“工程可维护性”就是:代码以后好不好改、好不好查问题、好不好让别人接手。

为什么前面的校验会提升可维护性?因为如果没有校验,可能出现这种情况:--batc_size=32

程序没报错,但其实没生效,还是用默认值在训练。几天后你发现结果不对,就很难排查: 到底是模型问题、数据问题,还是参数根本没传进去?如果有校验,程序一开始就报:Unknown config key: batc_size,那问题立刻就清楚了。所以这些检查会让工程更容易维护,因为它们能:更早发现问题,报错更明确,减少隐蔽 bug。让后来的人更容易理解系统行为。

总的来说:

防呆设计:防止用户乱传参数、拼错参数、传错类型

配置校验:具体去检查参数名和参数值是否合法

工程可维护性:通过这些检查,让程序更稳定、更容易排查和维护

二、config/ 文件夹里的配置

config/ 里的每个 .py 文件,都是一套实验场景参数模板。它们不是功能代码,不负责“实现训练逻辑”,它们负责的是:告诉 train.py:这次训练/评估应该用哪套参数。所以你可以把它理解成:train.py:总控程序,config/*.py:不同场景下的训练方案内容,每个配置文件适用什么场景。

1. config/train_shakespeare_char.py

适用场景:新手入门,字符级语言模型,小模型训练,调试训练流程,普通机器上先跑通项目,现在学shakespeare_char 时应该用它。因为它对应的数据集就是:dataset= 'shakespeare_char'

也就是说,它和你前面看的 data/shakespeare_char/prepare.py 是一套。

相关知识类型:字符级 tokenization、从零训练(scratch training)、小型 Transformer、训练参数入门

2. config/finetune_shakespeare.py

适用场景:学习“微调”概念、从预训练 GPT-2 出发,继续适配 Shakespeare 数据、想对比“从零训练”和“微调”的区别,它对应的数据集是:

dataset= 'shakespeare'

init_from= 'gpt2-xl'

这里不是 shakespeare_char,而是 shakespeare。这份数据是用 GPT-2 的 BPE tokenizer 做的,不是字符级。

相关知识类型:微调(finetuning)、预训练模型迁移

3. config/train_gpt2.py

适用场景:大规模训练、复现 GPT-2 风格训练、OpenWebText 数据集、多 GPU/高算力环境

这个不适合刚入门时直接学,因为:模型大、数据大、参数复杂、工程难度高

相关知识类型:大模型预训练、、OpenWebText、分布式训练 DDP、大批量训练

4. 设置baseline,不同模型的loss对比

config/eval_gpt2.py

config/eval_gpt2_medium.py

config/eval_gpt2_large.py

config/eval_gpt2_xl.py

这几个文件的适用场景:不训练,只评估,看不同 GPT-2 预训练模型在数据集上的 loss,做 baseline 对比,它们不是拿来“学训练流程”的第一选择,更像是: “拿现成模型来测效果”,相关知识类型:模型评估、baseline、loss 对比、不同模型规模比较,拿 4 个已经存在的 GPT-2 预训练版本,分别测一下 loss,当参照物,4 个现成选手,先下场跑一遍,给你一条成绩参考线。因为一般来说,模型越大,表示能力越强,所以在同样任务上更容易把预测做对,loss 就更低。在同类模型、训练得也比较充分的前提下,通常越大的模型 loss 越低。

因为“大模型”通常意味着它有更多参数,也就是更大的表达能力。比如它通常会有:更多层、更宽的隐藏维度、更多注意力头、更多总参数量这带来的结果是:它能学到更复杂的规律。

可以拿它们做基线比较,看小模型和大模型在同一数据上的表现差多少,帮你判断自己训练/微调出来的结果到底算不算好,baseline 把它理解成:参考线。为什么要有 baseline,因为你训练完一个模型,哪怕得到一个数字,比如:val loss = 2.90

你也不知道这到底算:好、一般、还是很差,单独一个数字没有意义。

所以必须找个“参照物”来比较,这个参照物就是 baseline。

举个最简单的例子假设你自己训练了一个模型,在验证集上:

val loss = 2.90

然后你拿现成的 gpt2 来测同一个验证集,发现:gpt2 val loss = 3.12,那就说明:你的模型比这个 baseline 更好。但如果拿 gpt2-medium 来测,结果是:gpt2-medium val loss = 2.84,那就说明:你的模型还不如这个更强的 baseline。所以 baseline 的作用就是:帮你判断结果到底处在什么水平。

为什么 nanoGPT 里有 4 个 baseline,因为作者想比较 4 个现成模型:gpt2、gpt2-medium、gpt2-large、gpt2-xl,它们都先在同一个数据集上测一遍。

这样你就知道:小模型大概什么水平、中模型什么水平、大模型什么水平、最大模型什么水平,这几条线都可以当 baseline。在这个项目里 baseline 主要回答从零训练了一个模型,或者微调了一个模型,比现成 GPT-2 差多少?比小一点的 GPT-2 好还是差?我这次改动到底有没有提升?这个结果值不值得继续做?这些都靠 baseline 来判断。

5. config/train_shakespeare_char.py 内的参数讲解

(1)训练流程与实验管理参数

out_dir

eval_interval

eval_iters

log_interval

always_save_checkpoint

它们在配置什么:

输出目录放哪里

多久评估一次

每次评估测多少个 batch

多久打印一次训练日志

保存 checkpoint 的策略

属于哪类知识:训练流程、验证集评估

(2)日志与实验跟踪

参数:

wandb_log

wandb_project

wandb_run_name

它们在配置什么:

是否启用 WandB

实验项目名

本次运行名字

属于哪类知识:

实验记录

可视化监控

训练追踪

主要在哪用到:train.py

按需补充知识点:WandB 是什么、为什么训练实验要记录超参数和 loss 曲线

(3)数据与输入形式

参数:

dataset

gradient_accumulation_steps

batch_size

block_size

它们在配置什么:

用哪份数据

一次更新前累积几次梯度

每次并行喂多少条样本

每条样本长度多长

属于哪类知识:

数据加载

mini-batch 训练

上下文窗口

梯度累计

主要在哪用到:train.py 的 get_batch()、train.py 的训练循环、block_size 还会传到 model.py

(4)模型结构

参数:

n_layer

n_head

n_embd

dropout

它们在配置什么:

n_layer:Transformer 堆多少层

n_head:每层注意力有多少个头

n_embd:每个 token 的向量维度

dropout:训练时做多强的随机丢弃

属于哪类知识:

Transformer 结构

多头注意力

embedding

正则化 / 防过拟合

主要在哪用到:train.py 先收集这些参数、model.py 真正根据它们搭模型

(5)优化与训练稳定性

参数:

learning_rate

max_iters

beta2

它们在配置什么:

学习率多大

训练总共多少步

AdamW 优化器内部平滑参数之一

属于哪类知识:

优化器

梯度下降

AdamW

训练稳定性

主要在哪用到:train.py、model.py 的 configure_optimizers(...)

按需补充的知识点:学习率是什么、Adam / AdamW 是什么、为什么学习率太大或太小都不行、iter 是什么,和 epoch 有什么区别


(6)学习率调度

参数:

lr_decay_iters

min_lr

warmup_iters

它们在配置什么:

学习率衰减持续多久

最低降到多少

前多少步做 warmup

属于哪类知识:

学习率调度

warmup

cosine decay

收敛控制

主要在哪用到:

train.py 的 get_lr()

按需补充知识点:为什么学习率不是固定不变、warmup 为什么常见、学习率衰减为什么有助于后期稳定训练


(7)运行环境

注释里给了可选项:

device

compile

它们在配置什么:

用 CPU 还是 GPU

是否启用 torch.compile

属于哪类知识:

PyTorch 运行设备

性能优化

平台兼容性

主要在哪用到:

train.py

按需补充知识点:cpu / cuda 区别、torch.compile 是什么、为什么 Windows / CPU 场景常要关掉部分优化

总结配置内容

这份 config/train_shakespeare_char.py 本质上在配置 3 件大事:

数据怎么喂:dataset、batch_size、block_size

模型长什么样:n_layer、n_head、n_embd、dropout

模型怎么学(训练流程和验证):learning_rate、max_iters、warmup_iters、lr_decay_iters、eval_interval、loss、checkpoint

如果这三块需要慢慢吃透,后面看 train.py 就不会乱。

config/train_shakespeare_char.py 配置的是一套小型字符级 GPT 训练方案,核心覆盖了:

数据输入、模型结构、优化训练、学习率调度、评估与保存、运行环境

打基础,最优先补的是:Transformer 结构(n_layer/n_head/n_embd) 和 优化训练(learning_rate/max_iters)。

这次我们了解了配置内容,接下来可以按需补充需要学习的知识点,或者从实践中去看下参数的变化,会给模型训练结果带来什么不一样的结果。下篇会讲一下并记录一下简单的训练结果。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐