总览 · ← 返回运行 20261003-004922-search-t2-embryo-interp-g24
节点 n10 在终选来历上
mix 基座上实现 T2EI-01 按型组成线性插值:目标比例 p_T=(1−t)p_A+t·p_B 分配型配额,型内两阶段按 t·adj 分配(提交 adj=0,共享型细胞全取早期),去掉父节点的 τ 相似度偏置;表达与坐标不修改。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-004922-search-t2-embryo-interp-g24 |
|---|---|
| 父节点 | n8 |
| 子节点 | n12 |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 改进 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 60.29(-0.1) · proxy 60.29(-0.1) · 3 次复测均分 60.34 |
| 审查 | 未审查 |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 19 分 |
| 程序版本 | 819069b545d21a5b9ce2603d58843e66ccae25df (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 819069b545:solution/METHOD.md
mix 基座上实现 T2EI-01 按型组成线性插值:目标比例 p_T=(1−t)p_A+t·p_B 分配型配额,型内两阶段按 t·adj 分配(提交 adj=0,共享型细胞全取早期),去掉父节点的 τ 相似度偏置;表达与坐标不修改。
方法
基座 = 父节点 2/8(seed mix):括号 E6.75+E8.0 → E7.25(t=0.4),procrustes3d 对齐, scale_damp=0.5,log 线性 RMS,n=5000(manifest min/max 内)。
PLAN 机制(family T2EI-01,组成插值,实现完整):替换 mix_indices——
- 按两阶段型比例线性插值得目标组成 p_T=(1−t)·p_A[T]+t·p_B[T](单阶段型自然退化为 (1−t)p_A 或 t·p_B);
- 总配额 n 按 p_T 最大余数法分配 c_T,超出可用数时封顶并把余额重分给有余量的型;
- 型内两阶段分配 n_B,T=round(c_T·t·ADJ)(单阶段型全取该阶段,不足从另一阶段补);
- 型内均匀无放回抽样;坐标与表达取被抽细胞自身值。
τ 偏置已按 PLAN 删除(无偏路径)。常数 COMPOS_ADJ=0.0(环境变量 VEC_COMPOS_ADJ
仅本地测试);VEC_COMPOS_INTERP=0 走关闭对照。
单阶段退路:目标无括号时 = seed(最后观测阶段分层抽样),未改动。
机制生效证据(proxy, seed 0)
- 实际型组成 vs 目标 p_T 的 Pearson = 0.99999(>0.99 达标)。
- vs 父节点 8(frac=0.5 统一抽取):后期(B)细胞 1000→1049(adj=0);其中共享型 B 细胞 519→86,B-only 15 型 481→963(恢复完整插值丰度,如 Forebrain 344→…按 c_T 配额), A-only 7 型 1139→854(回到插值丰度)。不同型的 delta 方向不同(非全局重加权)。
- 四组分随 ADJ(A 半,见下表):shape_scale 随 adj 单调升(66.7→77.3),cell_state 单调降(50.4→33.0),expression_change/local_spatial 在 adj≤0.2 时优于父。
机制关闭对照(mechanism_off_control)
VEC_COMPOS_INTERP=0(统一 frac=0.5、τ=0)输出与父节点 8 以
VEC_BIAS_TAU=0 VEC_T_DRAW_FRAC=0.5 运行逐位相同(X、coords、genes 全等已验证);
该对照 A 半 59.88 {cs 52.56, ec 60.17, ls 58.27, ss 68.53}(父节点 8 已测)。
机制开启(提交配置 adj=0)A 半 59.40:未达 PLAN 预期(ss 未回升至 71+,
反而 −1.8;cs −2.2)。如实报告:组成插值在本代理上没有净胜父节点,差距在噪声(~2 分)内。
查分记录(A 半,proxy,seed 0,共 4/20 次)
| 配置 | board | cell_state | expr_change | local_spatial | shape_scale |
|---|---|---|---|---|---|
| 父 8 对照 τ=0,frac0.5 | 59.88 | 52.56 | 60.17 | 58.27 | 68.53 |
| compos adj=1.0 | 55.63 | 32.95 | 60.79 | 51.50 | 77.28 |
| compos adj=0.5 | 57.72 | 42.26 | 59.84 | 57.54 | 71.25 |
| compos adj=0.2 | 59.19 | 48.02 | 61.46 | 59.47 | 67.81 |
| compos adj=0.0(提交) | 59.40 | 50.36 | 61.19 | 59.33 | 66.72 |
关键发现(供后续节点):① PLAN 假设"按型组成插值回升 shape_scale"被证伪——ss 由共享型 的 B 细胞量驱动(adj 单调),全局组成换成插值丰度反而略降 ss;② cell_state 主要由 总 B 细胞量与 A-only 过采样驱动,父节点 frac=0.5 的近统一抽取已接近 cs/ss 权衡前沿; ③ 组成插值稳定带来 ec(+1.0~1.4) 与 ls(+1.1~1.2),但 cs 损失更大。
验证过 / 没验证
- 验证:关闭对照逐位等于父 8 对照;seed 0 重跑逐位确定;adj=0 输出与查分文件逐位一致; n=5000、X 有限、vec-check ok;运行 ~2s。
- 没验证:B 半分;adj∈(0,0.2) 细扫(前沿单调,预期不超父);组成阻尼 d(t_comp=t·d) 与型内 split 解耦的第二自由度(时间不足未实现);真实括号(t=1/3、共有型 11)上 adj=0 使共享型几乎全取 E7.25 之前的早期细胞,方向与代理一致但未直接检验。
- 生物学知识来源:无外部先验,仅用视图内数据(型计数、时间差)现场计算。
- 视图无关:不读 board/mode/路径/绝对时间;t、括号、n 均由 manifest 现场算出; adj 为常数。
调研员的计划
| 名称 | 按型组成线性插值替代统一frac抽样,修复shape_scale同时保持cell_state |
|---|---|
| 动机 | 父节点8(60.43)中cell_state 53.16最弱,但shape_scale从父2的74.43降至68.99(−5.44),原因是t_draw_frac=0.5统一削减后期细胞,丢失了后期阶段的空间覆盖。ANALYSIS建议2/3均指向解耦或按型组成插值。节点5(60.63)与节点8差距0.2在噪声内,说明frac=0.5的cell_state增益已饱和,下一步收益在恢复shape_scale。节点3/4(型内表达插值)gen_failed、节点7(1-NN位移)退化为常数位移、节点6(伪时间ramp)净负——这些方向不再重复。本方案实现T2EI-01的组成插值核心(尚未被任何节点实现过),放弃已证无效的τ偏置。 |
| 做法 | 基座=父节点8的run.py,删除τ偏置(设τ=0,走无偏路径)。核心改动在mix_indices替换函数内: 1. 读入stage_a、stage_b的labels,计算每型在两阶段的比例 p_A[T]=n_A,T/N_A, p_B[T]=n_B,T/N_B。 2. 目标比例 p_T=(1−t)·p_A[T]+t·p_B[T](仅存在于至少一个阶段的型;两阶段都有的型正常插值,单阶段型按其在的那个阶段的比例乘(1−t)或t)。 3. 总配额 n=5000(与父相同),按 p_T 分配 c_T=round(n·p_T/Σp),余数按最大余数法补齐(复用现有_alloc逻辑)。 4. 型T内从A、B两阶段的分配:n_B,T=round(c_T·t),n_A,T=c_T−n_B,T;若某阶段该型细胞不足则从另一阶段补足。 5. 型内均匀抽样(无τ偏置),用现有_weighted_stratified但logw全零即退化为均匀。 6. 坐标与表达均取被抽细胞自身的值,不做额外修改。scale_damp=0.5、procrustes3d不变。 关键参数:无新超参(t由manifest算出,n=5000不变)。如需微调可试n_B,T=round(c_T·t·adj),adj∈{0.8,1.0,1.2},但首轮用adj=1.0。 单阶段退路:目标无括号时与父相同(最后观测阶段分层抽样)。 vec-score筛选:先跑adj=1.0(1次),对比四组分与父节点8(59.63 A半);若shape_scale回升≥2且cell_state不降≥1,再试adj=0.8/1.2(最多再2次)。总查分≤5次。 |
| 风险 | 1) 按型插值后总后期细胞数可能与frac=0.5时不同(可能更多),cell_state可能回落——Engineer应在第一次查分后对比cell_state,若降>2分则提高adj或回退。2) 某些型在一阶段极少(<5个),配额分配可能产生0或过抽样——需clip到[0, stage_count]。3) 型标签在两阶段不完全一致(新型出现/旧型消失),单阶段型的处理需明确。4) 30分钟时限紧——代码改动集中在biased_mix函数内约30行,不需要新依赖;先在小数据上验证型配额正确性再全量跑。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:父节点版本 e3fd3c0ce1。改动的文件:solution/METHOD.md +42 −43、solution/run.py +116 −78
diff --git a/solution/METHOD.md b/solution/METHOD.mdindex 0724725..ff2eb07 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,61 +1,60 @@-mix 基座上实现 T2EI-01 型内跨阶段相似度加权抽样(τ=0.2 保持打开);对照显示该机制在本榜中性偏负,主要增益来自组合 node 5 已验证的 t_draw=0.5·t 后抽减半。+mix 基座上实现 T2EI-01 按型组成线性插值:目标比例 p_T=(1−t)p_A+t·p_B 分配型配额,型内两阶段按 t·adj 分配(提交 adj=0,共享型细胞全取早期),去掉父节点的 τ 相似度偏置;表达与坐标不修改。 ## 方法 -基座 = 父节点 2(seed mix):括号 E6.75+E8.0 → E7.25(t=0.4),procrustes3d 对齐,-scale_damp=0.5,log 线性 RMS,按型分层抽 n=5000。+基座 = 父节点 2/8(seed mix):括号 E6.75+E8.0 → E7.25(t=0.4),procrustes3d 对齐,+scale_damp=0.5,log 线性 RMS,n=5000(manifest min/max 内)。 -**PLAN 机制(family T2EI-01,实现完整)**:分层抽样中,型 T 内每个细胞的抽样权重-w_i = exp(cos(x_i, μ_{T,other}) / τ),μ 为另一阶段该型的均值表达(`type_means`),-按权重无放回抽取(`rng.choice(..., p=w)`);另一阶段没有该型时权重均匀。型配额分配-逐行复刻 `transport.stratified_choice`,只改型内选择。不修改任何表达值或坐标——-改变的是哪些细胞进入输出。常数 `BIAS_TAU=0.2`(环境变量 `VEC_BIAS_TAU` 仅本地测试用)。+**PLAN 机制(family T2EI-01,组成插值,实现完整)**:替换 `mix_indices`——+1. 按两阶段型比例线性插值得目标组成 p_T=(1−t)·p_A[T]+t·p_B[T](单阶段型自然退化为+ (1−t)p_A 或 t·p_B);+2. 总配额 n 按 p_T 最大余数法分配 c_T,超出可用数时封顶并把余额重分给有余量的型;+3. 型内两阶段分配 n_B,T=round(c_T·t·ADJ)(单阶段型全取该阶段,不足从另一阶段补);+4. 型内均匀无放回抽样;坐标与表达取被抽细胞自身值。+τ 偏置已按 PLAN 删除(无偏路径)。常数 `COMPOS_ADJ=0.0`(环境变量 `VEC_COMPOS_ADJ`+仅本地测试);`VEC_COMPOS_INTERP=0` 走关闭对照。 -**组合部件**:`T_DRAW_FRAC=0.5`,即 t_draw = 0.5·t = 0.2,后期阶段抽 1000/5000 而非-2000/5000(node 5 已验证的组成修复,非本 PLAN 机制)。+**单阶段退路**:目标无括号时 = seed(最后观测阶段分层抽样),未改动。 -**单阶段退路**:目标无括号时退化为最后观测阶段分层抽样(与 seed 相同,无偏置)。+## 机制生效证据(proxy, seed 0) -## 机制生效证据(τ=0.2, t_draw_frac=0.5, proxy)--- 被抽细胞的跨阶段余弦 vs 全体:A 侧 0.4337 vs 0.4188,B 侧 0.5220 vs 0.5128- (右移,偏置确实选中了更接近另一阶段的细胞;τ=0.05 时右移更大:0.4667/0.5439)。-- 四组分随 τ(frac=1,A 半):τ=0(父) cell_state 37.49 → τ=0.2: 35.91 → τ=0.05: 33.39;- τ=−0.05: 39.43、τ=−0.2: 37.08。正偏置单调伤 cell_state。-- frac=0.5 时:τ=0(对照) 59.88 {cs 52.56, ec 60.17, ls 58.27, ss 68.53};- τ=0.2 59.63 {cs 51.65, ec 60.04, ls 58.24, ss 68.59};τ=−0.05 58.35。- **机制净效应 ≈ −0.25(噪声内),未达 PLAN 预期的 cell_state +2**。+- 实际型组成 vs 目标 p_T 的 Pearson = 0.99999(>0.99 达标)。+- vs 父节点 8(frac=0.5 统一抽取):后期(B)细胞 1000→1049(adj=0);其中共享型 B 细胞+ 519→86,B-only 15 型 481→963(恢复完整插值丰度,如 Forebrain 344→…按 c_T 配额),+ A-only 7 型 1139→854(回到插值丰度)。不同型的 delta 方向不同(非全局重加权)。+- 四组分随 ADJ(A 半,见下表):shape_scale 随 adj 单调升(66.7→77.3),cell_state+ 单调降(50.4→33.0),expression_change/local_spatial 在 adj≤0.2 时优于父。 ## 机制关闭对照(mechanism_off_control) -τ=0(等价权重全相等)且 frac=1 时走原库 `interpolate`,输出与父节点 2 **逐位相同**-(已验证 X、coords、genes 全等)。τ=0 且 frac=0.5 的对照分 59.88 vs 机制开 59.63:-按 PLAN 风险条款 1(cell_state 差 <1 分即放弃),该机制应判无效;提交按"机制保持-打开"惯例取 τ=0.2(差值在噪声内),但如实说明:**本节点分数增益主要来自 t_draw_frac-组成部件,不是 T2EI-01 偏置机制**。不冒充。+`VEC_COMPOS_INTERP=0`(统一 frac=0.5、τ=0)输出与父节点 8 以+`VEC_BIAS_TAU=0 VEC_T_DRAW_FRAC=0.5` 运行**逐位相同**(X、coords、genes 全等已验证);+该对照 A 半 59.88 {cs 52.56, ec 60.17, ls 58.27, ss 68.53}(父节点 8 已测)。+机制开启(提交配置 adj=0)A 半 59.40:**未达 PLAN 预期**(ss 未回升至 71+,+反而 −1.8;cs −2.2)。如实报告:组成插值在本代理上没有净胜父节点,差距在噪声(~2 分)内。 -## 查分记录(A 半,proxy,seed 0)+## 查分记录(A 半,proxy,seed 0,共 4/20 次) | 配置 | board | cell_state | expr_change | local_spatial | shape_scale | |---|---:|---:|---:|---:|---:|-| 父节点 2 | 57.23 | 37.49 | 59.72 | 57.27 | 74.43 |-| τ=0.05 | 54.57 | 33.39 | 60.78 | 50.59 | 73.50 |-| τ=0.2 | 56.43 | 35.91 | 60.92 | 53.34 | 75.53 |-| τ=−0.05 | 57.80 | 39.43 | 59.80 | 56.72 | 75.27 |-| τ=−0.2 | 57.24 | 37.08 | 60.57 | 55.46 | 75.86 |-| τ=−0.05, frac0.5 | 58.35 | 51.68 | 58.40 | 54.21 | 69.11 |-| τ=0, frac0.5(对照) | 59.88 | 52.56 | 60.17 | 58.27 | 68.53 |-| **τ=0.2, frac0.5(提交)** | **59.63** | 51.65 | 60.04 | 58.24 | 68.59 |+| 父 8 对照 τ=0,frac0.5 | 59.88 | 52.56 | 60.17 | 58.27 | 68.53 |+| compos adj=1.0 | 55.63 | 32.95 | 60.79 | 51.50 | 77.28 |+| compos adj=0.5 | 57.72 | 42.26 | 59.84 | 57.54 | 71.25 |+| compos adj=0.2 | 59.19 | 48.02 | 61.46 | 59.47 | 67.81 |+| **compos adj=0.0(提交)** | **59.40** | 50.36 | 61.19 | 59.33 | 66.72 | -用了 7/20 次查分。+关键发现(供后续节点):① PLAN 假设"按型组成插值回升 shape_scale"被证伪——ss 由共享型+的 B 细胞量驱动(adj 单调),全局组成换成插值丰度反而略降 ss;② cell_state 主要由+总 B 细胞量与 A-only 过采样驱动,父节点 frac=0.5 的近统一抽取已接近 cs/ss 权衡前沿;+③ 组成插值稳定带来 ec(+1.0~1.4) 与 ls(+1.1~1.2),但 cs 损失更大。 ## 验证过 / 没验证 -- 验证:off 对照逐位等于父节点;seed 0 重跑逐位确定;seed 0/1 输出过 `vec-check`;- 提交文件与查分 59.63 的配置逐位相同;运行 ~2s、内存远低于限额。-- 没验证:B 半分与多种子均值(无权限);τ 的 Pearson/欧氏距离备选(正余弦方向均- 已显示机制无效,换度量预期同样无效,未耗查分额度);frac 的 finer 扫描(0.45/0.55)。-- 生物学知识来源:无外部生物学先验,仅用视图内数据(型均值、余弦相似度)现场计算。-- 视图无关:不读 board/mode/路径/绝对时间;τ、frac 为常数;t 与括号由 manifest 时间差- 现场算出。风险:frac=0.5 使真实括号(t=1/3)的后期抽取从 ~1667 降到 ~833,代理上- 该方向已验证(node 5 与本节点),但真实目标 E7.25 的细胞状态无法直接检验。+- 验证:关闭对照逐位等于父 8 对照;seed 0 重跑逐位确定;adj=0 输出与查分文件逐位一致;+ n=5000、X 有限、vec-check ok;运行 ~2s。+- 没验证:B 半分;adj∈(0,0.2) 细扫(前沿单调,预期不超父);组成阻尼 d(t_comp=t·d)+ 与型内 split 解耦的第二自由度(时间不足未实现);真实括号(t=1/3、共有型 11)上+ adj=0 使共享型几乎全取 E7.25 之前的早期细胞,方向与代理一致但未直接检验。+- 生物学知识来源:无外部先验,仅用视图内数据(型计数、时间差)现场计算。+- 视图无关:不读 board/mode/路径/绝对时间;t、括号、n 均由 manifest 现场算出;+ adj 为常数。diff --git a/solution/run.py b/solution/run.pyindex ca6559a..3f037a7 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,20 +1,28 @@ #!/usr/bin/env python3-"""mix (T2 interpolation) + type-internal cross-stage similarity-biased draws.+"""mix (T2 interpolation) + per-type compositional interpolation (T2EI-01). Base pipeline is the seed ``mix`` (parent node 2): bracket the target with the nearest inputs, align frames (procrustes3d), rescale both clouds to-exp(log r_a + SCALE_DAMP·t·Δlog r), draw cells stratified by type —-round(t·n) from the later stage, the rest from the earlier one.--Mechanism (T2EI-01): inside each cell type's stratified draw, replace the-uniform choice with a weighted choice where cell i of stage S with type T gets-log-weight cos(x_i, mu_{T,other}) / BIAS_TAU, mu being the other stage's-type-mean expression. Types absent from the other stage keep uniform weights.-Expression values and coordinates are never modified — only *which* cells are-drawn changes.--Mechanism-off control: BIAS_TAU <= 0 routes to the untouched library-``interpolate``, producing output bit-identical to the parent seed.+exp(log r_a + SCALE_DAMP*t*dlog r), draw n cells stratified by type.++Mechanism (family T2EI-01, compositional interpolation): instead of drawing a+uniform fraction t from the later stage with each stage's own type profile,+build the target type composition p_T = (1-t)*p_A[T] + t*p_B[T], allocate the+output quota per type (largest remainder), then split each type's quota between+stages as n_B,T = round(c_T * t * ADJ) (all from the stage that has the type+when the other lacks it; deficits are filled from the other stage). Within a+type, cells are drawn uniformly without replacement. The tau similarity bias+of parent node 8 is removed (tau = 0 path). Expression values and coordinates+are never modified — only *which* cells are drawn changes.++ADJ controls how many of a shared type's cells come from the later stage:+ADJ=1 reproduces (in expectation) the plain mix stage totals with the exact+interpolated per-type composition; ADJ<1 keeps shared types "younger" while+late-only types still get their full interpolated abundance.++Mechanism-off control: VEC_COMPOS_INTERP=0 routes to parent node 8's uniform+stratified draw with T_DRAW_FRAC=0.5 and tau=0 (bit-identical to parent 8 run+with VEC_BIAS_TAU=0 VEC_T_DRAW_FRAC=0.5). Single-stage fallback (target not bracketed): unchanged from the seed. """@@ -31,35 +39,88 @@ import numpy as np import src.task2_spatial.methods as methods_mod from src.task2_spatial.methods import interpolate from src.task2_spatial.sample import 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}-BIAS_TAU = 0.2-T_DRAW_FRAC = 0.5 # draw fraction of later-stage cells: t_draw = T_DRAW_FRAC * t---def _log_weights(stage, means_other: dict[str, np.ndarray], tau: float) -> np.ndarray:- labels = np.asarray(stage.labels).astype(str)- Xd = as_dense(stage.X).astype(np.float64)- norms = np.linalg.norm(Xd, axis=1)- logw = np.zeros(len(labels), dtype=np.float64)- for lab, mu in means_other.items():- idx = np.flatnonzero(labels == lab)- if idx.size == 0:- continue- mu = mu.astype(np.float64)- nmu = float(np.linalg.norm(mu))- if nmu < 1e-12:+COMPOS_INTERP = True+COMPOS_ADJ = 0.0 # later-stage share of a shared type's quota: t * COMPOS_ADJ+T_DRAW_FRAC = 0.5 # only used by the mechanism-off control path+++def _compos_mix(labels_a, labels_b, tt: float, n: int, rng: np.random.Generator, adj: float, diag: dict | None = None):+ la = np.asarray(labels_a).astype(str)+ lb = np.asarray(labels_b).astype(str)+ na_tot, nb_tot = len(la), len(lb)+ n = int(min(max(int(n), 1), na_tot + nb_tot))+ ta_u, ca_u = np.unique(la, return_counts=True)+ tb_u, cb_u = np.unique(lb, return_counts=True)+ ma = {str(k): int(v) for k, v in zip(ta_u, ca_u)}+ mb = {str(k): int(v) for k, v in zip(tb_u, cb_u)}+ types = sorted(set(ma) | set(mb))+ tt = float(tt)+ p = np.array(+ [(1.0 - tt) * (ma.get(T, 0) / max(na_tot, 1)) + tt * (mb.get(T, 0) / max(nb_tot, 1)) for T in types],+ dtype=np.float64,+ )+ s = float(p.sum())+ if s <= 0.0:+ p = np.ones(len(types), dtype=np.float64)+ s = float(len(types))+ raw = p / s * n+ alloc = np.floor(raw).astype(int)+ rem = int(n - alloc.sum())+ order = np.argsort(-(raw - alloc), kind="stable")+ for i in range(rem):+ alloc[order[i % len(order)]] += 1+ avail = np.array([ma.get(T, 0) + mb.get(T, 0) for T in types], dtype=int)+ excess = int(np.maximum(alloc - avail, 0).sum())+ alloc = np.minimum(alloc, avail)+ while excess > 0:+ head = avail - alloc+ cand = np.flatnonzero(head > 0)+ if cand.size == 0:+ break+ cand = cand[np.argsort(-head[cand], kind="stable")]+ add = int(min(excess, len(cand)))+ for j in range(add):+ alloc[cand[j]] += 1+ excess -= add+ ia_parts, ib_parts = [], []+ for T, cT in zip(types, alloc):+ cT = int(cT)+ if cT <= 0: continue- s = (Xd[idx] @ mu) / np.maximum(norms[idx] * nmu, 1e-12)- logw[idx] = s / tau- return logw---def _weighted_stratified(labels, n: int, rng: np.random.Generator, logw: np.ndarray) -> np.ndarray:- """Same type allocation as transport.stratified_choice, weighted within type."""+ aa, ab = ma.get(T, 0), mb.get(T, 0)+ if ab == 0:+ nbT = 0+ elif aa == 0:+ nbT = cT+ else:+ nbT = int(np.clip(int(round(cT * tt * adj)), 0, cT))+ nbT = min(nbT, ab)+ naT = min(cT - nbT, aa)+ nbT = min(cT - naT, ab)+ if naT > 0:+ ia_parts.append(rng.choice(np.flatnonzero(la == T), naT, replace=False))+ if nbT > 0:+ ib_parts.append(rng.choice(np.flatnonzero(lb == T), nbT, replace=False))+ ia = np.concatenate(ia_parts) if ia_parts else np.array([], dtype=int)+ ib = np.concatenate(ib_parts) if ib_parts else np.array([], dtype=int)+ if diag is not None:+ achieved = alloc / max(int(alloc.sum()), 1)+ target = p / s+ diag["pearson_compos"] = float(np.corrcoef(achieved, target)[0, 1]) if len(types) > 1 else 1.0+ diag["n_shared_types"] = int(sum(1 for T in types if T in ma and T in mb))+ diag["n_b_only_types"] = int(sum(1 for T in types if T not in ma))+ diag["n_a_only_types"] = int(sum(1 for T in types if T not in mb))+ bmass_bonly = float(sum(alloc[i] for i, T in enumerate(types) if T not in ma))+ diag["b_mass_bonly"] = bmass_bonly+ diag["b_mass_shared"] = float(len(ib)) - bmass_bonly+ return ia, ib+++def _weighted_stratified(labels, n: int, rng: np.random.Generator) -> np.ndarray:+ """Same uniform type allocation as transport.stratified_choice (off-control).""" labels = np.asarray(labels).astype(str) n = int(min(max(n, 1), len(labels))) if n >= len(labels):@@ -86,13 +147,7 @@ def _weighted_stratified(labels, n: int, rng: np.random.Generator, logw: np.ndar if k <= 0: continue idx = np.flatnonzero(labels == lab)- lw = logw[idx]- if float(lw.max() - lw.min()) < 1e-12:- picks.append(rng.choice(idx, int(k), replace=False))- else:- w = np.exp(lw - lw.max())- w /= w.sum()- picks.append(rng.choice(idx, int(k), replace=False, p=w))+ picks.append(rng.choice(idx, int(k), replace=False)) return np.concatenate(picks) @@ -103,7 +158,8 @@ def main() -> None: parser.add_argument("--seed", type=int, default=0) args = parser.parse_args() - tau = float(os.environ.get("VEC_BIAS_TAU", BIAS_TAU))+ compos = os.environ.get("VEC_COMPOS_INTERP", "1" if COMPOS_INTERP else "0") not in ("0", "", "false")+ adj = float(os.environ.get("VEC_COMPOS_ADJ", COMPOS_ADJ)) t_draw_frac = float(os.environ.get("VEC_T_DRAW_FRAC", T_DRAW_FRAC)) manifest = load_manifest(args.data)@@ -119,46 +175,28 @@ def main() -> None: stage_b = read_stage(args.data, b, genes) params = board_params(manifest, "mix", PARAMS, args.seed) - diag: dict = {"bias_tau": tau, "t_draw_frac": t_draw_frac}- if tau != 0 or t_draw_frac != 1.0:- if tau != 0:- means_a = type_means(stage_a.X, stage_a.labels)- means_b = type_means(stage_b.X, stage_b.labels)- logw_a = _log_weights(stage_a, means_b, tau)- logw_b = _log_weights(stage_b, means_a, tau)- else:- logw_a = np.zeros(stage_a.n)- logw_b = np.zeros(stage_b.n)+ diag: dict = {"compos_interp": bool(compos), "adj": adj, "t_draw_frac": t_draw_frac}+ orig_mix = methods_mod.mix_indices+ if compos: - orig_mix = methods_mod.mix_indices+ def patched(labels_a, labels_b, tt, n, rng):+ ia, ib = _compos_mix(labels_a, labels_b, tt, n, rng, adj, diag)+ return ia, ib - drawn: dict = {}+ else: - def biased_mix(labels_a, labels_b, tt, n, rng):+ def patched(labels_a, labels_b, tt, n, rng): n_b = int(np.clip(int(round(float(tt) * t_draw_frac * n)), 0, n)) n_a = int(n) - n_b- ia = _weighted_stratified(labels_a, n_a, rng, logw_a) if n_a > 0 else np.array([], dtype=int)- ib = _weighted_stratified(labels_b, n_b, rng, logw_b) if n_b > 0 else np.array([], dtype=int)- drawn["ia"], drawn["ib"] = ia, ib+ ia = _weighted_stratified(labels_a, n_a, rng) if n_a > 0 else np.array([], dtype=int)+ ib = _weighted_stratified(labels_b, n_b, rng) if n_b > 0 else np.array([], dtype=int) return ia, ib - methods_mod.mix_indices = biased_mix- try:- expr, coords, info = interpolate(stage_a, stage_b, t, params)- finally:- methods_mod.mix_indices = orig_mix- # Evidence: mean cross-stage cosine of drawn vs all cells per stage.- sa = logw_a * tau- sb = logw_b * tau- ia, ib = drawn.get("ia", np.array([], int)), drawn.get("ib", np.array([], int))- for tag, s, idx in (("a", sa, ia), ("b", sb, ib)):- nz = s[s != 0]- nzd = s[idx][s[idx] != 0] if idx.size else np.array([])- diag[f"cos_{tag}_all"] = float(nz.mean()) if nz.size else None- diag[f"cos_{tag}_drawn"] = float(nzd.mean()) if nzd.size else None- diag[f"n_from_{tag}"] = int(idx.size)- else:+ methods_mod.mix_indices = patched+ try: expr, coords, info = interpolate(stage_a, stage_b, t, params)+ finally:+ methods_mod.mix_indices = orig_mix keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped", "align")} print(json.dumps({"bracket": [a["stage"], b["stage"]], **keep, **diag}, default=float), file=sys.stderr)
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k007 | Interval staging and held-out-window filtering of external data | notes/official/来件/virtualembryo.ai/rules.md |
| k024 | World-model evaluation dimensions for state-transition predictors | notes/competition/07_biomedical_world_models.md |
| k026 | Canonicalise predicted 3D coordinates before submission | notes/pitfalls/04_scorer_invariance.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 在父8基座上删除τ相似度偏置,将mix_indices替换为按型组成线性插值:目标比例p_T=(1−t)p_A+t·p_B分配型配额(最大余数+封顶重分),型内两阶段按n_B,T=round(c_T·t·ADJ)分配;PLAN首试ADJ=1.0,扫描后实际提交ADJ=0.0(共享型全取早期细胞),仅改抽样组成,不改表达与坐标。 |
|---|---|
| 各组分数的变化 | cell_state:变坏:51.65 vs 53.16,−1.51(超噪声,ADJ=0使共享型后期细胞519→86所致) expression_change:变好:62.09 vs 60.05,+2.04(超出T2约1分噪声,与代理上ec+1.0~1.4方向一致) local_spatial:噪声内偏正:60.27 vs 59.53,+0.74(接近1分噪声) shape_scale:变坏:67.14 vs 68.99,−1.85(超噪声,PLAN预期的'回升≥2'被证伪) 榜分:噪声内:60.29 vs 60.43,−0.14 |
| family_id | T2EI-01 |
| 假设是否成立 | 否 |
| 经验 |
|
| mechanism_active | 是 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 4 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 3 次:bash 2、write 1 |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 14,184 · 输出 1,081 · 思考 1,027 |
| 任务(第一行) | 分析节点 n10 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/analyst.jsonl 9 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 21 |
| 工具调用 | 共 24 次:bash 18、write 3、edit 2、read 1 |
| 用时 | 16 分 |
| token 数 | 输入 62,381 · 输出 10,598 · 思考 20,198 |
| 任务(第一行) | 按计划修改程序:按型组成线性插值替代统一frac抽样,修复shape_scale同时保持cell_state |
| 最后的回答(摘录) | **节点 10 完成**(improve,父 8 = 60.43)。
**做了什么**:按 PLAN 实现 T2EI-01 按型组成线性插值(p_T=(1−t)p_A+t·p_B 配额 + 型内 t·ADJ 两阶段分配,删 τ 偏置),关闭对照逐位等于父 8 对照(已验证)。扫描 ADJ∈{1.0, 0.5, 0.2, 0.0},提交最佳 ADJ=0.0。
**查分**(A 半,4/20 次):adj=1.0→55.63、0.5→57.72、0.2→59.19、**0.0→59.40** {cs 50.4, ec 61.2, ls 59.3, ss 66.7};父对照 59.88。PLAN 的"组成插值回升 shape_scale"假设被证伪:ss 由共享型 B 细胞量单调驱动,组成插值稳定带来 ec/ls +1 但 cs 损失更大,未超父(差距在噪声内),已如实写入 METHOD.md。
**下一步最值得试**:① cs/ss 前沿上父的 frac=0.5 近最优,改进需第二自由度——组成目标阻尼 d(t_comp=t·d)与型内 split 解耦,保持父的全局组成、只改共享型的型内阶段配比;② ec 对组成插值敏感(+1.4),可试仅对表达走组成插值、坐标走 frac=0.5 抽取的解耦方案(ANALYSIS 建议 2)。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/engineer.jsonl 119 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 2 分 |
| token 数 | 输入 10,733 · 输出 1,428 · 思考 3,867 |
| 任务(第一行) | 为节点 n10(改进,父节点 n8)写改进计划 PLAN.json |
| 最后的回答(摘录) | 至68.99(−5.44),原因是t_draw_frac=0.5统一削减后期细胞,丢失了后期阶段的空间覆盖。ANALYSIS建议2/3均指向解耦或按型组成插值。节点5(60.63)与节点8差距0.2在噪声内,说明frac=0.5的cell_state增益已饱和,下一步收益在恢复shape_scale。节点3/4(型内表达插值)gen_failed、节点7(1-NN位移)退化为常数位移、节点6(伪时间ramp)净负——这些方向不再重复。本方案实现T2EI-01的组成插值核心(尚未被任何节点实现过),放弃已证无效的τ偏置。",
"approach": "基座=父节点8的run.py,删除τ偏置(设τ=0,走无偏路径)。核心改动在mix_indices替换函数内:\n1. 读入stage_a、stage_b的labels,计算每型在两阶段的比例 p_A[T]=n_A,T/N_A, p_B[T]=n_B,T/N_B。\n2. 目标比例 p_T=(1−t)·p_A[T]+t·p_B[T](仅存在于至少一个阶段的型;两阶段都有的型正常插值,单阶段型按其在的那个阶段的比例乘(1−t)或t)。\n3. 总配额 n=5000(与父相同),按 p_T 分配 c_T=round(n·p_T/Σp),余数按最大余数法补齐(复用现有_alloc逻辑)。\n4. 型T内从A、B两阶段的分配:n_B,T=round(c_T·t),n_A,T=c_T−n_B,T;若某阶段该型细胞不足则从另一阶段补足。\n5. 型内均匀抽样(无τ偏置),用现有_weighted_stratified但logw全零即退化为均匀。\n6. 坐标与表达均取被抽细胞自身的值,不做额外修改。scale_damp=0.5、procrustes3d不变。\n\n关键参数:无新超参(t由manifest算出,n=5000不变)。如需微调可试n_B,T=round(c_T·t·adj),adj∈{0.8,1.0,1.2},但首轮用adj=1.0。\n\n单阶段退路:目标无括号时与父相同(最后观测阶段分层抽样)。\n\nvec-score筛选:先跑adj=1.0(1次),对比四组分与父节点8(59.63 A半);若shape_scale回升≥2且cell_state不降≥1,再试adj=0.8/1.2(最多再2次)。总查分≤5次。",
"expected_groups": ["shape_scale", "cell_state"],
"risks": "1) 按型插值后总后期细胞数可能与frac=0.5时不同(可能更多),cell_state可能回落——Engineer应在第一次查分后对比cell_state,若降>2分则提高adj或回退。2) 某些型在一阶段极少(<5个),配额分配可能产生0或过抽样——需clip到[0, stage_count]。3) 型标签在两阶段不完全一致(新型出现/旧型消失),单阶段型的处理需明确。4) 30分钟时限紧——代码改动集中在biased_mix函数内约30行,不需要新依赖;先在小数据上验证型配额正确性再全量跑。",
"family_id": "T2EI-01",
"mechanism": "将mix的统一后期抽取比例(frac·t)替换为按型线性插值组成:每型的目标比例p_T=(1−t)·p_A+t·p_B,型内再按t分配两阶段细胞数。改变的是每种细胞类型在输出中的数量配比,而非表达值或坐标。",
"vs_constant_shift": "常数位移对每个细胞加同一向量,不改变细胞类型组成;本方案改变各型在输出中的相对数量(有的型增加、有的减少),从而改变群体组成结构。全局组成重加权是对所有型乘同一系数;本方案是逐型独立插值,不同型的变化方向和幅度不同。",
"mechanism_evidence": "1) 输出中每型的实际比例与目标p_T的Pearson相关(应>0.99);2) 对比父节点8:列出后期细胞数变化最大的前5个型及其delta;3) 四组分各自变化:预期shape_scale回升≥2、cell_state变化在±1内;4) 总后期细胞数与父节点(1000/5000)的对比。",
"mechanism_off_control": "设VEC_COMPOS_INTERP=0(或代码内标志),此时回退到父节点8的抽样逻辑(统一frac=0.5、τ=0),输出应与父节点8逐位相同。Engineer验证:关闭后运行,比较X矩阵和坐标数组的np.array_equal。预期差别:关闭时shape_scale≈68.6(父8水平),开启后shape_scale应回升至71+。",
"sources": []
}
``` |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/researcher.jsonl 6 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-embryo-interp-g24/nodes/10/researcher.stderr |