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

总览 · ← 返回运行 20261003-094242-search-t2-embryo-interp-g24-D-s2

节点 n5 在终选来历上

mix 混抽 + 共有类型时间差向量强收敛:a 侧细胞 +α·t·Δ_type、b 侧 −α·(1−t)·Δ_type(α=5,只移已表达项、只留 |Δ|≥0.25 基因),坐标不动。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261003-094242-search-t2-embryo-interp-g24-D-s2
父节点n2
子节点n8、n9
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 61.51(+4.3) · proxy 61.51(+4.3) · 3 次复测均分 61.66
审查通过 1 越界读取:未发现——run.py 仅通过 view_io 的 load_manifest/read_stage/panel_genes 读取 --data 视图内文件(run.py:157-168),无绝对路径、'..'、/mnt、/home、下载或目标阶段文件访问,import 的 src.task2_spatial 为环境提供的任务脚手架而非评分器代码。; 2 硬编码目标统计量:未发现——位移向量 Δ=μ_b−μ_a 由两个输入阶段现场计算(run.py:82-94),常量仅为通用超参(α=5、|Δ|≥0.25 阈值、共有类型 ≥10 细胞),无写死的类型比例表、基因列表或表达数值。…
用时?从运行开始到结束(或到现在)的挂钟时间。17 分
程序版本ce70a2f10a25a699dab4e3caddb7335bf4f793a8 (programs.git)

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

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

mix 混抽 + 共有类型时间差向量强收敛:a 侧细胞 +α·t·Δ_type、b 侧 −α·(1−t)·Δ_type(α=5,只移已表达项、只留 |Δ|≥0.25 基因),坐标不动。

方法(family T2EI-01,PLAN 指定的类型级表达时间收敛)

在父节点 2 的 mix 管线(procrustes3d 对齐、scale_damp=0.5、按类型分层混抽 (1−t, t)、n=5000)之上,新增一步:

  1. 对两个括号阶段都出现(各 ≥10 细胞)的类型,Δ_type = μ_b − μ_a(该类型两阶段伪批量均值差),只保留 |Δ| ≥ 0.25 的基因(与 DE 阈值一致,小变化视为噪声)。
  2. 来自 stage_a 的该类型细胞:x ← clip(x + α·t·Δ, 0);来自 stage_b 的:x ← clip(x − α·(1−t)·Δ, 0)。
  3. 稀疏保持(关键结构修复):只对细胞中已表达(x>0)的项做位移,零项保持零。位移是逐类型常数向量,若不限制到已表达项,零元比例会从 93% 掉到 54%,细胞不再像真实细胞,variogram/mmd_u 崩溃(见下)。
  4. 坐标完全不动 → 表达-位置配对(neighborhood_mmd)不因机制本身被破坏。
  5. 单输入阶段退路:与父节点一致,分层复制最后观测阶段,不做位移。
  6. 参数:α 默认 5.0,环境变量 T2_CONVERGE_ALPHA 覆盖(提交时保持打开);α=0 为机制关闭对照。

机制生效证据(seed 0,proxy E6.75+E8.0→E7.25,t=0.4)

  • α=0 输出与父节点 run.py 输出逐位相同(X 与坐标 array_equal=True),管线正确。
  • α=5:10 个共有类型全部位移;型内表达标准差比 0.91(变化 <10%,型内结构未坍缩);型间均值距离比 0.79(收缩);零元比例 0.929→0.941(b 侧下移经 clip 略增,结构保持)。
  • 加权伪批量几乎不动:抽样比例 (1−t, t) 使两侧位移在全局均值中精确抵消(α 大不改变整体均值,只消解型内端点双峰);de_score 的变化来自 clip 的不对称。

对照与查分结果(A 半,seed 0,除注明外)

配置总分cell_statevariogram skillmmd_u skillneighborhood skill
α=0(对照=父节点)56.3636.230.2160.5090.545
α=0.5 稠密位移(无稀疏保持)56.0227.330.0970.4500.496
α=0.2 稠密~55.430.640.1260.4870.527
α=0.5 稀疏56.6337.100.2280.5140.544
α=1.0 稀疏56.9538.330.2430.5240.544
α=1.5 稀疏57.4140.030.2620.5390.545
α=2.5 稀疏58.8144.330.3150.5720.557
α=4 稀疏60.2747.420.3570.5920.576
α=5 稀疏(提交)60.5547.820.3710.5850.583
α=6 稀疏60.4347.260.3810.5650.584
α=10 稀疏57.9340.820.3920.4240.543
α=5,seed 160.3447.82---

稠密位移(PLAN 原式,不加稀疏保持)在所有 α 上都比对照差:它同时打坏稀疏结构。机制的收益全部来自"稀疏保持 + 大 α"这一修正版。

验证过 / 没验证

  • 验证:α=0 逐位复现父节点;α 网格 0.2–10(A 半,13 次查分);平台在 4–6,取中值 5(对平台边缘最稳);seed 0/1 分数一致(60.55 / 60.34);输出确定(同 seed 逐位相同);vec-check 通过;运行 ~30s、峰值内存远低于限值。
  • 没验证:final 视图真实括号(E7.25+E8.0→E7.5,t=1/3)无法本地查分。α=5 远超 PLAN 的 {0.2..1.0} 建议区间,是在代理的大跨度括号(E6.75→E8.0,Δ 很大)上调出的;真实括号更窄、Δ 更小,同样的 α 产生的绝对位移也更小(Δ 正比于括号跨度),预期方向可迁移,但平台位置可能偏移。α=10 时 mmd_u 崩溃说明过冲有真实代价,故不取平台右缘。
  • B 半噪声 ~1 分:+4.2(56.36→60.55)远超噪声,但正式分是 B 半,幅度可能不同。

知识来源

未使用任何文献/数据库先验;Δ_type 完全由视图内两个输入阶段现场计算(无保留阶段信息、无硬编码类型名/比例/表达值)。|Δ|≥0.25 阈值沿用评分简报中 DE 指标的显著性阈值,属通用约定而非禁窗知识。

风险与下一步

  • variogram skill 仍只有 0.371(<0.5 地板):型内端点双峰未完全消除。下一步可试:按分位数把 a 侧型内分布映射到插值分布,或对 Δ 位移加型内随机权重(保持共变结构)。
  • occupancy_dice skill 0.369 一直很低且对表达机制不敏感(坐标项),是形状组剩余失分主因,需坐标侧改进。

调研员的计划

名称mix+类型级表达时间收敛(改善 cell_state/variogram)
动机父节点 2 的 cell_state 组仅 37.49,是四组中最弱的。拆到指标:variogram skill 0.228(得分 2.85/12.5,远低于地板 6.25),mmd_u skill 0.521(得分 6.52/12.5,刚过地板)。METHOD.md 已注明原因:两端真实细胞按比例混抽形成双峰分布,不像中间阶段。mix 只做了组成插值(抽哪边的细胞),没有做类型内表达插值(细胞表达值仍停在端点),导致混合后基因共变结构(variogram)和状态分布(mmd_u)都偏离中间目标。
做法在 mix 框架上增加类型级表达收敛步骤:
1. 对共有类型(两阶段都出现的类型),计算该类型在 stage_a 和 stage_b 的均值表达向量 μ_a, μ_b,得到时间变化向量 Δ = μ_b − μ_a。
2. 来自 stage_a 的该类型细胞:x ← x + α·t·Δ;来自 stage_b 的:x ← x − α·(1−t)·Δ。α 为收敛阻尼,初值 0.5,搜索 {0.2, 0.3, 0.5, 0.7, 1.0}。t 为插值比例(proxy 上约 0.4)。
3. 仅出现在单侧的类型不做位移。
4. 坐标不动,保持表达-位置配对。
5. 单输入阶段退路:无括号时直接复制最后阶段细胞,不做位移(与现有 fallback 一致)。
6. vec-score 筛选:先跑 α=0(对照)和 α=0.5,比较 cell_state 组(重点看 variogram 和 mmd_u 的 skill);若 variogram skill 升到 0.4 以上再细化 α;同时监控 neighborhood_mmd skill 不低于 0.5(结构门)、de_direction 不降。
7. 表达值截断到 [0, +∞),不引入负值。
风险1) α 过大导致型内方差坍缩,mmd_u 反而变差——Engineer 应在 α=1.0 时检查型内标准差是否降到真值的一半以下;2) 类型标签在两个阶段间不完全对应(n_shared_types 少),大部分细胞得不到位移——检查 info 里 n_shared_types,若 <5 则退化为全局均值收敛;3) 邻域组对表达微扰敏感——监控 neighborhood_mmd skill,若降到 0.5 以下立即降 α;4) 预期提升 ~3-5 分(cell_state 从 37→42+),大于 1 分噪声但需 2 次查分确认。

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

对比:父节点版本 9b12f3efec。改动的文件:solution/METHOD.md +52 −0、solution/README.md +5 −5、solution/run.py +135 −11

diff --git a/solution/METHOD.md b/solution/METHOD.mdnew file mode 100644index 0000000..f16e960--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,52 @@+mix 混抽 + 共有类型时间差向量强收敛:a 侧细胞 +α·t·Δ_type、b 侧 −α·(1−t)·Δ_type(α=5,只移已表达项、只留 |Δ|≥0.25 基因),坐标不动。++## 方法(family T2EI-01,PLAN 指定的类型级表达时间收敛)++在父节点 2 的 mix 管线(procrustes3d 对齐、scale_damp=0.5、按类型分层混抽 (1−t, t)、n=5000)之上,新增一步:++1. 对两个括号阶段都出现(各 ≥10 细胞)的类型,Δ_type = μ_b − μ_a(该类型两阶段伪批量均值差),只保留 |Δ| ≥ 0.25 的基因(与 DE 阈值一致,小变化视为噪声)。+2. 来自 stage_a 的该类型细胞:x ← clip(x + α·t·Δ, 0);来自 stage_b 的:x ← clip(x − α·(1−t)·Δ, 0)。+3. **稀疏保持(关键结构修复)**:只对细胞中已表达(x>0)的项做位移,零项保持零。位移是逐类型常数向量,若不限制到已表达项,零元比例会从 93% 掉到 54%,细胞不再像真实细胞,variogram/mmd_u 崩溃(见下)。+4. 坐标完全不动 → 表达-位置配对(neighborhood_mmd)不因机制本身被破坏。+5. 单输入阶段退路:与父节点一致,分层复制最后观测阶段,不做位移。+6. 参数:α 默认 5.0,环境变量 `T2_CONVERGE_ALPHA` 覆盖(提交时保持打开);α=0 为机制关闭对照。++## 机制生效证据(seed 0,proxy E6.75+E8.0→E7.25,t=0.4)++- α=0 输出与父节点 run.py 输出逐位相同(X 与坐标 array_equal=True),管线正确。+- α=5:10 个共有类型全部位移;型内表达标准差比 0.91(变化 <10%,型内结构未坍缩);型间均值距离比 0.79(收缩);零元比例 0.929→0.941(b 侧下移经 clip 略增,结构保持)。+- 加权伪批量几乎不动:抽样比例 (1−t, t) 使两侧位移在全局均值中精确抵消(α 大不改变整体均值,只消解型内端点双峰);de_score 的变化来自 clip 的不对称。++## 对照与查分结果(A 半,seed 0,除注明外)++| 配置 | 总分 | cell_state | variogram skill | mmd_u skill | neighborhood skill |+|---|---:|---:|---:|---:|---:|+| α=0(对照=父节点) | 56.36 | 36.23 | 0.216 | 0.509 | 0.545 |+| α=0.5 稠密位移(无稀疏保持) | 56.02 | 27.33 | 0.097 | 0.450 | 0.496 |+| α=0.2 稠密 | ~55.4 | 30.64 | 0.126 | 0.487 | 0.527 |+| α=0.5 稀疏 | 56.63 | 37.10 | 0.228 | 0.514 | 0.544 |+| α=1.0 稀疏 | 56.95 | 38.33 | 0.243 | 0.524 | 0.544 |+| α=1.5 稀疏 | 57.41 | 40.03 | 0.262 | 0.539 | 0.545 |+| α=2.5 稀疏 | 58.81 | 44.33 | 0.315 | 0.572 | 0.557 |+| α=4 稀疏 | 60.27 | 47.42 | 0.357 | 0.592 | 0.576 |+| **α=5 稀疏(提交)** | **60.55** | **47.82** | **0.371** | **0.585** | **0.583** |+| α=6 稀疏 | 60.43 | 47.26 | 0.381 | 0.565 | 0.584 |+| α=10 稀疏 | 57.93 | 40.82 | 0.392 | 0.424 | 0.543 |+| α=5,seed 1 | 60.34 | 47.82 | - | - | - |++稠密位移(PLAN 原式,不加稀疏保持)在所有 α 上都比对照差:它同时打坏稀疏结构。机制的收益全部来自"稀疏保持 + 大 α"这一修正版。++## 验证过 / 没验证++- 验证:α=0 逐位复现父节点;α 网格 0.2–10(A 半,13 次查分);平台在 4–6,取中值 5(对平台边缘最稳);seed 0/1 分数一致(60.55 / 60.34);输出确定(同 seed 逐位相同);vec-check 通过;运行 ~30s、峰值内存远低于限值。+- 没验证:final 视图真实括号(E7.25+E8.0→E7.5,t=1/3)无法本地查分。α=5 远超 PLAN 的 {0.2..1.0} 建议区间,是在代理的大跨度括号(E6.75→E8.0,Δ 很大)上调出的;真实括号更窄、Δ 更小,同样的 α 产生的绝对位移也更小(Δ 正比于括号跨度),预期方向可迁移,但平台位置可能偏移。α=10 时 mmd_u 崩溃说明过冲有真实代价,故不取平台右缘。+- B 半噪声 ~1 分:+4.2(56.36→60.55)远超噪声,但正式分是 B 半,幅度可能不同。++## 知识来源++未使用任何文献/数据库先验;Δ_type 完全由视图内两个输入阶段现场计算(无保留阶段信息、无硬编码类型名/比例/表达值)。|Δ|≥0.25 阈值沿用评分简报中 DE 指标的显著性阈值,属通用约定而非禁窗知识。++## 风险与下一步++- variogram skill 仍只有 0.371(<0.5 地板):型内端点双峰未完全消除。下一步可试:按分位数把 a 侧型内分布映射到插值分布,或对 Δ 位移加型内随机权重(保持共变结构)。+- occupancy_dice skill 0.369 一直很低且对表达机制不敏感(坐标项),是形状组剩余失分主因,需坐标侧改进。diff --git a/solution/README.md b/solution/README.mdindex d3647c3..aa33d1e 100644--- a/solution/README.md+++ b/solution/README.md@@ -1,6 +1,6 @@-# mix(T2:embryo:val_interp)+# mix + 类型级表达时间收敛(T2:embryo:val_interp) -T2 方法卡的全胚插值选择:`mix`,align=procrustes3d(共有类型质心三维 Kabsch),scale_damp=0.5(目标 RMS 只走 log 线性的一半,防止代理上冲过真值)。其余同心脏 mix:括号两端按 (1−t, t) 分层抽真实细胞,表达和坐标一起走,细胞数夹到 [583, 5000]。-proxy(E6.75 + E8.0 → E7.25,t=0.4)预期 55.96(seed 0 实测 55.957,与方法卡一致;表达 59.1 / 状态 36.3 / 形状 73.6 / 邻域 54.9)。-final(E7.25 + E8.0 → E7.5,t=1/3):n=5000,RMS 168.2,z_dot 0.93,共有类型 11,与 `data/processed/t2/T2__embryo__val_interp__mix.h5ad` 逐位相同。-已知弱点:细胞状态组只有 36(两端细胞混抽不像中间阶段);scale_damp=0.5 是按代理慢增长段调的,真实括号 E7.25→E8.0 是快增长段,RMS 168 可能偏小。+父节点 mix(procrustes3d、scale_damp=0.5、分层混抽)之上新增:共有类型按 Δ=μ_b−μ_a+对 a 侧 +α·t·Δ、b 侧 −α·(1−t)·Δ 位移,只动已表达项、只留 |Δ|≥0.25 基因,clip≥0,坐标不动。+α 默认 5(`T2_CONVERGE_ALPHA` 可覆盖;α=0 逐位复现父节点)。proxy A 半:对照 56.36 → 60.55(seed 1:60.34)。+详见 METHOD.md。diff --git a/solution/run.py b/solution/run.pyindex 7ba73af..28df8a5 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,28 +1,150 @@ #!/usr/bin/env python3-"""mix (T2 interpolation): real cells from both bracketing inputs, drawn (1−t, t).+"""mix + per-type temporal expression convergence (T2 interpolation). -Brackets the target with the nearest inputs before and after it, puts both in-one frame (``ALIGN``), rescales both clouds to the log-linear RMS+Parent (node 2) mix: brackets the target with the nearest inputs before and+after it, aligns both clouds in one frame (procrustes3d on shared-type+centroids), rescales both to the damped log-linear RMS exp(log r_a + SCALE_DAMP·t·Δlog r), and draws cells stratified by type:-round(t·n) from the later stage, the rest from the earlier one. Expression and-coordinates travel together. n is log-linear in t, clipped to the board range.-Parameters are the T2 card's choice for this board (selected_params.json).-If the target is not bracketed, falls back to the latest input before it.+round(t·n) from the later stage, the rest from the earlier one. Coordinates+travel with the cells. n is log-linear in t, clipped to the board range.++New mechanism (CONVERGE_ALPHA, family T2EI-01): for every cell type present in+both bracketing stages (≥10 cells per side), compute its temporal change+vector Δ = μ_b − μ_a from the stage pseudobulk means, keeping only genes with+|Δ| ≥ 0.25 (the DE threshold; smaller changes are noise). Cells drawn from the+earlier stage get x ← x + α·t·Δ; cells from the later stage get+x ← x − α·(1−t)·Δ, applied only to entries already expressed in the cell and+clipped at 0. This moves the two endpoint sub-populations of each type toward+their intermediate state (opposite directions, type-specific magnitude).+Preserving the sparse on/off structure is essential: a dense per-gene shift+drops the zero fraction from 93% to 54% and collapses variogram/mmd_u.+Coordinates are untouched, so the expression–position pairing is preserved by+construction. α = 0 disables the mechanism and reproduces the parent mix+bit-for-bit under the same seed.++α = 5 (plateau 4–6 on the proxy bracket; α = 10 collapses mmd_u) is far above+the naive interpolation value α = 1: because the stratified draw weights+(1−t, t) exactly cancel the shifts in the overall pseudobulk, larger α does+not move the population mean but keeps collapsing the within-type endpoint+bimodality until clipping and over-shooting take over.++If the target is not bracketed, falls back to a stratified copy of the latest+input before it (no displacement possible without two stages). """  from __future__ import annotations  import argparse import json+import os import sys  import numpy as np -from src.task2_spatial.methods import interpolate-from src.task2_spatial.sample import take+from src.task2_spatial.frame import align_pair, log_interp, rms_radius, scale_to_rms+from src.task2_spatial.methods import _jitter+from src.task2_spatial.sample import interp_count, mix_indices, take+from src.task2_spatial.shift import type_means+from src.task2_spatial.transport import as_dense from src.task2_spatial.view_io import board_params, interp_bracket, load_manifest, panel_genes, read_stage, write_t2  PARAMS = {"align": "procrustes3d", "scale_damp": 0.5}+CONVERGE_ALPHA = float(os.environ.get("T2_CONVERGE_ALPHA", "5.0"))+# Only shift genes whose temporal change is real (|Δ| >= DE threshold) and only+# entries already expressed in the cell, so the sparse on/off structure of real+# cells is preserved (a dense per-gene shift destroys it and tanks variogram/mmd).+CONVERGE_MIN_DELTA = float(os.environ.get("T2_CONVERGE_MIN_DELTA", "0.25"))+CONVERGE_NNZ_ONLY = os.environ.get("T2_CONVERGE_NNZ_ONLY", "1") == "1"+++def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):+    t = float(t)+    damp = float(params.get("scale_damp", 1.0))+    align = str(params.get("align", "procrustes"))+    rng = np.random.default_rng(int(params.get("seed", 0)))++    aligned_a, aligned_b, info = align_pair(stage_a.coords, stage_b.coords, stage_a.labels, stage_b.labels, align)+    rms_a = rms_radius(stage_a.coords)+    rms_b = rms_radius(stage_b.coords)+    target_rms = log_interp(rms_a, rms_b, t, damp)+    ca = scale_to_rms(aligned_a, target_rms)+    cb = scale_to_rms(aligned_b, target_rms)+    n = interp_count(stage_a.n, stage_b.n, t, int(params["min_cells"]), int(params["max_cells"]),+                     float(params.get("count_damp", 1.0)))+    ia, ib = mix_indices(stage_a.labels, stage_b.labels, t, n, rng)++    xa = as_dense(stage_a.X, ia) if ia.size else np.zeros((0, len(stage_a.genes)), np.float32)+    xb = as_dense(stage_b.X, ib) if ib.size else np.zeros((0, len(stage_b.genes)), np.float32)++    conv = {"alpha": alpha, "n_shared_types_converged": 0, "within_type_std_rel": None,+            "between_type_mean_dist_rel": None}+    if alpha != 0.0 and ia.size and ib.size:+        means_a = type_means(stage_a.X, stage_a.labels)+        means_b = type_means(stage_b.X, stage_b.labels)+        la = np.asarray(stage_a.labels).astype(str)+        lb = np.asarray(stage_b.labels).astype(str)+        cnt_a = {k: int((la == k).sum()) for k in means_a}+        cnt_b = {k: int((lb == k).sum()) for k in means_b}+        shared = sorted(k for k in set(means_a) & set(means_b) if cnt_a[k] >= 10 and cnt_b[k] >= 10)+        delta = {}+        for lab in shared:+            d = (means_b[lab] - means_a[lab]).astype(np.float32)+            if CONVERGE_MIN_DELTA > 0:+                d = np.where(np.abs(d) >= CONVERGE_MIN_DELTA, d, np.float32(0.0)).astype(np.float32)+            delta[lab] = d+        if shared:+            before = np.vstack([xa, xb]).astype(np.float64)+            labs_a = np.asarray(stage_a.labels).astype(str)[ia]+            labs_b = np.asarray(stage_b.labels).astype(str)[ib]+            def _shift(block, w, d):+                out = np.clip(block + np.float32(w) * d, 0.0, None)+                if CONVERGE_NNZ_ONLY:+                    return np.where(block > 0, out, block)+                return out++            for lab in shared:+                d = delta[lab]+                ma = labs_a == lab+                if ma.any():+                    xa[ma] = _shift(xa[ma], alpha * t, d)+                mb = labs_b == lab+                if mb.any():+                    xb[mb] = _shift(xb[mb], -alpha * (1.0 - t), d)+            after = np.vstack([xa, xb]).astype(np.float64)+            # mechanism evidence: within-type std and between-type mean distance+            labs = np.concatenate([labs_a, labs_b])+            stds, dists_b, dists_a = [], [], []+            centroids = {}+            for lab in shared:+                m = labs == lab+                if m.sum() >= 5:+                    stds.append((after[m].std(axis=0).mean(), before[m].std(axis=0).mean()))+                centroids[lab] = (after[m].mean(axis=0), before[m].mean(axis=0))+            keys = list(centroids)+            for i in range(len(keys)):+                for j in range(i + 1, len(keys)):+                    dists_a.append(np.linalg.norm(centroids[keys[i]][0] - centroids[keys[j]][0]))+                    dists_b.append(np.linalg.norm(centroids[keys[i]][1] - centroids[keys[j]][1]))+            if stds:+                arr = np.array(stds)+                conv["within_type_std_rel"] = float(arr[:, 0].mean() / max(arr[:, 1].mean(), 1e-12))+            if dists_a:+                conv["between_type_mean_dist_rel"] = float(np.mean(dists_a) / max(np.mean(dists_b), 1e-12))+            conv["n_shared_types_converged"] = len(shared)++    expr = np.clip(np.vstack([xa, xb]), 0.0, None).astype(np.float32) if (ia.size or ib.size) else np.zeros((0, len(stage_a.genes)), np.float32)+    coord_parts = []+    if ia.size:+        coord_parts.append(np.asarray(ca[ia], dtype=np.float64))+    if ib.size:+        coord_parts.append(np.asarray(cb[ib], dtype=np.float64))+    coords = _jitter(np.vstack(coord_parts), rng)+    coords = scale_to_rms(coords, target_rms)+    info.update(+        t=t, n=int(expr.shape[0]), rms_a=rms_a, rms_b=rms_b, target_rms=target_rms,+        out_rms=rms_radius(coords), n_from_a=int(ia.size), n_from_b=int(ib.size), **conv,+    )+    return expr, coords.astype(np.float32), info   def main() -> None:@@ -44,8 +166,10 @@ def main() -> None:     stage_a = read_stage(args.data, a, genes)     stage_b = read_stage(args.data, b, genes)     params = board_params(manifest, "mix", PARAMS, args.seed)-    expr, coords, info = interpolate(stage_a, stage_b, t, params)-    keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped", "align")}+    expr, coords, info = mix_converge(stage_a, stage_b, t, params, CONVERGE_ALPHA)+    keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped",+                                     "align", "alpha", "n_shared_types_converged", "within_type_std_rel",+                                     "between_type_mean_dist_rel", "n_from_a", "n_from_b")}     print(json.dumps({"bracket": [a["stage"], b["stage"]], **keep}, default=float), file=sys.stderr)     write_t2(args.out, expr, coords, genes, seed=args.seed) 

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

用到的知识库条目

编号标题出处
k007Interval staging and held-out-window filtering of external datanotes/official/来件/virtualembryo.ai/rules.md
k028LLM-driven code evolution for analysis algorithms10.64898/2026.02.26.707870
k027Joint expression-geometry generation with relative geometrynotes/competition/03_solution_landscape.md

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

改了什么在父节点 2 的 mix 管线(procrustes3d 对齐、scale_damp=0.5、按类型分层混抽 (1-t,t)、n=5000)之上新增类型级表达时间收敛:共有类型 Δ=μ_b-μ_a(只保留 |Δ|>=0.25 的基因),a 侧细胞 +α·t·Δ、b 侧 -α·(1-t)·Δ,且位移只作用于该细胞已表达(x>0)的项、clip>=0,坐标完全不动;α 默认 5(T2_CONVERGE_ALPHA 可覆盖,α=0 关闭机制)。
各组分数的变化cell_state:明显变好,是本节点的主要收益:variogram 0.02952→0.01395(skill 0.228→0.389,得分 2.85→4.86,+2.00),mmd_u 0.01657→0.0122(skill 0.521→0.597,+0.94);组 37.49→49.28(+11.79 个百分点 ≈ +2.94 榜分)。
expression_change:略变好、幅度接近噪声:de_score 0.2069→0.2759(skill 0.562→0.587,+0.31 分),de_direction 0.3757→0.3919(+0.09 分,在 T2 约 1 分噪声内)。Engineer 归因于 clip 的不对称,方向与 PLAN 的'de_direction 不降'一致。
local_spatial:变好且高于噪声:neighborhood_mmd 0.05791→0.04971(skill 0.573→0.610,得分 14.32→15.26,+0.94),组 57.27→61.02(+3.75 个百分点);结构门未受影响(邻域 skill 已在 0.5 地板之上)。
shape_scale:完全不变(+0.00):d2_shape 0.00841、occupancy_dice 0.7735(skill 0.367)、scale_log_ratio 0.0099 三项与父节点逐位相同——坐标不动,符合设计;occupancy_dice 仍是形状组主要失分项。
family_idT2EI-01
假设是否成立是
经验
  1. 在稀疏表达数据上做逐类型常数向量位移时,若把位移加到全部基因(含零项),零元率从 93% 掉到 54%,variogram skill 反降到 0.097(对照 0.216)、总分低于对照;把位移限制到该细胞已表达项(x>0)后同样的机制变成 +2.0 分的收益——结构保持是这类位移机制的成败开关,不是可选修饰。
  2. 分层混抽权重 (1-t, t) 与相向位移(a 侧 +α·t·Δ、b 侧 -α·(1-t)·Δ)在全局伪批量上精确抵消,因此 α 可以远超朴素插值值 1:本节点 α 平台在 4–6(α=5 得分最高),α=10 时 mmd_u skill 崩到 0.424;说明类型级收敛改的是型内分布形状而非均值,DE 两项对此不敏感,而过冲的代价体现在 mmd_u。
  3. 带 α=0 的关闭对照(逐位复现父节点)+ α 网格扫描,使本节点的收益可干净归因于所声称机制;变好集中在 variogram/mmd_u(表达分布)且形状三项逐位不变,与'只改表达、不动坐标'的机制声明一致,排除了全局重加权解释。
  4. PLAN 预设的 variogram skill >=0.4 才细化 α 的门槛实际达到 0.389(略低于阈值),但仍远高于地板 0.5 以下的位置;提示阈值应按'相对地板与对照'而非绝对数值设定,否则会误判为无效。
  5. Engineer 自述的 56.36→60.55 是 proxy A 半的结果,与变化量表(57.23→61.51,+4.28)不是同一次查分;方向和机制一致但绝对值应以变化量表为准,跨半的幅度不可直接搬用。
  6. 型均值位移只能把型内端点双峰压到一定程度:variogram skill 0.389 仍低于地板 0.5,说明该机制的收益已接近自身上限,继续在 α 上加密网格的边际收益小(4–6 已是平台)。
mechanism_active是
下一步建议
  1. 针对 cell_state/variogram(skill 0.389,仍低于地板 0.5):在保留 nnz-only 位移的前提下加型内异质性——对每个细胞的位移乘型内随机权重 w~Beta 或按该细胞到型均值的投影分位数缩放,或对 a 侧型内分布做分位数映射到插值目标,目标把 variogram skill 推过 0.5;同时监控 mmd_u skill 不低于 0.585、neighborhood skill 不低于 0.60。
  2. 针对 shape_scale/occupancy_dice(skill 0.367,得分 3.06/8.33,与表达机制正交):只做坐标侧改动,如按目标云的 PCA 特征谱做逐轴各向异性缩放(而非当前各向同性 scale_to_rms)或重调 scale_damp(在 0.4/0.5/0.7 上网格),保持 d2_shape 与 scale_log_ratio 的 skill 不掉(现分别 0.934、0.932)。
  3. 针对参数迁移:真实括号更窄(E7.25+E8.0→E7.5,t=1/3,Δ 幅度更小),α=5 是在大跨度代理括号上调出的;在可查分的视图上把 α 网格扩到 {2,3,4,5,6,7} 并检查平台位置是否随括号跨度移动,必要时改用'位移总量归一化'(按 |Δ| 的均值缩放 α)以获得跨括号可迁移的参数。

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

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

分析员

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

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数38
工具调用共 39 次:bash 29、edit 6、read 2、write 2
用时14 分
token 数输入 77,158 · 输出 13,339 · 思考 15,640
任务(第一行)按计划修改程序:mix+类型级表达时间收敛(改善 cell_state/variogram)
最后的回答(摘录)
**做了什么**:在父节点 mix 上实现 PLAN 的类型级时间收敛(T2EI-01),并做了一个关键结构修复——位移只作用于已表达项且只保留 |Δ|≥0.25 基因(稠密位移会把零元率从 93% 打到 54%,反而降分)。α 网格 0.2→10 扫描后取平台(4–6)中值 α=5,坐标不动。

**查分**(proxy A 半,14 次):对照 α=0(与父节点逐位相同)56.36 → α=5 得 **60.55**(seed 1:60.34);cell_state 36.2→47.8(variogram skill 0.216→0.371,mmd_u 0.509→0.585),neighborhood 0.545→0.583,DE 组略升。α=10 时 mmd_u 崩溃(0.424),故不取更高。vec-check 通过、同 seed 逐位确定、~30s CPU。

**下一步最值得试**:① variogram 仍低于地板——型内端点双峰未消尽,可试分位数映射或型内随机权重位移;② occupancy_dice skill 0.369 是形状组主要失分,需坐标侧改进(与表达机制正交);③ 真实括号更窄(E7.25→E8.0,t=1/3),α 平台位置可能偏移,后续节点可在 final 视图验证 α∈[3,6] 的敏感性。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/engineer.jsonl 194 KB
/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时1 分
token 数输入 9,269 · 输出 1,051 · 思考 2,837
任务(第一行)为节点 n5(改进,父节点 n2)写改进计划 PLAN.json
最后的回答(摘录)
```json
{
  "name": "mix+类型级表达时间收敛(改善 cell_state/variogram)",
  "motivation": "父节点 2 的 cell_state 组仅 37.49,是四组中最弱的。拆到指标:variogram skill 0.228(得分 2.85/12.5,远低于地板 6.25),mmd_u skill 0.521(得分 6.52/12.5,刚过地板)。METHOD.md 已注明原因:两端真实细胞按比例混抽形成双峰分布,不像中间阶段。mix 只做了组成插值(抽哪边的细胞),没有做类型内表达插值(细胞表达值仍停在端点),导致混合后基因共变结构(variogram)和状态分布(mmd_u)都偏离中间目标。",
  "approach": "在 mix 框架上增加类型级表达收敛步骤:\n1. 对共有类型(两阶段都出现的类型),计算该类型在 stage_a 和 stage_b 的均值表达向量 μ_a, μ_b,得到时间变化向量 Δ = μ_b − μ_a。\n2. 来自 stage_a 的该类型细胞:x ← x + α·t·Δ;来自 stage_b 的:x ← x − α·(1−t)·Δ。α 为收敛阻尼,初值 0.5,搜索 {0.2, 0.3, 0.5, 0.7, 1.0}。t 为插值比例(proxy 上约 0.4)。\n3. 仅出现在单侧的类型不做位移。\n4. 坐标不动,保持表达-位置配对。\n5. 单输入阶段退路:无括号时直接复制最后阶段细胞,不做位移(与现有 fallback 一致)。\n6. vec-score 筛选:先跑 α=0(对照)和 α=0.5,比较 cell_state 组(重点看 variogram 和 mmd_u 的 skill);若 variogram skill 升到 0.4 以上再细化 α;同时监控 neighborhood_mmd skill 不低于 0.5(结构门)、de_direction 不降。\n7. 表达值截断到 [0, +∞),不引入负值。",
  "expected_groups": ["cell_state"],
  "risks": "1) α 过大导致型内方差坍缩,mmd_u 反而变差——Engineer 应在 α=1.0 时检查型内标准差是否降到真值的一半以下;2) 类型标签在两个阶段间不完全对应(n_shared_types 少),大部分细胞得不到位移——检查 info 里 n_shared_types,若 <5 则退化为全局均值收敛;3) 邻域组对表达微扰敏感——监控 neighborhood_mmd skill,若降到 0.5 以下立即降 α;4) 预期提升 ~3-5 分(cell_state 从 37→42+),大于 1 分噪声但需 2 次查分确认。",
  "family_id": "T2EI-01",
  "mechanism": "对共有类型,按该类型的实际时间变化向量 Δ 将端点细胞表达向中间收敛,收敛幅度由 α·t(或 α·(1−t))控制,方向取决于细胞来源阶段。",
  "vs_constant_shift": "不是给所有细胞加同一个向量:(1) 位移向量 Δ 逐类型不同,正比于该类型真实时间变化;(2) 来自 stage_a 和 stage_b 的细胞位移方向相反(相向收敛,而非同向平移);(3) 幅度由插值比例 t 和阻尼 α 共同决定。全局常数位移对所有细胞加同一 Δ,不区分类型和来源阶段,无法消除双峰。",
  "mechanism_evidence": "Engineer 应输出:(1) 位移前后每个共有类型的型内表达标准差(应基本不变,<10% 变化);(2) 型间均值距离(应收缩 α·t 比例);(3) variogram skill 和 mmd_u skill 的绝对值变化;(4) 若 α=0 时指标与父节点一致,说明管线正确。",
  "mechanism_off_control": "设 α=0(或命令行 --converge-alpha 0),所有细胞表达不做位移,输出应与父节点 mix 完全一致(相同 seed 下逐位相同)。若 α=0 与 α=0.5 的 variogram/mmd_u 无差别,说明机制未生效。",
  "sources": []
}
```
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/researcher.jsonl 4 KB
/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/researcher.stderr

审查员

角色审查员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数8
工具调用共 12 次:bash 6、read 5、write 1
用时1 分
token 数输入 20,683 · 输出 1,368 · 思考 3,038
任务(第一行)审查节点 n5 的程序是否越界读取、写死目标、钻评分器漏洞
最后的回答(摘录)
REVIEW.json written
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/reviewer.jsonl 80 KB
/home/spark-longxinyang/vec/runs/formal/20261003-094242-search-t2-embryo-interp-g24-D-s2/nodes/5/reviewer.stderr