总览 · ← 返回运行 20261003-171955-search-t2-embryo-interp-chain-12h
节点 n10
T2EI-01:类型组成 logit 插值 + 类型内残差保持的强度有界伪批量表达位移(s=5),坐标 procrustes3d 对齐后按阻尼 log-RMS 缩放,细胞按目标组成分层抽取,表达/坐标配对原样保留。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-171955-search-t2-embryo-interp-chain-12h |
|---|---|
| 父节点 | (种子,没有父节点) |
| 子节点 | n12 |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 草稿 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 61.62 · proxy 61.62 · 3 次复测均分 61.30 |
| 审查 | 未审查 |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 22 分 |
| 程序版本 | 8d7ac0cf1e2b719e843ac8560cf3f390df75cefb (programs.git) |
| 导入自 | 20261003-094242-search-t2-embryo-interp-g24-D-s2#10 |
| 备注 | re-scored at launch (origin 20261003-094242-search-t2-embryo-interp-g24-D-s2 node 10, score there 61.62) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 8d7ac0cf1e:solution/METHOD.md
T2EI-01:类型组成 logit 插值 + 类型内残差保持的强度有界伪批量表达位移(s=5),坐标 procrustes3d 对齐后按阻尼 log-RMS 缩放,细胞按目标组成分层抽取,表达/坐标配对原样保留。
方法(family_id: T2EI-01,按 PLAN 实现)
- 视图无关地从
manifest["inputs"]按时间排序取目标的括号阶段 (a, b),t=(target−a)/(b−a),只用时间差,不看绝对时间/视图字段。无括号(单输入或外推)时退路 = 锚阶段细胞按类型分层抽到 [min_cells, max_cells] 原样输出(copy_last 式)。 - 组成机制(T2EI_COMPOSITION,默认开):共有类型 q=expit((1−t)·logit(p_a)+t·logit(p_b)),logit 前 p clip 到 [0.005,0.995];仅一端有的类型按该端权重保留((1−t)p_a 或 t·p_b);归一化后按 q 分配 n 个细胞,共有类型内部按 (1−t,t) 分到两端,无放回抽取。n = log 线性插值(n_a,n_b,t) 夹到榜的 [min,max](proxy 上 = 5000)。
- 表达机制(T2EI_STRENGTH,默认 s=5.0):共有类型 Δ=μ_b−μ_a(全阶段伪批量均值),只保留 |Δ|≥0.25(T2EI_DELTA_MIN)的基因;a 侧细胞 x+=s·t·Δ、b 侧 x−=s·(1−t)·Δ,只作用于 x>0 项、结果 clip≥0。型内残差 (x−μ) 在正项上原样保留(加的是型级常向量)。
- 坐标:procrustes3d 对齐(共有类型质心 Kabsch,z 符号随旋转),两朵云缩到 target RMS = exp(log rms_a + 0.5·t·Δlog rms)(T2EI_SCALE_DAMP=0.5);抽样细胞的坐标原样携带(不插值坐标点),重复坐标加 1e-4·RMS 抖动,最后整体恢复到 target RMS。表达与位置的配对因此保持真实。
- 确定性:
np.random.default_rng(seed),无全局随机状态;纯 CPU(EXECUTION.json gpu=false),proxy 视图全程 <10 s。
机制生效的证据(proxy,E6.75+E8.0→E7.25,t=0.4,stderr 打印)
- 组成:输出 q 与线性 (1−t)p_a+t·p_b 明显不同(Unknown −0.034、EXE-Endoderm +0.013、Caudal Epiblast −0.008 等);两侧抽样数 2739/2261,偏离 mix 的 3000/2000。
- 表达:11 个共有类型全部位移,|Δ|₁ 137–254;a 侧权重 s·t=2、b 侧 s·(1−t)=3,伪批量移到并越过型中点(s>1 部分被 x>0/clip≥0 截断)。
- 残差保持:位移是型级常向量,正项残差不变(结构性保证,未逐型打印相关系数)。
- 四组分(A 半,seed 0):对照→开启 = cell_state 36.54→47.37、expression_change 59.8→62.08、shape_scale 74.91→76.42、local_spatial 54.38→57.99。
关闭机制对照(同一程序,T2EI_COMPOSITION=0 T2EI_STRENGTH=0)
- 输出退回 mix 式 (1−t,t) 分层混抽、表达不动:总分 56.40(cell_state 36.54),复现 mix 种子画像(~57、cell_state ~37)。
- 开启(默认):总分 60.97;seed 1 复核 60.71。两机制分解:只开组成 55.19(组成机制单独反而略降,主要伤 mmd_u/邻域),只开表达 s=5 60.62;合开 60.97 ≈ 加性。
验证过 / 没验证
- 验证(proxy A 半,共 9 次查分):s∈{0,1,3,5,6,8} 扫描,峰值平台 s=5–6(s=1 55.99→s=5 60.97→s=8 60.06);Δ_min 0.25 vs 0.1 无差(60.97 两者);seed 0/1 差 0.26(噪声内);vec-check 通过;默认输出与显式参数输出逐字节一致(确定性)。
- 没验证:B 半与正式分;多输入阶段(final 视图 3 输入)实际运行——代码按括号选取应成立但未跑过该视图;无括号的 copy_last 退路未在真实外推榜上跑过;s>8、λ 型逐细胞加权(节点 8 的机制,本 draft 未混入)。
参数与知识来源
- 关键默认:align=procrustes3d、scale_damp=0.5(方法卡胚插值推荐值)、s=5.0、Δ_min=0.25、组成 logit clip 0.005。环境变量 T2EI_{COMPOSITION,STRENGTH,SCALE_DAMP,DELTA_MIN} 可覆盖(提交时默认=开启)。
- 生物学知识来源:仅方法卡/实验表内的既有事实(z 为离散切片轴、procrustes3d 在胚插值代理上形状最好、mix 的邻域稳定 52–55、|Δ|≥0.25 阈值沿用节点 5);未使用任何保留阶段/基因型信息、外部文献数据。s=5 过冲优于 s=1 中点是纯经验结果(与节点 5/8 的 α=5 一致),与 PLAN 默认 s=1 不同,已按扫描数据改为 5。
调研员的计划
| 名称 | 组成 logit 插值 + 类型内残差保持表达插值(T2EI-01) |
|---|---|
| 动机 | mix 种子(节点 2)总分 57.23 但 cell_state 仅 37.49,低于地板(~50):mmd_u raw 0.01657(skill 0.521)、variogram raw 0.02952(skill 0.228)都很差——把两端真实细胞按 (1−t,t) 混抽产生双峰分布,不像中间阶段。节点 5 用类型级常数收敛位移把 cell_state 提到 49.28,但它保留 mix 的组成、且 α=5 过冲;组成插值在全树中从未试过。本 draft 按控制器指定实现 T2EI-01:用 logit 线性插值定类型组成(新机制),配类型内残差保持的有界表达插值。 |
| 做法 | 1) 以 agent/seeds/T2__embryo__val_interp/mix 为基座(procrustes3d 对齐、scale_damp=0.5、分层抽样、n=5000),先复现 ~57 分确认管线正确。2) 视图文本无关地按时间排序取目标前后两个括号阶段,t=(target−a)/(b−a),不硬编码时间标签。3) 组成插值:各类型比例 p_a、p_b,共有类型做 logit 插值 logit(q)=(1−t)·logit(p_a)+t·logit(p_b)(logit 前把 p clip 到 [0.005,0.995]),仅一端有的类型按该端权重保留,最后归一化得目标组成;按 q 分配 n 个细胞,共有类型内部再按 (1−t,t) 分到两端。4) 类型内表达插值:共有类型 Δ=μ_b−μ_a,仅保留 |Δ|≥0.25 基因;a 侧细胞 x+=s·t·Δ、b 侧 x−=s·(1−t)·Δ,只作用于 x>0 项、clip≥0(保留细胞残差);强度 s 默认 1.0(恰好移到类型中点),环境变量 T2EI_STRENGTH 覆盖,搜索 [0.5,1.5]。组成开关 T2EI_COMPOSITION(0=退回 mix 的 (1−t,t) 分层组成)。5) 坐标完全不动(保形状/邻域)。6) 先 ~2000 细胞小样 vec-score 看 mmd_u 走向,再全量;cell_state 增益 <1 分时复查一次确认(T2 噪声 ~1)。7) 单输入阶段退路:括号阶段 <2 时关闭两机制,直接 copy_last 最近观测阶段。 |
| 风险 | 1) logit 组成插值与线性差异可能很小(类型比例中等时两者接近)→ cell_state 增益落在噪声内;Engineer 应先打印输出类型组成与 (1−t,t) mix 的差值,若几乎不变说明机制没咬合。2) 有界强度 s=1 可能比节点 5 的 α=5 过冲位移在 DE(秩/方向型)上吃亏,若 expression_change 低于节点 5 可试 s→1.5。3) 组成变化会改变坐标云抽样,可能扰动当前很高的 shape_scale(74.43),需盯 d2_shape/occupancy_dice。4) 两端类型标签词表不一致时只取交集做共有类型。5) 小样本先跑,避免全量超时(30 分钟、20 次查分)。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:这个提交的上一版(种子程序:相对空仓库)。改动的文件:solution/EXECUTION.json +1 −0、solution/METHOD.md +31 −0、solution/run.py +254 −0
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..065ffcc--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,31 @@+T2EI-01:类型组成 logit 插值 + 类型内残差保持的强度有界伪批量表达位移(s=5),坐标 procrustes3d 对齐后按阻尼 log-RMS 缩放,细胞按目标组成分层抽取,表达/坐标配对原样保留。++## 方法(family_id: T2EI-01,按 PLAN 实现)++1. 视图无关地从 `manifest["inputs"]` 按时间排序取目标的括号阶段 (a, b),t=(target−a)/(b−a),只用时间差,不看绝对时间/视图字段。无括号(单输入或外推)时退路 = 锚阶段细胞按类型分层抽到 [min_cells, max_cells] 原样输出(copy_last 式)。+2. **组成机制(T2EI_COMPOSITION,默认开)**:共有类型 q=expit((1−t)·logit(p_a)+t·logit(p_b)),logit 前 p clip 到 [0.005,0.995];仅一端有的类型按该端权重保留((1−t)p_a 或 t·p_b);归一化后按 q 分配 n 个细胞,共有类型内部按 (1−t,t) 分到两端,无放回抽取。n = log 线性插值(n_a,n_b,t) 夹到榜的 [min,max](proxy 上 = 5000)。+3. **表达机制(T2EI_STRENGTH,默认 s=5.0)**:共有类型 Δ=μ_b−μ_a(全阶段伪批量均值),只保留 |Δ|≥0.25(T2EI_DELTA_MIN)的基因;a 侧细胞 x+=s·t·Δ、b 侧 x−=s·(1−t)·Δ,只作用于 x>0 项、结果 clip≥0。型内残差 (x−μ) 在正项上原样保留(加的是型级常向量)。+4. 坐标:procrustes3d 对齐(共有类型质心 Kabsch,z 符号随旋转),两朵云缩到 target RMS = exp(log rms_a + 0.5·t·Δlog rms)(T2EI_SCALE_DAMP=0.5);抽样细胞的坐标原样携带(不插值坐标点),重复坐标加 1e-4·RMS 抖动,最后整体恢复到 target RMS。表达与位置的配对因此保持真实。+5. 确定性:`np.random.default_rng(seed)`,无全局随机状态;纯 CPU(EXECUTION.json gpu=false),proxy 视图全程 <10 s。++## 机制生效的证据(proxy,E6.75+E8.0→E7.25,t=0.4,stderr 打印)++- 组成:输出 q 与线性 (1−t)p_a+t·p_b 明显不同(Unknown −0.034、EXE-Endoderm +0.013、Caudal Epiblast −0.008 等);两侧抽样数 2739/2261,偏离 mix 的 3000/2000。+- 表达:11 个共有类型全部位移,|Δ|₁ 137–254;a 侧权重 s·t=2、b 侧 s·(1−t)=3,伪批量移到并越过型中点(s>1 部分被 x>0/clip≥0 截断)。+- 残差保持:位移是型级常向量,正项残差不变(结构性保证,未逐型打印相关系数)。+- 四组分(A 半,seed 0):对照→开启 = cell_state 36.54→47.37、expression_change 59.8→62.08、shape_scale 74.91→76.42、local_spatial 54.38→57.99。++## 关闭机制对照(同一程序,T2EI_COMPOSITION=0 T2EI_STRENGTH=0)++- 输出退回 mix 式 (1−t,t) 分层混抽、表达不动:总分 56.40(cell_state 36.54),复现 mix 种子画像(~57、cell_state ~37)。+- 开启(默认):总分 60.97;seed 1 复核 60.71。两机制分解:只开组成 55.19(组成机制单独反而略降,主要伤 mmd_u/邻域),只开表达 s=5 60.62;合开 60.97 ≈ 加性。++## 验证过 / 没验证++- 验证(proxy A 半,共 9 次查分):s∈{0,1,3,5,6,8} 扫描,峰值平台 s=5–6(s=1 55.99→s=5 60.97→s=8 60.06);Δ_min 0.25 vs 0.1 无差(60.97 两者);seed 0/1 差 0.26(噪声内);vec-check 通过;默认输出与显式参数输出逐字节一致(确定性)。+- 没验证:B 半与正式分;多输入阶段(final 视图 3 输入)实际运行——代码按括号选取应成立但未跑过该视图;无括号的 copy_last 退路未在真实外推榜上跑过;s>8、λ 型逐细胞加权(节点 8 的机制,本 draft 未混入)。++## 参数与知识来源++- 关键默认:align=procrustes3d、scale_damp=0.5(方法卡胚插值推荐值)、s=5.0、Δ_min=0.25、组成 logit clip 0.005。环境变量 T2EI_{COMPOSITION,STRENGTH,SCALE_DAMP,DELTA_MIN} 可覆盖(提交时默认=开启)。+- 生物学知识来源:仅方法卡/实验表内的既有事实(z 为离散切片轴、procrustes3d 在胚插值代理上形状最好、mix 的邻域稳定 52–55、|Δ|≥0.25 阈值沿用节点 5);未使用任何保留阶段/基因型信息、外部文献数据。s=5 过冲优于 s=1 中点是纯经验结果(与节点 5/8 的 α=5 一致),与 PLAN 默认 s=1 不同,已按扫描数据改为 5。diff --git a/solution/run.py b/solution/run.pynew file mode 100644index 0000000..8b85989--- /dev/null+++ b/solution/run.py@@ -0,0 +1,254 @@+"""T2 interpolation: logit composition interpolation + bounded type-midpoint+expression interpolation on top of a mix-style coordinate frame (family T2EI-01).++Mechanism switches (env):+ T2EI_COMPOSITION 1 (default) = logit-interpolated type composition;+ 0 = mix-style (1-t, t) stratified draw of real cells.+ T2EI_STRENGTH s (default 1.0) = bounded per-type expression displacement;+ 0 = no displacement (cells carried unchanged).+ T2EI_SCALE_DAMP default 0.5, damping of the log-linear RMS interpolation.+"""++from __future__ import annotations++import argparse+import os+import sys++import numpy as np++from src.task2_spatial.view_io import (+ anchor_entry,+ interp_bracket,+ load_manifest,+ panel_genes,+ read_stage,+ write_t2,+)+from src.task2_spatial.frame import align_pair, log_interp, rms_radius, scale_to_rms+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+++def _env_float(name: str, default: float) -> float:+ raw = os.environ.get(name)+ if raw is None or raw.strip() == "":+ return default+ return float(raw)+++def _env_flag(name: str, default: bool) -> bool:+ raw = os.environ.get(name)+ if raw is None or raw.strip() == "":+ return default+ return raw.strip().lower() not in ("0", "false", "no", "off")+++def _fractions(labels: np.ndarray, types: list[str]) -> np.ndarray:+ n = max(len(labels), 1)+ return np.array([(labels == t).sum() / n for t in types], dtype=np.float64)+++def _logit(p: np.ndarray, eps: float = 0.005) -> np.ndarray:+ p = np.clip(p, eps, 1.0 - eps)+ return np.log(p / (1.0 - p))+++def _expit(z: np.ndarray) -> np.ndarray:+ return 1.0 / (1.0 + np.exp(-z))+++def main() -> None:+ ap = argparse.ArgumentParser()+ ap.add_argument("--data", required=True)+ ap.add_argument("--out", required=True)+ ap.add_argument("--seed", type=int, default=0)+ args = ap.parse_args()++ strength = _env_float("T2EI_STRENGTH", 5.0)+ comp_on = _env_flag("T2EI_COMPOSITION", True)+ scale_damp = _env_float("T2EI_SCALE_DAMP", 0.5)+ delta_min = _env_float("T2EI_DELTA_MIN", 0.25)++ view = args.data+ manifest = load_manifest(view)+ genes = panel_genes(view, manifest)+ lo = int(manifest["min_cells"])+ hi = int(manifest["max_cells"])+ rng = np.random.default_rng(int(args.seed))++ a_entry, b_entry, t = interp_bracket(manifest)++ # Fallback: no bracketing pair (e.g. single input stage) -> carry the anchor stage.+ if b_entry is None:+ stage = read_stage(view, a_entry, genes)+ n = int(np.clip(stage.n, min(lo, stage.n), hi))+ idx = take(stage.labels, n, rng) if n < stage.n else np.arange(stage.n)+ write_t2(args.out, as_dense(stage.X, idx), stage.coords[idx], genes, seed=args.seed)+ print(f"[T2EI] no bracket -> copy anchor stage, n={len(idx)}", file=sys.stderr)+ return++ stage_a = read_stage(view, a_entry, genes)+ stage_b = read_stage(view, b_entry, genes)+ la = np.asarray(stage_a.labels).astype(str)+ lb = np.asarray(stage_b.labels).astype(str)++ n = interp_count(stage_a.n, stage_b.n, t, lo, hi)++ # Coordinates: procrustes3d frame, both clouds scaled to a damped log-linear RMS.+ al_a, al_b, info = align_pair(stage_a.coords, stage_b.coords, la, lb, "procrustes3d")+ rms_a = rms_radius(stage_a.coords)+ rms_b = rms_radius(stage_b.coords)+ target_rms = log_interp(rms_a, rms_b, t, scale_damp)+ ca = scale_to_rms(al_a, target_rms)+ cb = scale_to_rms(al_b, target_rms)++ types = sorted(set(la.tolist()) | set(lb.tolist()))+ pa = _fractions(la, types)+ pb = _fractions(lb, types)+ in_a = pa > 0+ in_b = pb > 0+ shared = in_a & in_b++ if comp_on:+ q = np.zeros_like(pa)+ q[shared] = _expit((1.0 - t) * _logit(pa[shared]) + t * _logit(pb[shared]))+ q[in_a & ~in_b] = (1.0 - t) * pa[in_a & ~in_b]+ q[~in_a & in_b] = t * pb[~in_a & in_b]+ q = q / q.sum()+ else:+ q = None++ idx_a_list, idx_b_list = [], []+ if q is None:+ ia, ib = mix_indices(la, lb, t, n, rng)+ idx_a_list.append(ia)+ idx_b_list.append(ib)+ else:+ counts = np.floor(q * n).astype(int)+ pools_a = {ty: np.flatnonzero(la == ty) for ty in types if (la == ty).any()}+ pools_b = {ty: np.flatnonzero(lb == ty) for ty in types if (lb == ty).any()}+ # first pass, capped by pool sizes+ ka = np.zeros(len(types), dtype=int)+ kb = np.zeros(len(types), dtype=int)+ for i, ty in enumerate(types):+ k = int(counts[i])+ if k <= 0:+ continue+ if shared[i]:+ k_a = int(round((1.0 - t) * k))+ k_a = min(k_a, pools_a[ty].size)+ k_b = min(k - k_a, pools_b[ty].size)+ if k_a + k_b < k:+ k_a = min(k - k_b, pools_a[ty].size)+ ka[i], kb[i] = k_a, k_b+ elif in_a[i]:+ ka[i] = min(k, pools_a[ty].size)+ else:+ kb[i] = min(k, pools_b[ty].size)+ deficit = int(n - ka.sum() - kb.sum())+ # redistribute the floor/deficit surplus to types with spare pool capacity+ spare_a = np.array([max(pools_a.get(ty, np.empty(0)).size - ka[i], 0) for i, ty in enumerate(types)])+ spare_b = np.array([max(pools_b.get(ty, np.empty(0)).size - kb[i], 0) for i, ty in enumerate(types)])+ order = np.argsort(-(q + 1e-12))+ guard = 0+ while deficit > 0 and guard < 4 * len(types) + 8:+ progressed = False+ for i in order:+ if deficit <= 0:+ break+ if spare_b[i] > 0 and (not shared[i] or spare_a[i] <= 0):+ kb[i] += 1+ spare_b[i] -= 1+ deficit -= 1+ progressed = True+ elif spare_a[i] > 0:+ ka[i] += 1+ spare_a[i] -= 1+ deficit -= 1+ progressed = True+ if not progressed:+ break+ guard += 1+ for i, ty in enumerate(types):+ if ka[i] > 0:+ idx_a_list.append(rng.choice(pools_a[ty], int(ka[i]), replace=False))+ if kb[i] > 0:+ idx_b_list.append(rng.choice(pools_b[ty], int(kb[i]), replace=False))++ idx_a = np.concatenate(idx_a_list) if idx_a_list else np.array([], dtype=int)+ idx_b = np.concatenate(idx_b_list) if idx_b_list else np.array([], dtype=int)+ idx_a = np.sort(idx_a)+ idx_b = np.sort(idx_b)++ # Expression: bounded, residual-preserving per-type displacement towards the type midpoint.+ Xa = as_dense(stage_a.X, idx_a) if idx_a.size else np.empty((0, len(genes)), dtype=np.float32)+ Xb = as_dense(stage_b.X, idx_b) if idx_b.size else np.empty((0, len(genes)), dtype=np.float32)+ labels_a_sel = la[idx_a] if idx_a.size else np.array([], dtype=str)+ labels_b_sel = lb[idx_b] if idx_b.size else np.array([], dtype=str)++ shift_report = []+ if strength != 0.0 and shared.any():+ means_a = type_means(stage_a.X, la)+ means_b = type_means(stage_b.X, lb)+ wa = float(strength) * float(t)+ wb = float(strength) * (1.0 - float(t))+ for ty in types:+ if not (ty in means_a and ty in means_b):+ continue+ d = (means_b[ty] - means_a[ty]).astype(np.float32)+ d = np.where(np.abs(d) >= delta_min, d, 0.0).astype(np.float32)+ if not np.any(d):+ continue+ ma = labels_a_sel == ty+ if ma.any():+ blk = Xa[ma]+ db = np.broadcast_to(d, blk.shape)+ pos = blk > 0+ upd = np.clip(blk[pos] + wa * db[pos], 0.0, None)+ new = blk.copy()+ new[pos] = upd+ Xa[ma] = new+ mb = labels_b_sel == ty+ if mb.any():+ blk = Xb[mb]+ db = np.broadcast_to(d, blk.shape)+ pos = blk > 0+ upd = np.clip(blk[pos] - wb * db[pos], 0.0, None)+ new = blk.copy()+ new[pos] = upd+ Xb[mb] = new+ shift_report.append((ty, int(ma.sum()), int(mb.sum()), float(np.abs(d).sum())))++ expr = np.vstack([Xa, Xb])+ coords = np.vstack([ca[idx_a], cb[idx_b]])++ # jitter exact-duplicate coordinates, then restore the target RMS+ rounded = np.round(coords, 5)+ _, inv, cnt = np.unique(rounded, axis=0, return_inverse=True, return_counts=True)+ if cnt.max() > 1:+ coords = coords.copy()+ dup = cnt[inv] > 1+ coords[dup] = coords[dup] + rng.normal(0.0, 1e-4 * (target_rms + 1e-8), size=(int(dup.sum()), 3))+ coords = scale_to_rms(coords, target_rms)++ write_t2(args.out, expr, coords.astype(np.float32), genes, seed=args.seed)++ # ---- mechanism evidence ----+ lin = (1.0 - t) * pa + t * pb+ print(f"[T2EI] t={t:.4f} n={expr.shape[0]} (from a: {len(idx_a)}, from b: {len(idx_b)}) "+ f"rms_a={rms_a:.1f} rms_b={rms_b:.1f} target_rms={target_rms:.1f} out_rms={rms_radius(coords):.1f} "+ f"z_dot={info.get('z_dot'):.3f} n_shared={int(shared.sum())}", file=sys.stderr)+ print(f"[T2EI] comp_on={comp_on} strength={strength} scale_damp={scale_damp}", file=sys.stderr)+ if comp_on:+ print("[T2EI] composition: type q_logit q_linear diff", file=sys.stderr)+ for i, ty in enumerate(types):+ if q[i] > 1e-4 or lin[i] > 1e-4:+ print(f"[T2EI] {ty:<24s} {q[i]:.4f} {lin[i]:.4f} {q[i] - lin[i]:+.4f}", file=sys.stderr)+ for ty, na, nb, dmag in shift_report:+ print(f"[T2EI] shift {ty:<24s} n_a={na} n_b={nb} |delta|_1={dmag:.2f}", file=sys.stderr)+++if __name__ == "__main__":+ main()
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k007 | Interval staging and held-out-window filtering of external data | notes/official/来件/virtualembryo.ai/rules.md |
| k023 | Time-split validation with a held-out intermediate or next time point | notes/handover/02_知识学习路线.md |
| k009 | Conditional / OT flow matching for population transport | arXiv:2210.02747 (Lipman et al., Flow Matching for Generative Modeling) |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 从零实现 T2EI-01:类型组成 logit 插值 + 类型内残差保持的伪批量表达位移(只作用 x>0 项、|Δ|≥0.25 基因),坐标 procrustes3d 对齐 + scale_damp=0.5 的 RMS 缩放、按目标组成分层抽 n=5000。注意实际默认 s=5(过冲),与 PLAN 声称的 s=1(恰好移到型中点)不符,Engineer 依 proxy 扫描改了参数并在 METHOD.md 注明——因此真正驱动增益的是类节点5 的大强度型级位移,而非'有界移到中点'。 |
|---|---|
| 各组分数的变化 | cell_state:明显变好 +11.63(37.49→49.12):mmd_u raw 0.01657→0.01148(skill 0.521→0.612,得分 +1.13)、variogram raw 0.02952→0.01502(skill 0.228→0.371,得分 +1.78),但 49.12 仍略低于地板 50 expression_change:变好 +2.88(59.72→62.60):de_score raw 0.2069→0.3448(skill 0.562→0.614,得分 +0.64)、de_direction 0.3757→0.3899(+0.08);组增益主要来自 de_score,远超 T2 ~1 分噪声 local_spatial:变好 +3.46(57.27→60.73):neighborhood_mmd raw 0.05791→0.0503(skill 0.573→0.607,得分 +0.86,超过噪声),坐标不动而表达位移改善了邻域平均表达的配对 shape_scale:噪声内 -0.39(74.43→74.04):d2_shape/scale_log_ratio 得分不变,occupancy_dice raw 0.7735→0.7646(-0.10),坐标未动,符合预期 |
| family_id | T2EI-01 |
| 假设是否成立 | 是 |
| 经验 |
|
| mechanism_active | 是 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 4 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 3 次:— |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 16,630 · 输出 1,388 · 思考 790 |
| 任务(第一行) | 分析节点 n10 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/10/analyst.jsonl (文件不在) |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 26 |
| 工具调用 | 共 32 次:— |
| 用时 | 14 分 |
| token 数 | 输入 71,432 · 输出 11,678 · 思考 11,322 |
| 任务(第一行) | 按计划修改程序:组成 logit 插值 + 类型内残差保持表达插值(T2EI-01) |
| 最后的回答(摘录) | Done. Summary:
**做了什么**:从零实现 PLAN 的 T2EI-01 家族——类型组成 logit 插值(q=expit((1−t)logit(p_a)+t·logit(p_b)),单端类型按端权重保留)+ 类型内残差保持的有界伪批量表达位移(只移 x>0 项、|Δ|≥0.25 基因),坐标 procrustes3d 对齐 + scale_damp=0.5 的 RMS 缩放,细胞按目标组成分层无放回抽取(n=5000)。修复了一个关键 bug(布尔掩码索引副本导致表达位移原本未写回)。强度扫描 s∈{0,1,3,5,6,8} 峰值在 5–6,默认 s=5(与 PLAN 的 s=1 不同,扫描数据支持,METHOD.md 已注明)。
**查分结果**(proxy A 半,9/20 次):关闭对照(COMPOSITION=0, STRENGTH=0)56.40,复现 mix 种子画像(cell_state 36.5);默认开启 **60.97**(cell_state 47.4、expr 62.1、shape 76.4、local 58.0),seed 1 复核 60.71。分解:只开组成 55.19(单独略伤 mmd_u/邻域),只开表达 60.62,合开 ≈ 加性。确定性、vec-check、单输入退路均通过。
**下一步最值得试**:组成 logit 机制单独为负、与表达位移合成为正但幅度在噪声边缘——可试组成阻尼 λ(linear↔logit 混合)或把 logit 组成与节点 8 的逐细胞投影加权(λ=6)组合;cell_state 仍是四组最弱(47 vs 地板 50),压缩型内分布宽度(而非刚性平移)是最可能的增益点。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/10/engineer.jsonl (文件不在) |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 7 分 |
| token 数 | 输入 9,736 · 输出 9,670 · 思考 8,192 |
| 任务(第一行) | 为节点 n10(草稿,父节点 nNone)写改进计划 PLAN.json,思路 T2EI-01 |
| 最后的回答(摘录) | 28,但它保留 mix 的组成、且 α=5 过冲;组成插值在全树中从未试过。本 draft 按控制器指定实现 T2EI-01:用 logit 线性插值定类型组成(新机制),配类型内残差保持的有界表达插值。", "approach": "1) 以 agent/seeds/T2__embryo__val_interp/mix 为基座(procrustes3d 对齐、scale_damp=0.5、分层抽样、n=5000),先复现 ~57 分确认管线正确。2) 视图文本无关地按时间排序取目标前后两个括号阶段,t=(target−a)/(b−a),不硬编码时间标签。3) 组成插值:各类型比例 p_a、p_b,共有类型做 logit 插值 logit(q)=(1−t)·logit(p_a)+t·logit(p_b)(logit 前把 p clip 到 [0.005,0.995]),仅一端有的类型按该端权重保留,最后归一化得目标组成;按 q 分配 n 个细胞,共有类型内部再按 (1−t,t) 分到两端。4) 类型内表达插值:共有类型 Δ=μ_b−μ_a,仅保留 |Δ|≥0.25 基因;a 侧细胞 x+=s·t·Δ、b 侧 x−=s·(1−t)·Δ,只作用于 x>0 项、clip≥0(保留细胞残差);强度 s 默认 1.0(恰好移到类型中点),环境变量 T2EI_STRENGTH 覆盖,搜索 [0.5,1.5]。组成开关 T2EI_COMPOSITION(0=退回 mix 的 (1−t,t) 分层组成)。5) 坐标完全不动(保形状/邻域)。6) 先 ~2000 细胞小样 vec-score 看 mmd_u 走向,再全量;cell_state 增益 <1 分时复查一次确认(T2 噪声 ~1)。7) 单输入阶段退路:括号阶段 <2 时关闭两机制,直接 copy_last 最近观测阶段。", "expected_groups": ["cell_state", "expression_change"], "risks": "1) logit 组成插值与线性差异可能很小(类型比例中等时两者接近)→ cell_state 增益落在噪声内;Engineer 应先打印输出类型组成与 (1−t,t) mix 的差值,若几乎不变说明机制没咬合。2) 有界强度 s=1 可能比节点 5 的 α=5 过冲位移在 DE(秩/方向型)上吃亏,若 expression_change 低于节点 5 可试 s→1.5。3) 组成变化会改变坐标云抽样,可能扰动当前很高的 shape_scale(74.43),需盯 d2_shape/occupancy_dice。4) 两端类型标签词表不一致时只取交集做共有类型。5) 小样本先跑,避免全量超时(30 分钟、20 次查分)。", "family_id": "T2EI-01", "mechanism": "用 logit 空间线性插值重排输出细胞类型组成(比例走平滑轨迹而非 (1−t,t) 直混),再对两端共有类型做残差保持的有界伪批量表达插值,把细胞推向类型中点。", "vs_constant_shift": "每型常数位移(如节点 5)不改变输出类型组成——组成仍停在 mix 的 (1−t,t);全局组成重加权改组成却不改单细胞表达。本方案核心新机制是 logit 组成插值(重排各型细胞数量这一群体结构),并同时对每个细胞做有界、保留残差的表达插值;类型内分量虽是型级向量,但强度有界(移到中点而非 α=5 过冲)且与组成变化耦合,非单纯加常数。", "mechanism_evidence": "1) 打印输出类型组成,证明其偏离 (1−t,t) mix 且落在两端 logit 插值处;2) 逐类型报告伪批量均值位移≈s·t·Δ(向中点靠拢);3) 细胞残差 (x−μ_self) 与原始相关≈1,证明残差保留;4) 四组分分解:cell_state(mmd_u/variogram skill)上升、expression_change 持平或升、local_spatial(neighborhood_mmd)不塌、shape_scale 基本不变(坐标未动)。", "mechanism_off_control": "同一程序设 T2EI_COMPOSITION=0 且 T2EI_STRENGTH=0:组成退回 mix 的 (1−t,t) 分层抽样、表达位移为 0,应逐位(或分数上)复现 mix 种子(~57 分、cell_state ~37)。预期差别:开启后 cell_state(mmd_u、variogram)明显上升而形状组不变;若关闭后输出与开启完全相同,说明机制未运行。", "sources": []} ``` |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/10/researcher.jsonl (文件不在) |