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

总览 · ← 返回运行 20261001-114429-search-t1-g18-continue

节点 n8 终选程序?按该运行锁定的规则最终选出的程序;可能是候选节点,也可能由护栏回退到基线。在终选来历上

冻结父本类型配额,类内按增殖打分做成熟端加权无放回抽样(θ=0.5,E-S 算法),3-seed 均值 56.06→58.13。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261001-114429-search-t1-g18-continue
父节点n2
子节点n11
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 57.89(+1.9) · proxy 57.89(+1.9) · proxy2 57.89(+1.9) · 3 次复测均分 58.13
审查通过 1 越界读取:未发现问题。唯一的文件读取是 mature.py:29-48 从 manifest['prior'] 的相对路径拼 Path(view) 读 msigdb GMT,属视图内 prior;无绝对路径/..//mnt/downloads/打分器路径,无网络调用(grep 全源码无 urllib/requests/socket)。; 2 硬编码目标统计量:未发现问题。类型权重 heart=1.6/edge=0.25 是规则型家族权重且由框架函数 src.task1_temporal.reweight.type_weights 按运行时出现的类型名套用(mature.py:92-101…
用时?从运行开始到结束(或到现在)的挂钟时间。36 分
程序版本8936c91c4967e891bc34976a82eda62c7227af9b (programs.git)
导入自20261001-032558-search-t1-spark-c3#8
备注re-scored at launch (origin 20261001-032558-search-t1-spark-c3 node 8, score there 57.89)

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

来自 programs.git 8936c91c49:solution/METHOD.md

冻结父本类型配额,类内按增殖打分做成熟端加权无放回抽样(θ=0.5,E-S 算法),3-seed 均值 56.06→58.13。

方法

  • 类型配额与父节点 2(heart_jcf_peri)逐位一致:复用 src.task1_temporal.reweight 的 type_weights(心脏×1.6、边缘×0.25、丢 Neural Tube)+ largest_remainder,N=4000。
  • 新自由度:类内选谁。每细胞成熟分 m_i = −z_c(cycle_i):
    • cycle_i = 面板基因全细胞 z 分数后取 HALLMARK_E2F_TARGETS(199 基因,prior/msigdb GMT 现场读取)集内均值;
    • 在每个类型内部再 z 化;凋亡项(HALLMARK_APOPTOSIS,161 基因)实测降分,λ=0 出货。
  • 类内 Efraimidis–Spirakis 加权无放回抽样:v_i = exp(clip(θ·m_i, ±log4)),key_i = log(u_i)/v_i,每类取 top n_c。 单一 default_rng(seed),u_i 按原始行号一次性生成(θ 间配对比较)。θ=0 且 λ=0 时走父本 heart_reweight 原路径(逐位复现 55.97)。
  • 表达矩阵不做任何修改,输出 100% 真实细胞。

关键参数

θ=0.5(出货),λ_apopt=0,N=4000,clip=±log4。

查分结果(proxy,T1:val)

配置seed 0seed 1seed 2均值
父本 A0(θ=0)55.9756.3255.9056.06
θ=+0.2557.40---
θ=+0.557.8958.3458.1658.13
θ=+0.7557.62---
θ=−0.2552.14---
θ=+0.5, λ=0.557.13---

θ=+0.5 分组(seed 0):de_recovery 52.53 / direction 60.75 / cell_state 61.44 / covariation 55.67。 相对 A0:cell_state +4.9、direction +2.2、covariation +1.0、de_recovery −0.5(3-seed 均值口径), 出货门槛(均值 ≥ +2.0 且无组跌 >3.0)满足。

验证过的

  • A0 逐位复现 55.97(锚点);ship 配置对 refactor 前后逐位一致;vec-check 通过;运行 ~6 s、内存与父本同量级。
  • 符号方向确定:负 θ 大幅降分,正 θ 在 0.25–0.75 区间稳定优于父本,峰值 ≈0.5。
  • 深度诊断:corr(cycle, log10 depth)=0.366 < 0.5,未做深度残差化;θ=0.5 输出深度均值仅 −1.6%。
  • 方差守卫:随机 3000 基因上,θ=0.5 vs A0 的全基因方差比 1.045,无类内塌缩。
  • 单输入阶段(proxy)与两输入(final)走完全相同代码路径(只读 inputs_by_time[-1]),θ 可直接迁移。

没验证的

  • final 视图(E8.5+E9.5,目标 E10.5)上的实际分数;E9.5 类型集更大(21 型),θ=0.5 的幅度是否仍最优未测。
  • θ 在 0.5–0.75 之间的细调(有意不做,防 proxy 过拟合)。
  • prior GMT 缺失时的退化路径(代码上回退为类内均匀抽样=父本语义,未在真实缺失场景跑过;final 视图 prior 应存在)。

下一步建议

在 final 两阶段视图上,可用 E8.5→E9.5 的每类型伪批量差值替代/叠加增殖打分作为 m_i(proxy 无法验证此扩展);θ 细网格 {0.4,0.5,0.6} × 3 seed。

调研员的计划

名称冻结父本类型权重,改用类内成熟端配额重采样(θ 粗网格 + 3 seed)
动机父节点 2(55.97)四组里 de_recovery 53.06 最弱、covariation 54.97 次弱,而它完全不改表达,只在类型层重加权后抽 4000 个真实细胞。对照节点 1/3(copy_last:de_recovery 恰好 50.00、direction 50.16、cell_state 48.07)可见父本的全部增益都来自『类型组成』这一个自由度(de_recovery +3.06、direction +8.40、cell_state +8.83、covariation +3.43),而『同一类型内部抽哪些细胞』这个自由度从未被动过——父本在类内是均匀抽样。E8.5→E9.5 的真实变化除了组成还有各谱系内部的成熟推进,只靠组成抬不动 de_recovery。节点 4 已证明在类型层再乘一个数据导出因子是死路(γ=±0.25/0.35/1.0 全部降分,N=5118 也降分,只有 γ=0 持平),说明父本手调权重已近局部最优,继续在 w_c 上做文章没有空间;节点 5 则证明 largest-remainder 配额 + 保底 10 + 类内无放回抽样这套采样部件本身有效(相对 copy_last:cell_state +5.54、direction +7.21)。所以本节点把数据导出的信号(prior/ 增殖基因集打分)从类型层挪到类内细胞层,用『只改选谁、不改表达』的方式产生真实的类内位移:输出仍是 100% 真实细胞,不会被位移类方法的均值塌缩伤到 covariation,且类型配额逐位不动,cell_state 56.90 受保护。
做法总目标:在类型配额与父本逐位一致的前提下,开一个新自由度——类内成熟端优先抽样,用 θ 一个标量控制强度,θ=0 精确退化。全程只读 inputs_by_time(manifest)[-1]。

步骤 0(必须,≤5 min,查分 1 次):先读 src/task1_temporal/reweight.py,搞清 heart_reweight 怎么把类型权重变成抽样(有放回还是无放回、输出有无重复行)、类型权重是否以可复用函数/字典暴露。原样跑父本 run.py --seed 0,必须逐位复现 55.97,记为 A0(唯一锚点与最终退路)。若权重表没有暴露,就 import 它的内部映射来复用,绝不重新手写任何类型名或阶段名。

步骤 1(≤10 min,不查分):新增 solution/mature.py,两块:
(a) 每细胞成熟打分 m_i:从视图 prior/ 的 gmt 按集名正则取增殖基因集(节点 5 用的 199 个)与凋亡基因集(161 个);对面板基因做全细胞 z 分数后取集内均值得 cycle_i、apopt_i;再在每个类型内部 z 化,初版 m_i = −z_c(cycle_i)(成熟=低周期),λ_apopt=0。零成本诊断:先打印 corr(m_i, log10(每细胞总计数)),若 |corr|>0.5,把 m_i 对 log 深度做线性残差化后再用,防止选到低深度细胞。
(b) 配额 + 类内无放回加权抽样:类型权重与父本逐位一致 → n_c = largest_remainder(N·w_c·p_c),N=4000,保底 10(复用节点 5 已验证部件);类内权重 v_i = exp(clip(θ·m_i, −log4, +log4));用 Efraimidis–Spirakis 无放回加权抽样:key_i = log(u_i)/v_i,每类取 key 最大的 n_c 个。关键实现细节:全程只用一个 np.random.default_rng(args.seed),u_i 按原始行号顺序一次性生成,所有 θ 共享同一批 u_i,使 θ=0 与 θ≠0 成为配对比较,把抽样噪声从组间差里减掉。θ=0 时 v_i≡1,退化为均匀无放回分层抽样,记为 A1。

步骤 2(查分 1 次):先比 A0 vs A1,把『去重复的精确配额』本身的效应分离出来。若 A1 ≥ A0 − 2,以 A1 为新基座;若 A1 比 A0 低 >2 分,放弃自写抽样器,改为在 heart_reweight 的每细胞权重上乘 v_i(保持父本抽样语义不动),A1 分支记为负结果。

步骤 3(查分 4 次):θ 粗网格 {+0.5, +0.25, −0.25, −0.5},seed 0,只用 0.25 步长,不细调(避免过拟合 proxy)。符号不确定…
风险1) θ 无信号或符号错(最大风险)。与节点 4 的区别要说清:节点 4 动的是类型间权重,既受 k020 的取材范围变化污染,又与父本手调权重双计数;本方案类型配额逐位不动,只用增殖打分给同一类型内部的细胞排序,取材偏倚对类内比较不构成混淆;而且只改『选谁』不改表达,不存在节点 4 删掉的那个『分化轴位移』分支特有的离流形/均值塌缩风险。若 4 个 θ 全落在 ±2 分内,就按干净负结果处理,退回 A0 并短路死代码。发现点:步骤 3 的 4 次查分(约第 15–20 分钟)。
2) A1(去重复的精确配额)本身可能降分:父本有放回抽样产生的重复行也许恰好锐化了心脏类型的分布。发现点在第 2 次查分;退路是改在 heart_reweight 的每细胞权重上乘 v_i。
3) 增殖打分被技术因素(测序深度/dropout)主导而非生物成熟度 → 会把低质量细胞选进去,同时伤 covariation 与 cell_state。尽早发现:步骤 1 的相关性诊断(零查分成本),|corr|>0.5 必须做深度残差化后再用。
4) θ 过大致类内多样性塌缩(只剩极端细胞):clip |θ·m| ≤ log4 把富集上限锁在 4×,只做粗网格;出货前对比输出与 A0 的每类型方差,任一类型方差掉 >30% 就降 θ 或放弃。
5) 单一标量 θ 过拟合 proxy(T1 噪声 ~2 分):只做 0.25 步长粗网格 + ≥3 seed 均值 + 『榜分 ≥+2.0 且无组跌 >3.0』的出货门槛;配对 u_i 设计进一步压低比较方差。
6) prior/ gmt 不可读或基因名对不上面板:节点 5 已证明可读,风险低;若真失败,整个机制放弃、直接出 A0,绝不临时改用硬编码基因名(违规)。
7) 30 分钟不够:砍项顺序已写死(先砍可选凋亡项 → 再砍多 seed → 最后只留 A0/A1 对比),任何情况下 A0 都已在前 5 分钟拿到,不会空手而归。
8) 合规:不新增任何类型名、阶段名或保留阶段统计量;类型权重一律复用父本模块;m_i 只由 prior/ 基因集与输入阶段表达算出;不针对打分器漏洞(不做坐标旋转、不缩放、不利用行序)。
9) 若最终出货的是 A1 而不是 θ≠0,收益可能只有 1–2 分即落在噪声内:此时必须在 METHOD.md 里标注『需 3 seed 复核、证据强度弱』,避免下游节点把它当作已验证部件继续叠加。

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

对比:父节点版本 39e48cc98a。改动的文件:solution/METHOD.md +49 −0、solution/README.md +4 −3、solution/mature.py +148 −0、solution/run.py +26 −6

diff --git a/solution/METHOD.md b/solution/METHOD.mdnew file mode 100644index 0000000..299dc91--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,49 @@+冻结父本类型配额,类内按增殖打分做成熟端加权无放回抽样(θ=0.5,E-S 算法),3-seed 均值 56.06→58.13。++## 方法++- 类型配额与父节点 2(heart_jcf_peri)逐位一致:复用 `src.task1_temporal.reweight` 的+  `type_weights`(心脏×1.6、边缘×0.25、丢 Neural Tube)+ `largest_remainder`,N=4000。+- 新自由度:**类内选谁**。每细胞成熟分 `m_i = −z_c(cycle_i)`:+  - `cycle_i` = 面板基因全细胞 z 分数后取 `HALLMARK_E2F_TARGETS`(199 基因,prior/msigdb GMT 现场读取)集内均值;+  - 在每个类型内部再 z 化;凋亡项(HALLMARK_APOPTOSIS,161 基因)实测降分,λ=0 出货。+- 类内 Efraimidis–Spirakis 加权无放回抽样:`v_i = exp(clip(θ·m_i, ±log4))`,`key_i = log(u_i)/v_i`,每类取 top n_c。+  单一 `default_rng(seed)`,u_i 按原始行号一次性生成(θ 间配对比较)。θ=0 且 λ=0 时走父本 `heart_reweight` 原路径(逐位复现 55.97)。+- 表达矩阵不做任何修改,输出 100% 真实细胞。++## 关键参数++θ=0.5(出货),λ_apopt=0,N=4000,clip=±log4。++## 查分结果(proxy,T1:val)++| 配置 | seed 0 | seed 1 | seed 2 | 均值 |+|---|---|---|---|---|+| 父本 A0(θ=0) | 55.97 | 56.32 | 55.90 | **56.06** |+| θ=+0.25 | 57.40 | - | - | - |+| θ=+0.5 | 57.89 | 58.34 | 58.16 | **58.13** |+| θ=+0.75 | 57.62 | - | - | - |+| θ=−0.25 | 52.14 | - | - | - |+| θ=+0.5, λ=0.5 | 57.13 | - | - | - |++θ=+0.5 分组(seed 0):de_recovery 52.53 / direction 60.75 / cell_state 61.44 / covariation 55.67。+相对 A0:cell_state +4.9、direction +2.2、covariation +1.0、de_recovery −0.5(3-seed 均值口径),+出货门槛(均值 ≥ +2.0 且无组跌 >3.0)满足。++## 验证过的++- A0 逐位复现 55.97(锚点);ship 配置对 refactor 前后逐位一致;vec-check 通过;运行 ~6 s、内存与父本同量级。+- 符号方向确定:负 θ 大幅降分,正 θ 在 0.25–0.75 区间稳定优于父本,峰值 ≈0.5。+- 深度诊断:corr(cycle, log10 depth)=0.366 < 0.5,未做深度残差化;θ=0.5 输出深度均值仅 −1.6%。+- 方差守卫:随机 3000 基因上,θ=0.5 vs A0 的全基因方差比 1.045,无类内塌缩。+- 单输入阶段(proxy)与两输入(final)走完全相同代码路径(只读 `inputs_by_time[-1]`),θ 可直接迁移。++## 没验证的++- final 视图(E8.5+E9.5,目标 E10.5)上的实际分数;E9.5 类型集更大(21 型),θ=0.5 的幅度是否仍最优未测。+- θ 在 0.5–0.75 之间的细调(有意不做,防 proxy 过拟合)。+- prior GMT 缺失时的退化路径(代码上回退为类内均匀抽样=父本语义,未在真实缺失场景跑过;final 视图 prior 应存在)。++## 下一步建议++在 final 两阶段视图上,可用 E8.5→E9.5 的每类型伪批量差值替代/叠加增殖打分作为 m_i(proxy 无法验证此扩展);θ 细网格 {0.4,0.5,0.6} × 3 seed。diff --git a/solution/README.md b/solution/README.mdindex e66c7c3..92fd13c 100644--- a/solution/README.md+++ b/solution/README.md@@ -1,4 +1,5 @@-# heart_jcf_peri+# heart_jcf_peri + 类内成熟端抽样(node 8) -run2(20260927-172643-grok-t1)的 T1 胜者:对最新输入阶段按细胞类型重加权再抽 4000 个真实细胞,不改表达。丢 Neural Tube;心脏类(CM、内皮/心内膜、SHF/PHM、JCF、心包、心外膜原基)×1.6;表面外胚层、EXEM、轴旁中胚层 ×0.25;其余 ×1。-proxy 预期 55.97(seed 0,与 run2 的预测逐位相同)。final 读 E9.5,类型集合已含 E9.5 的名字(V-CM、Endocardium、BEC、aPHM、pPHM、Proepicardium)。+父本类型配额(心脏×1.6 / 边缘×0.25 / 丢 Neural Tube,largest_remainder,4000 细胞)逐位不动;+类内用 prior/msigdb `HALLMARK_E2F_TARGETS` 增殖打分(每类型内 z 化取负)做 Efraimidis–Spirakis+加权无放回抽样,θ=0.5。表达不修改。proxy 3-seed 均值 58.13(父本 56.06)。diff --git a/solution/mature.py b/solution/mature.pynew file mode 100644index 0000000..a1ab620--- /dev/null+++ b/solution/mature.py@@ -0,0 +1,148 @@+"""Within-type mature-end weighted resampling.++Keeps the parent's type quotas bit-for-bit (largest_remainder on+counts * type_weights from src.task1_temporal.reweight), but inside each type+selects cells by a proliferation-derived maturity score m_i = -z_c(cycle_i)+(- lam * z_c(apopt_i)), using Efraimidis-Spirakis weighted sampling without+replacement: key_i = log(u_i) / v_i, v_i = exp(clip(theta * m_i, +-log4)).++Scores come only from the view's prior/ GMT gene sets (HALLMARK_E2F_TARGETS,+HALLMARK_APOPTOSIS) and the input stage expression. theta = 0 reduces to+uniform within-type sampling.+"""++from __future__ import annotations++import sys+from pathlib import Path++import numpy as np+from scipy import sparse++from src.task1_temporal.reweight import DROP_TYPES, largest_remainder, type_weights++CLIP = np.log(4.0)+PROLIF_SET = "HALLMARK_E2F_TARGETS"+APOPT_SET = "HALLMARK_APOPTOSIS"+++def _read_gmt(path: Path) -> dict[str, list[str]]:+    out = {}+    with path.open() as fh:+        for line in fh:+            parts = line.rstrip("\n").split("\t")+            if len(parts) >= 3:+                out[parts[0]] = parts[2:]+    return out+++def _gmt_path(view, manifest: dict) -> Path | None:+    for entry in manifest.get("prior", []):+        p = Path(view) / entry["path"]+        if p.is_dir():+            cand = p / "hallmark_mouse.gmt"+            if cand.exists():+                return cand+        elif p.suffix == ".gmt" and p.name.startswith("hallmark"):+            return p+    return None+++def set_scores(X, genes: list[str], view, manifest: dict, lam_apopt: float,+               verbose: bool = True):+    """Per-cell z-scored set means for proliferation and apoptosis.++    Returns (None, None) when the prior GMT is unavailable -> caller must fall+    back to uniform within-type sampling.+    """+    gmt_file = _gmt_path(view, manifest)+    if gmt_file is None:+        return None, None+    gmt = _read_gmt(gmt_file)+    if PROLIF_SET not in gmt:+        return None, None+    gene_idx = {g: i for i, g in enumerate(genes)}+    sets = {}+    for name, key in ((PROLIF_SET, "cycle"), (APOPT_SET, "apopt")):+        if key == "apopt" and (lam_apopt == 0.0 or name not in gmt):+            sets[key] = np.zeros(0, dtype=int)+            continue+        idx = [gene_idx[g] for g in gmt[name] if g in gene_idx]+        sets[key] = np.asarray(idx, dtype=int)+        if verbose:+            print(f"[mature] {name}: {len(idx)}/{len(gmt[name])} genes on panel",+                  file=sys.stderr)++    sub = X[:, np.concatenate([sets["cycle"], sets["apopt"]])].toarray().astype(np.float64)+    mu = sub.mean(axis=0)+    sd = sub.std(axis=0)+    sd[sd < 1e-12] = 1.0+    z = (sub - mu) / sd+    nc = len(sets["cycle"])+    cycle = z[:, :nc].mean(axis=1)+    apopt = z[:, nc:].mean(axis=1) if sets["apopt"].size else np.zeros(X.shape[0])++    if verbose:+        depth = np.log10(np.maximum(np.asarray(X.sum(axis=1)).ravel(), 1e-9))+        c = np.corrcoef(cycle, depth)[0, 1]+        print(f"[mature] corr(cycle, log10 depth) = {c:.3f}", file=sys.stderr)+    return cycle, apopt+++def mature_reweight_full(X, labels: np.ndarray, genes: list[str], view,+                         manifest: dict, n_cells: int, seed: int, theta: float,+                         lam_apopt: float = 0.0, heart_weight: float = 1.6,+                         edge_weight: float = 0.25, verbose: bool = True):+    cycle, apopt = set_scores(X, genes, view, manifest, lam_apopt, verbose)++    types = [str(t) for t in np.unique(labels) if str(t) not in DROP_TYPES]+    counts = np.array([(labels == t).sum() for t in types], dtype=np.float64)+    alloc = largest_remainder(counts * type_weights(types, heart_weight, edge_weight),+                              n_cells)++    # maturity score, z-normalised within each type+    m = np.zeros(X.shape[0], dtype=np.float64)+    pools = {}+    for t in types:+        idx = np.flatnonzero(labels == t)+        pools[t] = idx+        if cycle is None:+            continue+        for s, w in ((cycle, -1.0), (apopt, -lam_apopt)):+            if w == 0.0:+                continue+            sc = s[idx]+            sd = sc.std()+            if sd < 1e-12:+                continue+            m[idx] += w * (sc - sc.mean()) / sd++    # paired uniforms: one draw per input cell, shared across all theta+    rng = np.random.default_rng(seed)+    u = rng.uniform(size=X.shape[0])+    u = np.clip(u, 1e-300, 1.0 - 1e-15)++    if verbose and theta != 0.0:+        print(f"[mature] theta={theta} lam={lam_apopt}", file=sys.stderr)++    blocks = []+    for t, n in zip(types, alloc):+        n = int(n)+        if n <= 0:+            continue+        pool = pools[t]+        if n >= pool.size:+            choice = rng.choice(pool, size=n, replace=True)+            blocks.append(X[choice])+            continue+        if theta == 0.0:+            v = np.ones(pool.size)+        else:+            v = np.exp(np.clip(theta * m[pool], -CLIP, CLIP))+        key = np.log(u[pool]) / v+        pick = pool[np.argsort(-key)[:n]]+        blocks.append(X[np.sort(pick)])++    out = sparse.vstack(blocks, format="csr").astype(np.float32)+    out.eliminate_zeros()+    return outdiff --git a/solution/run.py b/solution/run.pyindex a752b21..83ba1b5 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,10 +1,14 @@ #!/usr/bin/env python3-"""heart_jcf_peri: run2's T1 winner. Reweight the latest input stage by cell type.+"""heart_jcf_peri quotas + within-type mature-end resampling (node 8). -Neural Tube dropped; heart types (CM, endothelium/endocardium, SHF/PHM, JCF,-pericardium, proepicardium) x1.6; surface ectoderm, EXEM, paraxial mesoderm-x0.25; everything else x1. 4000 real cells, no expression shift. Proxy reads-E8.5, final reads E9.5; the type set already names both stages' labels.+Type quotas are bit-for-bit the parent's (heart x1.6, edge x0.25, drop Neural+Tube, largest_remainder). Inside each type, cells are drawn by+Efraimidis-Spirakis weighted sampling without replacement with weights+v_i = exp(clip(theta * m_i, +-log4)), where m_i = -z_c(E2F-proliferation score)+(- lam * z_c(apoptosis score)) is z-normalised within the type. Gene sets come+from the view's prior/msigdb hallmark GMT; no expression is modified.+theta = 0 (and lam = 0) falls back to the parent's heart_reweight exactly.+Same code path for 1-input (proxy) and 2-input (final) views. """  from __future__ import annotations@@ -23,6 +27,8 @@ from src.task1_temporal.view_io import ( )  N_CELLS = 4000+SHIP_THETA = 0.5+SHIP_LAM = 0.0   def main() -> None:@@ -30,13 +36,27 @@ def main() -> None:     parser.add_argument("--data", required=True)     parser.add_argument("--out", required=True)     parser.add_argument("--seed", type=int, default=0)+    parser.add_argument("--theta", type=float, default=SHIP_THETA)+    parser.add_argument("--lam", type=float, default=SHIP_LAM)     args = parser.parse_args()      manifest = load_manifest(args.data)     genes = panel_genes(args.data, manifest)     last = read_stage(args.data, inputs_by_time(manifest)[-1], genes)     n = target_n_cells(manifest, N_CELLS)-    X = heart_reweight(last.X, labels_of(last), n_cells=n, seed=args.seed)+    labels = labels_of(last)+    if args.theta == 0.0 and args.lam == 0.0:+        X = heart_reweight(last.X, labels, n_cells=n, seed=args.seed)+    else:+        import os+        import sys++        sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))+        from mature import mature_reweight_full++        X = mature_reweight_full(last.X, labels, genes, args.data, manifest,+                                 n_cells=n, seed=args.seed, theta=args.theta,+                                 lam_apopt=args.lam)     write_prediction(X, genes, args.out, seed=args.seed)  

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

用到的知识库条目

编号标题出处
k014Scorer noise and invariance on our proxy boardsnotes/pitfalls/04_scorer_invariance.md
k020Correcting sampling-scope (dissection) bias in compositionnotes/guides/modeling_and_evaluation_guide.html
k007Interval staging and held-out-window filtering of external datanotes/来件/virtualembryo.ai/rules.md

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

改了什么冻结父本(node 2, heart_jcf_peri)的类型配额,新增 solution/mature.py:用 prior/msigdb HALLMARK_E2F_TARGETS 增殖打分(类内 z 化取负,m_i=-z_c(cycle))做 Efraimidis-Spirakis 加权无放回类内抽样,出货 θ=0.5、λ_apopt=0;θ=0 时逐位退化回父本 heart_reweight。表达矩阵不修改。
各组分数的变化cell_state:明确变好:+4.54(56.90→61.44),超过 T1 噪声 ~2,是本节点最强信号
covariation:噪声内:+0.70(54.97→55.67),未受损(守卫达成)
de_recovery:噪声内:-0.53(53.06→52.53),是唯一略降的组但远小于 T1 噪声 ~2
direction:边缘变好:+2.19(58.56→60.75),刚好在噪声 ~2 的边界上,单 seed 不足以定论
假设是否成立是
经验
  1. 在类型配额逐位冻结的前提下,只改『类内选谁』这一自由度即可提升榜分:E2F 增殖打分反向加权(选成熟端)θ=+0.5 使 cell_state +4.54(超噪声)、榜分 +1.92(单 seed 在噪声边缘),且 covariation 不受伤——证明『选真实细胞的子集』类方法不会触发位移类方法的均值塌缩。
  2. θ 符号明确且非对称:θ=-0.25→52.14(大幅降),+0.25→57.40、+0.5→57.89、+0.75→57.62(seed 0),说明『选低增殖(成熟端)细胞』方向正确,峰值约 0.5,网格粗调 4 次查分即可定符号和量级。
  3. 加凋亡项是负结果:λ_apopt=0.5 使 seed 0 从 57.89 降到 57.13,成熟度打分只用增殖(E2F)即可,别叠加凋亡基因集。
  4. 配对 u_i 设计(单一 default_rng,按原始行号一次性生成 uniform,所有 θ 共享)使 θ 间比较成为配对比较,有效压低抽样噪声——本次 A0 逐位复现 55.97 也验证了退化路径正确。
  5. 零查分成本的诊断值得保留:corr(cycle, log10 depth)=0.366<0.5 免除了深度残差化;方差比 1.045 排除了类内多样性塌缩。
  6. 榜分单 seed +1.92 在噪声(~2)内,Engineer 的出货依据是 3-seed 均值 +2.07(58.13 vs 56.06),刚过其自设的 +2.0 门槛——证据强度是『弱过线』而非稳健,下游不应把幅度继续往大调而不复核。
下一步建议
  1. 针对 de_recovery(唯一受损组,52.53):试只对非心脏类型施加 θ(心脏类保持均匀抽样),或对 DE 高变基因加权后再算 cycle 打分,3 seed 复核,验证能否在不丢 cell_state 增益的前提下收回 de_recovery。
  2. 针对全局:θ 细网格 {0.4, 0.5, 0.6} × 3 seed,但只有当 3-seed 均值差 >2 才换 θ,否则维持 0.5(防 proxy 过拟合)。
  3. 针对 final 迁移:proxy 与 final 走同一代码路径(只读 inputs_by_time[-1]),θ=0.5 可直接迁移;若 final 有 ≥2 输入阶段,可用 E8.5→E9.5 每类型伪批量差值叠加/替代增殖打分作 m_i,但这是未验证扩展,必须先 proxy 侧小查分再上。

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

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

分析员

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

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数45
工具调用共 49 次:—
用时27 分
token 数输入 59,171 · 输出 14,288 · 思考 6,504
任务(第一行)按计划修改程序:冻结父本类型权重,改用类内成熟端配额重采样(θ 粗网格 + 3 seed)
最后的回答(摘录)
做了什么:冻结父本(heart_jcf_peri)类型配额,新增类内成熟端加权抽样——用 prior/msigdb E2F 增殖打分(类内 z 化取负)做 Efraimidis–Spirakis 无放回抽样,θ=0 时逐位退化回父本。

查分结果(proxy,共耗 9 次查询):
- 父本 A0 3-seed 均值 56.06(55.97/56.32/55.90,seed 0 逐位复现)
- θ=+0.5:57.89/58.34/58.16,均值 **58.13**(+2.07,出货);cell_state +4.9、direction +2.2、covariation +1.0、de_recovery −0.5
- θ=+0.25→57.40,+0.75→57.62,−0.25→52.14(符号明确);凋亡项 λ=0.5→57.13(负结果,弃用)
- 守卫通过:深度 corr 0.366、方差比 1.045、运行 1.9s、vec-check ok

下一步最值得试:final 视图上用 E8.5→E9.5 每类型伪批量差值叠加/替代增殖打分作 m_i;θ 细网格 {0.4,0.5,0.6}×3 seed;de_recovery 是唯一受损组,可试仅对非心脏类型施加 θ 或对 DE 基因加权打分。
原始记录位置/home/spark-longxinyang/vec/g18_wt/agent/runs/20261001-114429-search-t1-g18-continue/nodes/8/engineer.jsonl (文件不在)

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数6
工具调用共 9 次:—
用时7 分
token 数输入 33,676 · 输出 3,226 · 思考 13,888
任务(第一行)为节点 n8(改进,父节点 n2)写改进计划 PLAN.json
最后的回答(摘录)
PLAN.json written
原始记录位置/home/spark-longxinyang/vec/g18_wt/agent/runs/20261001-114429-search-t1-g18-continue/nodes/8/researcher.jsonl (文件不在)

审查员

角色审查员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数8
工具调用共 12 次:—
用时1 分
token 数输入 19,192 · 输出 1,588 · 思考 2,202
任务(第一行)审查节点 n8 的程序是否越界读取、写死目标、钻评分器漏洞
最后的回答(摘录)
REVIEW.json written
原始记录位置/home/spark-longxinyang/vec/g18_wt/agent/runs/20261001-114429-search-t1-g18-continue/nodes/8/reviewer.jsonl (文件不在)