总览 · ← 返回运行 20261003-105537-search-t2-heart-extrap-g24-D
节点 n18
T2HX-02 型内OT配对逐细胞表达速度外推(坐标不动、DE硬门控):速度被型内单细胞噪声主导、88.7%条目触clip整流致dp方向失效;按PLAN止损规则以机制关(逐位=copy_last)提交
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-105537-search-t2-heart-extrap-g24-D |
|---|---|
| 父节点 | n17 |
| 子节点 | — |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 改进 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 50.00(+0.0) · proxy_noscale 50.00(+0.0) |
| 审查 | 未审查 |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 24 分 |
| 程序版本 | 5fa95e285483ebec248e67d8a8c7abf8bc68670e (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 5fa95e2854:solution/METHOD.md
T2HX-02 型内OT配对逐细胞表达速度外推(坐标不动、DE硬门控):速度被型内单细胞噪声主导、88.7%条目触clip整流致dp方向失效;按PLAN止损规则以机制关(逐位=copy_last)提交
方法(PLAN 家族 T2HX-02,机制完整实现,开关 VEC_ALPHA,提交态默认 0=关)
- 基座:
anchor_entry锚阶段(外推榜=末输入)整份输出(n=24826 ≤ max_cells=25179,无抽样),坐标、行序、基因序、细胞数逐位不动;只允许表达沿速度场位移。 - 机制(VEC_ALPHA>0):(1)
extrap_step取上一输入与锚阶段;(2) 每个共有细胞型内,在联合表达 PCA-30(按维 std 归一、成本中位数归一)上用 balanced Sinkhorn(ε=0.05,200 迭代)配对;(3) 锚细胞速度 v_i = x_i^anchor − 其配对计划下前阶段伙伴的 barycenter(型在前阶段缺失则 v_i=0);单型 >5000 细胞一侧确定性抽 5000 配对、余者 PCA 空间 1-NN 传播;(4) x_pred = max(x + α·v, 0),α∈{0.01,0.02,0.05};(5) DE 硬门控:dp=pb(pred)−pb(anchor)、dt_approx=pb(anchor)−pb(prev),std(dp)<1%·std(dt_approx) 则判 DE 保护未过、不查分回退 α=0。 - 单输入阶段退路:
extrap_step无 prev 或锚≠末输入时直接 copy_last。 - 视图无关:不读 board/mode/路径;锚与步长只由时间差决定(平移不变);PCA
random_state=0,抽样用default_rng(seed),α>0 两次运行 sha256 相同(6ae7ae1d…)。未硬编码任何由已发布阶段算出的常数。
机制生效证据(PLAN mechanism_evidence / risks 对应项,seed 0,A 半视图)
- 配对非随机(risk 1 中止条件未触发):32 型中 32 型两阶段共有;逐型中位余弦(v_i vs 型均速度)0.31–0.67,全部 ≥0.3;配对覆盖 24826/24826 细胞(moved_frac=1.0)。
- 速度场确为逐细胞、非常数位移(vs_constant_shift):型内逐维 std 0.61–0.97,|v| 中位 25.64、p95 30.69;但型均速度模长 ≈ med_cos·|v| ≈ 8–16,即型内噪声分量 ≥ 系统时间分量——速度主要量度单细胞离散而非发育方向。
- clip 伪影击穿方向(risk 2 触发):α=0.01/0.02/0.05 下 88.7% 的 (细胞,基因) 条目 x+αv<0 被整流到 0(阈值为 5%)。整流偏置与系统信号同随 α 线性缩放,故 spearman(dp, dt_approx)=0.073 与 α 无关——不存在能通过调 α 修复方向的档位。
- DE 硬门控判定:std(dp)/std(dt_approx) = 0.0049(α=0.01)、0.0098(α=0.02)均 <1% → 按 PLAN 步骤(7) 不查分直接回退;仅 α=0.05(比值 0.0244)过门控,对其查分。
- 四组分变化(α=0.05 vs 机制关,A 半):expression_change 50.00→43.38(de_score 原始 0→−0.597、skill 0.38,方向劣于随机;de_direction 0→−0.0505);cell_state 50.00→49.69(mmd_u 0.05832→0.0586、variogram 0.05806→0.060043,逐细胞噪声注入);local_spatial 50.00→49.70(neighborhood_mmd 0.1126→0.11585,坐标虽未动,表达噪声仍损害邻域平均分布);shape_scale 50.00→49.70(三项 skill 仍 0.5,微降来自分组 skill 份额)。榜分 48.11。
机制关对照(PLAN mechanism_off_control)
- VEC_ALPHA=0(提交默认,且不设环境变量时同态):跳过速度计算,输出 sha256=a26c0b78ed1aa4c4… 与父节点 copy_last 逐位一致;同一文件父节点已实测 50.00(σ=0),不重复查分。
- VEC_ALPHA=0.05:
vec-score --task T2:heart:val_extrap/proxy_noscale实测 48.11(1 次查分,quota_left=19)。 - PLAN 判定规则执行:48.11 ≤ 50.5 → 机制无收益,以 α=0 提交。
已验证 / 未验证
- 已验证:off 态逐位=copy_last(sha 比对);α>0 确定性(两次运行同 sha);seed 0/1 通过 vec-score check;α=0.05 A 半 48.11 及四组分分解;DE 门控与 clip 诊断离线复现。
- 未验证:B 半分数(off 态与父节点同文件,预期同为地板);伪装视图重跑(代码无视图/绝对时间依赖,off 态输出=视图数据原样,预期通过);α=0.01/0.02 的查分(被 PLAN 硬门控拦截,未耗额度)。
- 生物学知识来源:无外部知识;仅使用视图内两阶段表达与官方细胞型标签。未使用保留阶段/基因型的任何测量信息。
结论与下一步
T2HX-02 双向证伪:逐细胞 OT 速度在本数据上=型内噪声+clip 整流,方向信息(spearman 0.07)不足以过 DE 保护后仍有正收益;坐标不动确实保住了 neighborhood 的大头(49.70 vs node 15 动坐标的 45.64 形状组),但表达侧损失无法避免。至此 copy_last 基座上"视图内两阶段速度做加法位移"的三个粒度(全局 node 8、按型 node 4、逐细胞 OT 本节点)全部 ≤ 地板,加法位移族应视为关闭。剩余未试方向仅:(a) 乘法/log 域位移以规避零值整流偏置(但 node 14 的 variogram 教训表明共变结构脆弱);(b) 接受本榜地板、把预算转向插值榜(ANALYSIS 建议 3)。
调研员的计划
| 名称 | 型内OT配对表达速度外推(坐标不动,DE硬门控) |
|---|---|
| 动机 | 父节点17及ANALYSIS确认:copy_last基座上视图内几何/表达微扰族(T2HX-01/02/03/04/06,5个节点)全部≤地板50.00。node 15尝试T2HX-02 OT位移场但动了坐标(48.92),neighborhood_mmd(25分+门控形状25分)被破坏。ANALYSIS唯一剩余建议是'引入跨阶段时间方向信息的配对型内细化'。本方案与node 15的关键区别:坐标完全不动,仅沿OT配对速度微调表达,从而保护neighborhood_mmd和表达-位置配对。 |
| 做法 | 步骤:(1) 读两个输入阶段(如E8.25、E8.75),按型(labels字段)分组;(2) 每型内用balanced Sinkhorn(epsilon=0.05,max_iter=200)在表达空间配对两阶段细胞,得映射π;(3) 对锚阶段(最晚输入)每个细胞i计算速度 v_i = x_{π(i)}^{t2} − x_i^{t1}(若i在t1无配对则v_i=0);(4) 外推 x_pred_i = x_anchor_i + α·v_i,α初始0.02,搜索{0.01,0.02,0.05};(5) clip到[0,∞);(6) 坐标、行序、基因序、细胞数全部照抄锚阶段(=copy_last坐标);(7) DE硬门控:计算伪批量dp与真值方向(用两阶段差近似)的std比值,若std(dp)<1%·std(dt_approx)则判定α太小、DE保护未过,不查分直接回退α=0;(8) 快速筛选:先对前2000个细胞+500基因子矩阵验证std(dp)门控和mmd_u方向,通过后再全量写入;(9) 全量写入后查vec-score(最多2次:α最优档+α=0对照)。单输入阶段退路:若视图只有一个输入阶段,无法算速度,直接输出copy_last(=α=0)。 |
| 风险 | (1) 两输入阶段细胞型组成差异大导致OT配对质量差、速度方向错误→Engineer应在步骤(3)后打印每型配对数和中位余弦相似度,若中位<0.3则中止;(2) clip伪影(node 6/8教训):α=0.02时若>5%基因被clip到0,降到0.01;(3) 本地尺子高估(ANALYSIS已确认外推榜本地-官网不兑现):即使本地>50.5也需警惕,但本方案最多查2次分,不追本地微幅领先;(4) 30分钟时限:Sinkhorn在25000细胞×500基因上可能慢→先按型分块并行,单型>5000细胞时随机采样5000做配对再kNN传播到全量。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:父节点版本 7586402eb4。改动的文件:solution/METHOD.md +19 −21、solution/run.py +140 −84
diff --git a/solution/METHOD.md b/solution/METHOD.mdindex e97c2a7..eedb034 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,34 +1,32 @@-# T2HX-06 坐标规范化:copy_last 基座上做质心归零→PCA主轴对齐→det=+1修正→第三矩定向的刚体规范化;A半实测榜分与机制关相同(八项skill全部=地板),按PLAN判定规则以机制关(逐位=copy_last)提交+# T2HX-02 型内OT配对逐细胞表达速度外推(坐标不动、DE硬门控):速度被型内单细胞噪声主导、88.7%条目触clip整流致dp方向失效;按PLAN止损规则以机制关(逐位=copy_last)提交 -## 方法(PLAN 家族 T2HX-06,机制完整实现,开关 VEC_CANON,提交态默认 0=关)+## 方法(PLAN 家族 T2HX-02,机制完整实现,开关 VEC_ALPHA,提交态默认 0=关) -- 基座:`anchor_entry` 锚阶段整份输出(n=24826 ≤ max_cells=25179,无抽样),表达矩阵、行序、基因序逐位不动,只允许坐标做刚体变换。-- 机制(`VEC_CANON=1`):(1) 减质心;(2) 协方差 `eigh` → 特征值降序排列主轴,旋转;(3) det(R)<0 则翻最后一轴,保证真旋转;(4) 各轴按第三矩符号定向(使 m3>0),特征值近简并(λ_{j+1}/λ_j>0.95,`VEC_DEGEN`)或 |m3|<1e-9·rms³ 的轴跳过定向;**若定向翻转数为奇数,撤销 |m3| 最小轴的翻转**——总变换保持 det=+1,绝不镜像点云(镜像是生物学错误,且利用评分器只搜 4 种 det=+1 翻转的镜像盲区属于规则明令禁止的 scorer gaming)。-- 单输入阶段退路:机制只用坐标,不需两阶段差分,任意输入数可跑。-- 视图无关:不读 board/mode/路径,不依赖绝对时间(anchor 按“时间差”选,统一平移不变),输出只取决于视图数据与 seed。+- 基座:`anchor_entry` 锚阶段(外推榜=末输入)整份输出(n=24826 ≤ max_cells=25179,无抽样),坐标、行序、基因序、细胞数逐位不动;只允许表达沿速度场位移。+- 机制(VEC_ALPHA>0):(1) `extrap_step` 取上一输入与锚阶段;(2) 每个共有细胞型内,在联合表达 PCA-30(按维 std 归一、成本中位数归一)上用 balanced Sinkhorn(ε=0.05,200 迭代)配对;(3) 锚细胞速度 v_i = x_i^anchor − 其配对计划下前阶段伙伴的 barycenter(型在前阶段缺失则 v_i=0);单型 >5000 细胞一侧确定性抽 5000 配对、余者 PCA 空间 1-NN 传播;(4) x_pred = max(x + α·v, 0),α∈{0.01,0.02,0.05};(5) DE 硬门控:dp=pb(pred)−pb(anchor)、dt_approx=pb(anchor)−pb(prev),std(dp)<1%·std(dt_approx) 则判 DE 保护未过、不查分回退 α=0。+- 单输入阶段退路:`extrap_step` 无 prev 或锚≠末输入时直接 copy_last。+- 视图无关:不读 board/mode/路径;锚与步长只由时间差决定(平移不变);PCA `random_state=0`,抽样用 `default_rng(seed)`,α>0 两次运行 sha256 相同(6ae7ae1d…)。未硬编码任何由已发布阶段算出的常数。 -## 机制生效证据(PLAN mechanism_evidence 对应项)+## 机制生效证据(PLAN mechanism_evidence / risks 对应项,seed 0,A 半视图) -1. **规范化数值**(VEC_DEBUG 打印,seed 0):质心≈0(锚坐标本已居中,‖centroid‖~1e-13);特征值 [18720.2, 16467.3, 11849.9],λ比 0.88/0.72,无近简并、无跳过轴;det_R=+1.000000;第三矩 pre=[+105092, −470136, +46267]。-2. **第三矩定向被 det=+1 守卫撤销**:唯一 m3<0 的轴(轴1)翻转会使总 det=−1(镜像),按守卫撤销 → flips=[],点云只被 PCA 旋转。这是刻意的:det=+1 的任何符号构型评分器自己都会枚举,规范化无信息增益;det=−1(镜像)被规则禁止。-3. **不变量核验**:off 态输出 sha256=a26c0b78ed1aa4c4…与父节点 copy_last **逐位一致**;on 态两次运行(on.h5ad / on2.h5ad)sha256 相同(确定性);seed 1 亦通过 vec-check。表达矩阵、行序、细胞数、点集内在几何(全部点对距离)off/on 相同。-4. **四组分对比**(on vs off,A半):expression_change 与 cell_state 原始值逐位相同(de=0/0,mmd_u=0.05856,variogram=0.058616,nb=0.11445);shape_scale 的 d2_shape 0.04911→0.04891、occupancy_dice 0.8066→0.8148、scale_log_ratio −0.4334→−0.4375 出现小幅漂移(刚体不变量理论上不动,漂移来自评分器对旋转后坐标重算 PCA 对齐/占据网格的浮点与抽样路径),但八项 skill 全部仍=0.5,组分与榜分不变。+1. **配对非随机**(risk 1 中止条件未触发):32 型中 32 型两阶段共有;逐型中位余弦(v_i vs 型均速度)0.31–0.67,全部 ≥0.3;配对覆盖 24826/24826 细胞(moved_frac=1.0)。+2. **速度场确为逐细胞、非常数位移**(vs_constant_shift):型内逐维 std 0.61–0.97,|v| 中位 25.64、p95 30.69;但型均速度模长 ≈ med_cos·|v| ≈ 8–16,即**型内噪声分量 ≥ 系统时间分量**——速度主要量度单细胞离散而非发育方向。+3. **clip 伪影击穿方向**(risk 2 触发):α=0.01/0.02/0.05 下 88.7% 的 (细胞,基因) 条目 x+αv<0 被整流到 0(阈值为 5%)。整流偏置与系统信号同随 α 线性缩放,故 spearman(dp, dt_approx)=0.073 与 α 无关——**不存在能通过调 α 修复方向的档位**。+4. **DE 硬门控判定**:std(dp)/std(dt_approx) = 0.0049(α=0.01)、0.0098(α=0.02)均 <1% → 按 PLAN 步骤(7) 不查分直接回退;仅 α=0.05(比值 0.0244)过门控,对其查分。+5. **四组分变化**(α=0.05 vs 机制关,A 半):expression_change 50.00→43.38(de_score 原始 0→−0.597、skill 0.38,方向劣于随机;de_direction 0→−0.0505);cell_state 50.00→49.69(mmd_u 0.05832→0.0586、variogram 0.05806→0.060043,逐细胞噪声注入);local_spatial 50.00→49.70(neighborhood_mmd 0.1126→0.11585,坐标虽未动,表达噪声仍损害邻域平均分布);shape_scale 50.00→49.70(三项 skill 仍 0.5,微降来自分组 skill 份额)。榜分 48.11。 ## 机制关对照(PLAN mechanism_off_control) -- VEC_CANON=0(提交默认):跳过规范化,输出与 copy_last 逐位一致(同 sha256),分数=父节点实测 50.00(同一文件评分 σ=0,不重复查分)。-- VEC_CANON=1:`vec-score --task T2:heart:val_extrap/proxy_noscale` 实测 **50.00**(1 次查分,quota_left=19),所有 skill=0.5。--## PLAN 判定规则执行--榜分 50.00 不 >50.5 → 按 PLAN 步骤(4) 提交**未规范化版**(=copy_last 逐位)。机制假设(“copy_last 的原始坐标方向不在评分器 4 种翻转能覆盖的最优对齐上”)**被证伪**:occupancy_dice 在评分器内部已做质心归零+主轴对齐+4 种 det=+1 翻转取最优,提交前再做 det=+1 刚体规范化是恒等变换(score-wise);唯一能改变 occupancy 的是镜像(det=−1),而那属于规则禁止的镜像盲区利用且生物学上错误(心脏左右手性固定)。文献 k026 “刚体旋转可使形状分变化>噪声”在本榜的 det=+1 子空间内不成立。+- VEC_ALPHA=0(提交默认,且不设环境变量时同态):跳过速度计算,输出 sha256=a26c0b78ed1aa4c4… 与父节点 copy_last **逐位一致**;同一文件父节点已实测 50.00(σ=0),不重复查分。+- VEC_ALPHA=0.05:`vec-score --task T2:heart:val_extrap/proxy_noscale` 实测 **48.11**(1 次查分,quota_left=19)。+- PLAN 判定规则执行:48.11 ≤ 50.5 → 机制无收益,以 α=0 提交。 ## 已验证 / 未验证 -- 已验证:off=copy_last 逐位(sha 比对);on 确定性(两次运行同 sha);seed 0/1 均通过 vec-check;on 态 A 半 50.00。-- 未验证:B 半分数(同规则同地板,on 为刚体变换预期同为地板);伪装视图重跑(代码无视图/绝对时间依赖,预期通过)。-- 生物学知识来源:仅“心脏手性固定、镜像胚胎非真实形态”这一通用发育常识;未使用任何保留阶段/基因型的测量信息,未硬编码任何由已发布阶段算出的常数。+- 已验证:off 态逐位=copy_last(sha 比对);α>0 确定性(两次运行同 sha);seed 0/1 通过 vec-score check;α=0.05 A 半 48.11 及四组分分解;DE 门控与 clip 诊断离线复现。+- 未验证:B 半分数(off 态与父节点同文件,预期同为地板);伪装视图重跑(代码无视图/绝对时间依赖,off 态输出=视图数据原样,预期通过);α=0.01/0.02 的查分(被 PLAN 硬门控拦截,未耗额度)。+- 生物学知识来源:无外部知识;仅使用视图内两阶段表达与官方细胞型标签。未使用保留阶段/基因型的任何测量信息。 ## 结论与下一步 -T2HX-06 双向证伪(刚体规范化=恒等;镜像=禁止)。连同 ANALYSIS 的结论,本榜 copy_last 基座上的视图内几何/表达微扰族(T2HX-01/02/03/04/06)已全部穷尽且均≤地板。下一步若在本榜找增量,只剩“引入视图外时间方向信息”的跨阶段配对型内细化(ANALYSIS next_suggestions 2),且须先离线验证 std(dp)<1%·std(dt) 硬门槛。+T2HX-02 双向证伪:逐细胞 OT 速度在本数据上=型内噪声+clip 整流,方向信息(spearman 0.07)不足以过 DE 保护后仍有正收益;坐标不动确实保住了 neighborhood 的大头(49.70 vs node 15 动坐标的 45.64 形状组),但表达侧损失无法避免。至此 copy_last 基座上"视图内两阶段速度做加法位移"的三个粒度(全局 node 8、按型 node 4、逐细胞 OT 本节点)全部 ≤ 地板,加法位移族应视为关闭。剩余未试方向仅:(a) 乘法/log 域位移以规避零值整流偏置(但 node 14 的 variogram 教训表明共变结构脆弱);(b) 接受本榜地板、把预算转向插值榜(ANALYSIS 建议 3)。diff --git a/solution/run.py b/solution/run.pyindex d792e6c..a88358a 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,27 +1,30 @@ #!/usr/bin/env python3-"""T2HX-06: deterministic rigid canonicalization of copy_last coordinates.--Base: anchor stage (last input at or before the target) copied out verbatim--- expression matrix, row order, gene order untouched; only the coordinate-cloud may be rigidly re-oriented.--Mechanism (VEC_CANON=1):- 1) subtract centroid,- 2) PCA rotation with eigenvalues in decreasing order (principal axes),- 3) flip last axis if det(R) < 0 (proper rotation, det = +1),- 4) orient each axis by the sign of its third moment (make it positive);- axes whose eigenvalue is near-degenerate with the next one- (lam_{j+1}/lam_j > VEC_DEGEN, default 0.95) or whose third moment is- numerically negligible keep the eigenvector sign as returned by eigh- (deterministic for a given input).--The point set, all pairwise distances, the expression matrix and the-expression<->position pairing are unchanged; only the numeric coordinate-frame is rotated/translated.--VEC_CANON=0 (default) skips the canonicalization and reproduces copy_last-bit-for-bit (mechanism-off control). With a single input stage the base is-the same anchor stage; the mechanism needs no two-stage difference.+"""T2HX-02: per-type OT-paired expression velocity extrapolation, coords frozen.++Base: anchor stage (last input at or before the target) copied out verbatim --+row order, gene order, coordinates and cell count untouched (= copy_last when+the mechanism is off).++Mechanism (VEC_ALPHA > 0):+ 1) read the previous input stage and the anchor stage;+ 2) within each shared cell type, pair anchor cells to previous-stage cells+ with a balanced Sinkhorn plan (epsilon=0.05, 200 iterations) on a joint+ expression-PCA cost (median-normalized squared distances);+ 3) per anchor cell i: velocity v_i = x_i^anchor - barycenter of its matched+ previous-stage partners (v_i = 0 for cells whose type is absent in the+ previous stage, or when there is a single input stage);+ 4) x_pred = max(x_anchor + alpha * v, 0); coordinates / row order unchanged;+ 5) DE hard gate: dp = pb(pred) - pb(anchor), dt_approx = pb(anchor) -+ pb(prev); if std(dp) < 0.01 * std(dt_approx) the DE no-change protection+ keeps the DE terms at floor, so the mechanism cannot gain -> fall back to+ alpha = 0 (bit-for-bit copy_last).++Types with more than TYPE_CAP cells on either side are paired on a+deterministic subsample; velocities of the remaining cells are propagated from+their nearest paired cell in PCA space (k = 1).++VEC_ALPHA=0 (default) skips the whole mechanism and reproduces copy_last+bit-for-bit (mechanism-off control). """ from __future__ import annotations@@ -30,67 +33,94 @@ import argparse import os import numpy as np+from sklearn.decomposition import PCA+from sklearn.neighbors import NearestNeighbors from src.task2_spatial.sample import take from src.task2_spatial.view_io import ( anchor_entry,+ extrap_step, load_manifest, panel_genes, read_stage, write_t2, ) -CANON = os.environ.get("VEC_CANON", "0") == "1"-DEGEN = float(os.environ.get("VEC_DEGEN", "0.95"))+ALPHA = float(os.environ.get("VEC_ALPHA", "0.0"))+EPS = float(os.environ.get("VEC_EPS", "0.05"))+MAX_ITER = int(os.environ.get("VEC_MAXITER", "200"))+TYPE_CAP = int(os.environ.get("VEC_TYPE_CAP", "5000"))+PCA_DIM = int(os.environ.get("VEC_PCA_DIM", "30")) DEBUG = bool(os.environ.get("VEC_DEBUG")) -def canonicalize(coords: np.ndarray) -> tuple[np.ndarray, dict]:- C = np.asarray(coords, dtype=np.float64)- info: dict = {"n": C.shape[0]}- centroid = C.mean(axis=0)- Z = C - centroid- info["centroid"] = centroid.tolist()- cov = (Z.T @ Z) / max(Z.shape[0] - 1, 1)- lam, V = np.linalg.eigh(cov)- order = np.argsort(lam)[::-1]- lam = lam[order]- V = V[:, order]- if np.linalg.det(V) < 0:- V = V.copy()- V[:, -1] *= -1.0- info["eigenvalues"] = lam.tolist()- info["det_R"] = float(np.linalg.det(V))- Zr = Z @ V- rms = float(np.sqrt((Zr**2).sum(axis=1).mean()))- info["rms"] = rms- m3 = (Zr**3).mean(axis=0)- info["third_moment_pre"] = m3.tolist()- flips = []- skipped = []- for j in range(Zr.shape[1]):- near_degen = j + 1 < len(lam) and lam[j] > 0 and (lam[j + 1] / lam[j]) > DEGEN- negligible = abs(m3[j]) < 1e-9 * rms**3- if near_degen or negligible:- skipped.append(j)- elif m3[j] < 0:- flips.append(j)- # keep the total transform a proper rotation (det = +1): the third-moment- # orientation must not mirror the cloud (biologically wrong, and mirroring- # to exploit the scorer's det=+1-only flip search is gaming). If the flip- # count is odd, undo the flip on the axis with the smallest |m3|.- undo = None- if len(flips) % 2 == 1:- undo = min(flips, key=lambda j: abs(m3[j]))- flips = [j for j in flips if j != undo]- info["undo_axis"] = undo- info["skipped_axes"] = skipped- for j in flips:- Zr[:, j] *= -1.0- info["flipped_axes"] = flips- info["third_moment_post"] = (Zr**3).mean(axis=0).tolist()- info["det_total"] = float(np.linalg.det(V) * ((-1.0) ** len(flips)))- return Zr, info+def _sinkhorn_balanced(cost: np.ndarray, eps: float, max_iter: int) -> np.ndarray:+ a = np.ones(cost.shape[0]) / cost.shape[0]+ b = np.ones(cost.shape[1]) / cost.shape[1]+ K = np.exp(-cost / eps)+ K = np.maximum(K, 1e-300)+ u, v = np.ones_like(a), np.ones_like(b)+ for _ in range(max_iter):+ u = a / np.maximum(K @ v, 1e-300)+ v = b / np.maximum(K.T @ u, 1e-300)+ plan = u[:, None] * K * v[None, :]+ if not np.isfinite(plan).all() or plan.sum() <= 0:+ return np.outer(a, b)+ return plan+++def velocity_field(Xa: np.ndarray, Xb: np.ndarray, la: np.ndarray, lb: np.ndarray,+ rng: np.random.Generator) -> tuple[np.ndarray, dict]:+ """Per-cell OT-paired velocity for the anchor cells (rows of Xa)."""+ info: dict = {}+ n_a, n_b = Xa.shape[0], Xb.shape[0]+ fit_a = Xa if n_a <= TYPE_CAP else Xa[rng.choice(n_a, TYPE_CAP, replace=False)]+ fit_b = Xb if n_b <= TYPE_CAP else Xb[rng.choice(n_b, TYPE_CAP, replace=False)]+ k = int(min(PCA_DIM, fit_a.shape[0] + fit_b.shape[0] - 1, Xa.shape[1]))+ pca = PCA(n_components=max(k, 2), random_state=0)+ Z = pca.fit_transform(np.vstack([fit_a, fit_b]).astype(np.float64))+ za_all = pca.transform(Xa.astype(np.float64))+ zb_all = pca.transform(Xb.astype(np.float64))+ scale = np.std(Z, axis=0) + 1e-8+ za_all = za_all / scale+ zb_all = zb_all / scale++ V = np.zeros((n_a, Xa.shape[1]), dtype=np.float64)+ types_a, types_b = np.asarray(la).astype(str), np.asarray(lb).astype(str)+ per_type = []+ for t in sorted(set(types_a.tolist())):+ ia = np.flatnonzero(types_a == t)+ ib = np.flatnonzero(types_b == t)+ if len(ib) == 0:+ per_type.append((t, len(ia), 0, 0.0, 0.0))+ continue+ ia_sub = ia if len(ia) <= TYPE_CAP else np.sort(rng.choice(ia, TYPE_CAP, replace=False))+ ib_sub = ib if len(ib) <= TYPE_CAP else np.sort(rng.choice(ib, TYPE_CAP, replace=False))+ xa_s = Xa[ia_sub].astype(np.float64)+ xb_s = Xb[ib_sub].astype(np.float64)+ d2 = np.maximum(+ (za_all[ia_sub] ** 2).sum(1)[:, None] + (zb_all[ib_sub] ** 2).sum(1)[None, :]+ - 2.0 * za_all[ia_sub] @ zb_all[ib_sub].T, 0.0)+ d2 /= np.median(d2) + 1e-8+ plan = _sinkhorn_balanced(d2, EPS, MAX_ITER)+ mass = plan.sum(axis=1, keepdims=True) + 1e-12+ xbary = (plan @ xb_s) / mass+ v_sub = xa_s - xbary+ if len(ia_sub) == len(ia):+ V[ia] = v_sub+ else:+ nn = NearestNeighbors(n_neighbors=1).fit(za_all[ia_sub])+ j = nn.kneighbors(za_all[ia])[1][:, 0]+ V[ia] = v_sub[j]+ vnorm = np.linalg.norm(v_sub, axis=1)+ tv = v_sub.mean(axis=0)+ tn = np.linalg.norm(tv) + 1e-12+ cos = (v_sub @ tv) / (vnorm * tn + 1e-12)+ within_std = float(v_sub.std(axis=0).mean())+ per_type.append((t, len(ia), len(ib), float(np.median(cos)), within_std))+ info["per_type"] = per_type+ info["n_paired_cells"] = int(sum(r[1] for r in per_type if r[2] > 0))+ return V, info def main() -> None:@@ -112,22 +142,48 @@ def main() -> None: X = stage.X[rows].toarray().astype(np.float32) coords = stage.coords[rows] - if CANON:- coords, info = canonicalize(coords)- if DEBUG:- print(- "canon: centroid={centroid} eig={eigenvalues} det_R={det_R:.6f} "- "rms={rms:.4f} m3_pre={third_moment_pre} m3_post={third_moment_post} "- "flips={flipped_axes} skipped={skipped_axes} det_total={det_total:.6f}".format(- **{k: info.get(k) for k in info}- ),- flush=True,- )- elif DEBUG:- print("canon OFF: bit-for-bit copy_last", flush=True)+ if ALPHA > 0:+ prev_entry, last_entry, _ratio = extrap_step(manifest)+ if prev_entry is None or float(last_entry["time"]) != float(anchor_entry(manifest)["time"]):+ if DEBUG:+ print("single input or anchor != last: fallback copy_last", flush=True)+ else:+ prev = read_stage(args.data, prev_entry, genes)+ Xa = X.astype(np.float64)+ Xb = prev.X.toarray().astype(np.float64)+ V, info = velocity_field(X, prev.X.toarray().astype(np.float32),+ stage.labels[rows], prev.labels, rng)+ pba = Xa.mean(axis=0)+ pbb = Xb.mean(axis=0)+ dt_approx = pba - pbb+ Xp = np.maximum(Xa + ALPHA * V, 0.0)+ dp = Xp.mean(axis=0) - pba+ std_ratio = float(np.std(dp) / (np.std(dt_approx) + 1e-12))+ clip_frac = float((Xa + ALPHA * V < 0).mean())+ moved = float((np.abs(V).sum(axis=1) > 1e-9).mean())+ vnorm = np.linalg.norm(V, axis=1)+ sp = float(np.corrcoef(_rank(dp), _rank(dt_approx))[0, 1])+ if DEBUG:+ print(f"gate: std(dp)/std(dt_approx)={std_ratio:.4f} clip_frac={clip_frac:.4f} "+ f"moved_frac={moved:.4f} |v| med={np.median(vnorm):.4f} "+ f"p95={np.percentile(vnorm, 95):.4f} spearman(dp,dt_approx)={sp:.4f}",+ flush=True)+ for t, na, nb, cos, wstd in info["per_type"]:+ print(f" type {t}: n_anchor={na} n_prev={nb} med_cos={cos:.3f} within_std={wstd:.4f}",+ flush=True)+ if std_ratio < 0.01:+ if DEBUG:+ print("DE hard gate: alpha too small, fallback to copy_last", flush=True)+ else:+ X = Xp.astype(np.float32) write_t2(args.out, X, coords, genes, seed=args.seed) +def _rank(x: np.ndarray) -> np.ndarray:+ from scipy.stats import rankdata+ return rankdata(x)++ if __name__ == "__main__": main()
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k007 | Interval staging and held-out-window filtering of external data | notes/official/来件/virtualembryo.ai/rules.md |
| k026 | Canonicalise predicted 3D coordinates before submission | notes/pitfalls/04_scorer_invariance.md |
| k016 | Degenerate-solution checks for population predictions | notes/handover/02_知识学习路线.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 实现了 T2HX-02 型内 balanced-Sinkhorn(ε=0.05)OT 配对的逐细胞表达速度外推(坐标/行序/细胞数完全不动,含 DE 硬门控与 VEC_ALPHA 开关);离线诊断显示速度被型内单细胞噪声主导(|v| 中位 25.6、型内逐维 std 0.61–0.97 ≥ 系统分量)、88.7% 条目触 clip 整流、spearman(dp,dt_approx)=0.073 且不随 α 变,α=0.05 实测 48.11 < 地板,按 PLAN ≤50.5 止损规则以 α=0 提交,提交输出与父节点 copy_last 逐位一致(sha256 相同)。 |
|---|---|
| 各组分数的变化 | cell_state:噪声内(提交态):mmd_u 0.05832→0.05832、variogram 0.05806→0.05806,得分各 6.25 不变。机制开时 mmd_u 0.05832→0.0586、variogram 0.05806→0.060043,组 50.00→49.69(逐细胞噪声注入)。 expression_change:噪声内(提交态 = copy_last):de_score 原始 0→0、de_direction 0→0,skill 均 0.500,得分 6.25+6.25 不变。机制开(α=0.05,未提交)时 de_score 原始 0→−0.597(skill 0.38,劣于随机),组 50.00→43.38。 local_spatial:噪声内(提交态):neighborhood_mmd 0.1126→0.1126,得分 12.50 不变。机制开时 neighborhood_mmd 0.1126→0.11585,组 50.00→49.70——即使坐标不动,表达侧逐细胞噪声仍损害邻域平均分布。 shape_scale:噪声内(提交态):d2_shape 0.04911、occupancy_dice 0.8066、scale_log_ratio −0.4334 全部不变,得分 4.17×3。机制开时三项 skill 仍 0.5,组 49.70(微降来自分组 skill 份额)——坐标不动确实保住了形状组大头(对比 node 15 动坐标时形状组 45.64)。 |
| family_id | T2HX-02 |
| 假设是否成立 | 否 |
| 经验 |
|
| mechanism_active | 否 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 3 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 2 次:bash 1、write 1 |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 16,433 · 输出 1,486 · 思考 424 |
| 任务(第一行) | 分析节点 n18 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/analyst.jsonl 9 KB /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 22 |
| 工具调用 | 共 27 次:bash 19、read 3、todowrite 2、write 2、edit 1 |
| 用时 | 20 分 |
| token 数 | 输入 61,637 · 输出 9,263 · 思考 13,368 |
| 任务(第一行) | 按计划修改程序:型内OT配对表达速度外推(坐标不动,DE硬门控) |
| 最后的回答(摘录) | **做了什么**:按 PLAN 完整实现 T2HX-02(型内 balanced-Sinkhorn ε=0.05 配对 → 逐细胞表达速度外推,坐标/行序/细胞数不动,DE 硬门控,VEC_ALPHA 开关)。离线诊断:配对非随机(med_cos 0.31–0.67)但速度被型内单细胞噪声主导(|v| 中位 25.6,型内 std ≥ 系统分量);α=0.01/0.02 未过 std(dp)≥1% 门控(回退不查分);所有 α 下 88.7% 条目触 clip 整流,spearman(dp,dt_approx)=0.073 且不随 α 变(信号与整流同线性缩放,无档位可修)。 **查分结果**(1/20 额度):α=0.05 = **48.11**(de_score 原始 −0.597 劣于随机,四组全 ≤ 地板);机制关(默认提交态)sha256 与父节点 copy_last 逐位一致 = 50.00,未重复查分。按 PLAN ≤50.5 规则以 α=0 提交。确定性(双运行同 sha)、seed 0/1 格式检查、视图无关性均通过。 **下一步最值得试**:加法位移族三个粒度(全局/按型/逐细胞 OT)已全部 ≤ 地板,应关闭;本榜 18 节点停在地板且本地-官网不兑现,建议把预算转向插值榜,或仅在 log 域乘法位移(规避零值整流)方向做最后一次低成本试探。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/engineer.jsonl 134 KB /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 2 分 |
| token 数 | 输入 15,752 · 输出 1,122 · 思考 6,250 |
| 任务(第一行) | 为节点 n18(改进,父节点 n17)写改进计划 PLAN.json |
| 最后的回答(摘录) | ```json
{"name": "型内OT配对表达速度外推(坐标不动,DE硬门控)",
"motivation": "父节点17及ANALYSIS确认:copy_last基座上视图内几何/表达微扰族(T2HX-01/02/03/04/06,5个节点)全部≤地板50.00。node 15尝试T2HX-02 OT位移场但动了坐标(48.92),neighborhood_mmd(25分+门控形状25分)被破坏。ANALYSIS唯一剩余建议是'引入跨阶段时间方向信息的配对型内细化'。本方案与node 15的关键区别:坐标完全不动,仅沿OT配对速度微调表达,从而保护neighborhood_mmd和表达-位置配对。",
"approach": "步骤:(1) 读两个输入阶段(如E8.25、E8.75),按型(labels字段)分组;(2) 每型内用balanced Sinkhorn(epsilon=0.05,max_iter=200)在表达空间配对两阶段细胞,得映射π;(3) 对锚阶段(最晚输入)每个细胞i计算速度 v_i = x_{π(i)}^{t2} − x_i^{t1}(若i在t1无配对则v_i=0);(4) 外推 x_pred_i = x_anchor_i + α·v_i,α初始0.02,搜索{0.01,0.02,0.05};(5) clip到[0,∞);(6) 坐标、行序、基因序、细胞数全部照抄锚阶段(=copy_last坐标);(7) DE硬门控:计算伪批量dp与真值方向(用两阶段差近似)的std比值,若std(dp)<1%·std(dt_approx)则判定α太小、DE保护未过,不查分直接回退α=0;(8) 快速筛选:先对前2000个细胞+500基因子矩阵验证std(dp)门控和mmd_u方向,通过后再全量写入;(9) 全量写入后查vec-score(最多2次:α最优档+α=0对照)。单输入阶段退路:若视图只有一个输入阶段,无法算速度,直接输出copy_last(=α=0)。",
"expected_groups": ["expression_change", "cell_state"],
"risks": "(1) 两输入阶段细胞型组成差异大导致OT配对质量差、速度方向错误→Engineer应在步骤(3)后打印每型配对数和中位余弦相似度,若中位<0.3则中止;(2) clip伪影(node 6/8教训):α=0.02时若>5%基因被clip到0,降到0.01;(3) 本地尺子高估(ANALYSIS已确认外推榜本地-官网不兑现):即使本地>50.5也需警惕,但本方案最多查2次分,不追本地微幅领先;(4) 30分钟时限:Sinkhorn在25000细胞×500基因上可能慢→先按型分块并行,单型>5000细胞时随机采样5000做配对再kNN传播到全量。",
"family_id": "T2HX-02",
"mechanism": "用视图内两个观测阶段做型内balanced-OT配对,得到细胞级表达速度向量,沿该速度对锚阶段表达做小步外推;坐标完全不动以保护表达-位置配对(neighborhood_mmd)。",
"vs_constant_shift": "常数位移对每个型施加同一向量(所有同型细胞移动相同方向和幅度);本方案的速度是逐细胞由OT配对决定的——同型内不同细胞因配对对象不同而获得不同速度向量,产生型内异质性变化,且速度方向由个体细胞在表达空间的位置决定而非型均值。",
"mechanism_evidence": "(1) 打印每型内速度向量的型内标准差:若≈0则退化为常数位移,机制未生效;(2) 打印被实际移动的细胞比例(|v_i|>ε的占比)和位移幅度分布;(3) 对比α=0与α>0时de_score/de_direction原始值是否从0变化(过DE保护门槛);(4) 对比mmd_u和variogram是否朝改善方向动(若mmd_u恶化>0.002则机制有害)。",
"mechanism_off_control": "环境变量VEC_ALPHA=0(默认提交态):跳过速度计算和外推,输出与copy_last逐位相同(表达、坐标、行序均不动),预期分数=50.00=地板。对比:VEC_ALPHA>0时若分数≤50.5则判定机制无收益,以α=0提交。",
"sources": []}
``` |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/researcher.jsonl 5 KB /home/spark-longxinyang/vec/runs/formal/20261003-105537-search-t2-heart-extrap-g24-D/nodes/18/researcher.stderr |