10月9日,知乎挂出一个新的提问,顶着"机器学习、过拟合、模型评估"的话题标签:第一次做机器学习项目,模型分数忽高忽低该先排查什么?题主的描述平淡到扎心:拿公开数据集练手,同一套代码多跑几次,“结果都不太一样”。他列了三个嫌疑人——数据划分、随机种子,还是模型本身?知乎
这个问题暂时还没几个人回答,但小红书这边,同一痛点已经吵了三年多。我把2023年5月到今天能翻到的8篇高热练手帖拉了一遍:累计点赞1736、收藏2245、评论188。收藏比点赞还多——这类帖子大家不是看过就划,是囤着照着做的。对完8篇帖子和这个新提问,先说一个有点反常识的结论:
"分数忽高忽低"其实是两个问题捆在一起,8篇帖子里说清楚的没几篇——“不稳定"和"不可复现”,嫌疑人根本不一样。多数人第一反应去动种子,方向就偏了:种子管的是可复现,管和"稳不稳"关系不大。
顺带一提,7月底就有新手把训练和验证的loss、accuracy曲线拍屏发了出来,问这个训练结果算正常吗,31条评论几乎全在替他判断曲线形状(59赞)。 "这个结果正常吗"就是整个切片最高频的一问。小红书

先量带:波动是不是"正常",本来就能算出来
帖子里全是"同样的代码跑几次结果差别特别大",没人给尺子。尺子其实当场能算:测试集读数噪声。按二项分布,95%置信半宽≈1.96×√(p(1-p)/n)——准确率85%左右时:小红书
测试集1000条:半宽约±2.2个点
测试集200条:半宽约±5个点
测试集100条:半宽约±7个点
也就是说,如果你拿几百条的小数据集练手,同一个模型换个测试集切法,分数摆出2~5个点的差距不是bug,是数学。这还没完:如果你每跑一次都重新划分train/val/test,"划分运气"会再叠一层,run与run之间的差距只会更大。所以排查第一步不是调参,是写下两个数:你的测试集有多少条?你是不是每次跑都在重切数据?
分流:带内的别修,带外的按这个顺序查
带内波动(差异一两个点、测试集又小):不是故障,是读数。做法是收口而不是深挖——固定种子清单(社区惯用42、123、666),跑5次,报均值±标准差。收藏帖里最常见的示范写法是"五次成绩85.2、86.1、85.8、84.9、85.5,报85.5±0.4"。小红书
带外波动:小红书画像"算法博士"6月那篇接过一个典型案例——seed=58时R²有0.9几,换seed=52直接掉到0.58(44赞39藏11评)。帖主的判断很克制:差一两个点正常,“0.9掉到0.58已经不是正常波动范围,背后大概率藏着别的问题”。他给的嫌疑人排序恰好和多数人的直觉相反:小红书
数据量太小:几百条样本,切分全凭运气,验证集赶上难样本R²直接崩;
模型对初始化过敏感:没正则化、学习率偏大,换组初始值就困在坏解里;
预处理/泄露问题:归一化在切分前就在全量数据上做了?特征选择先于切分?泄露程度随切分变化,分数自然忽高忽低。
想知道波动是不是出在模型侧,最省事的是给训练过程拍张X光片:损失曲线诊断那篇帖(51赞92藏)把曲线分成五种形态——训练降、验证升=过拟合信号;两条都不动=学习率太小或到容量瓶颈;两条都升=学习率过大或结构写错。下面这张就是被349赞、318收藏的那篇《机器学习:损失曲线》里的"健康对照":train/val同步下降、间距稳定不发散。你的曲线要是长成别的形状,忽高忽低就不是"随机性"在坑你,是训练本身有问题。小红书小红书

把8篇帖的归因做个统计,7篇练手帖里4篇把第一嫌疑人指向数据与切分(分层抽样没做、训练/验证分布不一致、标注不统一、类别不均衡、增强不匹配),3篇指向种子与运行环境(seed没设全链路、cuDNN/cuBLAS不确定性)。注意两拨帖子的用途其实不同:讲数据切分的,教你"跑稳";讲种子环境的,教你"复现"——这也是为什么"调种子让分数变好看"治不了忽高忽低。
顺带把"复现"那拨的干货存个档:aesdhj那篇172赞227藏的帖子指出,`torch.manual_seed`只是起步,random、numpy、cuda、cudnn.deterministic/benchmark要全套设置,"数据增强用了random,numpy的shuffle也会影响结果,必须全设!"也在它的清单里。即使如此,CUDA 10.2以上的cuBLAS仍可能不确定——PyTorch官方复现文档的写法是`use_deterministic_algorithms(True)`外加`CUBLAS_WORKSPACE_CONFIG`环境变量。“8个致命细节"那篇(69赞108藏)补的另外几刀更琐碎也更致命:batch size减半学习率就要等比缩、AdamW≠Adam+L2、scheduler是epoch-based还是iteration-based、mAP按VOC还是COCO算、F1是macro还是micro、Pillow和cv2读图RGB顺序都不同。这些不是"波动原因”,是"你和别人对不上数"的原因。小红书
藏在水面下的争议:遍历种子挑最高分,算不算作弊
点赞最高的帖(1086赞1367藏104评)来自"吃鱼学博士",她把一个普遍操作说破了:遍历大量种子、保存测试集分数最好的那个模型——“这样的操作应该是常见的,但也是导致模型复现不出来的潜在原因”。她自己的答案是"不合理":完全按测试集精度选种子,违背测试集不可见原则,等于从头到尾按想要的结果训练和分析。小红书
“该报哪次数据"那篇的评论区把这层窗户纸捅到了投稿现实:帖主讲了自己师弟的遭遇——只报一次最好结果被质疑cherry-picking拒了,“老老实实跑了五次才投过”,并提到现在的趋势是"很多会议要求提供多个随机种子的结果”(94赞90藏20评,20条评论基本都在这件事上站队)。这不是学术圈 paranoia:眼下正值NeurIPS 2026放榜季,知乎"如何看待NeurIPS 2026接收量到达7900篇""如何评价NeurIPS 2026的审稿结果"连续挂在热门,12月6—12日悉尼开会前,论文越多、复现的人越多,"只报一次run"的生存空间就越小。小红书知乎
还有一层"分数不可信"要单独记一笔:小红书那篇Calibration帖(207赞329藏)说的现象和波动同源不同病——模型报80%置信度的样本,实际准确率可能只有50%。帖子里附的CIFAR-100实验图就是证据:LeNet和ResNet报出的"把握"和真实正确率一对直方图,偏差就是四五十个点的大档。分数会晃,分数的"可信度"也会骗人,别把模型吐出来的数字当仪表盘读数。小红书

按时间成本分三档的排查清单
给正在练手的你一张可以直接抄走的表(5分钟档先做,做完大部分人就无需再往下烧时间):
5分钟:算自己的读数噪声半宽;确认是否每次重切数据;检查划分是否用了分层抽样;检查归一化/特征选择是否在切分之后。
30分钟:全链路设种+确定性开关跑3~5次,记均值±标准差;核对batch size↔学习率联动、BN统计;核对指标口径(mAP、F1平均方式、crop数)。
2小时起:仅在复现论文数字对不上时进入——逐行对比作者预处理、scheduler启动时机、优化器隐藏参数,锁依赖版本或用作者环境镜像。
分人群最后说一句
课程作业党/小数据集练手党:你一半的"波动"是数学噪声,停手,把"跑5次报均值±标准差"写进报告,比多调三个epoch更像专业选手。复现党:别先怀疑模型,先核指标口径和数据切分。要投稿要组会汇报的:多个种子已经是明规则,报best单run等于递刀。
下次分数忽高忽低,先量带、再谈划分、后动模型。波动不是敌人——不知道自己碰上的是哪种波动,才是。
(知乎的"第一次做机器学习项目,模型分数忽高忽低该先排查什么?"提问刚挂出来,按题主那个排查顺序之问,这张表就是可以直接拿去用的答案。)