
系列《从小白到 AI 大模型开发工程师的进阶之路》 技术点AI-0223 梯度下降 主人公小蓝伞 前置AI-0222 优化问题 本期产出独立实验脚本、原始输出、失败样本和验收清单小蓝伞在同一份合成线性数据上跑三种批次看到随机梯度误差更小却没有注意它做了六千四百次更新全批次只做一百次。 本期按准备环境、运行完整脚本、读取结果和复验失败的顺序完成实践。梯度下降更新参数以降低训练目标。泛化需要独立评价学习率、批次大小、更新次数和数据顺序影响训练轮数相同不代表更新预算相同。 输入均为教学合成数据不是生产经历。一、小蓝伞遇到的问题预测为斜率乘输入加截距损失为残差平方平均。斜率梯度是两倍残差与输入乘积的平均截距梯度是两倍残差平均。两个梯度必须用同一旧参数状态计算再完成更新不能更新斜率后用新斜率计算另一梯度而不说明算法变化。二、先给结论梯度下降更新参数以降低训练目标。泛化需要独立评价学习率、批次大小、更新次数和数据顺序影响训练轮数相同不代表更新预算相同。推荐先验证解析梯度和小样本再扫学习率比较批次同时报告更新数泛化结论必须使用独立数据。不推荐省略输入语义和指标口径仅凭单次输出扩大结论。成功判据三种策略保存更新数、训练与留出误差过大学习率最终损失大于首轮零轮没有伪造历史。三、任务与数据契约项目本期约定输入完整代码构造的合成数据输出数值、图表或异常及原始日志环境Windows 11、Python 3.13.9依赖见记录不在范围真实业务、生产容量和跨设备性能四、前置准备在新目录保存工作目录中的实验.py为main.py再执行python -m venv .venv .\.venv\Scripts\python.exe -m pip install numpy2.3.5 .\.venv\Scripts\python.exe main.py本次实际执行使用 Windows 11、Python 3.13.9代码只生成合成输入不依赖账号、令牌或隐藏文件。五、核心原理学习率控制沿负梯度更新幅度。全批次每次使用全部训练数据。小批次每次使用一组有限记录。SGD本例每次使用单条记录更新。留出误差独立样本上的目标误差。三种批次改变什么全批次每次使用所有训练记录小批次每次八条随机梯度每次一条。小批次和随机梯度的方向有样本噪声但每轮包含更多更新。本例固定学习率、轮数与初始参数展示行为差异它不是同更新预算的性能排名需要把次数直接写入结果。学习率过大的确定性失败把全批次学习率改为一点二三十轮中损失从约二点零五升到五点九九乘十的八次方。固定数据后这种爆炸不是网络或随机服务故障应先检查学习率、尺度和梯度。拒绝非有限参数、记录损失轨迹比盲目增加轮数更有价值。怎样进行公平比较可按相同更新数、相同数据访问量或相同墙钟预算比较但要选择并声明一个口径。每种口径回答不同工程问题。比较时保留数据划分、初始化、评价频率和随机顺序先检查结果正确再测时间避免把绘图、生成数据和日志算进训练核心。六、完整项目完整脚本位于_work/第69期-梯度下降/实验.py。它包含正常、边界和失败断言复制到main.py后可独立运行。import numpy as np def train(x,y,mode,lr.03,epochs100): 以固定样本顺序比较三种批次学习率和轮数保持一致。 rngnp.random.default_rng(62) parameternp.zeros(2) history[] size{batch:len(x),mini:8,sgd:1}[mode] for _ in range(epochs): orderrng.permutation(len(x)) for start in range(0,len(x),size): idsorder[start:startsize] designnp.column_stack([x[ids],np.ones(len(ids))]) gradient2*design.T(designparameter-y[ids])/len(ids) parameter-lr*gradient history.append(float(np.mean((x*parameter[0]parameter[1]-y)**2))) return parameter,history rngnp.random.default_rng(20261013) xnp.linspace(-1,1,64) y2*x1rng.normal(0,.1,len(x)) valid_xnp.linspace(-1,1,40) valid_y2*valid_x1 for mode in (batch,mini,sgd): p,htrain(x,y,mode) print(f{mode} updates{100*(len(x)//{batch:64,mini:8,sgd:1}[mode])} train{h[-1]:.6f} holdout{np.mean((valid_x*p[0]p[1]-valid_y)**2):.6f}) _,badtrain(x,y,batch,lr1.2,epochs30) print(过大学习率初始/最终损失,round(bad[0],6),round(bad[-1],6)) assert bad[-1]bad[0] _,zerotrain(x,y,batch,epochs0) assert zero[] print(零轮训练历史为空) 实现与结果的进一步核验数据生成与评价目标训练输入均匀分布在负一到一标签为两倍输入加一再加固定种子噪声留出标签不含噪声专门检查学习到的直线是否接近生成规律。训练与留出数据目标不同的设计必须公开否则较低留出损失看起来反常。它是教学控制不代表真实验证集可以删去噪声。更新预算的数字核对六十四训练点全批次每轮一更新小批次八条每轮八更新单样本每轮六十四更新。共一百轮便是一百、八百和六千四百步。记录次数揭露比较口径读者可以再按相同更新预算重新比较没有额外运行结果时不要替这种比较填写想象数字。损失归一化决定梯度尺度代码把梯度除以当前批样本数因此每批使用平均损失。若改为求和而学习率不变更新规模也变比较批大小时会混入另一变量。末批不足整批时同样按实际数量处理。梯度尺度、样本访问量和参数更新量都应从代码直接核对不能只看模式名称。停止条件如何设定可使用验证指标早停、目标改变量、梯度范数和最大轮数但每项只提供一部分信息。损失发散时先停止并保留最后有效参数不继续训练以期自然恢复遇到非有限值检查输入尺度和梯度。零轮输出空历史是合法边界应标未训练而不是把初始参数包装为收敛模型。保存训练工件记录参数、随机状态、数据划分、学习率、批大小和评价轨迹重跑才有相同问题。只保存最终斜率截距不足以证明过程只保存图又无法复核参数。后续Adam对照将统一更新数当前篇则明确展示轮数相同导致的预算差异。七、可复现失败案例学习率1.2导致损失由2.05升至约5.99e8零轮历史为空不代表收敛。 这是构造的教学失败不是线上事故。复现顺序是保存输入、运行脚本、记录输出、只改一个条件后重跑。修复后必须同时检查正常样本不能用默认值掩盖错误。八、实验设计与实际结果三种策略保存更新数、训练与留出误差过大学习率最终损失大于首轮零轮没有伪造历史。 本次已经执行退出状态为0完整输出见工作目录。控制变量、样本量和参数写在脚本中。batch updates100 train0.029147 holdout0.021292 mini updates800 train0.007826 holdout0.000126 sgd updates6400 train0.007940 holdout0.000003 过大学习率初始/最终损失 2.054818 599135470.743341 零轮训练历史为空数字怎样对应本期机制全批次一百轮训练损失约零点零二九一留出误差零点零二一三小批次八百更新训练损失约零点零零七八留出误差零点零零零一三随机梯度六千四百更新在这份简单数据上留出误差更小。留出目标是无噪声直线不代表真实业务数据分布。九、常见问题与排查顺序先检查对象定义再检查输入、形状、分母、索引或时间点最后检查实现与环境。训练损失衡量拟合训练数据验证集帮助选择轮数和超参数测试集用于最终评估。早停和学习率调整若反复参考测试集也会污染评估。本篇只手写简单回归零轮训练历史为空是合法边界不能把它当成训练完成。 不要把一次成功当成稳定性证明也不要把技术指标直接换成业务价值。十、系统与依赖差异本次只在记录的 Windows 和库版本运行。浮点末位、计时、字体、编码和表格默认行为可能跨环境变化未执行部分保持待核验。十一、验证清单执行脚本核对退出状态与本篇实际输出。重跑本篇正常、边界和失败样本检查数值或拒绝结果。更换数据时重新检查对象、分母和评价条件。验收判据三种策略保存更新数、训练与留出误差过大学习率最终损失大于首轮零轮没有伪造历史。十二、面试题与追问学习率在本期是什么答控制沿负梯度更新幅度。 预测为斜率乘输入加截距损失为残差平方平均。斜率梯度是两倍残差与输入乘积的平均截距梯度是两倍残差平均。两个梯度必须用同一旧参数状态计算再完成更新不能更新斜率后用新斜率计算另一梯度而不说明算法变化。追问改变这个条件后哪一个输出或失败判据应该变化全批次在本期是什么答每次使用全部训练数据。 全批次每次使用所有训练记录小批次每次八条随机梯度每次一条。小批次和随机梯度的方向有样本噪声但每轮包含更多更新。本例固定学习率、轮数与初始参数展示行为差异它不是同更新预算的性能排名需要把次数直接写入结果。追问改变这个条件后哪一个输出或失败判据应该变化小批次在本期是什么答每次使用一组有限记录。 全批次一百轮训练损失约零点零二九一留出误差零点零二一三小批次八百更新训练损失约零点零零七八留出误差零点零零零一三随机梯度六千四百更新在这份简单数据上留出误差更小。留出目标是无噪声直线不代表真实业务数据分布。追问改变这个条件后哪一个输出或失败判据应该变化SGD在本期是什么答本例每次使用单条记录更新。 把全批次学习率改为一点二三十轮中损失从约二点零五升到五点九九乘十的八次方。固定数据后这种爆炸不是网络或随机服务故障应先检查学习率、尺度和梯度。拒绝非有限参数、记录损失轨迹比盲目增加轮数更有价值。追问改变这个条件后哪一个输出或失败判据应该变化留出误差在本期是什么答独立样本上的目标误差。 可按相同更新数、相同数据访问量或相同墙钟预算比较但要选择并声明一个口径。每种口径回答不同工程问题。比较时保留数据划分、初始化、评价频率和随机顺序先检查结果正确再测时间避免把绘图、生成数据和日志算进训练核心。追问改变这个条件后哪一个输出或失败判据应该变化十三、工程判断与下一期先验证解析梯度和小样本再扫学习率比较批次同时报告更新数泛化结论必须使用独立数据。 下一期为AI-0224 Adam 与自适应优化。本期保留的契约和反例会继续使用。从本地证据到实际决策随机性与可复现脚本每轮打乱训练索引但种子固定三种策略使用同一生成约定。固定种子仅复现当前顺序不保证跨设备逐位一致。若比较多个随机种子应预先定义次数和汇总不能选最佳一条轨迹。数据噪声与训练打乱各自有来源记录时分开。欠拟合与过拟合的边界学习率过小或轮数不足可能没有逼近训练最优容量过大或训练过久则可能拟合噪声。训练损失下降与留出指标关系需要轨迹观察。本例简单直线不展示复杂过拟合所以不能把标题问题当作已经完成所有泛化实验它用独立留出强调评价职责。数值失败的处置损失爆炸时停止继续更新保留参数与输入摘要检查数据尺度、梯度符号、归一化和步长。不能遇到无穷就截成最大浮点数当训练成功。异常处理需要让调用方知道模型未完成回滚到有效工件再在小样本上复验修复。从手写到成熟训练器手写回归帮助核对梯度和批次意义成熟框架负责设备、并行和通用算子。换工具不能改变损失分母或评价数据迁移时先跑同一小数据对照参数和更新。框架默认优化器、批次和梯度清零都应显式设置避免因为默认不同得到似是而非比较。业务输入改变时重做什么新数据若单位、范围或噪声不同需要重新检查学习率稳定性和评价。新增特征要审查时间可得性训练验证拆分要符合实体与时间。当前合成结果不是上线门槛门槛应由业务目标和独立数据决定而不是复制本文最小损失。官方资料Optimization and root finding (scipy.optimize) — SciPy v1.18.0 Manual用于核对本期技术机制或接口查阅日期为2026-10-13。适用边界只覆盖脚本中的合成数据、明确假设和已记录版本。真实业务需追加授权、监控、资源预算、回滚和领域验证。