这次不是给旧流程补一个按钮

SEUPhyX 的密立根油滴实验系统这次更新,核心不是把页面文案改漂亮,也不是把传统分类模型再包一层 UI,而是重新回答了一个教学问题:学生还没有被直接告知元电荷和整数倍关系时,系统应该怎样让他们看见数据自己长出来的结构?

最新提交 394e36c 把这个问题写进了项目文档和主流程。现在的主线不再是“先拿分类标签,再做拟合”,而是:

  1. 学生录入下落时间 t 和平衡电压 U
  2. 系统把每个油滴换算成连续电荷估计 Q
  3. 在一维 Q 分布上做无监督聚类。
  4. 聚类之后再用半峰宽筛选高置信点。
  5. 对多个 Q 簇的 U-t 曲线做共享符号表达式搜索。
  6. 最后才把发现出来的簇间距拿去和公认元电荷做解释性对照。

这条链路更符合我想要的教学叙事:不是把答案先塞给模型,而是让 AI 帮学生把实验数据里的规律显影。

数据记录页先把“参考答案”藏起来

记录阶段现在只显示学生自己的红色 Q-U 散点,不再把参考数据直接叠在旁边。这个改动看起来很小,但对教学节奏很重要。

如果一开始就看到参考数据,学生很容易把注意力放到“我要让点落到哪里”,而不是“我测出来的数据意味着什么”。所以现在记录页只承担记录和观察的功能:录入 FallingTime(t/s)BalanceVoltage(U/V),计算连续的 ChargeEstimate(1e-19C),然后把自己的点画出来。

参考数据不是被删除了,而是被移动到后面的分析页,作为背景和对照出现。

数据分类页变成真正的 Q 聚类页

原来的“分类”容易让人误以为系统已经知道每个点属于哪个整数电荷类别。现在这个页面更接近“机器学习聚类分析”:

  • 默认方法是 K-Means。
  • 也可以选择 Gaussian Mixture、DBSCAN 或 KDE 峰发现。
  • 参考数据可以作为灰色背景显示,但默认不抢占页面。
  • 学生数据仍然用红色强调。
  • 点击执行 AI 聚类之后,系统才给 Q 簇着色,并标记半峰宽之外的点。

关键点是半峰宽过滤发生在聚类之后。也就是说,系统不会先手动删掉“不像样”的点,再假装聚类很漂亮;它会先让算法面对真实分布,再把偏离簇中心太远的点标成 half_width_outlier,保留在图和表里,但不送入后续拟合。

这让结果更诚实,也更适合作为实验教学材料。

符号回归页负责把多个簇合成一条规律

真正有意思的部分在“机器学习-符号回归”页。

系统会先拿到高置信的 Q 簇数据,再搜索多个簇共享的曲线规律。现在的实现不只是一条全局拟合线,而是保留了三种发现路径:

  • 全局候选式搜索:直接比较多个候选表达式。
  • 两阶段联合回归:先找共同的时间幂指数,再找曲线系数和簇中心 Q_c 的关系。
  • 神经网络 teacher 蒸馏:先用 MLP 学一个平滑的 U=f(t,Q_c) 曲面,再压缩成可解释的符号表达式。

最后系统优先使用 teacher 蒸馏的结果;如果不可用,再回退到两阶段联合回归或全局候选式搜索。

我喜欢这个结构,因为它没有把“AI”停留在分类器输出一个标签上,而是把 AI 放在了发现规律的位置。它既有机器学习的容错和拟合能力,又保留了物理实验报告需要的可解释公式。

传统方法没有消失,只是退回对照位

旧的传统分类和物理约束拟合仍然保留,但位置变了。

传统 U-t 分类页现在更像对照流程,用来查看预训练 SVM 或学生自训练模型的输出。Predicted 是模型预测标签,不是实验真值,也不是当前 AI 聚类和符号回归的前置条件。

旧版 physics_guided_regression() 也还在,它会围绕整数 N、全局参数 A,b 和残差过滤做传统物理拟合。现在它适合作为对照检验,而不是主线叙事。

这次重构最重要的边界就是:ChargeCluster 属于当前 AI 发现流程,PhysicsN 属于传统物理拟合路径,不能混着讲。

文档也变成了系统的一部分

这次提交新增了 CODEX_CONTEXT.md,相当于给后续开发者和 AI agent 写了一份入口说明。它把当前入口、页面职责、session state、核心字段、聚类逻辑、符号回归逻辑、报告逻辑和常见误区都整理出来。

这对 SEUPhyX 很重要。因为这个项目已经不只是几个脚本,而是一个有教学顺序、有状态流、有报告生成、有本地和云端入口的系统。如果每次开发都从零读代码,很容易把旧流程和新流程混在一起。

把系统边界写清楚,本身就是开发的一部分。

当前版本的意义

这次开发把 SEUPhyX 从“能跑的实验辅助工具”往“有明确教学方法的 AI 实验系统”推了一步。

它现在更像一条完整的课堂路径:

学生先记录自己的数据,看见自己的 Q-U 分布;再让机器学习在 Q 分布里找簇;然后用符号回归把多个簇的曲线关系合成表达式;最后才回到物理意义,把簇间距和元电荷联系起来。

这比直接给出答案更慢一点,但更接近实验本身。
数据不是为了证明模型,而是为了让规律从混乱里出现。