总览 · ← 返回运行 20261003-004922-search-t2-heart-interp-g24-D
节点 n24
实现 T2HI-01 型内倾斜抽样:按两阶段型均值漂移方向 exp(±γ·投影) 加权重抽 mix 细胞,代理上目标组微升却被 shape_scale 抵消、净分不越噪,按止损以 γ=0(与父逐位一致)提交。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-004922-search-t2-heart-interp-g24-D |
|---|---|
| 父节点 | n19 |
| 子节点 | n26 |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 改进 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 61.41(+0.0) · proxy 61.41(+0.0) · 3 次复测均分 61.33 |
| 审查 | 通过 检查项1(越界读取):未发现问题——run.py 仅通过 load_manifest/read_stage/panel_genes 从 --data 视图读取(run.py:431-447),import 仅限 src.task2_spatial 框架模块,无绝对路径、无网络访问。; 检查项2(硬编码目标统计量):未发现问题——所有常量为算法超参数(K=20、STRENGTH=1.5、MAX_FRAC=0.45 等,run.py:61-72),细胞比例/配额/型均值差 d_type 均由 mix_indices、_wtake、_type_tilt_weights 从输入阶段现场计算,无写死的… |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 21 分 |
| 程序版本 | 23148fe95d13fa8401d8a3ac8aaa7912a2c46c4d (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 23148fe95d:solution/METHOD.md
实现 T2HI-01 型内倾斜抽样:按两阶段型均值漂移方向 exp(±γ·投影) 加权重抽 mix 细胞,代理上目标组微升却被 shape_scale 抵消、净分不越噪,按止损以 γ=0(与父逐位一致)提交。
方法族 / 实现
family_id = T2HI-01(型内亚群组成时间插值:倾斜 mix 抽样),按 PLAN 实现于 run.py:
_type_tilt_weights(stage_a, stage_b, gamma):对每个细胞型,若两括号阶段该型各 ≥3 个细胞,取表达矩阵(视图内 500 基因),算型均值差d_type = mean_hi − mean_lo(单位化d_hat);每细胞投影s_i = (X_i − 型总均值)·d_hat;权重w_lo = exp(−γ·s)(下括号)、w_hi = exp(+γ·s)(上括号),减去侧内最大值做数值稳定。缺失/退化/单侧型权重全为 1(均匀抽样)。不修改任何表达值,只决定哪些真实输入细胞进入 mix。_wtake:逐位复制sample.stratified_choice的分型配额逻辑,仅把型内rng.choice(idx, k, replace=False)换成带p=w[idx]/sum的加权抽样(配额、类型顺序不变)。_interpolate_mix_tilted:逐位复制methods.interpolate(coord=mix, expr=carry)的对齐/RMS 管线(align_pairprocrustes 保 z、log_interptarget_rms、scale_to_rms、_jitter、_pack_expr),仅把mix_indices换成_wtake加权抽样;返回源行索引ia, ib以便下游标签精确对应。抽中细胞的表达与坐标照常进入型内 kNN 坐标平滑(k=20, strength=1.5, max_frac=0.45, k_adaptive)等父19全部后处理,逻辑逐位不改。- 单输入阶段退路:
interp_bracket返回b=None,走父逻辑(分层抽末阶段),γ 不参与、无新行为。 - 关闭对照:
--gamma 0(默认值GAMMA=0.0)走原interpolate分支,与父19逐位一致。
对照结果(mechanism_off_control)
γ=0(默认)输出与父节点19在同一视图 seed 0 上的输出比较:X 与 spatial_3D 均 np.array_equal = True(preds/default_s0.h5ad vs preds/g0.h5ad)。A 半查分四组分(cell_state 65.93 / expression_change 63.83 / local_spatial 61.70 / shape_scale 52.68)与父19 METHOD.md 记录的关闭对照值逐项相同,交叉验证 γ=0 未引入副作用。默认参数即关闭态。
机制生效证据(proxy A 半,seed 0)
| γ | tilt_n_types(生效型) | tilt_n_skipped(退化型) | lo 侧平均投影偏移 | hi 侧平均投影偏移 |
|---|---|---|---|---|
| 0.3 | 5 | 28 | −2.87 | +1.95 |
| 0.7 | 5 | 28 | −4.77 | +3.70 |
投影偏移随 γ 单调增大,方向符合设计(下括号细胞被拉向漂移起点=负、上括号被拉向终点=正)→ 权重确实起作用。仅 5 个两阶段共有型(与 align 的 n_shared_types=5 一致)能算 d_type,其余 28 个单侧/小样本型退化为均匀抽样,因此倾斜只作用于少数细胞,效果受限。
机制检验:证伪(vec-score,A 半,seed 0,共用 3/20 次查分)
| 配置 | board | cell_state | expression_change | local_spatial | shape_scale |
|---|---|---|---|---|---|
| 关闭对照 γ=0(=父19) | 61.03 | 65.93 | 63.83 | 61.70 | 52.68 |
| γ=0.3 | 60.99 (−0.05) | 66.26 (+0.33) | 63.77 (−0.06) | 61.59 (−0.11) | 52.34 (−0.34) |
| γ=0.7 | 61.00 (−0.03) | 66.30 (+0.37) | 64.20 (+0.37) | 61.72 (+0.02) | 51.81 (−0.87) |
四组分变化符合 PLAN 预期模式:目标组 cell_state(+0.33/+0.37)与 expression_change(γ=0.7 时 +0.37)确实向正方向移动(说明型内亚群组成倾斜对表达分布有可测影响),但幅度均 <0.4,远小于 T2 噪声(~1 分);同时被抽中细胞集合改变导致坐标点集变化,shape_scale 单调下降(−0.34/−0.87)抵消了表达侧增益,local_spatial 基本不动。净 board 两档均低于关闭对照(−0.03~−0.05)。精确命中 PLAN 主止损判据(两档榜分均不高于对照 +1 分)。
按 PLAN:方向虽对但增益远低于噪声且被 shape_scale 抵消,不再花查分细调 {0.15, 1.0}(γ↓→两方向都缩小趋近对照,γ↑→shape_scale 掉得更多,无净增益区间)。提交关闭态 γ=0。
提交内容
默认参数即关闭态:输出与父节点19逐位一致(np.array_equal 验证 X 与 spatial_3D 均 True;A 半四组分逐项相同)。查分共 3 次(额度 20)。vec-check 通过;seed 0 两次运行 X/coords 逐位一致(确定性);EXECUTION.json 为 {"gpu": false}(纯 CPU)。运行时间 ~2 s,内存 <0.5 GB。
生物学知识来源
无新增外部生物学知识。仅使用 PLAN 给定的通用先验:同一细胞型在两发育阶段的型内表达均值差 d_type 反映该型的发育漂移方向(谱系/成熟连续),据此把 mix 抽样沿该方向倾斜以插值型内亚群组成。所有统计量(d_type、投影、配额)均从视图内两括号阶段的表达与标签现场计算,无硬编码阶段统计量;全部时间为 manifest 相对时间,视图平移不变;不做坐标旋转以外的假设。
未验证
- γ ∈ {0.15, 1.0}(PLAN 止损后不再细调:净榜分在两档已单调低于对照,无越噪增益区间)。
- 放宽 tilt_n_types 门槛(<3 细胞型也倾斜):仅 5 个共有型可算 d_type,是本 board 括号(E8.25↔E9.5 只剩 5 个同名型)的固有限制,非参数问题。
- 单独抑制 shape_scale 下降(如倾斜后再做尺度校正):父节点已证伪 RMS 恢复/径向尺度会把尺度推离参考,叠加倾斜不改变该结论。
- B 半与 final 视图(关闭态与父逐位一致,迁移性等同父节点19)。
调研员的计划
| 名称 | 型内亚群组成时间插值:按两阶段表达漂移方向倾斜 mix 抽样 |
|---|---|
| 动机 | 父19/17 榜分 61.41,最弱组 shape_scale 52.70 但坐标侧已平台化(节点17/18/21 证伪 RMS 恢复、径向尺度、边界权重;ANALYSIS 明确建议查分预算转向表达侧)。表达侧三条路线已证伪:节点12 型×基因趋势位移(任何非零位移掉分)、节点19 型内表达平滑(降方差→cell_state 单调大跌,alpha=0.05 时 −4.76)、节点20 对角方差外扩(无方向信息,β 全档增益<噪声 +0.06)。ANALYSIS 教训:表达修改须保持逐细胞真实异质性、只能重塑群体分布而非改表达值。尚未试过的是在抽样层面做型内亚群组成的时间插值:mix 目前只在型间按 (1−t,t) 插值细胞数(节点2/9),型内抽样是均匀的,未利用两输入阶段型内表达分布差异这一可用信号。 |
| 做法 | 在父19 管线(mix + 型内 kNN 坐标平滑 k=20 strength=1.5 mf=0.45 k_adaptive,表达平滑关闭)的 mix 抽样步骤内加入型内倾斜权重,步骤:(1) 对每个细胞型,取两括号阶段该型细胞的表达矩阵(仅用视图内数据,500 基因),分别标准化到零均值;(2) 算两阶段型均值差向量 d_type(500 维),若该型在一侧细胞数<3 则 d_type=0(该型退化为均匀抽样);(3) 对每个细胞算投影分数 s_i = (X_i − 型总均值)·d_type / (||d_type||+1e-9);(4) 带权抽样:下括号阶段该型细胞的抽样权重 w_lo,i = exp(−γ·s_i),上括号 w_hi,i = exp(+γ·s_i),归一化后作为 np.random.choice 的 p;γ 为倾斜强度,初值网格 {0.3, 0.7},若方向对再试 {0.15, 1.0};γ=0 时所有权重=1,退化为父管线(关闭对照);(5) 抽中细胞的表达与坐标照常进入后续 procrustes 对齐、log-RMS 缩放、kNN 坐标平滑,逻辑逐位不改。单输入阶段退路:无两阶段差异可算,d_type 全为 0,权重全为 1,管线退化为父逻辑(分层抽末阶段),无新行为。vec-score 快速筛选:先验证 γ=0 输出与父19 逐位一致(np.array_equal,0 次查分),再各查 γ=0.3 和 γ=0.7 一次分(2 次查分)定方向;若两档榜分均不高于关闭对照 1 分以上(T2 噪声约 1 分)即提交关闭态;若某档升>1 分,再花 ≤2 次查分细调。总查分预算 ≤6 次。所有时间用相对 manifest 的时间,视图平移不变;不做任何坐标旋转、不硬编码任何阶段统计量。 |
| 风险 | ① 评分器的 cell_state 若只比较逐基因边际分布而非亚群比例,则型内重抽样不动边际分布,预期中性(增益<噪声)——Engineer 用两档 γ 快速定向即可发现,止损提交关闭态。② 权重改变了被抽中的细胞集合,坐标点集随之变化,可能扰动 local_spatial(父17 在 62.34 已较高)——缓解:这是换真实细胞而非移动坐标,且 kNN 平滑逻辑不变;若 local_spatial 掉>1.5 而表达组升<1,止损。③ d_type 方向可能噪声主导(小样本型)——已设<3 细胞退化为均匀;若大样本型也无效,说明型内分布两阶段差异太小,机制无信号,止损。④ 30 分钟时限:实现<50 行、无新依赖、父管线仅 1.6 s,风险低;若超时,优先保证关闭态逐位一致提交。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:父节点版本 738087c486。改动的文件:solution/METHOD.md +29 −28、solution/run.py +174 −14
diff --git a/solution/METHOD.md b/solution/METHOD.mdindex d4535c2..78beea6 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,50 +1,51 @@-实现 T2HI-04 型内坐标kNN表达平滑并在代理上证伪(cell_state 单调下降、expression_change 不动),按 PLAN 止损条款以关闭态(alpha=0,与父节点17逐位一致)提交。+实现 T2HI-01 型内倾斜抽样:按两阶段型均值漂移方向 exp(±γ·投影) 加权重抽 mix 细胞,代理上目标组微升却被 shape_scale 抵消、净分不越噪,按止损以 γ=0(与父逐位一致)提交。 ## 方法族 / 实现 -family_id = **T2HI-04**(型内坐标 kNN 表达平滑),按 PLAN 完整实现于 `run.py::_expr_smooth`:+family_id = **T2HI-01**(型内亚群组成时间插值:倾斜 mix 抽样),按 PLAN 实现于 `run.py`: -1. 在父管线(mix, align=procrustes, scale_damp=1 + 型内 kNN 坐标平滑 k=20, strength=1.5, max_frac=0.45, k_adaptive)产出的**最终坐标**上,对每个细胞类型分别建 cKDTree(`--k-expr 15`,k_eff=min(k, max(3, m−1)),m<4 的型跳过)。-2. 每个细胞 i 的 mu_i = 其 k_expr 个同型坐标近邻(去掉自身)的表达均值;`X_new[i] = (1−alpha)·X[i] + alpha·mu_i`,对全部 500 个基因。-3. 单输入阶段退路:mix 回退为父逻辑(分层抽末阶段),表达平滑仍在该单阶段输出的型内坐标上执行(不依赖两阶段信息)。-4. 关闭对照:`--expr-alpha 0`(**默认值**)完全跳过平滑步骤。+1. `_type_tilt_weights(stage_a, stage_b, gamma)`:对每个细胞型,若两括号阶段该型各 ≥3 个细胞,取表达矩阵(视图内 500 基因),算型均值差 `d_type = mean_hi − mean_lo`(单位化 `d_hat`);每细胞投影 `s_i = (X_i − 型总均值)·d_hat`;权重 `w_lo = exp(−γ·s)`(下括号)、`w_hi = exp(+γ·s)`(上括号),减去侧内最大值做数值稳定。缺失/退化/单侧型权重全为 1(均匀抽样)。**不修改任何表达值**,只决定哪些真实输入细胞进入 mix。+2. `_wtake`:逐位复制 `sample.stratified_choice` 的分型配额逻辑,仅把型内 `rng.choice(idx, k, replace=False)` 换成带 `p=w[idx]/sum` 的加权抽样(配额、类型顺序不变)。+3. `_interpolate_mix_tilted`:逐位复制 `methods.interpolate`(coord=mix, expr=carry)的对齐/RMS 管线(`align_pair` procrustes 保 z、`log_interp` target_rms、`scale_to_rms`、`_jitter`、`_pack_expr`),仅把 `mix_indices` 换成 `_wtake` 加权抽样;返回源行索引 `ia, ib` 以便下游标签精确对应。抽中细胞的表达与坐标照常进入型内 kNN 坐标平滑(k=20, strength=1.5, max_frac=0.45, k_adaptive)等父19全部后处理,逻辑逐位不改。+4. 单输入阶段退路:`interp_bracket` 返回 `b=None`,走父逻辑(分层抽末阶段),γ 不参与、无新行为。+5. 关闭对照:`--gamma 0`(**默认值** `GAMMA=0.0`)走原 `interpolate` 分支,与父19逐位一致。 ## 对照结果(mechanism_off_control) -用父节点17的原 run.py(逐行还原,字节数 12170 一致)在同一视图 seed 0 上生成输出,与本节点默认输出比较:**X 与 spatial_3D 均 `np.array_equal = True`(逐位一致)**。开启态仅 X 改变,坐标、细胞数、类型组成不变。+γ=0(默认)输出与父节点19在同一视图 seed 0 上的输出比较:**X 与 spatial_3D 均 `np.array_equal = True`**(`preds/default_s0.h5ad` vs `preds/g0.h5ad`)。A 半查分四组分(cell_state 65.93 / expression_change 63.83 / local_spatial 61.70 / shape_scale 52.68)与父19 METHOD.md 记录的关闭对照值逐项相同,交叉验证 γ=0 未引入副作用。默认参数即关闭态。 -## 机制生效证据(proxy A 半,seed 0,全部 17616 细胞被平滑,0 跳过)+## 机制生效证据(proxy A 半,seed 0) -| alpha | 型内基因方差比 after/before | mean\|ΔX\|/SD | 改变>1%的细胞比例 |-|---:|---:|---:|---:|-| 0.02 | 0.963 | 0.0068 | 100% |-| 0.05 | 0.909 | 0.0169 | 100% |-| 0.10 | 0.822 | 0.0339 | 100% |-| 0.15 | 0.741 | 0.0508 | 100% |-| 0.25 | 0.593 | 0.0846 | 100% |+| γ | tilt_n_types(生效型) | tilt_n_skipped(退化型) | lo 侧平均投影偏移 | hi 侧平均投影偏移 |+|---:|---:|---:|---:|---:|+| 0.3 | 5 | 28 | −2.87 | +1.95 |+| 0.7 | 5 | 28 | −4.77 | +3.70 | -方差随 alpha 单调下降、幅度与 alpha 成正比 → 低通滤波确实运行。+投影偏移随 γ 单调增大,方向符合设计(下括号细胞被拉向漂移起点=负、上括号被拉向终点=正)→ 权重确实起作用。仅 5 个两阶段共有型(与 align 的 `n_shared_types=5` 一致)能算 d_type,其余 28 个单侧/小样本型退化为均匀抽样,因此倾斜只作用于少数细胞,效果受限。 -## 机制检验:证伪(vec-score,A 半,seed 0)+## 机制检验:证伪(vec-score,A 半,seed 0,共用 3/20 次查分) -| 配置 | cell_state | expression_change | local_spatial | shape_scale |-|---|---:|---:|---:|---:|-| **关闭对照 alpha=0(=父17)** | **65.93** | **63.83** | 61.70 | 52.68 |-| alpha=0.05, k=15 | 61.17 (−4.76) | 63.82 (−0.01) | 61.64 | 52.68 |-| alpha=0.10, k=15 | 58.38 (−7.55) | 63.81 (−0.02) | 61.58 | 52.68 |+| 配置 | board | cell_state | expression_change | local_spatial | shape_scale |+|---|---:|---:|---:|---:|---:|+| **关闭对照 γ=0(=父19)** | **61.03** | 65.93 | 63.83 | 61.70 | 52.68 |+| γ=0.3 | 60.99 (−0.05) | 66.26 (+0.33) | 63.77 (−0.06) | 61.59 (−0.11) | 52.34 (−0.34) |+| γ=0.7 | 61.00 (−0.03) | 66.30 (+0.37) | 64.20 (+0.37) | 61.72 (+0.02) | 51.81 (−0.87) | -四组分变化完全符合 PLAN 预期模式(坐标不动 → local_spatial / shape_scale 只有噪声级微动;表达动 → cell_state / expression_change 动),但方向相反:**cell_state 随平滑强度单调大跌,expression_change 纹丝不动**。精确命中 PLAN 风险①的止损判据(cell_state 降 >1.5 且 expression_change 升 <1)。解释:评分器的细胞状态组看的是预测群体与参考群体的表达分布距离;mix 输出已是真实细胞,其"噪声"就是参考群体自带的单细胞异质性,对它做低通滤波只会把分布收窄、偏离参考。PLAN 步骤5的"仅高方差基因平滑"变体只会按比例缩小同一错误方向的效果,不再消耗查分额度。按 PLAN 止损条款:**两个非零 alpha 均低于关闭对照 → 提交关闭态**。+四组分变化符合 PLAN 预期模式:**目标组 cell_state(+0.33/+0.37)与 expression_change(γ=0.7 时 +0.37)确实向正方向移动**(说明型内亚群组成倾斜对表达分布有可测影响),但幅度均 <0.4,远小于 T2 噪声(~1 分);同时被抽中细胞集合改变导致坐标点集变化,**shape_scale 单调下降(−0.34/−0.87)抵消了表达侧增益**,local_spatial 基本不动。净 board 两档均低于关闭对照(−0.03~−0.05)。精确命中 PLAN 主止损判据(两档榜分均不高于对照 +1 分)。++按 PLAN:方向虽对但增益远低于噪声且被 shape_scale 抵消,不再花查分细调 {0.15, 1.0}(γ↓→两方向都缩小趋近对照,γ↑→shape_scale 掉得更多,无净增益区间)。**提交关闭态 γ=0**。 ## 提交内容 -默认参数即关闭态:输出与父节点17逐位一致(已验证)。查分共 5 次(额度 20)。`vec-check` 通过;seed 0/1 各自确定;`EXECUTION.json` 为 `{"gpu": false}`。+默认参数即关闭态:输出与父节点19逐位一致(`np.array_equal` 验证 X 与 spatial_3D 均 True;A 半四组分逐项相同)。查分共 3 次(额度 20)。`vec-check` 通过;seed 0 两次运行 X/coords 逐位一致(确定性);`EXECUTION.json` 为 `{"gpu": false}`(纯 CPU)。运行时间 ~2 s,内存 <0.5 GB。 ## 生物学知识来源 -无新增外部生物学知识;仅使用"发育中空间邻近细胞表达连续"这一通用先验(PLAN 给定),且该先验在本 board 的评分下被证伪——单细胞分辨率的异质性本身被评分器计为细胞状态相似度的一部分。+无新增外部生物学知识。仅使用 PLAN 给定的通用先验:同一细胞型在两发育阶段的型内表达均值差 `d_type` 反映该型的发育漂移方向(谱系/成熟连续),据此把 mix 抽样沿该方向倾斜以插值型内亚群组成。所有统计量(d_type、投影、配额)均从视图内两括号阶段的表达与标签现场计算,无硬编码阶段统计量;全部时间为 manifest 相对时间,视图平移不变;不做坐标旋转以外的假设。 ## 未验证 -- 高方差基因子集平滑(判定为同一方向、按比例更弱的效果,止损后不测)。-- k_expr ∈ {10, 20}(PLAN 规定仅当 alpha 方向正确时才调 k)。-- B 半与 final 视图(关闭态与父逐位一致,迁移性等同父节点17)。+- γ ∈ {0.15, 1.0}(PLAN 止损后不再细调:净榜分在两档已单调低于对照,无越噪增益区间)。+- 放宽 tilt_n_types 门槛(<3 细胞型也倾斜):仅 5 个共有型可算 d_type,是本 board 括号(E8.25↔E9.5 只剩 5 个同名型)的固有限制,非参数问题。+- 单独抑制 shape_scale 下降(如倾斜后再做尺度校正):父节点已证伪 RMS 恢复/径向尺度会把尺度推离参考,叠加倾斜不改变该结论。+- B 半与 final 视图(关闭态与父逐位一致,迁移性等同父节点19)。diff --git a/solution/run.py b/solution/run.pyindex a073596..88e5186 100644--- a/solution/run.py+++ b/solution/run.py@@ -53,12 +53,14 @@ import numpy as np from scipy.spatial import cKDTree from src.task2_spatial.frame import align_pair, log_interp, rms_radius, scale_to_rms-from src.task2_spatial.methods import interpolate+from src.task2_spatial.methods import _jitter, _limits, _pack_expr, interpolate from src.task2_spatial.sample import mix_indices, take+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": "procrustes", "scale_damp": 1.0} K = 20+GAMMA = 0.0 # family T2HI-01: within-type tilt of the mix draw along the two-stage type-mean drift; 0 = off (control, bit-identical to parent) EXPR_ALPHA = 0.0 # family T2HI-04: per-type kNN expression smoothing weight; 0 = off (control, bit-identical to parent node 17) K_EXPR = 15 STRENGTH = 1.5 # grid-searched on the proxy A-half; 0 = parent behaviour (control)@@ -195,6 +197,154 @@ def _expr_smooth(expr: np.ndarray, coords: np.ndarray, labels: np.ndarray, k: in return Xn.astype(np.float32), ev +def _type_tilt_weights(stage_a, stage_b, gamma: float):+ """Family T2HI-01: per-cell sampling weights tilting the mix draw along the+ within-type two-stage expression drift direction.++ For each type with >= 3 cells on both sides: d_type = mean_hi - mean_lo+ (unit-normalised); s_i = (X_i - pooled type mean) . d_hat; weights+ w_lo = exp(-gamma*s), w_hi = exp(+gamma*s) (stabilised by subtracting the+ side max). Types missing on one side, with < 3 cells, or with a degenerate+ d keep weight 1 (uniform draw). No expression value is modified: the weights+ only choose WHICH real input cells enter the mix.+ Returns (w_a, w_b, evidence).+ """+ la = np.asarray(stage_a.labels).astype(str)+ lb = np.asarray(stage_b.labels).astype(str)+ wa = np.ones(la.size, dtype=np.float64)+ wb = np.ones(lb.size, dtype=np.float64)+ n_tilted = 0+ n_skipped = 0+ shift_a = []+ shift_b = []+ for lab in np.unique(la):+ ia = np.flatnonzero(la == lab)+ ib = np.flatnonzero(lb == lab)+ if ia.size < 3 or ib.size < 3:+ n_skipped += 1+ continue+ Xa = as_dense(stage_a.X, ia).astype(np.float64)+ Xb = as_dense(stage_b.X, ib).astype(np.float64)+ d = Xb.mean(axis=0) - Xa.mean(axis=0)+ nd = float(np.linalg.norm(d))+ if nd < 1e-9:+ n_skipped += 1+ continue+ dhat = d / nd+ pooled = np.concatenate([Xa, Xb], axis=0).mean(axis=0)+ sa = (Xa - pooled) @ dhat+ sb = (Xb - pooled) @ dhat+ ta = np.exp(-gamma * (sa - sa.max()))+ tb = np.exp(gamma * (sb - sb.max()))+ wa[ia] = ta+ wb[ib] = tb+ n_tilted += 1+ # expected projection shift of the drawn cells vs uniform (evidence)+ shift_a.append(float((ta * sa).sum() / ta.sum() - sa.mean()))+ shift_b.append(float((tb * sb).sum() / tb.sum() - sb.mean()))+ ev = {+ "tilt_n_types": int(n_tilted),+ "tilt_n_skipped_types": int(n_skipped),+ "tilt_mean_proj_shift_lo": float(np.mean(shift_a)) if shift_a else 0.0,+ "tilt_mean_proj_shift_hi": float(np.mean(shift_b)) if shift_b else 0.0,+ }+ return wa, wb, ev+++def _wtake(labels: np.ndarray, n: int, rng: np.random.Generator, w: np.ndarray) -> np.ndarray:+ """stratified_choice replica with within-type weighted draws (same allocation)."""+ labels = np.asarray(labels).astype(str)+ n = int(min(max(n, 1), len(labels)))+ if n >= len(labels):+ return np.arange(len(labels))+ types, counts = np.unique(labels, return_counts=True)+ raw = counts / counts.sum() * n+ alloc = np.floor(raw).astype(int)+ rem = int(n - alloc.sum())+ order = np.argsort(-(raw - alloc))+ for i in range(rem):+ alloc[order[i % len(order)]] += 1+ alloc = np.minimum(alloc, counts)+ deficit = int(n - alloc.sum())+ if deficit > 0:+ spare = counts - alloc+ for i in np.argsort(-spare):+ k = int(min(deficit, spare[i]))+ alloc[i] += k+ deficit -= k+ if deficit == 0:+ break+ picks = []+ for lab, k in zip(types, alloc):+ if k <= 0:+ continue+ idx = np.flatnonzero(labels == lab)+ p = w[idx]+ s = float(p.sum())+ if not np.isfinite(s) or s <= 0:+ picks.append(rng.choice(idx, int(k), replace=False))+ else:+ picks.append(rng.choice(idx, int(k), replace=False, p=p / s))+ return np.concatenate(picks)+++def _interpolate_mix_tilted(stage_a, stage_b, t: float, params: dict, wa: np.ndarray, wb: np.ndarray):+ """Replica of methods.interpolate (coord=mix, expr=carry) with weighted within-type draws.++ Returns (expr, coords, info, ia, ib) so downstream labels come from the exact+ drawn source rows. Alignment / RMS logic is copied unchanged.+ """+ 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 = _limits(params, stage_a.n, stage_b.n, t, "interp")+ n_b = int(np.clip(int(round(t * n)), 0, n))+ n_a = n - n_b+ if n_a == 0:+ ia = np.array([], dtype=int)+ ib = _wtake(stage_b.labels, n_b, rng, wb)+ elif n_b == 0:+ ia = _wtake(stage_a.labels, n_a, rng, wa)+ ib = np.array([], dtype=int)+ else:+ ia = _wtake(stage_a.labels, n_a, rng, wa)+ ib = _wtake(stage_b.labels, n_b, rng, wb)+ expr_parts = []+ coord_parts = []+ if ia.size:+ expr_parts.append(as_dense(stage_a.X, ia))+ coord_parts.append(np.asarray(ca[ia], dtype=np.float64))+ if ib.size:+ expr_parts.append(as_dense(stage_b.X, ib))+ coord_parts.append(np.asarray(cb[ib], dtype=np.float64))+ expr = _pack_expr(expr_parts)+ 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),+ coord="mix",+ expr="carry",+ blend="convex",+ scale_damp=damp,+ nearer=("b" if t >= 0.5 else "a"),+ n_from_a=int(ia.size),+ n_from_b=int(ib.size),+ )+ return expr, coords.astype(np.float32), info, ia, ib++ def _pca_normalize(coords: np.ndarray) -> np.ndarray: """Deterministic PCA canonicalisation: centroid -> PCA axes -> det=+1 -> third-moment sign.""" C = np.asarray(coords, dtype=np.float64)@@ -275,6 +425,7 @@ def main() -> None: parser.add_argument("--k-adaptive", choices=("on", "off"), default=("on" if K_ADAPTIVE else "off")) parser.add_argument("--expr-alpha", type=float, default=EXPR_ALPHA) parser.add_argument("--k-expr", type=int, default=K_EXPR)+ parser.add_argument("--gamma", type=float, default=GAMMA) args = parser.parse_args() manifest = load_manifest(args.data)@@ -295,25 +446,34 @@ 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) ev = {}- need_labels = args.strength != 0.0 or args.expr_alpha != 0.0 labels = None- if need_labels:- n = int(info["n"])- n_from_a = int(info["n_from_a"])- # reproduce the source-row labels exactly as interpolate drew them- rng = np.random.default_rng(int(params["seed"]))- ia, ib = mix_indices(stage_a.labels, stage_b.labels, t, n, rng)- if len(ia) != n_from_a or len(ia) + len(ib) != n:- raise RuntimeError("source reproduction mismatch")+ if args.gamma != 0.0:+ wa, wb, tev = _type_tilt_weights(stage_a, stage_b, args.gamma)+ ev.update(tev)+ expr, coords, info, ia, ib = _interpolate_mix_tilted(stage_a, stage_b, t, params, wa, wb) labs_a = np.asarray(stage_a.labels).astype(str)[ia] labs_b = np.asarray(stage_b.labels).astype(str)[ib] labels = np.concatenate([labs_a, labs_b])+ else:+ expr, coords, info = interpolate(stage_a, stage_b, t, params)+ need_labels = args.strength != 0.0 or args.expr_alpha != 0.0+ if need_labels:+ n = int(info["n"])+ n_from_a = int(info["n_from_a"])+ # reproduce the source-row labels exactly as interpolate drew them+ rng = np.random.default_rng(int(params["seed"]))+ ia, ib = mix_indices(stage_a.labels, stage_b.labels, t, n, rng)+ if len(ia) != n_from_a or len(ia) + len(ib) != n:+ raise RuntimeError("source reproduction mismatch")+ labs_a = np.asarray(stage_a.labels).astype(str)[ia]+ labs_b = np.asarray(stage_b.labels).astype(str)[ib]+ labels = np.concatenate([labs_a, labs_b]) if args.strength != 0.0:- coords, ev = _knn_smooth(coords, labels, args.k, args.strength, args.max_frac,- adaptive=(args.k_adaptive == "on"))+ coords, ev_sm = _knn_smooth(coords, labels, args.k, args.strength, args.max_frac,+ adaptive=(args.k_adaptive == "on"))+ ev.update(ev_sm) if args.rescale_damp != 0.0 or args.aniso == "on": coords, ev2 = _rms_restore(coords, float(info["target_rms"]), args.rescale_damp, args.aniso == "on", args.aniso_damp, stage_a, stage_b, t,@@ -331,7 +491,7 @@ def main() -> None: print(json.dumps({"bracket": [a["stage"], b["stage"]], **keep, "strength": args.strength, "k": args.k, "pca_norm": args.pca_norm, "rescale_damp": args.rescale_damp, "aniso": args.aniso, "aniso_damp": args.aniso_damp, "k_adaptive": args.k_adaptive,- "expr_alpha": args.expr_alpha, "k_expr": args.k_expr, **ev}, default=float), file=sys.stderr)+ "expr_alpha": args.expr_alpha, "k_expr": args.k_expr, "gamma": args.gamma, **ev}, default=float), file=sys.stderr) write_t2(args.out, expr, coords, genes, seed=args.seed)
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k007 | Interval staging and held-out-window filtering of external data | notes/official/来件/virtualembryo.ai/rules.md |
| k027 | Joint expression-geometry generation with relative geometry | notes/competition/03_solution_landscape.md |
| k024 | World-model evaluation dimensions for state-transition predictors | notes/competition/07_biomedical_world_models.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 在父19管线的 mix 抽样步实现 T2HI-01 型内倾斜抽样(按两阶段型均值漂移方向 exp(±γ·投影) 加权抽细胞,_type_tilt_weights/_wtake/_interpolate_mix_tilted);代理上 γ=0.3/0.7 净榜分均低于 γ=0 对照(−0.05/−0.03),命中止损,最终以 γ=0 关闭态提交,输出与父19逐位一致(np.array_equal X/coords 均 True),故榜分与四组分与父完全相同(+0.00)。 |
|---|---|
| 各组分数的变化 | cell_state:不变(+0.00,关闭态;代理上 γ>0 时 +0.33/+0.37,噪声内) expression_change:不变(+0.00,提交为关闭态,与父19逐位一致;代理上 γ>0 时 +0.33~+0.37,在 T2 噪声~1 分内) local_spatial:不变(+0.00,关闭态;代理上 γ>0 时 −0.11/+0.02,噪声内) shape_scale:不变(+0.00,关闭态;代理上 γ>0 时 −0.34/−0.87 单调下降,抵消表达侧微增益) |
| family_id | T2HI-01 |
| 假设是否成立 | 否 |
| 经验 |
|
| mechanism_active | 是 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 2 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 1 次:write 1 |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 12,023 · 输出 927 · 思考 522 |
| 任务(第一行) | 分析节点 n24 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/analyst.jsonl 5 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 32 |
| 工具调用 | 共 35 次:bash 19、edit 9、read 6、write 1 |
| 用时 | 15 分 |
| token 数 | 输入 73,348 · 输出 10,796 · 思考 13,671 |
| 任务(第一行) | 按计划修改程序:型内亚群组成时间插值:按两阶段表达漂移方向倾斜 mix 抽样 |
| 最后的回答(摘录) | Done. Final state committed in `solution/`. **做了什么**:在父19管线的 mix 抽样步实现 PLAN 的 T2HI-01 型内倾斜抽样(`_type_tilt_weights` + `_wtake` + `_interpolate_mix_tilted`):按两括号阶段每个共有型的表达均值差方向 d_type,对每细胞投影 s_i,用 exp(∓γ·s) 加权下/上括号侧的型内抽样,只换被抽中的真实细胞、不改任何表达值或坐标变换。单输入退路不变。 **查分结果(proxy A半,seed0,用 3/20 次)**: - γ=0(对照)board 61.03,四组分与父19记录逐项相同 → 确认 γ=0 与父逐位一致(`np.array_equal` X/coords 均 True)。 - γ=0.3 board 60.99、γ=0.7 board 61.00,均低于对照。 - 机制确实生效:目标组 cell_state(+0.33/+0.37)、expression_change(γ=0.7 +0.37)向正方向移动,投影偏移随 γ 单调增大;但增益 <0.4 远低于噪声,且被 shape_scale 单调下降(−0.34/−0.87,因抽中细胞坐标集改变)抵消,净分为负。命中 PLAN 主止损判据 → 提交关闭态 γ=0(默认),与父19逐位一致。 **下一步最值得试**:本 board 括号 E8.25↔E9.5 只剩 5 个共有型,型内倾斜只作用于少数细胞,天花板很低;表达侧三条路线(趋势位移、kNN 平滑、方差外扩、亚群倾斜)均已证伪,坐标侧也平台化。建议换家族——例如利用 view 里挂载的 MOSTA E9.5 外部空间数据做型内坐标/表达先验(尚未被任何节点使用),或直接接受父17/19 平台、把预算留给其它 board。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/engineer.jsonl 226 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 5 分 |
| token 数 | 输入 12,489 · 输出 5,714 · 思考 8,192 |
| 任务(第一行) | 为节点 n24(改进,父节点 n19)写改进计划 PLAN.json |
| 最后的回答(摘录) | 闭)的 mix 抽样步骤内加入型内倾斜权重,步骤:(1) 对每个细胞型,取两括号阶段该型细胞的表达矩阵(仅用视图内数据,500 基因),分别标准化到零均值;(2) 算两阶段型均值差向量 d_type(500 维),若该型在一侧细胞数<3 则 d_type=0(该型退化为均匀抽样);(3) 对每个细胞算投影分数 s_i = (X_i − 型总均值)·d_type / (||d_type||+1e-9);(4) 带权抽样:下括号阶段该型细胞的抽样权重 w_lo,i = exp(−γ·s_i),上括号 w_hi,i = exp(+γ·s_i),归一化后作为 np.random.choice 的 p;γ 为倾斜强度,初值网格 {0.3, 0.7},若方向对再试 {0.15, 1.0};γ=0 时所有权重=1,退化为父管线(关闭对照);(5) 抽中细胞的表达与坐标照常进入后续 procrustes 对齐、log-RMS 缩放、kNN 坐标平滑,逻辑逐位不改。单输入阶段退路:无两阶段差异可算,d_type 全为 0,权重全为 1,管线退化为父逻辑(分层抽末阶段),无新行为。vec-score 快速筛选:先验证 γ=0 输出与父19 逐位一致(np.array_equal,0 次查分),再各查 γ=0.3 和 γ=0.7 一次分(2 次查分)定方向;若两档榜分均不高于关闭对照 1 分以上(T2 噪声约 1 分)即提交关闭态;若某档升>1 分,再花 ≤2 次查分细调。总查分预算 ≤6 次。所有时间用相对 manifest 的时间,视图平移不变;不做任何坐标旋转、不硬编码任何阶段统计量。",
"expected_groups": ["cell_state", "expression_change"],
"risks": "① 评分器的 cell_state 若只比较逐基因边际分布而非亚群比例,则型内重抽样不动边际分布,预期中性(增益<噪声)——Engineer 用两档 γ 快速定向即可发现,止损提交关闭态。② 权重改变了被抽中的细胞集合,坐标点集随之变化,可能扰动 local_spatial(父17 在 62.34 已较高)——缓解:这是换真实细胞而非移动坐标,且 kNN 平滑逻辑不变;若 local_spatial 掉>1.5 而表达组升<1,止损。③ d_type 方向可能噪声主导(小样本型)——已设<3 细胞退化为均匀;若大样本型也无效,说明型内分布两阶段差异太小,机制无信号,止损。④ 30 分钟时限:实现<50 行、无新依赖、父管线仅 1.6 s,风险低;若超时,优先保证关闭态逐位一致提交。",
"family_id": "T2HI-01",
"mechanism": "在 mix 抽样阶段,按两输入阶段型内表达均值差方向对每个细胞投影,用 exp(±γ·投影) 做倾斜抽样,使型内亚群组成按时间分数 t 在两阶段分布间插值;不改变任何被抽中细胞的表达值或坐标变换逻辑。",
"vs_constant_shift": "常数位移/全局组成重加权是对所有细胞加同一向量或按型乘同一系数;本机制按每个细胞在型内两阶段漂移方向上的投影赋不同权重(细胞级、方向有信息、型特异性),且只作用于抽样选择而不修改表达值——输出中每个细胞的表达仍是某个真实输入细胞的原始表达,不存在人工位移。",
"mechanism_evidence": "Engineer 记录并比较:(1) γ>0 时被抽中细胞的投影分数分布相对 γ=0 是否按预期偏移(下括号细胞平均投影应下降、上括号上升,用两阶段各型的均值偏移量衡量);(2) 型内亚群比例变化:对每型用型内前 3 个主成分做简单二分聚类,比较 γ=0 与 γ>0 时两阶段细胞占比是否向目标时间 t 移动;(3) 四组分各自变化:预期 cell_state 与 expression_change 动、local_spatial 与 shape_scale 基本不动(若 local_spatial 动则说明坐标点集变化过大,需报告)。机制未生效的判据:投影分数分布在 γ>0 与 γ=0 间无可分辨偏移(说明权重没起作用)。",
"mechanism_off_control": "γ=0(默认)时所有抽样权重=1,抽样退化为父管线的均匀分层抽样,表达、坐标、细胞数、类型组成逐位不变。Engineer 用 γ=0 输出与父19 输出做 np.array_equal 验证(X 与 spatial_3D 均须 True),不消耗查分;若不等则说明实现有副作用,先修复再测。预期差别:γ>0 时抽中细胞集合改变(表达矩阵行集合不同),但每行仍是某真实输入细胞的原始表达;γ=0 时与父逐位一致。"
}
``` |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/researcher.jsonl 22 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/researcher.stderr |
审查员
| 角色 | 审查员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 5 |
| 工具调用 | 共 9 次:read 7、bash 1、write 1 |
| 用时 | 不到 1 分 |
| token 数 | 输入 22,589 · 输出 1,248 · 思考 1,033 |
| 任务(第一行) | 审查节点 n24 的程序是否越界读取、写死目标、钻评分器漏洞 |
| 最后的回答(摘录) | REVIEW.json written |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/reviewer.jsonl 116 KB /home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24-D/nodes/24/reviewer.stderr |