00 背景知识速成-----全流程实现chatgpt2(预训练->sft->ppo)

发布时间:2026/9/18 8:13:29

00 背景知识速成-----全流程实现chatgpt2(预训练->sft->ppo) 00 背景知识速成看代码之前先花 20 分钟读懂这篇这篇不是讲解某个文件而是把读这些代码之前必须具备的背景知识集中讲一遍。整份 InstructGPT 项目反复用到这些概念先打通它们后面的逐行笔记会顺很多。如果你是零基础务必按顺序读这篇如果只是忘了某个概念可以直接跳到对应小节。目录数据是怎么进模型的字符 → token → id → 向量神经网络的最小零件nn.Linear、激活函数、Dropout概率与损失logits、softmax、交叉熵、log 概率、KL 散度训练到底在做什么前向、反向、梯度下降、epoch/batch/step张量操作速查广播、view/reshape、transpose、gather、flatten强化学习一分钟状态、动作、奖励、策略、价值、优势1. 数据是怎么进模型的字符 → token → id → 向量1.1 为什么机器不能直接读文字计算机只能处理数字。你好世界这串字模型是不认识的。所以第一步是把文字切成小块、编上号再变成向量。1.2 tokenizer分词器干的事tokenizer 文字 → 编号的转换器。它做的事这本书真是好看 --分词-- [这,本,书,真,是,好,看] --查词表-- [6821, 1726, 1210, 2682, 1878, 2619, 3554]token词元被切出来的最小单位。中文里通常一个字或一个词就是一个 token。词表vocab所有 token 的清单。本项目词表大小 21128每个 token 有个唯一编号 id0~21127。id编号token 在词表中的位置。tokenizer.encode(这本书)返回的就是一串 id。1.3 embedding嵌入干的事id 是整数但模型需要的是向量。Embedding 就是一张查表字典id6821 → 查表 → 一个 768 维的向量一堆小数nn.Embedding(vocab_size, emb_dim)内部是一张形状(21128, 768)的大表。id 是几就取第几行。取出来这行向量就是该词的意思语义相近的词向量也相近。这张表是训练学出来的——一开始是随机数训练后越来越好。对比 one-hot 编码也可以把 id 编成一个只有一位是 1 的 21128 维向量one-hot但那又稀疏又浪费而且看不出词与词的相似关系。Embedding 表等于把 21128 维压缩到 768 维还能学出语义。1.4 一句话总结数据流文字 --tokenizer-- token id 列表 --embedding-- (B, T, 768) 向量 [6821, 1726, ...] 每个 token 一个 768 维向量Bbatch一次喂几条样本。Tseq_len一条样本里多少个 token。形状(B, T, 768)就是整个模型世界的主语——几乎所有操作都在这个形状上进进出出。2. 神经网络的最小零件2.1 nn.Linear线性层一句乘法 加法nn.Linear(in_features,out_features)数学定义y xWᵀ b输入 x(..., in_features)权重 W(out_features, in_features)偏置 b(out_features,)输出 y(..., out_features)。通俗理解给输入的每个分量配一个权重加权求和再加个偏置得到新的一组数。它只能学线性关系所以后面必须接激活函数。2.2 激活函数让网络能弯曲如果全是线性层那多少层叠加都等于一层线性函数套线性函数还是线性学不了复杂东西。激活函数如 GELU、ReLU、sigmoid是非线性的让每一层的输出扭曲一下网络才有表达复杂规律的能力。线性层 --GELU-- 非线性 --线性层-- 非线性 ...2.3 Dropout随机丢一部分防过拟合训练时Dropout随机把一部分神经元的输出置 0比如 10%剩下的值放大一点。效果模型不能依赖某个特定的神经元被迫学得更平均、更鲁棒这就是为什么训练和推理要切换模式model.train()开 dropout、model.eval()关 dropout——推理时不需要随机丢。3. 概率与损失3.1 logits打分是什么模型最后一层输出的原始分数可以理解成模型认为每个词该被选中的热度。形状(B, T, 21128)——每个位置对词表 21128 个词各打一个分。分数是任意实数可正可负可大。它还不是概率。3.2 softmax把分数变成概率想让分数之和等于 1才能当概率用就用 softmaxprobs[i] exp(z[i]) / Σⱼ exp(z[j])exp是指数函数eˣ把任意数变成正数除以总和保证所有词的概率加起来 1分数越高概率越大但不是线性高分差距会被放大。数值稳定性技巧代码里反复出现z z - z.max(dim-1, keepdimTrue) # 先减每行最大值 probs softmax(z) # 结果一样但不会溢出为什么如果 z 里有很大的数比如 1000exp(1000)直接是inf算炸。先减去最大值最大的变成 0exp(0)1安全。softmax 对每个元素同时加/减同一个常数结果不变数学上等价。3.3 交叉熵损失cross entropy衡量猜得有多不准一句话模型给正确答案的概率越低损失越大。loss -log(P(正确答案))模型猜正确词的概率是 0.9 →-log(0.9) ≈ 0.105很小损失小 ✓模型猜正确词的概率是 0.0001 →-log(0.0001) ≈ 9.2很大损失大 ✗训练目标就是把这个损失降到最低也就是让正确词的概率越来越大。为什么要 log概率是 0~1 的乘数直接最小化损失时梯度很小取-log后概率越小损失增长越猛梯度更有推动力。另外 log 把连乘变成连加方便数学推导。代码里的标准用法PyTorchF.cross_entropy(logits,labels)# logits: (N, C)C 是类别数# labels: (N,)每个位置是正确答案的类别编号# 它内部自动做 softmax所以传 logits分数而不是概率注意F.cross_entropy内部已经带 softmax 了所以传原始 logits而不是 softmax 后的概率传概率反而错。3.4 log 概率与 KL 散度RLHF 里反复出现log 概率log P(x)。P(x) 是 0~1所以 log P(x) 是负数或 0。log 概率越大 概率越大。KL 散度Kullback-Leibler divergence度量一个分布 P 偏离另一个分布 Q 有多远。值越大越偏离等于 0 表示完全相同。在 RLHF 里我们不想让新策略偏离参考模型太多就在奖励里加一项偏离惩罚-β·(log π_θ − log π_ref)。log 相减正好是逐 token 的 KL 贡献——这就是 3-PPO.py 里rewards -beta * kl的由来。4. 训练到底在做什么4.1 一次训练的完整流程背下来1. 前向传播喂数据 → 模型算出预测 → 算出损失衡量错多少 2. 反向传播loss.backward() → 用链式法则算出每个参数的梯度该往哪改 3. 参数更新optimizer.step() → 让每个参数沿减小损失的方向走一小步 4. 清梯度optimizer.zero_grad() → 把上一步的梯度清零防止累加每一步对应一行代码optimizer.zero_grad()# 清梯度loss.backward()# 反传optimizer.step()# 更新4.2 梯度下降与学习率梯度损失函数对每个参数的偏导告诉它往哪个方向改、损失会变小。更新公式θ θ − lr × 梯度。学习率lr是每步走多远。lr 太大 → 步子太大容易跳过最优点甚至发散lr 太小 → 走得慢训练半天不收敛。本项目预训练5e-4SFT5e-5PPO1e-5——越到后面越小因为越到后期越要精细微调。4.3 epoch / batch / step 是什么词含义例子样本sample一条数据一条评论batch批一次喂给模型的样本集合8 条评论step / iteration步处理完一个 batch 并更新一次参数1 次optimizer.step()epoch轮把整个数据集完整过一遍全部评论过 1 遍 1 epoch关系1 epoch 数据条数 ÷ batch_size 个 step。本项目 SFTNUM_EPOCHS1表示只把数据过一遍防止灾难性遗忘。4.4 train() 和 eval() 的区别model.train()训练模式Dropout 开启。model.eval()评估模式Dropout 关闭且不更新任何参数。忘记切换是新手常见 bug评估时忘了eval()结果每次输出随机抖动。5. 张量操作速查读代码必备操作干什么例子x.shape看形状(2, 4, 768).unsqueeze(0)加一个维度(4,) → (1, 4)补 batch 维.squeeze(0)去掉一个维度(1, 4) → (4,).view(a,b,c)重排形状总元素数不变(2,4,768) → (2,4,12,64).reshape(a,b,c)同 view更宽容必要时复制同上.transpose(1,2)交换两个维度的顺序(2,4,12,64) → (2,12,4,64).flatten(0,1)把一段维度压平成一维(8,256,21128) → (2048,21128).cat([a,b], dim1)拼接(1,5)(1,1) → (1,6).gather(dim, index)按索引取数从词表维取出实际 token的分数.item()单元素张量 → Python 数取 loss 值.numel()元素总数8×2562048广播broadcasting形状对不上时自动拉齐(4, 768) (2, 4, 768) (2, 4, 768)规则从右往左对齐维度能配得上相等或一个为 1就自动扩展。位置嵌入(T, 768)和词嵌入(B, T, 768)相加靠的就是广播——(T,768)被自动复制到每个 batch。维数对不上会直接报错这是最常见的报错来源之一。view 为什么老报错requires contiguous[:, :-1, :]这类切片产生的结果内存可能不连续.view()要求连续内存所以报错.reshape()不报必要时自动复制。所以代码里错位后用.contiguous()或直接用view之前contiguous()一下。6. 强化学习一分钟6.1 四件套术语通俗理解本项目里状态 S“现在写到哪了”已生成的 token 序列动作 a“下一步选什么”选下一个 token策略 π(a|S)“在这种情况下选各种动作的概率”GPT-2 输出的概率分布奖励 R“这一步做得好不好”KL 惩罚 RM 打分6.2 强化学习和监督学习的本质区别监督学习有标准答案标签照答案学。比如 SFT 直接告诉模型下一个词该是 X。强化学习没有标准答案只有事后打分。模型自己试、被打分、再改进。就像学骑自行车没人告诉你往左 3 度只有摔了/没摔。6.3 为什么 RL 训练不稳定监督学习一批数据固定梯度是确定性的。强化学习数据是策略自己采样的——策略一变下一批数据的分布就变“自己给自己出题”。这就是 on-policy在轨的含义数据必须由当前策略产生。数据分布一直在变 奖励有噪声 → 训练容易来回震荡。所以 PPO 才要用旧策略的数据、限制一次更新幅度裁剪、用价值网络当基线降方差。6.4 策略梯度的一行直觉想让高分动作更常出现 梯度 ∝ A_t × ∇log π_θ(a_t|s_t) ↑ ↑ 这步多好 让这步更容易出现的改动方向优势 A_t 0这步比预期好→ 往提高该动作概率的方向更新A_t 0 → 往降低该动作概率的方向更新。读完这篇你应该能回答tokenizer 把文字变成了什么为什么还要 embeddingF.cross_entropy为什么传 logits 而不传概率一次训练为什么要有zero_grad → backward → step三步model.train()和model.eval()差在哪强化学习和监督学习最本质的区别是什么答不上来的话回去再看对应小节全答上来就可以开始读gpt_model.md了。
延伸阅读

更多相关文章

2026/9/17 9:48:09

STM32 HAL库核心函数解析与实战:从寄存器到高效开发

1. 从寄存器到HAL:STM32开发者的效率革命如果你是从51单片机或者早期直接操作STM32寄存器过来的开发者,第一次接触HAL库的感觉,大概率是既困惑又惊喜。困惑在于,以前直接写GPIOA->ODR | 0x0001;就能点亮一个灯,现在…

2026/9/17 9:03:06

深入解析MTK平台scatter.txt分区表:从ptgen工具链到实战定制

1. 项目概述:从零理解MTK分区表的生成脉络在MTK(联发科)平台的Android设备开发中,scatter.txt文件是一个绕不开的核心配置文件。无论是进行固件烧录、系统升级,还是深度定制分区布局,都离不开它。很多刚接触…

2026/9/8 6:19:03

从ASCII到虚拟键码:深入理解键盘鼠标编码原理与编程实践

1. 从一次“按键失灵”的调试说起:为什么我们需要了解键鼠的ASCII码那天下午,我正在调试一个用Python写的自动化脚本,它需要模拟用户按下“F5”键来刷新网页。我信心满满地写下了keyboard.press_and_release(F5),结果程序运行后&a…

2026/9/18 8:11:29

AI1505如何提升内容创作效率与质量

1. 项目背景与核心价值最近在内容创作圈子里有个新工具"AI1505"开始被频繁提及,作为一个常年和文字打交道的创作者,我第一时间做了深度测试。这个工具最吸引人的地方在于它号称能彻底解决内容创作中的"废稿焦虑"——那种写了半天却发…

2026/9/18 8:11:29

数据库系统概论怎么学?从关系模型到软考认证的完整路径

我大学时候最没当回事的一门课,就是《数据库系统概论》。当时觉得这就是教几个SQL语句嘛,select、from、where背一背,期末考试能过就行。直到后来工作了,被线上故障按在地上摩擦了几回,才回头把这门课翻出来重新啃。我…

2026/9/18 8:11:29

基于Django和LSTM的股票预测系统开发实践

1. 项目概述这个基于Django和LSTM的股票预测系统是一个典型的金融科技应用,它结合了深度学习技术和Web开发框架,旨在为投资者提供更准确的股票价格预测工具。系统通过LSTM神经网络模型分析历史股票数据,预测未来价格走势,并通过Dj…

2026/9/18 8:11:29

高考压线录取解析:风险与机遇并存

1. 压线录取现象的本质解析高考压线录取指的是考生的分数刚好达到某所院校或专业的最低录取分数线。这种情况每年都会在全国各地的高考录取中大量出现,形成了一个独特的"压线群体"。从数据统计角度看,压线录取具有明显的规律性。以2022年某省高…

2026/9/18 8:06:29

Windows专用设备化:注册表级Kiosk模式实战指南

1. 项目概述:让Windows变成一台“专用设备”你有没有遇到过这样的场景:一台电脑只用来跑某个特定程序——比如工厂产线上的数据采集终端、学校机房的考试系统、医院自助挂号机、或者家里给孩子用的纯学习平板?这些设备根本不需要Windows桌面、…

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码