总览 · ← 返回运行 20261001-233756-search-t1-abc-r0-B-population
节点 n28
copy_last 两级增殖重加权(β_type=-4、β_cell=-1)+ 增殖-表达斜率逐细胞放大(γ=-1.6、|slope|>0.1);PLAN 的确定性类型配额与类型自适应 γ 实测无效/有害,均默认关闭。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261001-233756-search-t1-abc-r0-B-population |
|---|---|
| 父节点 | n7 |
| 子节点 | n29 |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 改进 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 54.74(+0.2) · proxy 57.11(+0.3) · proxy2 57.11(+0.3) · X3 50.00(+0.0) · 3 次复测均分 54.66 |
| 审查 | 通过 1 越界读取:未发现问题——run.py 仅通过 view_io 接口读 args.data 指向的视图内文件(run.py:127-130),无绝对路径/`..`/prior 之外的读取,无联网。; 2 硬编码目标统计量:未发现问题——常量仅为超参数(β/γ/slope 阈值,run.py:49-56)和通用细胞周期基因列表 PROLIF(run.py:58-59,METHOD.md 注明来源为通用细胞周期标记注释),增殖得分、类型均值、斜率均从输入快照现场计算(run.py:134-207),无按类型名写死的比例或表达数值。; 3 钻评分器漏洞:未发现问题——抽样权重与表达调整基于增殖-… |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 13 分 |
| 程序版本 | ddc49f6e3ac762fcbb1f020e38cc4c742617bc58 (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git ddc49f6e3a:solution/METHOD.md
copy_last 两级增殖重加权(β_type=-4、β_cell=-1)+ 增殖-表达斜率逐细胞放大(γ=-1.6、|slope|>0.1);PLAN 的确定性类型配额与类型自适应 γ 实测无效/有害,均默认关闭。
方法
基底(继承 node 4/6/7,已验证):输出 = 最新「官方」输入阶段的 Efraimidis–Spirakis 加权无放回抽样,权重 = w_type × w_cell:
- w_type = max(1e-6, 1 + β_type·(prolif_type − mean_prolif)),β_type = -4(node 4);
- w_cell = max(1e-6, 1 + β_cell·(prolif_cell − prolif_type)),β_cell = -1(node 6)。
prolif 得分 = PROLIF 通用 cell-cycle 基因(Mki67, Top2a, Pcna, Cdk1, Ccna2, Ccnb1, Aurkb, Bub1, Cenpf, Nusc1,非阶段特异知识,来源:通用细胞周期标记注释)log 表达逐细胞均值,全部在输入快照内计算,单输入阶段可用。
表达调整(继承 node 7 机制、node 18 参数):每类型(≥20 细胞)内对全部源细胞做 OLS slope_g = cov(x_g, prolif)/var(prolif),保留 |slope_g| > 0.1;被选细胞 x_adj = x + γ·slope_g·(prolif_i − type_mean),γ = -1.6(放大类型内增殖-表达耦合),clip ≥0,1024 行分块。保护开关:所选阶段为外部来源、或抽样退化(n_target ≥ 池大小,如 X3)时跳过表达调整。
本节点实测(PLAN 三机制,proxy A 半 seed0,对照 = γ-1.6/sm0.1 随机抽样 = 57.59)
| 机制 | 结果 | 判定 |
|---|---|---|
| 确定性类型配额(最大余数法 + 类型内 E-S) | 55.60(covariation 53.0→49.1、cell_state 63.2→58.7、direction +0.5) | 有害,回退随机 E-S(PLAN 风险 1 兑现:全局 E-S 竞争的配额"噪声"本身有益) |
| 类型自适应 γ:γ_t = γ·clip((std_t/median_std)^α, 0.25, 4) | α=0.5/1.0/2.0 → 57.62/57.65/57.56(α=2 的 de_recovery 52.5→52.0) | 全部在 ±0.06 噪声内,无效,α=0 |
| 小类型斜率收缩 slope·n_t/(n_t+k)(n_t<50) | k=20/50 → 57.59(与对照逐字节相同:proxy 池无 20≤n_t<50 的类型) | 无效果,k=0 |
附加扫描:γ=-2.0 → 57.47、γ=-2.4 → 57.31(更负无益,-1.6 已是 A 半峰值区);sm=0.15 → 57.60(与 0.1 打平);β_cell=-2 → 55.28(大幅变差,维持 -1)。
发布配置与查分记录(A 半)
发布默认 = 对照配置(quota=0、α=0、k=0、γ=-1.6、sm=0.1、β=-4/-1),默认参数输出与查分文件逐字节一致(已核)。
- proxy seed0:57.59(cell_state 63.15 / covariation 53.02 / de_recovery 52.48 / direction 59.69)
- proxy seed1:57.31(一致,父配置 γ=-0.8/sm=0.05 的 A 半为 57.20/56.89)
- proxy2 seed0:57.59(外部 Qiu E9.0 被 pick_stage 忽略,输出同 proxy)
- X3 seed0:50.0(退化保护生效,= copy_last)
- 预期节点分 ≈ (57.6+57.6+50)/3 ≈ 55.1 A 半(父 54.54 板分 / node18 同配置 54.74 板分)
验证过
- 三视图(proxy/proxy2/X3)跑通、vec-check ok、运行 ~5 s、内存远低于限额。
- 确定性:仅 np.random.default_rng(seed)。
- 配额分配器单独验证过总和 = n_target(在 quota=1 分支,虽默认关闭)。
没验证 / 风险
- 发布配置与 node 18/21/23 机制相同(γ=-1.6、sm=0.1),A 半 57.59 vs 其记录的 A 半未见更高点;对父 node 7 的提升(+0.39 A 半)在 T1 噪声(~2 分)内,但方向与 node18 的 B 半结果(54.74 > 54.54)一致。
- 确定性配额在 B 半或其他视图是否同样有害未验证(A 半差距 -2.0,接近噪声边缘但四组指标同向恶化,判定可信度较高)。
- final 视图(E8.5+E9.5→E10.5)未测:若 E9.5 池 ≤ 目标细胞数则触发退化保护,退回 copy_last(安全无增益)。
- 类型自适应 γ 的无效可能因 proxy 池各类型 prolif 离散度差异小(median 归一后 ratio≈1);在类型异质性更大的视图上未测。
调研员的计划
| 名称 | 确定性类型配额抽样 + 类型自适应γ(按增殖离散度缩放表达调整强度) |
|---|---|
| 动机 | 父节点7最弱组为 de_recovery 51.69 和 covariation 52.88。子节点18/21/23/26反复证实:全局γ增大时 cell_state 与 covariation 呈等板分 trade-off(node26:'cov与cell_state是等board分trade-off曲线'),且 de_recovery 对一切表达级扰动免疫(7个节点均为51.69)。当前乘法权重 w_type·w_cell 的 E-S 抽样使类型配额受随机性扰动,direction 组(56.25)因此停滞。本方案用确定性类型配额消除组成噪声,同时用类型自适应γ在信号强的类型放大调整、信号弱的类型收缩调整,意图在不牺牲 covariation 的前提下提升 cell_state,并改善 direction。 |
| 做法 | 步骤1(确定性类型配额):将抽样拆为两层——先按 n_t = round(n_target × count_t·w_type_t / Σ_j count_j·w_type_j) 确定每类型配额(最大余数法修正总和),再在每类型内部用 w_cell 做 E-S 无放回抽样。β_type=-4 不变。这使组成完全由 β_type 决定,消除 E-S 全局竞争带来的配额噪声。 步骤2(类型自适应γ):对每个类型 t 计算增殖得分标准差 std_t;定义 γ_t = γ_base × (std_t / median(std_all))^α,clip 到 [0.25×γ_base, 4×γ_base]。α=0 退化为父逻辑(全局γ)。机制:增殖离散度高的类型斜率信号可靠,放大调整;离散度低的类型斜率是噪声,收缩保护 covariation。 步骤3(小类型斜率收缩):对细胞数 < 50 的类型,slope_g ×= n_t/(n_t+k),k 为收缩参数,防止少细胞类型的噪声斜率被放大。 关键参数初值与扫描范围:γ_base=-1.6(继承 node18 最优);SLOPE_MIN=0.1(继承 node18);α∈{0, 0.5, 1.0, 2.0}(α=0 为对照);k∈{0, 20, 50}(k=0 为对照)。 扫描策略(≤12次查分):① 固定γ=-1.6, k=0,扫α 4点(4次);② 取最优α,扫k 3点(3次);③ 若最优组合超对照≥1分,在γ∈{-1.2,-2.0}上确认(2次);④ 最优组合跑 seed1 确认(1次);⑤ X3 验证保护生效(1次)。 单输入退路:所有统计量(增殖得分、类型标签、表达矩阵)均在单个快照内计算,不依赖第二时间点。proxy2 的外部 Qiu 输入被 pick_stage 忽略(同父逻辑)。X3/退化视图:n_target≥池大小时跳过表达调整,确定性配额也退化为全量复制(等价 copy_last)。final 视图(E8.5+E9.5→E10.5):若 E9.5 池≤目标数,同样触发退化保护。 vec-score 快速筛选:先只跑 proxy A半 seed0 对比对照(α=0 即父逻辑),若某α下 proxy 总分 < 对照-1 则立即淘汰该α。 |
| 风险 | 1) 确定性配额可能不如随机 E-S(随机性可能恰好有益):Engineer 应在第一次查分时就对比 α=0+确定性配额 vs α=0+随机配额(即父逻辑),若确定性配额单独就降分则回退随机抽样,只保留自适应γ。2) α>0 使部分类型γ极小(接近0),等价于对这些类型关闭调整,可能损失 cell_state:观察分组中 covariation 是否如预期上升;若 cell_state 降>1 且 covariation 无补偿则判定失败。3) 改善幅度可能仍在 T1 噪声(~2分)内:用最优配置的 seed0+seed1 两次查分确认一致性,差距<1分则视为无进展。4) 小类型斜率收缩(k>0)可能过度抑制真实信号:若 k=50 低于 k=0 则弃用。5) 实现复杂度:确定性配额需处理余数分配(最大余数法),Engineer 应先用小数据(前200个细胞)验证配额总和正确。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:父节点版本 460e9acb2e。改动的文件:solution/METHOD.md +31 −25、solution/run.py +107 −33
diff --git a/solution/METHOD.md b/solution/METHOD.mdindex 88d77db..5732847 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,38 +1,44 @@-# copy_last 两级增殖重加权(β_type=-4、β_cell=-1)+ 增殖-表达回归斜率的逐细胞表达放大(γ=-0.8),外部/退化视图跳过表达调整。+# copy_last 两级增殖重加权(β_type=-4、β_cell=-1)+ 增殖-表达斜率逐细胞放大(γ=-1.6、|slope|>0.1);PLAN 的确定性类型配额与类型自适应 γ 实测无效/有害,均默认关闭。 ## 方法 -基底(继承节点 4/6,已验证):输出 = 最新「官方」输入阶段的加权无放回抽样(Efraimidis–Spirakis)。权重两级相乘:-- 类型级 w_type = max(1e-6, 1 + β_type·(prolif_type − mean_prolif)),β_type = **-4**(节点 4 扫出);-- 细胞级 w_cell = max(1e-6, 1 + β_cell·(prolif_cell − prolif_type)),β_cell = **-1**(节点 6 方向,本节点以乘法形式叠加)。+基底(继承 node 4/6/7,已验证):输出 = 最新「官方」输入阶段的 Efraimidis–Spirakis 加权无放回抽样,权重 = w_type × w_cell:+- w_type = max(1e-6, 1 + β_type·(prolif_type − mean_prolif)),β_type = **-4**(node 4);+- w_cell = max(1e-6, 1 + β_cell·(prolif_cell − prolif_type)),β_cell = **-1**(node 6)。 -prolif 得分 = PROLIF 基因(Mki67, Top2a, Pcna, Cdk1, Ccna2, Ccnb1, Aurkb, Bub1, Cenpf, Nusc1,通用 cell-cycle 标记,非阶段特异知识;与面板取交集,≥3 个才启用)log 表达的逐细胞均值,完全在输入快照内计算。+prolif 得分 = PROLIF 通用 cell-cycle 基因(Mki67, Top2a, Pcna, Cdk1, Ccna2, Ccnb1, Aurkb, Bub1, Cenpf, Nusc1,非阶段特异知识,来源:通用细胞周期标记注释)log 表达逐细胞均值,全部在输入快照内计算,单输入阶段可用。 -新增表达调整(本节点,PLAN 机制但**符号与预期相反**):-1. 对每个细胞类型(细胞数 ≥20),用该类型**全部**源细胞做 OLS:slope_g = cov(x_g, prolif)/var(prolif)(稀疏矩阵-向量积实现,无需稠密化全矩阵);只保留 |slope_g| > 0.05 的基因。-2. 对每个被选中细胞 i:x_adj[i,g] = x[i,g] + γ·slope_g·(type_mean_prolif − prolif_i),clip ≥0,按 1024 行分块稠密计算。-3. γ 扫描(proxy A 半):0 → 56.28;+0.05/+0.15/+0.3 → 56.24/55.89/55.31(PLAN 预设的正 γ **单调降分,证伪**);**-0.05/-0.1/-0.2/-0.4/-0.8/-1.6 → 56.40/56.58/56.68/56.83/57.20/57.37**。负 γ = 沿斜率**放大**细胞自身的增殖偏离(增强类型内增殖梯度对比),选 γ = **-0.8**(-1.6 总分仅 +0.17 且 covariation 从 53.6 掉到 51.6,判为 A 半过拟合风险,弃用)。-4. 跳过条件:所选阶段为外部来源,或抽样退化(n_target ≥ 池大小,如 X3)。X3 上未加保护时 γ=-0.8 使分数 50.0 → 43.2(covariation 28.8),加保护后恢复 50.0(已查分验证)。+表达调整(继承 node 7 机制、node 18 参数):每类型(≥20 细胞)内对全部源细胞做 OLS slope_g = cov(x_g, prolif)/var(prolif),保留 |slope_g| > **0.1**;被选细胞 x_adj = x + γ·slope_g·(prolif_i − type_mean),γ = **-1.6**(放大类型内增殖-表达耦合),clip ≥0,1024 行分块。保护开关:所选阶段为外部来源、或抽样退化(n_target ≥ 池大小,如 X3)时跳过表达调整。 -## 查分记录(A 半)+## 本节点实测(PLAN 三机制,proxy A 半 seed0,对照 = γ-1.6/sm0.1 随机抽样 = 57.59) -- proxy seed0 γ=-0.8:**57.20**(de_recovery 52.48 / direction 59.72 / cell_state 61.45 / covariation 53.56)-- proxy seed1 γ=-0.8:56.89(一致)-- proxy2 seed0:57.20(外部 Qiu E9.0 被忽略,输出与 proxy 逐字节相同,md5 已核)-- X3 seed0:50.0(保护生效,= copy_last)-- 基底 γ=0(β_cell=-1 乘法叠加):56.28,已高于节点 4(55.23)与节点 6(55.81)的 A 半查分-- β_type 重扫(γ=0):-3 → 55.62,-5 → 55.34,均低于 -4(56.28),维持 -4-- 预期节点分 ≈ (57.2+57.2+50)/3 ≈ 54.8 A 半(父 53.48)+| 机制 | 结果 | 判定 |+|---|---|---|+| 确定性类型配额(最大余数法 + 类型内 E-S) | **55.60**(covariation 53.0→49.1、cell_state 63.2→58.7、direction +0.5) | **有害,回退随机 E-S**(PLAN 风险 1 兑现:全局 E-S 竞争的配额"噪声"本身有益) |+| 类型自适应 γ:γ_t = γ·clip((std_t/median_std)^α, 0.25, 4) | α=0.5/1.0/2.0 → 57.62/57.65/57.56(α=2 的 de_recovery 52.5→52.0) | 全部在 ±0.06 噪声内,无效,α=0 |+| 小类型斜率收缩 slope·n_t/(n_t+k)(n_t<50) | k=20/50 → 57.59(与对照逐字节相同:proxy 池无 20≤n_t<50 的类型) | 无效果,k=0 |++附加扫描:γ=-2.0 → 57.47、γ=-2.4 → 57.31(更负无益,-1.6 已是 A 半峰值区);sm=0.15 → 57.60(与 0.1 打平);β_cell=-2 → 55.28(大幅变差,维持 -1)。++## 发布配置与查分记录(A 半)++发布默认 = 对照配置(quota=0、α=0、k=0、γ=-1.6、sm=0.1、β=-4/-1),默认参数输出与查分文件逐字节一致(已核)。++- proxy seed0:**57.59**(cell_state 63.15 / covariation 53.02 / de_recovery 52.48 / direction 59.69)+- proxy seed1:57.31(一致,父配置 γ=-0.8/sm=0.05 的 A 半为 57.20/56.89)+- proxy2 seed0:57.59(外部 Qiu E9.0 被 pick_stage 忽略,输出同 proxy)+- X3 seed0:50.0(退化保护生效,= copy_last)+- 预期节点分 ≈ (57.6+57.6+50)/3 ≈ 55.1 A 半(父 54.54 板分 / node18 同配置 54.74 板分) ## 验证过 -- 三视图(proxy/proxy2/X3)跑通、vec-check ok、运行 ~5 s、内存远低于 28 GB 限额。-- 确定性:仅 np.random.default_rng(seed);proxy 与 proxy2 输出 md5 相同。-- γ=0 时与父逻辑等价(β_cell 乘法叠加版)。+- 三视图(proxy/proxy2/X3)跑通、vec-check ok、运行 ~5 s、内存远低于限额。+- 确定性:仅 np.random.default_rng(seed)。+- 配额分配器单独验证过总和 = n_target(在 quota=1 分支,虽默认关闭)。 ## 没验证 / 风险 -- γ=-0.8 与 -0.4/-1.6 的差距(<0.6 分)在 T1 噪声(~2 分)内;-0.8 是折中(de_recovery +1、covariation -1.3 相对基底)。-- 负 γ 的机制解释:放大类型内增殖-表达耦合让群体在增殖轴上更分散,mmd_u 与 de_score 同升;B 半是否重现未验证。-- final 视图(E8.5+E9.5→E10.5)未测:若 E9.5 池 ≤ 目标细胞数,表达调整会被退化保护跳过,只剩 copy_last(安全但无增益)。-- 「退化即跳过」保护对 X3 有效,但若某视图池恰等于目标数而调整本可有益,也会被跳过。+- 发布配置与 node 18/21/23 机制相同(γ=-1.6、sm=0.1),A 半 57.59 vs 其记录的 A 半未见更高点;对父 node 7 的提升(+0.39 A 半)在 T1 噪声(~2 分)内,但方向与 node18 的 B 半结果(54.74 > 54.54)一致。+- 确定性配额在 **B 半**或其他视图是否同样有害未验证(A 半差距 -2.0,接近噪声边缘但四组指标同向恶化,判定可信度较高)。+- final 视图(E8.5+E9.5→E10.5)未测:若 E9.5 池 ≤ 目标细胞数则触发退化保护,退回 copy_last(安全无增益)。+- 类型自适应 γ 的无效可能因 proxy 池各类型 prolif 离散度差异小(median 归一后 ratio≈1);在类型异质性更大的视图上未测。diff --git a/solution/run.py b/solution/run.pyindex 71f82b5..6ac89a6 100644--- a/solution/run.py+++ b/solution/run.py@@ -1,21 +1,30 @@ #!/usr/bin/env python3-"""copy_last + two-level proliferation reweighting + proliferation-gradient-expression extrapolation.--Base (node 4/6): output a deterministic weighted subsample of the latest-official input stage. Type-level weight uses the type-mean proliferation-score (beta_type=-4, tuned); cell-level weight uses the within-type-deviation (beta_cell=-1, node 6).--New (this node): per cell type, regress each gene's expression on the cell's-proliferation score (OLS slope over ALL source cells of that type). Each-selected cell's expression is nudged along that slope toward its type's mean-proliferation level: x_adj[i,g] = x[i,g] + gamma * slope_g * (tmean - p_i),-applied only where |slope_g| > SLOPE_MIN, clipped to >= 0. Types with-< MIN_TYPE_CELLS cells are left untouched. gamma=0 reproduces the base.-Proliferation markers are generic cell-cycle genes (not stage-specific-knowledge); everything is computed within the input snapshot, so the method-works with a single input stage.+"""copy_last + two-level proliferation reweighting + type-adaptive+proliferation-gradient expression extrapolation.++Base (node 4/6/18): output a weighted subsample of the latest official input+stage. Type-level weight uses the type-mean proliferation score+(beta_type=-4); cell-level weight uses the within-type deviation+(beta_cell=-1). Expression adjustment: per cell type, regress each gene on+the cell's proliferation score (OLS over all source cells of that type) and+shift each selected cell along the slope (gamma=-1.6, |slope|>0.1).++This node tested the PLAN's three mechanisms on the proxy A-half and kept+the winner; the shipped default is the strongest slope configuration+(gamma=-1.6, |slope|>0.1, node 18 parameters) with the parent's global+Efraimidis-Spirakis sampling:+1. Deterministic type quotas (QUOTA flag): REJECTED - proxy A-half 55.60 vs+ 57.59 for random E-S (covariation -3.9, cell_state -4.4). The E-S quota+ "noise" is beneficial; code kept, default off.+2. Type-adaptive gamma, gamma_t = gamma*clip((std_t/median_std)^alpha,+ 0.25, 4) (ALPHA flag): NO EFFECT - alpha in {0.5,1,2} within +-0.06 of+ alpha=0 (57.59); alpha=2 slightly hurts de_recovery. Default 0.+3. Small-type slope shrinkage slope *= n_t/(n_t+k) for n_t<50 (KSHRINK+ flag): NO EFFECT - output byte-identical for k in {20,50}. Default 0.+Also scanned: gamma=-2.0/-2.4 worse (57.47/57.31), |slope|>0.15 ties+(57.60), beta_cell=-2 much worse (55.28).+Guards unchanged: skip expression adjustment on external stages or when+sampling degenerates (n_target >= pool size, e.g. test X3). """ from __future__ import annotations@@ -39,9 +48,12 @@ from src.task1_temporal.view_io import ( BETA_TYPE = -4.0 # tuned on T1 proxy A-half (node 4) BETA_CELL = -1.0 # within-type weight (node 6)-GAMMA = -0.8 # expression-adjustment strength (negative tuned on proxy A-half)-SLOPE_MIN = 0.05 # only adjust genes with |slope| above this+GAMMA = -1.6 # expression-adjustment strength (node 18)+SLOPE_MIN = 0.1 # only adjust genes with |slope| above this (node 18) MIN_TYPE_CELLS = 20+QUOTA = 0 # 1: deterministic type quotas; 0: parent's global E-S+ALPHA = 0.0 # type-adaptive gamma exponent (0 = global gamma)+KSHRINK = 0.0 # small-type slope shrinkage constant (0 = off) PROLIF = ["Mki67", "Top2a", "Pcna", "Cdk1", "Ccna2", "Ccnb1", "Aurkb", "Bub1", "Cenpf", "Nusc1"]@@ -56,12 +68,39 @@ def pick_stage(manifest): def weighted_sample(w: np.ndarray, n: int, rng: np.random.Generator) -> np.ndarray:- """Weighted sampling without replacement (Efraimidis-Spirakis), sorted."""+ """Weighted sampling without replacement (Efraimidis-Spirakis).""" if n >= len(w):- return sample_rows(len(w), n, rng)- keys = rng.random(len(w)) ** (1.0 / w)- idx = np.argsort(-keys, kind="stable")[:n]- return np.sort(idx)+ return np.arange(len(w))+ keys = rng.random(len(w)) ** (1.0 / np.maximum(w, 1e-12))+ return np.argsort(-keys, kind="stable")[:n]+++def quota_allocate(mass: np.ndarray, counts: np.ndarray, n_target: int) -> np.ndarray:+ """Largest-remainder allocation of n_target proportional to mass,+ capped by counts per type."""+ total = mass.sum()+ if total <= 0:+ alloc = np.minimum(counts, n_target // max(len(counts), 1))+ else:+ exact = mass / total * n_target+ alloc = np.floor(exact).astype(np.int64)+ alloc = np.minimum(alloc, counts)+ rem = n_target - int(alloc.sum())+ if rem > 0:+ frac = exact - np.floor(exact)+ room = counts - alloc+ order = np.argsort(-frac, kind="stable")+ i = 0+ while rem > 0 and i < 10 * len(order) + 10:+ t = order[i % len(order)]+ if room[t] > 0:+ alloc[t] += 1+ room[t] -= 1+ rem -= 1+ i += 1+ if room.sum() <= 0:+ break+ return alloc def main() -> None:@@ -70,12 +109,20 @@ def main() -> None: parser.add_argument("--out", required=True) parser.add_argument("--seed", type=int, default=0) parser.add_argument("--gamma", type=float, default=None)+ parser.add_argument("--slope-min", type=float, default=None) parser.add_argument("--beta-cell", type=float, default=None) parser.add_argument("--beta-type", type=float, default=None)+ parser.add_argument("--quota", type=int, default=None)+ parser.add_argument("--alpha", type=float, default=None)+ parser.add_argument("--kshrink", type=float, default=None) args = parser.parse_args() gamma = GAMMA if args.gamma is None else args.gamma+ slope_min = SLOPE_MIN if args.slope_min is None else args.slope_min beta_cell = BETA_CELL if args.beta_cell is None else args.beta_cell beta_type = BETA_TYPE if args.beta_type is None else args.beta_type+ use_quota = QUOTA if args.quota is None else args.quota+ alpha = ALPHA if args.alpha is None else args.alpha+ kshrink = KSHRINK if args.kshrink is None else args.kshrink manifest = load_manifest(args.data) genes = panel_genes(args.data, manifest)@@ -93,32 +140,57 @@ def main() -> None: score = Xc.mean(axis=1).astype(np.float64) inv = None+ type_score = None if score is not None: lab = labels_of(last) uniq, inv = np.unique(lab, return_inverse=True) inv = np.asarray(inv).ravel() n_types = len(uniq)- counts = np.bincount(inv, minlength=n_types).astype(np.float64)+ counts = np.bincount(inv, minlength=n_types).astype(np.int64) type_score = np.zeros(n_types, dtype=np.float64) np.add.at(type_score, inv, score) type_score /= counts ts = type_score[inv] mean_s = np.average(type_score, weights=counts) w_type = np.maximum(1.0 + beta_type * (ts - mean_s), 1e-6)+ w_type_t = np.maximum(1.0 + beta_type * (type_score - mean_s), 1e-6) w_cell = np.maximum(1.0 + beta_cell * (score - ts), 1e-6) if beta_cell != 0 else np.ones_like(w_type)- rows = weighted_sample(w_type * w_cell, n_target, rng)++ if use_quota and n_target < last.n_obs:+ alloc = quota_allocate(counts.astype(np.float64) * w_type_t, counts, n_target)+ parts = []+ for t in range(n_types):+ idx = np.flatnonzero(inv == t)+ sel = weighted_sample(w_cell[idx], int(alloc[t]), rng)+ parts.append(idx[sel])+ rows = np.sort(np.concatenate(parts)) if parts else np.zeros(0, dtype=np.int64)+ elif use_quota:+ rows = sample_rows(last.n_obs, n_target, rng)+ else:+ rows = weighted_sample(w_type * w_cell, n_target, rng)+ rows = np.sort(rows) else: rows = sample_rows(last.n_obs, n_target, rng) X = last.X Xsel = X[rows]- # Guard: only adjust expression on official stages. In external-only views- # (e.g. test question X3: different platform/technology, author cell-type- # labels) the within-type proliferation regression proved harmful- # (X3 A-half 50.0 -> 43.2), so we copy the cells untouched there.- degenerate = n_target >= last.n_obs # no real subsampling (e.g. test X3)+ # Guard: only adjust expression on official, non-degenerate views (X3).+ degenerate = n_target >= last.n_obs if gamma != 0.0 and score is not None and not is_external(entry) and not degenerate: n_types = int(inv.max()) + 1+ counts = np.bincount(inv, minlength=n_types).astype(np.float64)+ # per-type std of proliferation score+ std_t = np.zeros(n_types, dtype=np.float64)+ sq = np.zeros(n_types, dtype=np.float64)+ np.add.at(sq, inv, (score - type_score[inv]) ** 2)+ std_t = np.sqrt(sq / np.maximum(counts, 1))+ eligible = counts >= MIN_TYPE_CELLS+ med = np.median(std_t[eligible]) if eligible.any() else 1.0+ if not np.isfinite(med) or med <= 1e-8:+ med = 1.0+ ratio = np.clip((std_t / med) ** alpha if alpha != 0 else np.ones(n_types), 0.25, 4.0)+ gamma_t = gamma * ratio+ S = np.zeros((n_types, X.shape[1]), dtype=np.float32) for t in range(n_types): idx = np.flatnonzero(inv == t)@@ -129,10 +201,12 @@ def main() -> None: if denom <= 1e-8: continue slope = np.asarray(X[idx].T @ pc, dtype=np.float64).ravel() / denom- slope[np.abs(slope) <= SLOPE_MIN] = 0.0+ slope[np.abs(slope) <= slope_min] = 0.0+ if kshrink > 0 and len(idx) < 50:+ slope *= len(idx) / (len(idx) + kshrink) S[t] = slope.astype(np.float32) if np.any(S):- c = (-gamma) * (score[rows] - type_score[inv[rows]])+ c = (-gamma_t[inv[rows]]) * (score[rows] - type_score[inv[rows]]) trow = inv[rows] parts = [] chunk = 1024
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k041 | Within-stage pseudotime and graph toolkit offline: scanpy DPT/PAGA/Leiden, Palantir, CellRank 2 | 10.1186/s13059-019-1663-x (PAGA); 10.1038/s41587-019-0068-4 (Palantir); 10.1038/s41592-024-02303-9 (CellRank 2) |
| k031 | Offline OT toolkit in the sandbox: moscot TemporalProblem, wot OTModel, POT, geomloss | 10.1038/s41586-024-08453-2 (moscot); 10.1016/j.cell.2019.01.006 (Waddington-OT) |
| k018 | Damped per-type shift: shrinkage alpha on the observed delta | notes/plan/cards/T1.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 实现 PLAN 三机制(确定性类型配额、类型自适应 γ、小类型斜率收缩),A 半实测后全部默认关闭(QUOTA=0/ALPHA=0/KSHRINK=0);发布配置 = γ=-1.6、SLOPE_MIN=0.1(node18 参数),相对父 node7 仅参数从 γ=-0.8/sm=0.05 变为 γ=-1.6/sm=0.1,另加三个默认关闭的机制分支与 CLI 参数。 |
|---|---|
| 各组分数的变化 | cell_state:变好 +1.01(56.59→57.60),但幅度在 T1 噪声(~2 分)内,方向与 node18 的 B 半结果一致 covariation:变坏 -0.46(52.88→52.42),噪声内 de_recovery:不变 +0.00(51.69→51.69),再次证实 de_recovery 对表达级扰动免疫 direction:基本不变 -0.02(56.25→56.23),噪声内 榜分:+0.20(54.54→54.74),在 T1 噪声(~2 分)内,与 node18 同分(54.74),本质上是复现 node18 配置而非新进展 |
| 假设是否成立 | 否 |
| 经验 |
|
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 6 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 5 次:edit 2、write 1、read 1、bash 1 |
| 用时 | 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 13,793 · 输出 1,594 · 思考 640 |
| 任务(第一行) | 分析节点 n28 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/analyst.jsonl 23 KB /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 21 |
| 工具调用 | 共 23 次:bash 17、read 2、write 2、edit 2 |
| 用时 | 10 分 |
| token 数 | 输入 45,494 · 输出 8,967 · 思考 4,476 |
| 任务(第一行) | 按计划修改程序:确定性类型配额抽样 + 类型自适应γ(按增殖离散度缩放表达调整强度) |
| 最后的回答(摘录) | **做了什么**:实现并实测 PLAN 的三机制(确定性类型配额、类型自适应 γ、小类型斜率收缩),全部在 node7 基底(copy_last + β_type=-4/β_cell=-1 + 增殖-表达斜率放大)上以 A 半对照(γ=-1.6/sm=0.1,57.59)逐一判定:配额 **有害**(55.60,covariation -3.9)、自适应 γ **无效**(±0.06)、k 收缩 **无效果**(逐字节相同,proxy 无 20–50 细胞类型)。另扫 γ=-2.0/-2.4(更差)、sm=0.15(打平)、β_cell=-2(大幅差)。最终发布 = node18 参数配置(γ=-1.6、sm=0.1),三视图跑通、vec-check ok、默认输出与查分文件逐字节一致。 **查分**(用 14/20 次):proxy seed0 **57.59** / seed1 57.31(父配置 A 半 57.20/56.89);proxy2 57.59;X3 50.0(保护生效)。预期板分 ≈55.1 A 半,与 node18(54.74)同机制、略优于父(54.54)。 **下一步最值得试**:随机 E-S 的配额"噪声"本身是收益来源(确定性配额四组指标同向恶化)——可反向探索:在类型配额上**注入可控随机性/Dirichlet 扰动**,或直接优化 mmd_u 友好的类型比例倾斜;de_recovery 对所有已试表达级扰动仍卡在 52.5,可能需要在抽样轴(而非表达轴)上引入 DE 基因富集权重。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/engineer.jsonl 101 KB /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 2 分 |
| token 数 | 输入 17,031 · 输出 1,101 · 思考 6,323 |
| 任务(第一行) | 为节点 n28(改进,父节点 n7)写改进计划 PLAN.json |
| 最后的回答(摘录) | ```json
{
"name": "确定性类型配额抽样 + 类型自适应γ(按增殖离散度缩放表达调整强度)",
"motivation": "父节点7最弱组为 de_recovery 51.69 和 covariation 52.88。子节点18/21/23/26反复证实:全局γ增大时 cell_state 与 covariation 呈等板分 trade-off(node26:'cov与cell_state是等board分trade-off曲线'),且 de_recovery 对一切表达级扰动免疫(7个节点均为51.69)。当前乘法权重 w_type·w_cell 的 E-S 抽样使类型配额受随机性扰动,direction 组(56.25)因此停滞。本方案用确定性类型配额消除组成噪声,同时用类型自适应γ在信号强的类型放大调整、信号弱的类型收缩调整,意图在不牺牲 covariation 的前提下提升 cell_state,并改善 direction。",
"approach": "步骤1(确定性类型配额):将抽样拆为两层——先按 n_t = round(n_target × count_t·w_type_t / Σ_j count_j·w_type_j) 确定每类型配额(最大余数法修正总和),再在每类型内部用 w_cell 做 E-S 无放回抽样。β_type=-4 不变。这使组成完全由 β_type 决定,消除 E-S 全局竞争带来的配额噪声。\n步骤2(类型自适应γ):对每个类型 t 计算增殖得分标准差 std_t;定义 γ_t = γ_base × (std_t / median(std_all))^α,clip 到 [0.25×γ_base, 4×γ_base]。α=0 退化为父逻辑(全局γ)。机制:增殖离散度高的类型斜率信号可靠,放大调整;离散度低的类型斜率是噪声,收缩保护 covariation。\n步骤3(小类型斜率收缩):对细胞数 < 50 的类型,slope_g ×= n_t/(n_t+k),k 为收缩参数,防止少细胞类型的噪声斜率被放大。\n关键参数初值与扫描范围:γ_base=-1.6(继承 node18 最优);SLOPE_MIN=0.1(继承 node18);α∈{0, 0.5, 1.0, 2.0}(α=0 为对照);k∈{0, 20, 50}(k=0 为对照)。\n扫描策略(≤12次查分):① 固定γ=-1.6, k=0,扫α 4点(4次);② 取最优α,扫k 3点(3次);③ 若最优组合超对照≥1分,在γ∈{-1.2,-2.0}上确认(2次);④ 最优组合跑 seed1 确认(1次);⑤ X3 验证保护生效(1次)。\n单输入退路:所有统计量(增殖得分、类型标签、表达矩阵)均在单个快照内计算,不依赖第二时间点。proxy2 的外部 Qiu 输入被 pick_stage 忽略(同父逻辑)。X3/退化视图:n_target≥池大小时跳过表达调整,确定性配额也退化为全量复制(等价 copy_last)。final 视图(E8.5+E9.5→E10.5):若 E9.5 池≤目标数,同样触发退化保护。\nvec-score 快速筛选:先只跑 proxy A半 seed0 对比对照(α=0 即父逻辑),若某α下 proxy 总分 < 对照-1 则立即淘汰该α。",
"expected_groups": ["cell_state", "covariation", "direction"],
"risks": "1) 确定性配额可能不如随机 E-S(随机性可能恰好有益):Engineer 应在第一次查分时就对比 α=0+确定性配额 vs α=0+随机配额(即父逻辑),若确定性配额单独就降分则回退随机抽样,只保留自适应γ。2) α>0 使部分类型γ极小(接近0),等价于对这些类型关闭调整,可能损失 cell_state:观察分组中 covariation 是否如预期上升;若 cell_state 降>1 且 covariation 无补偿则判定失败。3) 改善幅度可能仍在 T1 噪声(~2分)内:用最优配置的 seed0+seed1 两次查分确认一致性,差距<1分则视为无进展。4) 小类型斜率收缩(k>0)可能过度抑制真实信号:若 k=50 低于 k=0 则弃用。5) 实现复杂度:确定性配额需处理余数分配(最大余数法),Engineer 应先用小数据(前200个细胞)验证配额总和正确。"
}
``` |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/researcher.jsonl 5 KB /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/researcher.stderr |
审查员
| 角色 | 审查员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 6 |
| 工具调用 | 共 10 次:read 6、bash 3、write 1 |
| 用时 | 1 分 |
| token 数 | 输入 19,274 · 输出 1,254 · 思考 2,207 |
| 任务(第一行) | 审查节点 n28 的程序是否越界读取、写死目标、钻评分器漏洞 |
| 最后的回答(摘录) | REVIEW.json written |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/reviewer.jsonl 83 KB /home/spark-longxinyang/vec/runs/formal/20261001-233756-search-t1-abc-r0-B-population/nodes/28/reviewer.stderr |