
人工智能大模型预训练分布式训练模型优化深度学习【免费下载链接】modded-nanogptNanoGPT (124M) in 90 seconds项目地址https://gitcode.com/GitHub_Trending/mo/modded-nanogpt点击查看免费下载本篇技术指南以 2025-09-10_Yarn 实验记录 为主体系统讲解 modded-nanogpt 如何在 124M 参数 NanoGPT 的百秒级训练竞速中引入 YaRNYet another RoPE extensioN论文 arXiv:2309.00071来平滑注意力窗口的逐级放大并结合旋转频率缩放与注意力 logit 缩放两套机制消除窗口切换时的 loss 尖峰。读完你将掌握窗口调度为什么会在 RoPE 上引发分布外问题、YaRN 与 attn_scale 的数学公式与常数调参、单份旋转嵌入表的存储优化以及最终验证窗口ws_validate的实验设计方法。背景更长的注意力窗口与 RoPE 的分布外问题在 modded-nanogpt 的训练竞速中一个朴素的观察是更长的注意力窗口训练更慢但能产出更低的 loss。因此理想方案不是全程用长窗口而是在训练早期用短窗口加速、后期逐步放大。但这引出了 RoPERotary Position Embedding的两个真实痛点低频率维度遭遇陌生旋转角。RoPE 各维度旋转频率不同训练时模型只见过某个旋转角度范围内的位置编码。例如一个每位置旋转 0.1 度的维度在窗口大小 384ws 384的训练中累计只会旋转0.1 * 384 38.4度当滑动窗口一次性放大到 896 时同一维度可能旋转到89.6度——这是从未见过的分布外数值会带来临时的 loss 尖峰。K/Q 归一化下的注意力困惑度随 key 数量增长。当 K、Q 向量做了 normQK norm后注意力窗口内的 key 数量越多注意力机制的平均困惑度越高。此时对softmax(d * QK)施加一个缩放因子d可以随窗口内 key 数量增长重新控制注意力分布的困惑度。这两点正是 YaRN 要解决的核心矛盾既要通过放大窗口拿到更低 loss又要让 RoPE 频率分布跟得上窗口变化避免切换时刻的验证损失崩坏。单份旋转嵌入表减少更新开销与内存占用该记录里一个重要的工程优化是只在模型根部保存一份旋转嵌入rotary embeddings的拷贝而不是在每个注意力层各存一份。收益有三减少窗口切换时的更新耗时、降低显存占用、潜在改善缓存局部性。实现代码如下# store single copy of rotary tensors angular_freq (1 / 1024) ** torch.linspace(0, 1, stepshead_dim//4, dtypetorch.float32) # half-truncate RoPE by YouJiacheng (w/ base freq tuning) angular_freq torch.cat([angular_freq, angular_freq.new_zeros(head_dim//4)]) t torch.arange(self.max_seq_len, dtypetorch.float32) theta torch.outer(t, angular_freq) self.rotary_cos nn.Buffer(theta.cos(), persistentFalse) self.rotary_sin nn.Buffer(theta.sin(), persistentFalse)这里有两个细节值得展开频率基线angular_freq从(1/1024)^0 1线性衰减到(1/1024)^1即最大角频率为每位置 1 弧度约 57 度这是对1024^(0..1)基线的直接实现half-truncate RoPEYouJiacheng把head_dim // 4个有效频率向量复制到head_dim // 2长度后再拼接等长的零向量实现只旋转一半维度的半截断式 RoPE配合基频调参使用使用nn.Buffer(..., persistentFalse)声明非持久化缓冲区cos/sin 表预计算好存为 buffer训练中只做就地更新。这一设计在当前仓库中已演进为 track_1_short/model/attention.py 中的Yarn类它按 head 宽度64/128分别维护 cos/sin 因子表支持配对头paired heads的2t/2t1打包布局并把半截断实现为ROTARY_DIM 64常量64 宽 head 全部维度旋转128 宽 head 只旋转前半部分其余保持固定。两套缩放频率缩放YaRN与注意力缩放attn_scale记录中最重要的调参结论是把两个常数做了经验修正YaRN 公式的 0.1 常数改为 0.2。原论文0.1 * log(curr/prev) 1中的 0.1 在实证中不够用attn_scale 起点从 0.12 改为 0.1。原恒定缩放 0.12 改为从 0.1 起步、随窗口增长按对数累积上升使训练全程的分布均值与原先相当取值落在 0.1 到 0.14 之间。# scale attention factor f in attnsoftmax(f*qk) logarithmically with window size windows list(dict.fromkeys(args.ws_schedule [args.ws_validate])) scale_factors [0.2 * math.log(curr / prev) 1 for prev, curr in zip(windows[:-1], windows[1:])] # start with 0.1, inspired by 0.12 from leloykun and learnable scalars used by brendanh0gan attn_scales list(accumulate([0.1] scale_factors, lambda acc, factor: acc * factor)) self.attn_scales dict(zip(windows, attn_scales))注意scale_factors的构造方式窗口序列去重dict.fromkeys保留顺序后相邻两档窗口计算0.2 * log(curr/prev) 1再以 0.1 为起点做累乘得到每档窗口对应的注意力缩放系数。这样softmax(f * QK)中的f会随着窗口档位逐级放大恰好抵消key 数量增加导致注意力困惑度上升的效应。0.1 的起点灵感来自 leloykun 的 0.12 以及 brendanh0gan 使用的可学习标量。YaRN 频率更新的实现alpha/beta 保持论文默认YaRN 本身实现非常直接该记录把alpha和beta保持在论文默认值 1 和 32原论文针对 Llama 调参并指出YaRN 引起的频率更新在窗口从 3 切到 7、以及维度 5 到 10 之间最为显著。def apply_yarn(self, old_window: int, new_window: int, alpha: int1, beta: int32): rotations args.block_size * old_window * self.angular_freq / (2 * torch.pi) scaling_factor old_window / new_window interpolation_weight torch.clamp((rotations - alpha) / (beta - alpha), 0, 1) self.angular_freq * scaling_factor interpolation_weight * (1 - scaling_factor) t torch.arange(self.max_seq_len, dtypetorch.float32, deviceself.angular_freq.device) theta torch.outer(t, self.angular_freq) self.rotary_cos.copy_(theta.cos()) self.rotary_sin.copy_(theta.sin())逐行解读rotations把角频率折算成在旧窗口长度上累计旋转了多少圈args.block_size * old_window是旧窗口对应的 token 数除以2π得到圈数scaling_factorold_window / new_window窗口放大时小于 1表示需要把高频维度的旋转频率压缩以延展位置空间NTK 式缩放interpolation_weight按(rotations - alpha) / (beta - alpha)裁剪到 [0,1]实现维度旋转圈数在 alpha 以下完全按缩放因子压缩、超过 beta 完全不压缩、中间线性过渡的 YaRN 插值最终angular_freq * scaling_factor interpolation_weight * (1 - scaling_factor)逐维度混频并就地重建 cos/sin 表。这一函数在当前仓库 track_1_short/model/attention.py 的Yarn.apply中继续存在并且把注意力缩放更新也合并进同一次调用self.attn_scale * 0.2 * math.log(new_window / old_window) 1——注意当前代码直接用math.log而不再依赖累积列表逻辑等价于记录中的累乘公式。用更长的窗口做最终验证ws_validatews_validate参数允许在比训练更长的注意力窗口上做最终验证。该记录中训练最终窗口为 11而验证窗口设为 13对应的调度函数为def get_ws(step: int): if step args.num_iterations: return args.ws_validate x step / (1 args.num_iterations) assert 0 x 1 ws_idx int(len(args.ws_schedule) * x) return args.ws_schedule[ws_idx]要点是训练步骤严格落在ws_schedule的离散档位上按进度比例索引唯独最后一步单独返回ws_validate从而在不改变训练过程的前提下让最终评估暴露模型在更长上下文下的真实能力。这一设计在当前仓库中演化为 track_1_short/schedule.py 的TrainingSchedule与 track_1_short/config.py 的WS_POST_YARN_EXT 20最终验证把长窗口再扩展到 20 个 block并在 train_gpt.py 中通过limit_yarn_rebuild/complete_yarn_tables控制旋转表的重建时机窗口变化只重建训练步实际读取的行验证前再把整张表补齐避免在计时区间内全量重建。训练超参微调cooldown_frac 与步数该记录同时清理了训练收尾阶段的配置cooldown_frac 从 0.45 提高到 0.5以配合总步数从 1705 降到 1670遵循固定冷却步数的经验法则步数变少冷却占比就得变大才能保住同样数量的 LR 衰减步降到 1695 步以下还有二级收益少读一次第 9 个数据文件大约节省 200ms 的墙钟时间——这类步数-文件读取边界对齐的微优化在百秒级竞速中直接换算成最终成绩。窗口档位long/short从 (3/1) → (7/3) → (11/5) 逐级放大当前仓库的 track_1_short/config.py 已把窗口粒度从 token 改为BLOCK_SIZE 128token 的 block 单位如window_sizes(1,3)→(3,7)→(5,11)→(6,13)并配套了 batch size 8→16→24→20→8 的调度可见同一套多阶段窗口放大 YaRN 平滑思想仍在延续。实验结论YaRN 消除了窗口切换的 loss 尖峰记录用对照实验证实了两件事没有 YaRN 时注意力窗口从 3 突然放大到 7验证 loss 会出现明显尖峰引入 YaRN 频率缩放后尖峰消失这是该 PR 能成立的关键证据把最终验证窗口从 11 扩展到 13loss 大约有0.0015 的提升。而且一个有意思的经验观察varunneal 提出奇数窗口表现显著更好。可能的解释包括短窗ws_short ws_long // 2的整除在奇偶长度下行为不同短窗低于长窗的 50% 时表现更好或模型学会了长/短窗口的固定比例、比例被大幅改变时表现变差——记录明确说明可能还有完全不同的解释属于未定论经验。消融实验ablation覆盖了四项new_record本 PR 完整配置no_attn_scale保持恒定 attn scale 0.12关掉注意力缩放no_freq_scale保持恒定旋转频率基于 1024^(0..1)关掉 YaRN 频率缩放prior_record先前记录 更新后的步数 1705→1670 与 cooldown frac 0.5。通过逐项开关可以量化频率缩放与注意力缩放各自对最终 loss 的贡献这是百秒级训练里做归因分析的标准打法。统计验证显著性检验与均值方差该记录用 7 次重复运行做统计验证证明 159.3s 的跑分成绩是可靠的import scipy.stats import torch accs [3.2779, 3.2779, 3.2789, 3.2778, 3.2789, 3.2785, 3.2806] times [159.447, 158.998, 159.467, 159.191, 159.503, 159.259, 159.468] print(p%.4f % scipy.stats.ttest_1samp(accs, 3.28, alternativeless).pvalue) # p0.0053 print(acc:,torch.std_mean(torch.tensor(accs))) # acc: (tensor(0.0010), tensor(3.2786)) print(time:,torch.std_mean(torch.tensor(times))) # time: (tensor(0.1897), tensor(159.3333))结论验证 loss 均值 3.2786标准差 0.0010对 3.28 基准做单侧 t 检验p 0.0053统计显著7 次运行耗时均值 159.33s标准差 0.19s方差极小说明成绩可复现。未来方向记录中提出的四个开放问题该记录末尾给出四点后续思考至今仍有参考价值优化器动量刹车训练像没有刹车的赛车——窗口放大、模型改变方向时若能有效压制优化器状态momentum中的动量项或许能减少瞬时损失作者在仅 Muon 参数上的初步实验结果是负面的分布式 bos token 查找8 个数据文件若每张 GPU 只负责 1 个文件而不是全部 8 个来定位 bos token 索引在零开销假设下最多可省200ms * 7 ≈ 1.4sRoPE 起始角频率把最大角频率定为每位置 1 弧度57 度看起来有些任意但实验把该值升到 180 度并未带来性能提升更细粒度的监控每 125 步才画一次验证 loss 会掩盖窗口切换瞬间的 loss 尖峰更细粒度的监控对这类竞速调优更有价值。源码落点速查组件仓库位置说明YaRN 实验记录records/track_1_short/2025-09-10_Yarn/ReadMe.md本文主体含完整代码与实验数据Yarn 类实现track_1_short/model/attention.pycos/sin 表、reset/apply/ensure_full、half-truncate训练调度track_1_short/schedule.py多阶段窗口调度、YaRN 更新时机、扩展验证窗口超参配置track_1_short/config.pyBLOCK_SIZE、LR_COOLDOWN_FRAC、TRAINING_STAGES、WS_POST_YARN_EXT训练入口train_gpt.pylimit_yarn_rebuild / complete_yarn_tables 的计时优化这套短窗起步 逐级放大 YaRN 频率缩放 attn_scale 对数累积 更长验证窗的组合拳是 modded-nanogpt 在约 159 秒内完成 124M 参数模型训练的关键一环其每个常数都有实证依据、每个改动都有消融对照的做法也值得任何追求极致训练效率的工程团队借鉴。赞分享人工智能大模型预训练分布式训练模型优化深度学习【免费下载链接】modded-nanogptNanoGPT (124M) in 90 seconds项目地址https://gitcode.com/GitHub_Trending/mo/modded-nanogpt点击查看免费下载相关推荐ebook-GPT-translator让阅读无国界一键翻译PDF/EPUB电子书的AI神器ebook GPT translator让阅读无国界一键翻译PDF/EPUB电子书的AI神器 ebook GPT translator是一款基于GPT技术的Modded-NanoGPT BatchSize 调优实战训练序列 48K 与验证序列 256K 的权衡Modded NanoGPT BatchSize 调优实战训练序列 48K 与验证序列 256K 的权衡 本文以 Modded NanoGPTNanoGPT人工智能大模型预训练分布式训练模型优化深度学习llm.c 基线复现记录Modded-NanoGPT 速度竞赛的起跑线与验证基准llm.c 基线复现记录Modded NanoGPT 速度竞赛的起跑线与验证基准 导读 本文解读 Modded NanoGPT https://link.gi人工智能大模型预训练分布式训练模型优化深度学习上一篇WSABuilds 完整指南在 Windows 10/11 上从零跑通带谷歌商店和 Root 的安卓环境下一篇AlaSQL 在 Chakra 引擎上的 SQL Logic Test 兼容性测试报告解读创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考