Virtual Embryo Challenge更新于 10-03 18:47(北京时间) / 每 5 分钟更新

总览 · ← 返回运行 20261002-034201-search-t1-abc-r1-B-population

节点 n28

node 12 基座(分层复制+心脏解剖重加权)上加三个已验证部件:logit 组成趋势 GAMMA_LOGIT=-2.4、型内转录活性反倾斜抽样 GAMMA_RNA=-1.0(Gumbel top-k 无放回,gate n<0.5×池)、小池精确输出 0.75×池不重复;表达值从不修改。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261002-034201-search-t1-abc-r1-B-population
父节点n12
子节点—
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 56.53(+0.6) · proxy 57.80(+0.7) · proxy2 57.80(+0.7) · X3 54.00(+0.5)
审查未审查
用时?从运行开始到结束(或到现在)的挂钟时间。9 分
程序版本e9c6b3283c2ece0c58e6731c89a6a7943966f989 (programs.git)

方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。

来自 programs.git e9c6b3283c:solution/METHOD.md

node 12 基座(分层复制+心脏解剖重加权)上加三个已验证部件:logit 组成趋势 GAMMA_LOGIT=-2.4、型内转录活性反倾斜抽样 GAMMA_RNA=-1.0(Gumbel top-k 无放回,gate n<0.5×池)、小池精确输出 0.75×池不重复;表达值从不修改。

方法

在 node 12(官方最新阶段分层抽样复制 + 心脏解剖重加权 + 线性组成趋势 GAMMA=-1.2 + N_FLOOR 重复补齐)上,把三个已在 node 17/20/23/26 验证的部件移植过来,表达值一律不改:

  1. 基座:输出细胞取最新官方输入阶段;无官方阶段(X3)取最新输入。proxy2 的 Qiu E9.0 只当参考(词表不可比,趋势跳过),输出与 proxy 完全一致。
  2. logit 组成趋势(替换原线性 GAMMA=-1.2):当最新两个输入阶段词表可比(覆盖 ≥0.5,如 X3 的 E8.75+E9.0、final 的 E8.5+E9.5)时,logit(p_target) = logit(p_last) + GAMMA_LOGIT×min(Δt_target/Δt_last, 1)×(logit(p_last)−logit(p_prev)),GAMMA_LOGIT=-2.4;非共享型保持 p_last;夹 MIN_FRAC=0.002 后归一。logit 空间防止比例外推成负数/超 1,比例整体大时不会过度平移。
  3. 解剖重加权(不变):心脏谱系 ×1.3、旁轴 ×0.1、神经管/表面外胚层 ×0、其余 ×1.0;键在输入阶段类型名上,未知名字(X3)为 no-op。
  4. 型内转录活性反倾斜抽样(新增,主杠杆):gate n_total < 0.5×池 时(proxy/proxy2/final 大池生效,X3 小池不触发),型内每细胞权重 w_i=(nnz_i/型内中位 nnz)^GAMMA_RNA,GAMMA_RNA=-1.0(低检出基因数细胞适度多选),Gumbel top-k 无放回。node 24/26 已验证该机制提升 covariation。
  5. 小池精确输出(替换原重复补齐):池 < N_FLOOR=3000 时(仅 X3,池 2174),输出 floor(0.75×池)=1630 个细胞,无上限最大余数法保持趋势后组成精确,类型内不放回、无重复细胞。node 22/23 验证优于重复补齐到 3000。
  6. 大池:n=clip(max(target_n×0.95, 3000), min, max),capped 最大余数分配、不放回。

关键参数(A 半实测)

  • GAMMA_RNA:proxy 扫描 -0.7/-1.0/-1.5/-2.0 → 57.74/58.16/58.05/57.64,取 -1.0(node 24 同值亦验证)。
  • GAMMA_LOGIT=-2.4、dt 比例封顶 1:沿用 node 17/20/23/26。
  • SMALL_FRAC=0.75:沿用 node 23/25(0.75 优于 0.95)。
  • HEART_W=1.3、PARAXIAL_W=0.1、神经管/表面外胚层 ×0、MIN_FRAC=0.002、OVERLAP_MIN=0.5、OUT_FRAC=0.95、N_FLOOR=3000:沿用 node 12。

验证过什么

  • 三视图 seed 0 全跑通 + vec-check ok;seed 1 亦跑通、格式合规;最终代码与查分代码输出逐元素一致(确定性)。运行 ~2 s/视图,内存远低于上限。
  • A 半查分(seed 0):proxy 58.16(父 57.09,+1.07;covariation 56.52 vs 54.13、cell_state 60.87 vs 58.53、direction 60.86 vs 57.04、de_recovery 53.54 vs 53.02);proxy2 58.16(输出与 proxy 相同);X3 54.30(父 53.53,+0.77)。三尺子均分 ≈56.87 vs 父 55.90,超树最佳 node 23(57.30 的 A 半对应值未知,本节点 proxy 58.16 已超 node 23 的 57.92)。
  • GAMMA_RNA 消融见上;-2.0 掉分(covariation 54.65),确认平台在 -1.0~-1.5。

没验证 / 局限

  • 只用 A 半;±0.2 级别的差距(-1.0 vs -1.5)在 B 半未必保持,取平台内值。
  • X3 的 +0.77 在噪声(~2 分)内,logit 趋势与 0.75×小池的各自贡献未在本基座上单独消融(沿用 node 23/26 的跨节点证据)。
  • final 视图(官方 E8.5+E9.5→E10.5)无沙箱:logit 趋势与 GAMMA_RNA gate 都会生效,方向按 X3/proxy 证据推断,未直接验证。
  • proxy2 仍忽略 Qiu E9.0 的表达信息(词表不可比),未做心脏谱系时间插值。

生物学知识来源

仅通用小鼠胚胎学定性事实(心脏为中心解剖 → 心脏谱系富集、神经管/表面外胚层/旁轴缩减),类型名单取自输入阶段已发布注释;未使用任何保留阶段/基因型的测量。

调研员的计划

名称Node12 加 GAMMA_RNA=-1.5 反倾斜 + logit 趋势 + 小池 0.75 精确输出
动机父节点 12 最弱组 de_recovery(53.02) 处于纯复制表达家族已知上限(~53, node 25 ANALYSIS),实际可提升空间在第二弱组 covariation(54.13)。树最佳 node 26 covariation=57.84(+3.7),差距来自三个已验证部件:(1) GAMMA_RNA=-1.5 反倾斜(node 26 实测 -1.5 优于 -0.45,covariation +3.46 超噪声);(2) logit 组成趋势 GAMMA=-2.4(nodes 17/20/23/26 均用,direction 58.5 vs node12 57.04);(3) 小池 0.75×精确输出(nodes 22/23 X3 +2.4/+1.1)。Node 21 在 node 12 上只加了 GAMMA_RNA=-0.45 + 0.95×小池,covariation 仅 +0.51;本次用 -1.5 + 0.75× + logit 趋势,是 node 26/23 已验证的更强配置。
做法在 node 12 代码上加三个杠杆,表达值仍不改:
1. 型内转录活性反倾斜抽样(主杠杆):w_i = (nnz_i / median_type)^GAMMA_RNA,Gumbel top-k 无放回。初值 GAMMA_RNA=-1.5,扫描 {-1.0, -1.5, -2.0},在 proxy A 半查分选峰。Gate:仅当 n_total < 0.5×pool_size 时启用(避免 X3 小池触发)。
2. X3 组成趋势改 logit 空间:logit(p_target) = logit(p_last) + GAMMA_LOGIT×(Δt_target/Δt_last, cap 1)×(logit(p_last)−logit(p_prev)),GAMMA_LOGIT=-2.4(沿用 node 17/20/23/26)。仅当两阶段词表可比(≥0.5)时生效;proxy 单阶段、proxy2 词表不可比均跳过,保持原比例。原线性 GAMMA=-1.2 代码删除。
3. 小池精确输出:池 < N_FLOOR 时(仅 X3,2174<3000),输出 floor(0.75×池)=1630 个细胞,无重复,用无上限最大余数法保持趋势后组成精确。删除原 N_FLOOR 重复补齐逻辑。
4. 验证顺序:先只加 GAMMA_RNA=-1.5 在 proxy 查分(1 query)→确认 covariation 提升后加 logit 趋势在 X3 查分(1 query)→加小池 0.75 在 X3 查分(1 query)→三视图 seed 0 全跑 + vec-check(3 queries)。总计 ≤6 queries,留余量给 GAMMA_RNA 扫描(2-3 queries)。
5. 单输入阶段退路(proxy):无趋势、无小池问题,仅 GAMMA_RNA 生效。final 视图(E8.5+E9.5):logit 趋势正常作用于官方两阶段,GAMMA_RNA 正常作用于大池。
风险1) GAMMA_RNA=-1.5 在 node 26 的 logit 基座上验证,移植到 node 12 的线性趋势基座(本次同时改 logit 故风险降低);若 covariation 未升反降,先回退到 -1.0。2) 小池 0.75×输出 1630 细胞比原 3000 少近半,de_recovery 可能因样本量减少而掉;Engineer 应对比 0.75×与 0.95×两档。3) logit 趋势在 X3 的增益约 +1~2 分,在噪声边缘,需 X3 多 seed 确认。4) 若三项叠加后 proxy 未超 57.5,说明 node 12 基座本身(线性趋势+HEART_W=1.3)与 node 17 基座(logit+内皮并入心脏族)有细微差异,应检查内皮权重。

代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。

对比:父节点版本 30011bc035。改动的文件:solution/METHOD.md +21 −23、solution/run.py +91 −50

diff --git a/solution/METHOD.md b/solution/METHOD.mdindex 1197f4d..785df7a 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,38 +1,36 @@-官方最新阶段分层抽样复制(表达不改)+ 心脏解剖重加权(神经管/表面外胚层丢弃、旁轴×0.1、心脏×1.3)+ 反向组成趋势外推 GAMMA=-1.2 + 输出数下限 3000。+node 12 基座(分层复制+心脏解剖重加权)上加三个已验证部件:logit 组成趋势 GAMMA_LOGIT=-2.4、型内转录活性反倾斜抽样 GAMMA_RNA=-1.0(Gumbel top-k 无放回,gate n<0.5×池)、小池精确输出 0.75×池不重复;表达值从不修改。  ## 方法 -在父节点 5(分层复制 + 阻尼组成趋势外推)基础上,加入本 run 已被 node 6/7/9/10 反复验证为唯一稳定提分的部件——**心脏解剖组成重加权**,并微调其强度、加入输出细胞数下限。表达值从不修改,只重采样真实细胞。+在 node 12(官方最新阶段分层抽样复制 + 心脏解剖重加权 + 线性组成趋势 GAMMA=-1.2 + N_FLOOR 重复补齐)上,把三个已在 node 17/20/23/26 验证的部件移植过来,表达值一律不改: -流程(每次运行现算,全部来自 view 输入):+1. **基座**:输出细胞取最新**官方**输入阶段;无官方阶段(X3)取最新输入。proxy2 的 Qiu E9.0 只当参考(词表不可比,趋势跳过),输出与 proxy 完全一致。+2. **logit 组成趋势**(替换原线性 GAMMA=-1.2):当最新两个输入阶段词表可比(覆盖 ≥0.5,如 X3 的 E8.75+E9.0、final 的 E8.5+E9.5)时,`logit(p_target) = logit(p_last) + GAMMA_LOGIT×min(Δt_target/Δt_last, 1)×(logit(p_last)−logit(p_prev))`,GAMMA_LOGIT=-2.4;非共享型保持 p_last;夹 MIN_FRAC=0.002 后归一。logit 空间防止比例外推成负数/超 1,比例整体大时不会过度平移。+3. **解剖重加权**(不变):心脏谱系 ×1.3、旁轴 ×0.1、神经管/表面外胚层 ×0、其余 ×1.0;键在输入阶段类型名上,未知名字(X3)为 no-op。+4. **型内转录活性反倾斜抽样**(新增,主杠杆):gate `n_total < 0.5×池` 时(proxy/proxy2/final 大池生效,X3 小池不触发),型内每细胞权重 `w_i=(nnz_i/型内中位 nnz)^GAMMA_RNA`,GAMMA_RNA=-1.0(低检出基因数细胞适度多选),Gumbel top-k 无放回。node 24/26 已验证该机制提升 covariation。+5. **小池精确输出**(替换原重复补齐):池 < N_FLOOR=3000 时(仅 X3,池 2174),输出 `floor(0.75×池)=1630` 个细胞,无上限最大余数法保持趋势后组成精确,类型内**不放回**、无重复细胞。node 22/23 验证优于重复补齐到 3000。+6. 大池:`n=clip(max(target_n×0.95, 3000), min, max)`,capped 最大余数分配、不放回。 -1. **基座**:输出细胞一律取最新**官方**输入阶段(`official[-1]`);无官方阶段的外部测试题(X3)退而取最新输入。proxy2 的 Qiu E9.0 心脏细胞只当参考、不作基座(沿用 node 2/3 结论)。-2. **组成趋势外推(GAMMA)**:当最新两个输入阶段的细胞类型词表可比(覆盖率 ≥ `OVERLAP_MIN=0.5`,如 X3 的 E8.75+E9.0、final 的官方 E8.5+E9.5),按 `p_target = p_last + GAMMA·(Δt_target/Δt_last)·(p_last − p_prev)` 外推每型比例,夹到 `MIN_FRAC=0.002` 再归一。词表不可比(proxy2:全胚 vs 心脏标签不相交)或只有一个阶段(proxy)时**跳过**,保留最新阶段原比例。实测 GAMMA 只作用于 X3(proxy 单阶段、proxy2 词表不可比都跳过)。-3. **解剖重加权**:对趋势后的比例乘以每型权重再归一——心脏谱系(CM 各型、SHF、PHM、心内膜/内皮、BEC、JCF、心包、心外膜)×`HEART_W=1.3`;旁轴中胚层 ×`PARAXIAL_W=0.1`;神经管、表面外胚层 ×0(丢弃,心脏为中心解剖时不在取样内);EXEM 及其余 ×1.0;未知名字(X3 的 heart field 标签)×1.0,故重加权在 X3 上是 no-op。-4. **输出细胞数**:`n = clip(max(target_n×OUT_FRAC(0.95), N_FLOOR=3000), min_cells, max_cells)`。池足够大(proxy/proxy2,E8.5=16787)→ n≈4862,类型内**不放回**抽样、最大余数法分配、禁止重复取细胞;池小于目标(X3,E9.0=2174)→ n=3000,允许类型内重复补齐。-5. 按分配从各型抽真实细胞,表达原样输出,`write_prediction` 写成合规 h5ad。+## 关键参数(A 半实测) -## 关键参数(均在 A 半实测)--- `GAMMA=-1.2`:X3 扫描 −1.0/−1.2/−1.4 → 52.58/53.60/53.67,−1.2~−1.4 为峰,取 node 9 已在 B 半验证的 −1.2。负号=向上一阶段组成收缩(父节点教训:符号方向须实测,不能靠直觉)。-- `HEART_W=1.3`:proxy 扫描 1.0/1.15/1.3/1.6/2.0 → 57.05/57.11/57.18/56.95/56.13,1.0–1.3 平台、2.0 掉分,取 1.3。-- `PARAXIAL_W=0.1`、神经管/表面外胚层 ×0、EXEM ×1.0:沿用 node 10 的细拆(EXEM 单调剂量峰在 ×1.0、表面外胚层丢弃)。-- `N_FLOOR=3000`:X3 扫描 2500/3000/3500 → 53.23/53.60/52.90,3000 为峰。-- `OUT_FRAC=0.95`、`MIN_FRAC=0.002`、`OVERLAP_MIN=0.5`:沿用父节点。+- `GAMMA_RNA`:proxy 扫描 -0.7/-1.0/-1.5/-2.0 → 57.74/**58.16**/58.05/57.64,取 -1.0(node 24 同值亦验证)。+- `GAMMA_LOGIT=-2.4`、dt 比例封顶 1:沿用 node 17/20/23/26。+- `SMALL_FRAC=0.75`:沿用 node 23/25(0.75 优于 0.95)。+- `HEART_W=1.3`、`PARAXIAL_W=0.1`、神经管/表面外胚层 ×0、`MIN_FRAC=0.002`、`OVERLAP_MIN=0.5`、`OUT_FRAC=0.95`、`N_FLOOR=3000`:沿用 node 12。  ## 验证过什么 -- **三视图 seed 0 均跑通 + `vec-check` ok**;seed 1、2 亦跑通、格式合规;同 seed 重跑输出逐元素相同(确定性)。运行 ~1–2 s,峰值内存远低于 28 GB 上限。-- **A 半查分**:proxy 57.18 / proxy2 57.18 / X3 53.60 → 节点均分 **≈55.99**(父节点 50.60,当前最佳 node 9 rank3 55.57)。分组:proxy cell_state 59.85、direction 59.68、covariation 55.26、de_recovery 53.0;X3 cell_state 57.65、covariation 50.59、direction/de_recovery ~52。-- **消融**:within-type 增殖偏置(prior GO/Reactome/hallmark 细胞周期基因打分,BETA=0.3)——X3 因 n>池 未触发(no-op),proxy **−5.0**(cell_state 59.4→51.1、covariation 54.9→48.7),按 PLAN gate 丢弃,代码已删除。+- **三视图 seed 0 全跑通 + `vec-check` ok**;seed 1 亦跑通、格式合规;最终代码与查分代码输出逐元素一致(确定性)。运行 ~2 s/视图,内存远低于上限。+- **A 半查分(seed 0)**:proxy **58.16**(父 57.09,+1.07;covariation 56.52 vs 54.13、cell_state 60.87 vs 58.53、direction 60.86 vs 57.04、de_recovery 53.54 vs 53.02);proxy2 **58.16**(输出与 proxy 相同);X3 **54.30**(父 53.53,+0.77)。三尺子均分 **≈56.87** vs 父 55.90,超树最佳 node 23(57.30 的 A 半对应值未知,本节点 proxy 58.16 已超 node 23 的 57.92)。+- GAMMA_RNA 消融见上;-2.0 掉分(covariation 54.65),确认平台在 -1.0~-1.5。  ## 没验证 / 局限 -- 只用 A 半查分;节点正式分用 B 半,小幅差异(HEART_W 1.0↔1.3、GAMMA −1.2↔−1.4 皆 <2 分噪声)未必在 B 半重现,故取平台内稳健值而非 A 半 argmax。-- **final 视图(官方 E8.5+E9.5,目标 E10.5)未测**:那里 GAMMA 会真正作用于官方两阶段、且 E9.5 出现的新型(V-CM/Endocardium/BEC/aPHM/pPHM/Proepicardium 等)已写入 HEART_TYPES 名单以正确加权,但无沙箱可查分。-- proxy2 仍完全忽略 Qiu E9.0(只当参考),未尝试用它做心脏谱系的时间插值——留作后续。-- X3 输出含约 38% 重复细胞(池 2174 < n 3000);实测净收益为正,但重复对 de_recovery 的长期影响未单独隔离。+- 只用 A 半;±0.2 级别的差距(-1.0 vs -1.5)在 B 半未必保持,取平台内值。+- X3 的 +0.77 在噪声(~2 分)内,logit 趋势与 0.75×小池的各自贡献未在本基座上单独消融(沿用 node 23/26 的跨节点证据)。+- **final 视图(官方 E8.5+E9.5→E10.5)无沙箱**:logit 趋势与 GAMMA_RNA gate 都会生效,方向按 X3/proxy 证据推断,未直接验证。+- proxy2 仍忽略 Qiu E9.0 的表达信息(词表不可比),未做心脏谱系时间插值。  ## 生物学知识来源 -仅用通用小鼠胚胎学定性事实:晚期以心脏为中心解剖 → 心脏谱系富集、神经管/表面外胚层/旁轴中胚层相对缩减(node 6/reweight.py 已记录的解剖动机)。类型名单取自**输入阶段**(已发布 E8.5/E9.5 注释),未使用任何保留阶段/基因型的测量。+仅通用小鼠胚胎学定性事实(心脏为中心解剖 → 心脏谱系富集、神经管/表面外胚层/旁轴缩减),类型名单取自输入阶段已发布注释;未使用任何保留阶段/基因型的测量。diff --git a/solution/run.py b/solution/run.pyindex 00b38d8..0db4107 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,5 +1,5 @@ #!/usr/bin/env python3-"""Stratified copy of the latest usable stage + damped composition-trend extrapolation.+"""Stratified copy of the latest usable stage + logit composition-trend extrapolation.  Output population = cells sampled from the latest *official* input stage (fallback: latest input of any kind when the view has no official stage, e.g.@@ -8,24 +8,29 @@ pseudobulk shift measured worse than copy on every ruler; alpha = 0).  Composition (cell-type proportions): when the two latest input stages share a comparable cell-type vocabulary (same dataset/annotation, e.g. X3's E8.75 +-E9.0, or T1 final's official E8.5 + E9.5), the per-type proportion trend-r = (p2 - p1) / dt is extrapolated to the target time with a damping factor-GAMMA, clipped and renormalised; cells are then drawn per type from the latest-stage (with replacement inside a type when needed). When the two latest stages-are not comparable (T1 proxy2: official whole-embryo E8.5 vs external heart-only-Qiu E9.0 with disjoint labels) or there is only one stage (T1 proxy), the+E9.0, or T1 final's official E8.5 + E9.5), the per-type proportion trend is+extrapolated in *logit* space to the target time with damping GAMMA_LOGIT and a+dt-ratio cap of 1, then renormalised. When the two latest stages are not+comparable (T1 proxy2: official whole-embryo E8.5 vs external heart-only Qiu+E9.0 with disjoint labels) or there is only one stage (T1 proxy), the proportions of the latest stage are kept as-is.  On top of the trend, an anatomical reweighting of the target composition is-applied (parent node 6/7/9/10 winning ingredient): the later stage is a-heart-centred dissection, so heart-lineage types are up-weighted (HEART_W),-paraxial mesoderm is down-weighted (PARAXIAL_W), and neural tube / surface-ectoderm (absent from the heart-centred later sample) are dropped. Weights are-keyed on *input-stage* type names (published E8.5/E9.5 annotations); unknown-names (e.g. X3's heart-field labels) get weight 1.0, so the reweighting is a-no-op there and only the GAMMA trend acts. The output size is floored at-N_FLOOR cells; when the pool is smaller (X3, 2174 cells) cells are reused to-reach it -- measured best at 3000 for X3.+applied (parent node 6/7/9/10/12 winning ingredient): heart-lineage types are+up-weighted (HEART_W), paraxial mesoderm down-weighted, neural tube / surface+ectoderm dropped. Weights are keyed on *input-stage* type names; unknown names+get weight 1.0 (no-op on external datasets).++Within-type sampling: when the output is comfortably smaller than the pool+(n_total < 0.5 * pool), cells are drawn by transcriptional-activity anti-tilt+weighted sampling without replacement (weight = (nnz / type-median nnz)^GAMMA_RNA,+Gumbel top-k), which measurably lifts covariation. Otherwise plain uniform+sampling within type.++Output size: pool >= N_FLOOR -> n = clip(target_n * OUT_FRAC, floor N_FLOOR, max);+pool < N_FLOOR (small external pools like X3, 2174 cells) -> n = floor(SMALL_FRAC+* pool), no duplicate padding: composition kept exact with uncapped+largest-remainder allocation, cells drawn without replacement.  Nothing about held-out stages/genotypes is used; all proportions, rates and type names are computed/read from the view's inputs at runtime. The only@@ -51,20 +56,17 @@ from src.task1_temporal.view_io import (     write_prediction, ) -GAMMA = -1.2          # damping of composition trend (X3 A-half: -1.2~-1.4 best)+GAMMA_LOGIT = -2.4    # damping of logit-space composition trend (nodes 17/20/23/26) OUT_FRAC = 0.95-N_FLOOR = 3000       # output size floor (X3 peak at 3000)-MIN_FRAC = 0.002     # floor for a type kept in the target composition-OVERLAP_MIN = 0.5    # min fraction of latest-stage cells whose type is also in the previous stage-HEART_W = 1.3        # multiplier on heart-lineage type fractions (proxy A-half: flat 1.0-1.3, 2.0 worse)+N_FLOOR = 3000        # pools >= this get the floor; smaller pools -> exact output+SMALL_FRAC = 0.75     # small-pool output = floor(SMALL_FRAC * pool), no duplicates+MIN_FRAC = 0.002      # floor for a type kept in the target composition+OVERLAP_MIN = 0.5     # min fraction of latest-stage cells whose type is also in prev stage+HEART_W = 1.3         # multiplier on heart-lineage type fractions PARAXIAL_W = 0.1+GAMMA_RNA = -1.0      # within-type activity anti-tilt exponent (proxy A-half: -1.0 > -0.7/-1.5/-2.0)+RNA_GATE = 0.5        # anti-tilt only when n_total < RNA_GATE * pool_size -# Anatomical reweighting of the target composition. General (textbook) knowledge-# of E8.5->E9.5 mouse dissection: the embryo is dissected heart-centred at the-# later stage, so neural tube / surface ectoderm / paraxial mesoderm /-# extra-embryonic mesoderm shrink while heart-lineage tissues grow. Names are-# those of the *input* stages (published E8.5/E9.5 annotations); no held-out-# measurement is used. Unknown names (e.g. external datasets) get weight 1.0. HEART_TYPES = {     "OFT/RV-CM", "IFT-CM", "AVC-CM", "SV-CM", "LV-CM", "RV-CM", "V-CM",     "Endothelium", "Endocardium", "BEC",@@ -86,12 +88,7 @@ def type_weight(t: str) -> float:   def apportion(fracs: np.ndarray, avail: np.ndarray, n_total: int) -> np.ndarray:-    """Largest-remainder allocation of n_total over fracs, capped at avail per type.--    Never asks for more cells than a type has (duplicated cells measurably hurt-    the DE-based groups); leftover quota goes to the types with the largest-    remaining fractional deficit that still have spare cells.-    """+    """Largest-remainder allocation of n_total over fracs, capped at avail per type."""     fracs = np.asarray(fracs, dtype=np.float64)     avail = np.asarray(avail, dtype=np.int64)     n_total = int(min(n_total, avail.sum()))@@ -114,6 +111,31 @@ def apportion(fracs: np.ndarray, avail: np.ndarray, n_total: int) -> np.ndarray:     return n  +def largest_remainder(fracs: np.ndarray, n_total: int) -> np.ndarray:+    """Uncapped largest-remainder allocation (keeps composition exact)."""+    raw = np.asarray(fracs, dtype=np.float64) * n_total+    n = np.floor(raw).astype(np.int64)+    order = np.argsort(-(raw - n))+    for j in order[: int(n_total - n.sum())]:+        n[j] += 1+    return n+++def logit(p: np.ndarray) -> np.ndarray:+    p = np.clip(p, 1e-6, 1 - 1e-6)+    return np.log(p / (1 - p))+++def cell_nnz(X) -> np.ndarray:+    """Per-cell count of nonzero genes (sparse-friendly)."""+    import scipy.sparse as sp++    if sp.issparse(X):+        Xc = X.tocsr()+        return np.diff(Xc.indptr).astype(np.float64)+    return (np.asarray(X) != 0).sum(axis=1).astype(np.float64)++ def main() -> None:     parser = argparse.ArgumentParser()     parser.add_argument("--data", required=True)@@ -135,7 +157,7 @@ def main() -> None:     types, counts = np.unique(pool_labels, return_counts=True)     fracs = counts.astype(np.float64) / counts.sum() -    # composition trend from the previous stage, only if vocabularies are comparable+    # composition trend (logit space) from the previous stage, only if comparable     prev_entry = None     for e in reversed(stages):         if e is not pool_entry and e["time"] < t_last:@@ -150,11 +172,18 @@ def main() -> None:         covered = fracs[shared].sum()         dt = t_last - float(prev_entry["time"])         if covered >= OVERLAP_MIN and dt > 0 and t_target > t_last:-            extrap = GAMMA * (t_target - t_last) / dt+            step = GAMMA_LOGIT * min((t_target - t_last) / dt, 1.0)             new = fracs.copy()             for i, t in enumerate(types):                 if shared[i]:-                    new[i] = fracs[i] + extrap * (fracs[i] - prev_frac[t])+                    p_last = min(max(fracs[i], MIN_FRAC), 1 - 1e-6)+                    p_prev = min(max(prev_frac[t], MIN_FRAC), 1 - 1e-6)+                    lg = logit(np.array([p_last]))[0] + step * (+                        logit(np.array([p_last]))[0] - logit(np.array([p_prev]))[0]+                    )+                    new[i] = 1.0 / (1.0 + np.exp(-lg))+                else:+                    new[i] = fracs[i]             new = np.clip(new, MIN_FRAC, None)             fracs = new / new.sum()         del prev@@ -166,27 +195,39 @@ def main() -> None:         fracs = adj / adj.sum()      rng = np.random.default_rng(args.seed)-    n_total = target_n_cells(manifest, pool.n_obs)-    n_total = max(int(n_total * OUT_FRAC), N_FLOOR, manifest["min_cells"])-    n_total = int(np.clip(n_total, manifest["min_cells"], manifest["max_cells"]))-    if n_total <= pool.n_obs:-        # enough real cells: no duplicates (capped apportion)+    n_target = target_n_cells(manifest, pool.n_obs)+    if pool.n_obs >= N_FLOOR:+        n_total = max(int(n_target * OUT_FRAC), N_FLOOR, manifest["min_cells"])+        n_total = int(np.clip(n_total, manifest["min_cells"], manifest["max_cells"]))+        n_total = min(n_total, pool.n_obs)         alloc = apportion(fracs, counts, n_total)     else:-        # pool smaller than target (e.g. X3): largest-remainder, allow duplication-        raw = fracs * n_total-        alloc = np.floor(raw).astype(np.int64)-        order = np.argsort(-(raw - alloc))-        for j in order[: int(n_total - alloc.sum())]:-            alloc[j] += 1+        # small pool (X3): exact output, no duplicate padding+        n_total = max(int(np.floor(SMALL_FRAC * pool.n_obs)), manifest["min_cells"])+        n_total = min(n_total, pool.n_obs, manifest["max_cells"])+        alloc = largest_remainder(fracs, n_total)++    # within-type activity anti-tilt weights (only when output << pool)+    use_rna_tilt = n_total < RNA_GATE * pool.n_obs+    if use_rna_tilt:+        nnz = cell_nnz(pool.X)      rows = []     for i, t in enumerate(types):         idx = np.flatnonzero(pool_labels == t)         n = int(alloc[i])-        if n > 0:-            # no duplicates while the pool is large enough; X3 (pool < target) reuses cells-            rows.append(rng.choice(idx, size=n, replace=n > len(idx)))+        if n <= 0:+            continue+        if use_rna_tilt and n <= len(idx):+            med = np.median(nnz[idx])+            wi = (np.maximum(nnz[idx], 1.0) / max(med, 1.0)) ** GAMMA_RNA+            keys = np.log(wi) + rng.gumbel(size=len(idx))+            take = idx[np.argpartition(-keys, n - 1)[:n]]+            rows.append(take)+        elif n <= len(idx):+            rows.append(rng.choice(idx, size=n, replace=False))+        else:+            rows.append(rng.choice(idx, size=n, replace=True))     rows = np.sort(np.concatenate(rows))     X = pool.X[rows]     write_prediction(X, genes, args.out, seed=args.seed)

调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。

用到的知识库条目

编号标题出处
k031Offline OT toolkit in the sandbox: moscot TemporalProblem, wot OTModel, POT, geomloss10.1038/s41586-024-08453-2 (moscot); 10.1016/j.cell.2019.01.006 (Waddington-OT)
k041Within-stage pseudotime and graph toolkit offline: scanpy DPT/PAGA/Leiden, Palantir, CellRank 210.1186/s13059-019-1663-x (PAGA); 10.1038/s41587-019-0068-4 (Palantir); 10.1038/s41592-024-02303-9 (CellRank 2)
k018Damped per-type shift: shrinkage alpha on the observed deltanotes/plan/cards/T1.md

分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。

改了什么在 node 12 基座上叠加三个部件:线性组成趋势 GAMMA=-1.2 改为 logit 空间 GAMMA_LOGIT=-2.4;新增型内转录活性反倾斜抽样 GAMMA_RNA=-1.0(Gumbel top-k 无放回,gate n<0.5×池);小池(X3)由重复补齐到 3000 改为精确输出 floor(0.75×池)=1630 无重复。表达值不改。
各组分数的变化cell_state:噪声内:+0.59 (58.53→59.12)
covariation:噪声内:+0.72 (54.13→54.85),T1 噪声约 2 分;Engineer 在 A 半 proxy 上声称 covariation +2.4,B 半榜上未重现
de_recovery:噪声内:+0.54 (53.02→53.56),仍是最弱组
direction:噪声内:+0.71 (57.04→57.75)
假设是否成立unclear
经验
  1. A 半查分与 B 半正式分可差约 1 分:本节点 A 半 proxy +1.07(covariation +2.4、direction +3.8),B 半榜上全部缩水到 +0.6~0.7(噪声内),A 半上看到的'超噪声'增益不可直接外推。
  2. 从其他基座(node 26 的 logit 基座)移植已验证部件到 node 12 基座时,增益没有可复现地转移:三部件叠加后 B 半各组均 <+0.8,方向为正但幅度全在噪声内。
  3. GAMMA_RNA 平台较宽(A 半 -0.7/-1.0/-1.5/-2.0 → 57.74/58.16/58.05/57.64),-1.0 与 -1.5 的 0.1 级差异在 B 半无意义,扫描时不必在平台内部精细选点。
  4. 跨节点比较部件效果时须注意基座差异:node 26 上 GAMMA_RNA=-1.5 得 covariation +3.46,本节点同机制在 node 12 基座上只得 +0.72(噪声内),说明该增益可能依赖 node 17 系基座的其他成分(如内皮并入心脏族)。
下一步建议
  1. 本节点方向全正但幅度小,可作为新基座保留;下一步针对 covariation 组:直接对比 node 17 基座与本节点的其余差异(内皮类型权重、HEART_W 生效范围),把缺失差异逐项补上再验证,而非继续叠加新部件。
  2. 针对 de_recovery(53.56,最弱组):试型内高方差基因覆盖倾斜抽样(node 26 提过),gate 同 RNA_GATE=0.5,在 X3 与 proxy 各查一次分,若无 >1 分提升即放弃(纯复制家族已知上限约 53)。
  3. 针对 proxy2:目前完全忽略 Qiu E9.0(词表不可比),可试按心脏谱系做两阶段时间插值选细胞(不改表达),先在 proxy2 单独查分确认非负再叠加。

对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。

只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。

分析员

角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。分析员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数?大模型一共回复了几轮(每轮可以调用多个工具)。4
工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。共 3 次:bash 2、write 1
用时不到 1 分
token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。输入 14,364 · 输出 1,029 · 思考 303
任务(第一行)分析节点 n28 的打分结果,写 ANALYSIS.json
最后的回答(摘录)
ANALYSIS.json written
原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/analyst.jsonl 10 KB
/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/analyst.stderr

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数21
工具调用共 25 次:bash 19、read 2、write 2、edit 2
用时6 分
token 数输入 44,362 · 输出 8,878 · 思考 3,481
任务(第一行)按计划修改程序:Node12 加 GAMMA_RNA=-1.5 反倾斜 + logit 趋势 + 小池 0.75 精确输出
最后的回答(摘录)
Done. Final state verified in `solution/`.

**做了什么**:在 node 12 基座上加三个已验证部件——(1) logit 组成趋势 GAMMA_LOGIT=-2.4 替换线性 GAMMA=-1.2;(2) 型内转录活性反倾斜抽样 GAMMA_RNA=-1.0(Gumbel top-k 无放回,gate n<0.5×池,A 半扫描 -0.7/-1.0/-1.5/-2.0 → 57.74/**58.16**/58.05/57.64);(3) 小池精确输出 0.75×池=1630、无重复。表达值不改。

**查分**(6/20 额度):proxy **58.16**(父 57.09,covariation +2.4、direction +3.8)、proxy2 **58.16**、X3 **54.30**(父 53.53)→ 均分 ≈**56.87** vs 父 55.90,proxy 超树最佳 node 23(57.92)。三视图 vec-check ok,seed 0/1 跑通,输出与查分代码逐位一致。

**下一步**:proxy2 完全忽略 Qiu E9.0——可试心脏谱系两阶段插值单独抬 proxy2;de_recovery(53.5)仍是最弱组,可试型内高方差基因覆盖倾斜(node 26 提过)或按 DE 基因结构加权抽样。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/engineer.jsonl 99 KB
/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时2 分
token 数输入 18,110 · 输出 1,107 · 思考 4,650
任务(第一行)为节点 n28(改进,父节点 n12)写改进计划 PLAN.json
最后的回答(摘录)
```json
{
  "name": "Node12 加 GAMMA_RNA=-1.5 反倾斜 + logit 趋势 + 小池 0.75 精确输出",
  "motivation": "父节点 12 最弱组 de_recovery(53.02) 处于纯复制表达家族已知上限(~53, node 25 ANALYSIS),实际可提升空间在第二弱组 covariation(54.13)。树最佳 node 26 covariation=57.84(+3.7),差距来自三个已验证部件:(1) GAMMA_RNA=-1.5 反倾斜(node 26 实测 -1.5 优于 -0.45,covariation +3.46 超噪声);(2) logit 组成趋势 GAMMA=-2.4(nodes 17/20/23/26 均用,direction 58.5 vs node12 57.04);(3) 小池 0.75×精确输出(nodes 22/23 X3 +2.4/+1.1)。Node 21 在 node 12 上只加了 GAMMA_RNA=-0.45 + 0.95×小池,covariation 仅 +0.51;本次用 -1.5 + 0.75× + logit 趋势,是 node 26/23 已验证的更强配置。",
  "approach": "在 node 12 代码上加三个杠杆,表达值仍不改:\n1. 型内转录活性反倾斜抽样(主杠杆):w_i = (nnz_i / median_type)^GAMMA_RNA,Gumbel top-k 无放回。初值 GAMMA_RNA=-1.5,扫描 {-1.0, -1.5, -2.0},在 proxy A 半查分选峰。Gate:仅当 n_total < 0.5×pool_size 时启用(避免 X3 小池触发)。\n2. X3 组成趋势改 logit 空间:logit(p_target) = logit(p_last) + GAMMA_LOGIT×(Δt_target/Δt_last, cap 1)×(logit(p_last)−logit(p_prev)),GAMMA_LOGIT=-2.4(沿用 node 17/20/23/26)。仅当两阶段词表可比(≥0.5)时生效;proxy 单阶段、proxy2 词表不可比均跳过,保持原比例。原线性 GAMMA=-1.2 代码删除。\n3. 小池精确输出:池 < N_FLOOR 时(仅 X3,2174<3000),输出 floor(0.75×池)=1630 个细胞,无重复,用无上限最大余数法保持趋势后组成精确。删除原 N_FLOOR 重复补齐逻辑。\n4. 验证顺序:先只加 GAMMA_RNA=-1.5 在 proxy 查分(1 query)→确认 covariation 提升后加 logit 趋势在 X3 查分(1 query)→加小池 0.75 在 X3 查分(1 query)→三视图 seed 0 全跑 + vec-check(3 queries)。总计 ≤6 queries,留余量给 GAMMA_RNA 扫描(2-3 queries)。\n5. 单输入阶段退路(proxy):无趋势、无小池问题,仅 GAMMA_RNA 生效。final 视图(E8.5+E9.5):logit 趋势正常作用于官方两阶段,GAMMA_RNA 正常作用于大池。",
  "expected_groups": ["covariation", "direction"],
  "risks": "1) GAMMA_RNA=-1.5 在 node 26 的 logit 基座上验证,移植到 node 12 的线性趋势基座(本次同时改 logit 故风险降低);若 covariation 未升反降,先回退到 -1.0。2) 小池 0.75×输出 1630 细胞比原 3000 少近半,de_recovery 可能因样本量减少而掉;Engineer 应对比 0.75×与 0.95×两档。3) logit 趋势在 X3 的增益约 +1~2 分,在噪声边缘,需 X3 多 seed 确认。4) 若三项叠加后 proxy 未超 57.5,说明 node 12 基座本身(线性趋势+HEART_W=1.3)与 node 17 基座(logit+内皮并入心脏族)有细微差异,应检查内皮权重。"
}
```
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/researcher.jsonl 4 KB
/home/spark-longxinyang/vec/runs/formal/20261002-034201-search-t1-abc-r1-B-population/nodes/28/researcher.stderr