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

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

节点 n12

mix+时间扭曲组成:按 t_draw=t^1.75 而非线性 t 从括号两端分层抽真实细胞(表达、坐标同行),专攻最弱的 cell_state 组。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261003-004922-search-t2-embryo-interp-g24-D
父节点n2
子节点n14、n16
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 61.02(+3.8) · proxy 61.02(+3.8) · 3 次复测均分 60.52
审查通过 1 越界读取:未发现问题。run.py 只通过 args.data 经 src.task2_spatial.view_io(load_manifest/read_stage/panel_genes)读视图内数据,导入的是任务库而非 src/common/evaluation,无绝对路径、'..'、/mnt、/home、网络访问。; 2 硬编码目标统计量:未发现问题。全部常量为 PARAMS(align/scale_damp=0.5, run.py:39)、MIN_TYPE_CELLS=10(run.py:40)、GAMMA=1.75/ALPHA=0(run.py:41-42);GAMMA 是…
用时?从运行开始到结束(或到现在)的挂钟时间。15 分
程序版本727300143bc6fa95c8d3d738fbaeb27bbbb515d4 (programs.git)

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

来自 programs.git 727300143b:solution/METHOD.md

mix+时间扭曲组成:按 t_draw=t^1.75 而非线性 t 从括号两端分层抽真实细胞(表达、坐标同行),专攻最弱的 cell_state 组。

方法

在父节点 2(mix:procrustes3d 对齐、scale_damp=0.5、细胞数 log 线性夹到 [min,max]、按 (1−t, t) 分层抽真实细胞)之上,只改抽取比例:

  • 组成扭曲:t_draw = t**GAMMA,GAMMA=1.75(默认常量,可用环境变量 T2EI_GAMMA 覆盖)。代理 t=0.4 → t_draw=0.201(5000 个细胞中 3994 来自 E6.75、1006 来自 E8.0)。
  • 坐标、target RMS(log 线性 + scale_damp=0.5)、细胞数 n、表达全部沿用父节点逻辑,逐位不变;只有"从哪端抽多少细胞"变了。
  • 生物学依据(通用机制知识,非保留阶段测量):早期胚胎在单位时间内细胞类型/状态扩张极快,后期阶段的细胞群与更早阶段差异远大于线性时间比例的假设,故线性 t 混抽会过采晚端细胞;对 t 做单调幂变换把组成拉向早端。t_draw 只由 manifest 的时间差算出,视图无关、时间平移不变。

PLAN(T2EI-01 型均值表达位移):已实现、机制对照已做,但方向有害,提交时关闭(ALPHA=0)

run.py 内完整实现了 PLAN 的型均值位移:共有型(两端各 ≥10 个细胞)按 delta_c = mean_b(c) − mean_a(c),a 端细胞 x += alpha·t·delta_c,b 端 x −= alpha·(1−t)·delta_c,单端型不动,负值裁剪为 0;开关 T2EI_ALPHA(默认 0.0)。

机制生效证据(alpha=1,代理 E6.75+E8.0→E7.25):10 个型被位移,位移向量 L2 范数 min/med/max = 13.6/21.8/26.1(>0 且型间有差异);各型均值与中间均值 (1−t)m_a+t·m_b 的余弦从两端间 0.613 升到 0.994;43% 的表达矩阵元素被改变,坐标不变。

机制对照(同程序 alpha=0 vs alpha=1,各 1 次 vec-score):

配置A半榜分cell_stateexpr_changeshapelocal_spatial
alpha=0(=父节点,逐位相同)56.4236.2359.8075.1754.48
alpha=0.552.8027.3459.6974.5749.60
alpha=1.048.4323.4559.4566.5744.28

alpha 越大 cell_state、local_spatial 越差(mmd_u 0.017→0.028,variogram 0.031→0.102):把端点细胞推到"两端型均值的凸组合"反而离真实中间阶段的细胞状态分布更远。PLAN 预期的 cell_state 增益没有出现(不是升 <2 分,是降 13 分),故按事实提交 alpha=0。alpha=1 与 GAMMA=1.75 组合也测过:56.27,同样差,排除"扭曲后再位移"的补救。

结果(proxy A 半,vec-score)

GAMMA(t_draw)榜分cell_stateexpr_changeshapelocal_spatial
1.0(父节点)56.4236.2359.8075.1754.48
1.5(0.253)59.3548.4260.2070.1458.64
1.75(0.201,提交)60.1253.2760.2767.9159.04
2.0(0.160)59.5754.5059.9666.8556.96
2.5(0.101)58.4855.5859.4264.8654.04

种子稳健性(GAMMA=1.75):seed 0/1/2 = 60.12 / 59.72 / 59.63,均值 59.82,比父节点高 ~3.4(>噪声 2)。cell_state 从 36 升到 ~53;代价是 shape_scale 75→68(d2_shape 0.006→0.029,a 端主导后点云形状略偏离),总分仍净增。

验证过 / 没验证过

  • 验证过:GAMMA=1.0 且 ALPHA=0 时输出与父节点逐位相同(X 与 spatial_3D 全等);seed 0 重跑逐位一致;vec-check 通过;n=5000、498 基因、runtime ~2s、纯 CPU(EXECUTION.json gpu=false)。
  • 没验证过:真实 final 括号(E7.25+E8.0→E7.5,t=1/3 → t_draw=0.146)上的效果——扭曲是 t 的单调函数、只依赖时间差,逻辑上同样成立,但最优 GAMMA 可能随括号不同;代理只有一个括号,GAMMA=1.75 是在其上调的点估计(1.5–2.0 都在 59+,峰较宽)。
  • 无括号退路(copy_last 式整段照抄+分层抽样)保留父节点原逻辑,未在本视图触发。

知识来源

未使用任何保留阶段/基因型的测量信息;未用外部数据(external 为空);未用 prior 文件。唯一生物学假设(早期发育细胞状态扩张快于线性时间)为通用发育生物学常识,且只通过 t 的单调变换进入程序。查分共 11 次(配额 20)。

调研员的计划

名称mix + 型均值表达插值:将端点细胞表达移向中间型均值
动机父节点 2(mix)cell_state 仅 37.49,远低于 seed copy_last 的 49.29 和其他三组(59.72/57.27/74.43)。原因:mix 直接抽取端点真实细胞,其表达谱仍是端点状态而非中间状态。节点 3 尝试类似改法但 gen_failed(实现崩溃,非方案错误)。节点 7 在 copy_last 上证明型内表达位移可改善 expression_change +2.03、local_spatial +4.78,说明表达微调方向有效。本次在 mix 上做更简单的型均值平移,避免节点 3 的复杂轨迹实现。
做法步骤:(1) 读取 stage_a、stage_b 及标签;(2) 对同时出现在两端的每个细胞型,计算型均值差 delta_c = mean(X_b[c]) - mean(X_a[c])(逐基因);(3) 对从 stage_a 抽出的型 c 细胞:X += t * delta_c;对从 stage_b 抽出的型 c 细胞:X -= (1-t) * delta_c;(4) 仅出现在单端的型不做位移(保持原表达);(5) 位移后裁剪负值为 0;(6) 坐标、细胞数、组成完全沿用 mix 原逻辑不变。关键参数:位移系数 alpha=1.0(完全按 t 比例移向中间型均值),搜索范围 [0.5, 1.0];若型内细胞数 < 10 则跳过该型不位移。单输入阶段退路:无括号时走 copy_last 原逻辑(只取最近输入,不位移)。vec-score 快筛:先跑 alpha=0(等价于父节点)确认基线分一致,再跑 alpha=1.0 看 cell_state 是否上升;若 cell_state 提升 < 2 分则尝试 alpha=0.5。
风险1) 型均值差噪声大(型内细胞少时均值不稳)→ 用最小细胞数阈值 10 过滤;2) 位移后方差结构被压缩导致表达过于均匀 → 只移均值不缩方差,保留细胞间差异;3) 与节点 3 同为表达插值方向,但节点 3 是 gen_failed(代码崩溃),本方案实现极简(仅均值加减),30 分钟内可完成;4) cell_state 评分可能不只看型均值还看分布形状 → 若提升有限则说明需要更高阶插值,但至少验证方向。Engineer 应在第一次查分时同时记录四组分,确认 cell_state 是否为主要增益来源。

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

对比:父节点版本 b616d893bf。改动的文件:solution/EXECUTION.json +1 −0、solution/METHOD.md +47 −0、solution/README.md +4 −5、solution/run.py +119 −12

diff --git a/solution/EXECUTION.json b/solution/EXECUTION.jsonnew file mode 100644index 0000000..9d5125c--- /dev/null+++ b/solution/EXECUTION.json@@ -0,0 +1 @@+{"gpu": false}diff --git a/solution/METHOD.md b/solution/METHOD.mdnew file mode 100644index 0000000..0b8d5cb--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,47 @@+mix+时间扭曲组成:按 t_draw=t^1.75 而非线性 t 从括号两端分层抽真实细胞(表达、坐标同行),专攻最弱的 cell_state 组。++## 方法++在父节点 2(mix:procrustes3d 对齐、scale_damp=0.5、细胞数 log 线性夹到 [min,max]、按 (1−t, t) 分层抽真实细胞)之上,只改**抽取比例**:++- 组成扭曲:`t_draw = t**GAMMA`,GAMMA=1.75(默认常量,可用环境变量 `T2EI_GAMMA` 覆盖)。代理 t=0.4 → t_draw=0.201(5000 个细胞中 3994 来自 E6.75、1006 来自 E8.0)。+- 坐标、target RMS(log 线性 + scale_damp=0.5)、细胞数 n、表达全部沿用父节点逻辑,逐位不变;只有"从哪端抽多少细胞"变了。+- 生物学依据(通用机制知识,非保留阶段测量):早期胚胎在单位时间内细胞类型/状态扩张极快,后期阶段的细胞群与更早阶段差异远大于线性时间比例的假设,故线性 t 混抽会**过采晚端**细胞;对 t 做单调幂变换把组成拉向早端。t_draw 只由 manifest 的时间差算出,视图无关、时间平移不变。++## PLAN(T2EI-01 型均值表达位移):已实现、机制对照已做,但方向有害,提交时关闭(ALPHA=0)++run.py 内完整实现了 PLAN 的型均值位移:共有型(两端各 ≥10 个细胞)按 `delta_c = mean_b(c) − mean_a(c)`,a 端细胞 `x += alpha·t·delta_c`,b 端 `x −= alpha·(1−t)·delta_c`,单端型不动,负值裁剪为 0;开关 `T2EI_ALPHA`(默认 0.0)。++机制生效证据(alpha=1,代理 E6.75+E8.0→E7.25):10 个型被位移,位移向量 L2 范数 min/med/max = 13.6/21.8/26.1(>0 且型间有差异);各型均值与中间均值 (1−t)m_a+t·m_b 的余弦从两端间 0.613 升到 0.994;43% 的表达矩阵元素被改变,坐标不变。++机制对照(同程序 alpha=0 vs alpha=1,各 1 次 vec-score):++| 配置 | A半榜分 | cell_state | expr_change | shape | local_spatial |+|---|---:|---:|---:|---:|---:|+| alpha=0(=父节点,逐位相同) | 56.42 | 36.23 | 59.80 | 75.17 | 54.48 |+| alpha=0.5 | 52.80 | 27.34 | 59.69 | 74.57 | 49.60 |+| alpha=1.0 | 48.43 | 23.45 | 59.45 | 66.57 | 44.28 |++alpha 越大 cell_state、local_spatial 越差(mmd_u 0.017→0.028,variogram 0.031→0.102):把端点细胞推到"两端型均值的凸组合"反而离真实中间阶段的细胞状态分布更远。PLAN 预期的 cell_state 增益没有出现(不是升 <2 分,是降 13 分),故按事实提交 alpha=0。alpha=1 与 GAMMA=1.75 组合也测过:56.27,同样差,排除"扭曲后再位移"的补救。++## 结果(proxy A 半,vec-score)++| GAMMA(t_draw) | 榜分 | cell_state | expr_change | shape | local_spatial |+|---|---:|---:|---:|---:|---:|+| 1.0(父节点) | 56.42 | 36.23 | 59.80 | 75.17 | 54.48 |+| 1.5(0.253) | 59.35 | 48.42 | 60.20 | 70.14 | 58.64 |+| **1.75(0.201,提交)** | **60.12** | 53.27 | 60.27 | 67.91 | 59.04 |+| 2.0(0.160) | 59.57 | 54.50 | 59.96 | 66.85 | 56.96 |+| 2.5(0.101) | 58.48 | 55.58 | 59.42 | 64.86 | 54.04 |++种子稳健性(GAMMA=1.75):seed 0/1/2 = 60.12 / 59.72 / 59.63,均值 59.82,比父节点高 ~3.4(>噪声 2)。cell_state 从 36 升到 ~53;代价是 shape_scale 75→68(d2_shape 0.006→0.029,a 端主导后点云形状略偏离),总分仍净增。++## 验证过 / 没验证过++- 验证过:GAMMA=1.0 且 ALPHA=0 时输出与父节点**逐位相同**(X 与 spatial_3D 全等);seed 0 重跑逐位一致;vec-check 通过;n=5000、498 基因、runtime ~2s、纯 CPU(EXECUTION.json gpu=false)。+- 没验证过:真实 final 括号(E7.25+E8.0→E7.5,t=1/3 → t_draw=0.146)上的效果——扭曲是 t 的单调函数、只依赖时间差,逻辑上同样成立,但最优 GAMMA 可能随括号不同;代理只有一个括号,GAMMA=1.75 是在其上调的点估计(1.5–2.0 都在 59+,峰较宽)。+- 无括号退路(copy_last 式整段照抄+分层抽样)保留父节点原逻辑,未在本视图触发。++## 知识来源++未使用任何保留阶段/基因型的测量信息;未用外部数据(external 为空);未用 prior 文件。唯一生物学假设(早期发育细胞状态扩张快于线性时间)为通用发育生物学常识,且只通过 t 的单调变换进入程序。查分共 11 次(配额 20)。diff --git a/solution/README.md b/solution/README.mdindex d3647c3..f47a3a9 100644--- a/solution/README.md+++ b/solution/README.md@@ -1,6 +1,5 @@-# 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 可能偏小。+父节点 2(mix,A半 56.42)之上把抽取比例从线性 t 改为 `t_draw = t^1.75`:坐标、RMS 缩放、细胞数、表达逻辑逐位沿用,只把混抽组成拉向早端括号阶段。proxy A半 60.12(seed 0/1/2 = 60.12/59.72/59.63),cell_state 36→53,local_spatial 54→59,代价 shape_scale 75→68。+PLAN 的型均值表达位移(T2EI-01)已实现(`T2EI_ALPHA` 开关,默认 0):对照实测 alpha=0.5/1.0 把榜分打到 52.8/48.4,cell_state 反而降,故关闭;证据与四组分见 METHOD.md。+无括号时退路 = 父节点 copy_last 逻辑。纯 CPU,~2s,5000 细胞 × 498 基因。diff --git a/solution/run.py b/solution/run.pyindex 7ba73af..3a4fe74 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,12 +1,22 @@ #!/usr/bin/env python3-"""mix (T2 interpolation): real cells from both bracketing inputs, drawn (1−t, t).--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-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).+"""mix with time-warped composition (T2 interpolation).++Same frame as the parent mix seed (procrustes3d alignment, scale_damp=0.5,+log-linear cell count clipped to the board range, stratified draw of real+cells from the bracketing stages, expression and coordinates travel together),+except the draw fraction is warped: instead of (1-t, t) the split uses+t_draw = t**GAMMA (GAMMA=1.75, tuned on the proxy). Early-stage embryos gain+cell types/states very fast, so a linear-in-time mix over-weights the later+bracket stage; the warp pulls the composition towards the earlier stage and+lifts cell_state and local_spatial without touching coordinates.++The program also implements the planned type-mean expression interpolation+(T2EI-01): with alpha>0 each drawn cell of a shared type c gets+x += alpha*t*(m_b(c)-m_a(c)) (a-side) or x -= alpha*(1-t)*(m_b(c)-m_a(c))+(b-side), types seen at only one stage or with < MIN_TYPE_CELLS cells are left+untouched. Proxy scoring showed this mechanism is harmful here (alpha=1 drops+cell_state 36->23 and the board score 56.4->48.4), so ALPHA defaults to 0.0;+alpha=0, gamma=1 reproduces the parent mix bit-for-bit. If the target is not bracketed, falls back to the latest input before it. """ @@ -14,15 +24,112 @@ 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, _limits+from src.task2_spatial.sample import 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}+MIN_TYPE_CELLS = 10+ALPHA = float(os.environ.get("T2EI_ALPHA", "0.0"))+GAMMA = float(os.environ.get("T2EI_GAMMA", "1.75"))+++def mix_type_shift(stage_a, stage_b, t: float, params: dict, alpha: float, gamma: float = 1.0):+    t = float(t)+    t_draw = float(np.clip(t ** gamma, 0.0, 1.0)) if gamma != 1.0 else 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 = _limits(params, stage_a.n, stage_b.n, t, "interp")+    ia, ib = mix_indices(stage_a.labels, stage_b.labels, t_draw, n, rng)++    xa = as_dense(stage_a.X, ia)+    xb = as_dense(stage_b.X, ib)+    shift_stats: dict = {}+    if alpha > 0.0 and ia.size and ib.size:+        la = np.asarray(stage_a.labels).astype(str)+        lb = np.asarray(stage_b.labels).astype(str)+        cnt_a = {k: int(v) for k, v in zip(*np.unique(la, return_counts=True))}+        cnt_b = {k: int(v) for k, v in zip(*np.unique(lb, return_counts=True))}+        means_a = type_means(stage_a.X, la)+        means_b = type_means(stage_b.X, lb)+        shared = [+            k for k in sorted(means_a) if k in means_b and cnt_a[k] >= MIN_TYPE_CELLS and cnt_b[k] >= MIN_TYPE_CELLS+        ]+        delta = {k: (means_b[k] - means_a[k]).astype(np.float32) for k in shared}+        back = {k: (-delta[k]).astype(np.float32) for k in shared}+        if shared:+            xa = _apply_delta(xa, la[ia], delta, alpha * t)+            xb = _apply_delta(xb, lb[ib], back, alpha * (1.0 - t))+            norms = np.array([float(np.linalg.norm(delta[k])) for k in shared])+            cos_before = np.mean([_cos(means_a[k], means_b[k]) for k in shared])+            mid = {k: (1.0 - t) * means_a[k] + t * means_b[k] for k in shared}+            got_a = {k: xa[la[ia] == k].mean(axis=0) for k in shared if (la[ia] == k).any()}+            got_b = {k: xb[lb[ib] == k].mean(axis=0) for k in shared if (lb[ib] == k).any()}+            cos_after = np.mean(+                [_cos((got_a[k] * (la[ia] == k).sum() + got_b[k] * (lb[ib] == k).sum())+                      / ((la[ia] == k).sum() + (lb[ib] == k).sum()), mid[k]) for k in got_a.keys() & got_b.keys()]+            )+            shift_stats = {+                "n_types_shifted": len(shared),+                "delta_norm_min": float(norms.min()),+                "delta_norm_med": float(np.median(norms)),+                "delta_norm_max": float(norms.max()),+                "cos_ab_before": float(cos_before),+                "cos_to_mid_after": float(cos_after),+            }++    expr = np.clip(np.vstack([p for p in (xa, xb) if p.size]), 0.0, None).astype(np.float32)+    coords = np.vstack([p for p in (ca[ia], cb[ib]) if len(p)])+    coords = _jitter(coords, 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),+        alpha=alpha,+        gamma=gamma,+        t_draw=t_draw,+        n_from_a=int(ia.size),+        n_from_b=int(ib.size),+        **shift_stats,+    )+    return expr, coords.astype(np.float32), info+++def _apply_delta(block: np.ndarray, labels: np.ndarray, delta: dict, weight: float) -> np.ndarray:+    out = block.copy()+    for lab, d in delta.items():+        mask = labels == lab+        if mask.any():+            out[mask] = np.clip(block[mask] + np.float32(weight) * d, 0.0, None)+    return out.astype(np.float32)+++def _cos(u: np.ndarray, v: np.ndarray) -> float:+    du = float(np.linalg.norm(u))+    dv = float(np.linalg.norm(v))+    if du < 1e-12 or dv < 1e-12:+        return 0.0+    return float(np.dot(np.asarray(u, dtype=np.float64), np.asarray(v, dtype=np.float64)) / (du * dv))   def main() -> None:@@ -44,8 +151,8 @@ 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_type_shift(stage_a, stage_b, t, params, ALPHA, GAMMA)+    keep = {k: info.get(k) for k in ("t", "t_draw", "gamma", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped", "align", "alpha", "n_types_shifted", "delta_norm_min", "delta_norm_med", "delta_norm_max", "cos_ab_before", "cos_to_mid_after", "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)上把分层抽取比例从线性 t 改为时间扭曲 t_draw = t^1.75(GAMMA=1.75,环境变量可调),坐标/RMS 缩放/细胞数/表达逻辑逐位沿用;PLAN 要求的 T2EI-01 型均值表达位移已实现(T2EI_ALPHA 开关)但对照后判定有害,提交时关闭(ALPHA=0),即实际生效的只有组成扭曲。
各组分数的变化cell_state:变好(+17.12,37.49→54.61,远超噪声)
expression_change:噪声内(+0.41,T2 噪声约 1 分)
local_spatial:变好(+3.04,57.27→60.31)
shape_scale:变坏(-5.40,74.43→69.03,早端主导后点云尺度/形状偏离目标)
family_idother
假设是否成立否
经验
  1. 在 T2:embryo:val_interp 的 mix 上,对共有型做"型均值差 delta_c 线性平移"(把端点细胞推到两端型均值凸组合)方向有害:Engineer 的同程序 alpha 对照显示 alpha=0.5/1.0 榜分 52.80/48.43(alpha=0 为 56.42),cell_state 36.2→27.3→23.5,local_spatial 54.5→49.6→44.3;alpha=1 与 GAMMA=1.75 组合也只有 56.27,说明"先扭曲再位移"救不回来。
  2. 型均值位移能达成"余弦逼近中间型均值"(0.613→0.994、位移范数 13.6/21.8/26.1、43% 元素被改)却仍掉分:说明 cell_state 评的不只是型均值位置,还包括细胞间分布形状/离散度,把均值拉到凸组合会压缩真实中间阶段的分布结构。
  3. 只改混抽比例(t_draw=t^1.75,不动坐标与表达)就能把 cell_state 拉 +17 分、local_spatial +3 分,代价是 shape_scale -5.4;在 mix 框架下"改组成"比"改表达"性价比高得多。
  4. 幂扭曲的收益曲线在 proxy 上峰较宽(GAMMA 1.5/1.75/2.0/2.5 → 59.35/60.12/59.57/58.48,cell_state 单调升 48.4→55.6 但 shape 单调降 70→65),GAMMA=1.75 是总分折中点而非 cell_state 最优点;final 上实测 61.02 略高于 proxy 的 60.12,说明该点估计可迁移,但最优值仍随括号而变。
  5. Engineer 报告的数字与变化量表基本一致(proxy cell_state ~53 vs final 54.61、榜分 60.12 vs 61.02),且 alpha=0/GAMMA=1 逐位复现父节点,off-control 做得到位;但 PLAN 预期"cell_state 应上升 ≥2 分"被明确否证(实际降 13 分),提交物与 PLAN 声称的机制不是同一个。
mechanism_active否
下一步建议
  1. 针对 shape_scale:在 GAMMA=1.75 组成扭曲基础上把 target RMS 的插值参数与 t_draw 对齐(用 log_interp(rms_a, rms_b, t_draw, damp) 或对 damp 做 0.3–0.7 网格),预期在保住 cell_state +17 的同时收回 -5.4 的形状损失(当前 d2_shape 0.006→0.029)。
  2. 针对 cell_state/shape 的权衡:做 GAMMA × scale_damp 二维小网格(GAMMA∈{1.5,1.75,2.0} × damp∈{0.35,0.5,0.65}),各 3 seed 取均值,找总分而非单组最优;注意 final 括号 t=1/3 → t_draw=0.146,扭曲更极端,最优 GAMMA 可能比 proxy 的 1.75 偏小。
  3. 针对表达:放弃型均值平移,改为保留型内细胞间差异的低风险微调(如按 t_draw 对共有型做型内分位数/协方差向中间阶段靠拢,或对少量标记基因做温和缩放),并必须带 alpha=0 逐位相同的 off-control;同时在心脏插值榜上跑一次 GAMMA=1.75 验证组成扭曲的可迁移性。

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

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

分析员

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

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数29
工具调用共 45 次:bash 26、read 9、edit 6、write 4
用时13 分
token 数输入 72,832 · 输出 12,074 · 思考 11,942
任务(第一行)按计划修改程序:mix + 型均值表达插值:将端点细胞表达移向中间型均值
最后的回答(摘录)
完成。总结:

**做了什么**:在父节点 2(mix)之上,(1) 按 PLAN 实现了 T2EI-01 型均值表达位移并做了机制开/关对照——alpha=0 与父节点逐位相同(56.42),alpha=0.5/1.0 分别掉到 52.8/48.4,cell_state 反降 9–13 分,机制有害,提交时关闭(ALPHA=0);(2) 改为时间扭曲组成:抽取比例 `t_draw = t^1.75`(单调、只依赖时间差,视图无关),坐标/RMS/细胞数逻辑逐位沿用父节点。

**查分**(proxy A 半,用 11/20 次):GAMMA=1.75 得 **60.12**(cell_state 36→53、local_spatial 54→59、shape 75→68),seed 0/1/2 = 60.12/59.72/59.63,均值比父节点 +3.4;vec-check 通过,重跑逐位确定。

**下一步最值得试**:在扭曲组成基础上单独修 shape_scale(如按 t_draw 一致性微调 target RMS 或对 a 端细胞坐标做轻微径向重排),以及在心脏插值榜上验证 GAMMA 的可迁移性。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24-D/nodes/12/engineer.jsonl 209 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24-D/nodes/12/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时1 分
token 数输入 7,052 · 输出 992 · 思考 1,902
任务(第一行)为节点 n12(改进,父节点 n2)写改进计划 PLAN.json
最后的回答(摘录)
{
  "name": "mix + 型均值表达插值:将端点细胞表达移向中间型均值",
  "motivation": "父节点 2(mix)cell_state 仅 37.49,远低于 seed copy_last 的 49.29 和其他三组(59.72/57.27/74.43)。原因:mix 直接抽取端点真实细胞,其表达谱仍是端点状态而非中间状态。节点 3 尝试类似改法但 gen_failed(实现崩溃,非方案错误)。节点 7 在 copy_last 上证明型内表达位移可改善 expression_change +2.03、local_spatial +4.78,说明表达微调方向有效。本次在 mix 上做更简单的型均值平移,避免节点 3 的复杂轨迹实现。",
  "approach": "步骤:(1) 读取 stage_a、stage_b 及标签;(2) 对同时出现在两端的每个细胞型,计算型均值差 delta_c = mean(X_b[c]) - mean(X_a[c])(逐基因);(3) 对从 stage_a 抽出的型 c 细胞:X += t * delta_c;对从 stage_b 抽出的型 c 细胞:X -= (1-t) * delta_c;(4) 仅出现在单端的型不做位移(保持原表达);(5) 位移后裁剪负值为 0;(6) 坐标、细胞数、组成完全沿用 mix 原逻辑不变。关键参数:位移系数 alpha=1.0(完全按 t 比例移向中间型均值),搜索范围 [0.5, 1.0];若型内细胞数 < 10 则跳过该型不位移。单输入阶段退路:无括号时走 copy_last 原逻辑(只取最近输入,不位移)。vec-score 快筛:先跑 alpha=0(等价于父节点)确认基线分一致,再跑 alpha=1.0 看 cell_state 是否上升;若 cell_state 提升 < 2 分则尝试 alpha=0.5。",
  "expected_groups": ["cell_state", "expression_change"],
  "risks": "1) 型均值差噪声大(型内细胞少时均值不稳)→ 用最小细胞数阈值 10 过滤;2) 位移后方差结构被压缩导致表达过于均匀 → 只移均值不缩方差,保留细胞间差异;3) 与节点 3 同为表达插值方向,但节点 3 是 gen_failed(代码崩溃),本方案实现极简(仅均值加减),30 分钟内可完成;4) cell_state 评分可能不只看型均值还看分布形状 → 若提升有限则说明需要更高阶插值,但至少验证方向。Engineer 应在第一次查分时同时记录四组分,确认 cell_state 是否为主要增益来源。",
  "family_id": "T2EI-01",
  "mechanism": "对 mix 抽出的每个端点细胞,按其所属型在两端间的均值差方向平移表达,使表达谱从端点状态移向中间时间点的型均值,从而让细胞状态更接近目标时间点。",
  "vs_constant_shift": "常数位移对所有细胞施加同一向量;本方案按细胞型分别计算位移方向和大小(每型一个 delta),且方向由两端该型的真实均值差决定、幅度由插值比例 t 控制,不同型位移不同,不同细胞因所属型不同而获得不同位移。",
  "mechanism_evidence": "Engineer 应输出:(1) 有多少型被位移、各型位移向量的 L2 范数分布(应 > 0 且型间有差异);(2) 位移前后各型均值与目标中间型均值((1-t)*mean_a + t*mean_b)的余弦距离变化;(3) 四组分各自变化,尤其 cell_state 应显著上升。若所有型位移范数为 0 或 cell_state 无变化,说明机制未生效。",
  "mechanism_off_control": "设 alpha=0(或加 --no-shift 标志),跳过所有表达位移步骤,输出等价于父节点 2 的纯 mix 结果。预期:关闭后四组分与父节点 2 完全一致(差异 < 0.1),开启后 cell_state 应有 ≥ 2 分变化。",
  "sources": []
}
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24-D/nodes/12/researcher.jsonl 4 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24-D/nodes/12/researcher.stderr

审查员

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