总览 · ← 返回运行 20261003-093415-search-t1-r2-D-s1
节点 n18
CollecTRI+ULM 调控程序族:两阶段按细胞类型估 TF 活性差并经签名调控网解码回表达;X3 上解码不敌其乱网对照,故默认 λ=0(机制关闭,≈copy_last),负结果如实上报。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-093415-search-t1-r2-D-s1 |
|---|---|
| 父节点 | (种子,没有父节点) |
| 子节点 | — |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 草稿 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 49.53 · X3 47.92 · proxy10 52.75 |
| 审查 | 未审查 |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 21 分 |
| 程序版本 | 217811c9ea03890203de8ecdb06dfe2868356881 (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 217811c9ea:solution/METHOD.md
CollecTRI+ULM 调控程序族:两阶段按细胞类型估 TF 活性差并经签名调控网解码回表达;X3 上解码不敌其乱网对照,故默认 λ=0(机制关闭,≈copy_last),负结果如实上报。
方法(family: regulatory_program,按 PLAN 实现)
- 网络:
prior/tf_regulons/collectri_mouse.tsv.gz,过滤到视图genes.txt内的 TF 与靶基因(1086 TF、37,105 条有符号边),source/target/weight(=sign(mor)) 去重。 - 活性:decoupler 2.2
dc.mt.ulm(adata, net, tmin=5, raw=False)(数据已是 log1p CP10k)。ULM 会按数据集 prune TF,两阶段的 TF 列取交集后再差分。 - 两阶段路径(X3/final,≥2 输入):对每个在最后两个输入阶段都出现的细胞类型,ΔA = mean(A_last) − mean(A_prev),乘 scale = β·T,T=(t_target−t_last)/(t_last−t_prev) 截断到 ≤2(只用时间差,视图无关)。解码:Δexpr[type,g] = λ/n_reg(g) · Σ_tf sign(tf→g)·ΔA[type,tf],仅 n_reg≥3 的基因(9.1% 面板),逐基因 clip ±0.5,且只加在原本表达的条目上(保住稀疏结构;未 mask 时 variogram skill 从 0.49 崩到 0.30)。输出 = 末阶段细胞均匀抽样 + 按类型加位移。
- 单输入路径(proxy10):均匀抽样复制末阶段。PLAN 的"调控偏差代表性细胞选择"(RP_SELECT=1 保留实现)实测把 proxy10 从 52.97 拉到 46.07(收窄分布伤 mmd_u/variogram),故默认关闭。
- off 对照:
--shuffle_regulon对 target 列做随机置换(保持每个 TF 出度、每个基因入度),其余步骤逐字节相同。
查分结果(A 半;vec-score)
| 变体 | X3 | X3 分组 (de/dir/state/cov) | proxy10 |
|---|---|---|---|
| copy_last 基线(node 1) | 47.92 | 46.2/52.4/50.4/48.8 | 52.75 |
| on λ=0.3 无 mask | 44.57 | 45.3/49.7/49.3/30.3 | — |
| on λ=0.3 + mask | 48.53 | 46.1/49.0/50.6/48.0 | — |
| on λ=3.0 + mask | 48.64 | 46.1/49.0/51.2/47.5 | — |
| on λ=3.0 + 逐细胞偏差解码 γ=1 | 48.20 | 44.5/49.0/51.8/46.4 | — |
| off(乱网)λ=3.0 + mask | 49.73 | 46.9/49.7/52.8/48.7 | — |
| 单输入=选择(PLAN Step4 原版) | — | — | 46.07 |
| 单输入=均匀抽样(shipped) | — | — | 52.97 |
机制生效证据(PLAN mechanism_evidence):(1) 每细胞修改基因数 = 表达且 n_reg≥3 的基因,占面板 9.1%(稀疏,>>0 且 <<全部);(2) Δexpr 幅度 ∝ 1/n_reg,与调控覆盖直接挂钩;(3) 型内 Δexpr 跨基因 std > 0(mean|Δ|≈0.043@λ=3,非均匀);(4) 四组分对比见上表;(5) n_reg≥3 基因占比 9.13%。
但 off 对照判负:乱网对照(49.73)≥ 真网(48.64),四组分全部持平或更好。按 PLAN 自己的判据,CollecTRI 结构在 X3(E8.75→E9.0→E9.5 心脏)上没有产生超过随机边配置的信号;位移只剩噪声,反而轻微伤害 cell_state/covariation。DE 两组(de_recovery 46.1、direction 49.0)与基线同在地板附近——PLAN 风险 1 应验:调控网覆盖/方向不足以捕捉该窗口真实变化的基因。因此提交版本默认 λ=0(RP_LAMBDA=0 即零位移,输出 = 末阶段均匀抽样,两视图 ≈ copy_last),机制代码完整保留、可用环境变量打开,不冒充成有效的位移方法。
验证过 / 没验证
- 验证:两视图跑通 + vec-check ok;seed 确定性(seed 7 两次逐元素相同);视图无关(只用时间差与数据);上表所有查分。
- 没验证:λ=0 下 shipped 预测的 vec-score(数学上零位移=均匀 copy,proxy 均匀版已测 52.97;X3 均匀版≈node 1 的 47.92±抽样噪声);final(E8.5+E9.5→E10.5)上的行为(机制默认关,与 copy_last 同);β、T_CAP、MIN_REG 的网格(λ=0 下不影响输出)。
知识来源
- CollecTRI(prior/tf_regulons,通用 TF–靶基因调控先验,不针对禁窗阶段);decoupler ULM 标准用法。未使用任何保留阶段/保留基因型的测量信息,未读 external/、未用 uns 调色板。
下一步建议
调控解码在 X3 判负,regulatory_program 族按当前形态(型均值 ΔA + 线性签名解码)不值得继续调参;若保留该族,应改用型间差异基因的富集方向约束(而非全网络线性解码),或直接放弃该族转向 composition_trend(node 7/16)与 graph_fate(node 10)的组合。
调研员的计划
| 名称 | regulatory_program: CollecTRI ULM activity transition + regulon-constrained decode |
|---|---|
| 动机 | Draft of regulatory_program family. Current best (node 7, rank3=56.41) gains from composition reweighting + per-type displacement, but de_recovery on X3 remains weak (node 7 proxy10 de_score 0.26, X3 de_score -0.026 at node 13). Regulatory coordination via TF regulons could improve de_direction and covariation by constraining expression changes to biologically coherent gene sets rather than per-gene noise. Node 13's covariation group (53.94→48.00 on X3 for node 7's parent) shows room for structured gene-gene coordination. |
| 做法 | Step 1: Load prior/tf_regulons/collectri_mouse.tsv.gz, filter to genes present in view's genes.txt. Expect ~800-1200 TFs, ~10k-20k target edges after filtering. Step 2: Compute per-cell TF activities via decoupler: dc.mt.ulm(adata, net, tmin=5) → adata.obsm['score_ulm']. Do NOT call dc.op.* downloaders. Step 3 (two-stage path, X3/final): For each cell type present in both stages, compute mean activity ΔA[tf] = mean(A_stage2[type]) - mean(A_stage1[type]). For each cell in last stage, predicted activity change = β × ΔA[cell_type], β=1.0 initial, search [0.5, 1.0, 1.5]. Decode: for gene g, Δexpr[g] = Σ_tf sign(tf→g) × |ΔA[tf]| × w_shrink, where w_shrink = λ_decode / (n_regulators[g]) to normalize by regulon size. λ_decode initial 0.3, search [0.1, 0.3, 0.5]. Clip Δexpr to [-0.5, 0.5] per gene. Only modify genes with ≥3 regulators in filtered net. Add Δexpr to original expression. If fewer than 2 input stages, skip to Step 4. Step 4 (single-stage path, proxy10): Compute activities. Within each cell type, compute per-cell 'regulatory deviation' δA = A_cell - A_type_mean. Select top fraction (keep_rate=0.85) cells with smallest ||δA|| (most representative regulatory state) via weight… |
| 风险 | 1) CollecTRI regulons may not cover the genes actually changing between E8.5→E9.5 (novel programs not in prior) → check coverage: fraction of DE genes with ≥1 regulator. If <30%, decode is too sparse to matter. 2) ULM activities may be too noisy per-cell; per-type mean helps but loses heterogeneity. 3) Overlapping regulons cause unstable inverse: mitigate with per-gene normalization by n_regulators. 4) Single-stage fallback (selection only) may not move scores above copy_last. Engineer should check after first vec-score: if de_score and de_direction both unchanged from copy_last, the regulon decode is not producing meaningful signal. 5) Memory: ULM on full gene matrix × full cells should be fine (<2GB), but avoid constructing dense TF×gene matrix if >500 TFs × >20k genes. |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:这个提交的上一版(种子程序:相对空仓库)。改动的文件:solution/EXECUTION.json +1 −0、solution/METHOD.md +39 −0、solution/run.py +229 −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..150aea5--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,39 @@+CollecTRI+ULM 调控程序族:两阶段按细胞类型估 TF 活性差并经签名调控网解码回表达;X3 上解码不敌其乱网对照,故默认 λ=0(机制关闭,≈copy_last),负结果如实上报。++## 方法(family: regulatory_program,按 PLAN 实现)++- 网络:`prior/tf_regulons/collectri_mouse.tsv.gz`,过滤到视图 `genes.txt` 内的 TF 与靶基因(1086 TF、37,105 条有符号边),source/target/weight(=sign(mor)) 去重。+- 活性:decoupler 2.2 `dc.mt.ulm(adata, net, tmin=5, raw=False)`(数据已是 log1p CP10k)。ULM 会按数据集 prune TF,两阶段的 TF 列取交集后再差分。+- **两阶段路径**(X3/final,≥2 输入):对每个在最后两个输入阶段都出现的细胞类型,ΔA = mean(A_last) − mean(A_prev),乘 scale = β·T,T=(t_target−t_last)/(t_last−t_prev) 截断到 ≤2(只用时间差,视图无关)。解码:Δexpr[type,g] = λ/n_reg(g) · Σ_tf sign(tf→g)·ΔA[type,tf],仅 n_reg≥3 的基因(9.1% 面板),逐基因 clip ±0.5,且**只加在原本表达的条目上**(保住稀疏结构;未 mask 时 variogram skill 从 0.49 崩到 0.30)。输出 = 末阶段细胞均匀抽样 + 按类型加位移。+- **单输入路径**(proxy10):均匀抽样复制末阶段。PLAN 的"调控偏差代表性细胞选择"(RP_SELECT=1 保留实现)实测把 proxy10 从 52.97 拉到 46.07(收窄分布伤 mmd_u/variogram),故默认关闭。+- **off 对照**:`--shuffle_regulon` 对 target 列做随机置换(保持每个 TF 出度、每个基因入度),其余步骤逐字节相同。++## 查分结果(A 半;vec-score)++| 变体 | X3 | X3 分组 (de/dir/state/cov) | proxy10 |+|---|---|---|---|+| copy_last 基线(node 1) | 47.92 | 46.2/52.4/50.4/48.8 | 52.75 |+| on λ=0.3 无 mask | 44.57 | 45.3/49.7/49.3/**30.3** | — |+| on λ=0.3 + mask | 48.53 | 46.1/49.0/50.6/48.0 | — |+| on λ=3.0 + mask | 48.64 | 46.1/49.0/51.2/47.5 | — |+| on λ=3.0 + 逐细胞偏差解码 γ=1 | 48.20 | 44.5/49.0/51.8/46.4 | — |+| **off(乱网)λ=3.0 + mask** | **49.73** | 46.9/49.7/52.8/48.7 | — |+| 单输入=选择(PLAN Step4 原版) | — | — | 46.07 |+| 单输入=均匀抽样(shipped) | — | — | 52.97 |++**机制生效证据(PLAN mechanism_evidence)**:(1) 每细胞修改基因数 = 表达且 n_reg≥3 的基因,占面板 9.1%(稀疏,>>0 且 <<全部);(2) Δexpr 幅度 ∝ 1/n_reg,与调控覆盖直接挂钩;(3) 型内 Δexpr 跨基因 std > 0(mean|Δ|≈0.043@λ=3,非均匀);(4) 四组分对比见上表;(5) n_reg≥3 基因占比 9.13%。++**但 off 对照判负**:乱网对照(49.73)≥ 真网(48.64),四组分全部持平或更好。按 PLAN 自己的判据,CollecTRI 结构在 X3(E8.75→E9.0→E9.5 心脏)上没有产生超过随机边配置的信号;位移只剩噪声,反而轻微伤害 cell_state/covariation。DE 两组(de_recovery 46.1、direction 49.0)与基线同在地板附近——PLAN 风险 1 应验:调控网覆盖/方向不足以捕捉该窗口真实变化的基因。因此**提交版本默认 λ=0**(RP_LAMBDA=0 即零位移,输出 = 末阶段均匀抽样,两视图 ≈ copy_last),机制代码完整保留、可用环境变量打开,不冒充成有效的位移方法。++## 验证过 / 没验证++- 验证:两视图跑通 + vec-check ok;seed 确定性(seed 7 两次逐元素相同);视图无关(只用时间差与数据);上表所有查分。+- 没验证:λ=0 下 shipped 预测的 vec-score(数学上零位移=均匀 copy,proxy 均匀版已测 52.97;X3 均匀版≈node 1 的 47.92±抽样噪声);final(E8.5+E9.5→E10.5)上的行为(机制默认关,与 copy_last 同);β、T_CAP、MIN_REG 的网格(λ=0 下不影响输出)。++## 知识来源++- CollecTRI(prior/tf_regulons,通用 TF–靶基因调控先验,不针对禁窗阶段);decoupler ULM 标准用法。未使用任何保留阶段/保留基因型的测量信息,未读 external/、未用 uns 调色板。++## 下一步建议++调控解码在 X3 判负,regulatory_program 族按当前形态(型均值 ΔA + 线性签名解码)不值得继续调参;若保留该族,应改用型间差异基因的富集方向约束(而非全网络线性解码),或直接放弃该族转向 composition_trend(node 7/16)与 graph_fate(node 10)的组合。diff --git a/solution/run.py b/solution/run.pynew file mode 100644index 0000000..29a37fe--- /dev/null+++ b/solution/run.py@@ -0,0 +1,229 @@+"""regulatory_program: CollecTRI ULM activity transition + regulon-constrained decode.++Two-stage views (>=2 inputs): per-cell-type TF activity change between the last two+input stages, extrapolated to the target and decoded back to expression via signed+regulon weights (only genes with >=3 regulators; per-gene shrink by regulon size).+Single-stage views: select the most representative cells per type by smallest+regulatory deviation (ULM activities), no expression modification.++Off control: --shuffle_regulon permutes the target column of the network+(preserves each TF out-degree and each gene in-degree) -> uncoordinated decode.+"""++from __future__ import annotations++import argparse+import gzip+import os+from pathlib import Path++import numpy as np+import pandas as pd+import scipy.sparse as sp++from src.task1_temporal import view_io++BETA = float(os.environ.get("RP_BETA", "1.0"))+# λ=0 ships the honest negative result: the CollecTRI decode scored BELOW its+# own off-control on X3 (48.64 vs 49.73), so the mechanism is disabled by+# default and the two-stage path reduces to a uniform copy of the last stage.+# Set RP_LAMBDA>0 to re-enable the regulon decode.+LAMBDA_DECODE = float(os.environ.get("RP_LAMBDA", "0.0"))+CLIP = float(os.environ.get("RP_CLIP", "0.5"))+MIN_REG = int(os.environ.get("RP_MIN_REG", "3"))+KEEP_RATE = float(os.environ.get("RP_KEEP", "0.85"))+SEL_LAMBDA = float(os.environ.get("RP_SEL_LAMBDA", "0.15"))+GAMMA = float(os.environ.get("RP_GAMMA", "0.0"))+T_CAP = float(os.environ.get("RP_TCAP", "2.0"))+USE_T = os.environ.get("RP_USE_T", "1") == "1"+++def load_net(view, manifest, genes, shuffle: bool, rng) -> pd.DataFrame:+ entry = next(p for p in manifest["prior"] if p["id"] == "tf_regulons")+ path = Path(view) / entry["path"]+ files = list(path.iterdir()) if path.is_dir() else [path]+ f = files[0]+ opener = gzip.open if str(f).endswith(".gz") else open+ net = pd.read_csv(opener(f, "rt"), sep="\t")+ gset = set(genes)+ net = net[net["tf"].isin(gset) & net["target"].isin(gset)].copy()+ net = net.rename(columns={"tf": "source", "target": "target", "mor": "weight"})+ net = net[["source", "target", "weight"]].drop_duplicates(["source", "target"])+ net["weight"] = np.sign(net["weight"].astype(float))+ net = net[net["weight"] != 0].reset_index(drop=True)+ if shuffle:+ perm = rng.permutation(len(net))+ net["target"] = net["target"].to_numpy()[perm]+ net = net.drop_duplicates(["source", "target"]).reset_index(drop=True)+ return net+++def activities(adata, net) -> pd.DataFrame:+ import decoupler as dc++ res = dc.mt.ulm(adata, net, tmin=5, raw=False, verbose=False)+ if res is None:+ return adata.obsm["score_ulm"]+ return res[0]+++def main() -> None:+ ap = argparse.ArgumentParser()+ ap.add_argument("--data", required=True)+ ap.add_argument("--out", required=True)+ ap.add_argument("--seed", type=int, required=True)+ ap.add_argument("--shuffle_regulon", action="store_true")+ args = ap.parse_args()++ view = args.data+ rng = np.random.default_rng(args.seed)+ manifest = view_io.load_manifest(view)+ genes = view_io.panel_genes(view, manifest)++ net = load_net(view, manifest, genes, args.shuffle_regulon, rng)+ if net.empty:+ raise RuntimeError("empty regulon network after filtering")++ inputs = view_io.inputs_by_time(manifest)+ last_entry = inputs[-1]+ adata_last = view_io.read_stage(view, last_entry, genes, missing="fill")+ labels_last = view_io.labels_of(adata_last)++ stats = {"n_tf": int(net["source"].nunique()), "n_edges": int(len(net))}++ if len(inputs) >= 2:+ prev_entry = inputs[-2]+ adata_prev = view_io.read_stage(view, prev_entry, genes, missing="fill")+ labels_prev = view_io.labels_of(adata_prev)++ A_last = activities(adata_last, net)+ A_prev = activities(adata_prev, net)++ dt_target = float(manifest["target"]["time"]) - float(last_entry["time"])+ dt_train = float(last_entry["time"]) - float(prev_entry["time"])+ T = dt_target / dt_train if dt_train > 0 else 1.0+ if not USE_T:+ T = 1.0+ T = float(min(T, T_CAP))+ scale = BETA * T++ delta_rows, row_types = [], []+ # ULM prunes TFs per dataset; restrict to the TFs scored in both stages+ common_tfs = [tf for tf in A_last.columns if tf in set(A_prev.columns)]+ A_last = A_last[common_tfs]+ A_prev = A_prev[common_tfs]+ mean_prev = A_prev.groupby(pd.Series(labels_prev, index=A_prev.index)).mean()+ ct_series = pd.Series(labels_last, index=A_last.index)+ mean_last = A_last.groupby(ct_series).mean()+ shared = [ct for ct in mean_last.index if ct in mean_prev.index]+ for ct in shared:+ dA = (mean_last.loc[ct] - mean_prev.loc[ct]).to_numpy() * scale+ delta_rows.append(dA)+ row_types.append(ct)++ if delta_rows:+ DA = np.vstack(delta_rows) # (n_types, n_tfs) in ULM column order+ tf_cols = list(A_last.columns)+ tf_idx = {tf: i for i, tf in enumerate(tf_cols)}+ net = net[net["source"].isin(tf_idx)]+ cols = net["target"].to_numpy()+ # gene <- tf signed matrix+ gene_pos = {g: i for i, g in enumerate(genes)}+ tfs = net["source"].to_numpy()+ src_i = np.array([tf_idx[t] for t in tfs])+ tgt_i = np.array([gene_pos[c] for c in cols])+ W = sp.csr_matrix((net["weight"].to_numpy(), (src_i, tgt_i)),+ shape=(len(tf_idx), len(genes)))+ n_reg = np.asarray(W.getnnz(axis=0)).ravel()+ keep_genes = n_reg >= MIN_REG+ w_gene = np.zeros(len(genes))+ w_gene[keep_genes] = LAMBDA_DECODE / n_reg[keep_genes]+ # decode: dExpr[type, gene] = sum_tf DA[type,tf] * sign * w_gene+ DEX = (DA @ W.toarray()) if W.shape[0] <= 2000 else None+ if DEX is None: # fallback chunked (never hit at current sizes)+ DEX = np.zeros((DA.shape[0], len(genes)))+ for s in range(0, DA.shape[0], 64):+ DEX[s:s + 64] = DA[s:s + 64] @ W.toarray()+ DEX = DEX * w_gene[None, :]+ DEX = np.clip(DEX, -CLIP, CLIP)+ DEX[:, ~keep_genes] = 0.0++ type_of = {ct: i for i, ct in enumerate(row_types)}+ row_ids = np.array([type_of.get(ct, -1) for ct in labels_last])++ # per-cell decode: type-mean transition (DEX) plus the cell's own+ # centered regulatory deviation decoded through the same regulons,+ # so gene-gene coordination is regulatory, not gene-independent+ Wd = W.toarray()+ Ac = A_last.to_numpy()+ ct_s = pd.Series(labels_last, index=A_last.index)+ type_mean_full = A_last.groupby(ct_s).transform("mean").to_numpy()+ devA = Ac - type_mean_full+ DEX_cell = (devA @ Wd) * w_gene[None, :] * GAMMA+ DEX_cell = np.clip(DEX_cell, -CLIP, CLIP)+ DEX_cell[:, ~keep_genes] = 0.0++ n_out = view_io.target_n_cells(manifest, adata_last.n_obs)+ idx = view_io.sample_rows(adata_last.n_obs, n_out, rng)+ X = adata_last.X[idx].toarray()+ rid = row_ids[idx]+ has = rid >= 0+ # modify only already-expressed entries: keeps the sparse structure+ # (covariation) intact instead of lifting every zero gene+ mask = X > 0+ shift = np.zeros_like(X)+ shift[has] = DEX[rid[has]] + DEX_cell[idx[has]]+ np.clip(shift, -CLIP, CLIP, out=shift)+ shift *= mask+ X = X + shift+ np.clip(X, 0.0, None, out=X)+ stats["frac_genes_modified"] = float(keep_genes.mean())+ stats["mean_abs_dex"] = float(np.abs(shift[mask]).mean()) if mask.any() else 0.0+ stats["pb_shift_std"] = float(np.std(shift.mean(axis=0))) if has.any() else 0.0+ view_io.write_prediction(sp.csr_matrix(X.astype(np.float32)), genes,+ args.out, seed=args.seed)+ _log(stats)+ return++ # single-stage fallback: no reliable regulatory trend can be estimated from+ # one stage. Deviation-based selection (RP_SELECT=1) narrows the cell+ # distribution and measurably hurt mmd_u/variogram, so the default is a+ # uniform subsample of the last stage.+ n_out = view_io.target_n_cells(manifest, adata_last.n_obs)+ if os.environ.get("RP_SELECT", "0") == "1":+ A_last = activities(adata_last, net)+ ct_series = pd.Series(labels_last, index=A_last.index)+ type_mean = A_last.groupby(ct_series).transform("mean")+ dev = np.linalg.norm(A_last.to_numpy() - type_mean.to_numpy(), axis=1)+ chosen = []+ for ct in pd.unique(labels_last):+ m = labels_last == ct+ pool = np.flatnonzero(m)+ k = min(max(1, int(round(n_out * m.mean()))), len(pool))+ if k >= len(pool):+ chosen.append(pool)+ continue+ d = dev[pool]+ n_cand = max(k, int(np.ceil(KEEP_RATE * len(pool))))+ cand = pool[np.argsort(d)[:n_cand]]+ dc_ = dev[cand]+ s = dc_.std() if dc_.std() > 0 else 1.0+ logits = -SEL_LAMBDA * (dc_ - dc_.mean()) / s * np.sqrt(len(cand))+ w = np.exp(logits - logits.max())+ w = w / w.sum()+ take = rng.choice(cand, size=k, replace=False, p=w)+ chosen.append(np.sort(take))+ idx = np.sort(np.concatenate(chosen))[:n_out]+ else:+ idx = view_io.sample_rows(adata_last.n_obs, n_out, rng)+ stats["n_selected"] = int(len(idx))+ view_io.write_prediction(adata_last.X[idx], genes, args.out, seed=args.seed)+ _log(stats)+++def _log(stats: dict) -> None:+ print("[regulatory_program]", stats, flush=True)+++if __name__ == "__main__":+ main()
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k042 | TF activity inference offline: decoupler (ulm/mlm) with the CollecTRI prior | data/external/prior/README.md; decoupler 2.2.0 (scverse/decoupler, BSD-3-Clause) |
| k037 | Lineage-prior generation of new cell types from literature edges and parent cells | notes/competition/05_lineage_graph.md; 06_e95_parent_draft.md; 09_t1_census_lineage.md §4-6; biology entries k043-k063 |
| k019 | Out-of-window late-stage data as an expression prior, not a bracket | notes/plan/cards/T1.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 从零实现 regulatory_program 族:CollecTRI(1086 TF/37k 边)+decoupler ULM 活性,两阶段按细胞类型估 ΔA、乘时间外推因子、经签名调控网线性解码(λ/n_reg 收缩、clip ±0.5、仅 n_reg≥3 基因、只改已表达条目),并做保度乱网 off 对照。off 对照判负(X3 on λ=3 为 48.64 ≤ off 乱网 49.73)后,提交版默认 RP_LAMBDA=0,实际输出 = 末阶段均匀抽样,两视图 ≈ copy_last 基线(proxy10 52.75、X3 47.92,与 node 1 基线数字一致)。 |
|---|---|
| 各组分数的变化 | cell_state:变坏:50.37 vs 53.21(-2.84);proxy10 mmd_u 0.0405 vs 0.0298,得分 -4.02;X3 mmd_u +0.73 在噪声内。 covariation:变坏:48.83 vs 54.21(-5.38);proxy10 variogram 得分 -1.27、X3 -0.98,两者合计超出 T1 约 2 分噪声,同样是退回基线所致(对照 node 3 高于基线)。 de_recovery:变坏:46.24 vs 53.69 对照组的 49.78(-3.54);主要来自 proxy10 de_score 原始值 0.0164 vs 0.2679,得分 -2.48;X3 项 -0.09 在噪声内。因提交版=copy_last,退回基线水平。 direction:变坏:52.36 vs 57.77(-5.41);proxy10 de_direction 原始值 0.1785 vs 0.36,得分 -3.15;X3 -0.46 在噪声内。 |
| family_id | regulatory_program |
| 假设是否成立 | 否 |
| 经验 |
|
| mechanism_active | 否 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 3 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 2 次:bash 1、write 1 |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 14,461 · 输出 1,206 · 思考 1,197 |
| 任务(第一行) | 分析节点 n18 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/analyst.jsonl 7 KB /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 37 |
| 工具调用 | 共 43 次:bash 27、edit 14、write 2 |
| 用时 | 18 分 |
| token 数 | 输入 66,117 · 输出 14,738 · 思考 8,658 |
| 任务(第一行) | 按计划修改程序:regulatory_program: CollecTRI ULM activity transition + regulon-constrained decode |
| 最后的回答(摘录) | 完成。总结: **做了什么**:从零实现 PLAN 的 regulatory_program 族——CollecTRI 网络(1086 TF / 37k 边)+ decoupler ULM 活性;两阶段路径按细胞类型估 ΔA、乘时间外推因子 T、经签名调控网线性解码(λ/n_reg 收缩、±0.5 clip、仅 n_reg≥3 基因、只改已表达条目);单输入路径按 PLAN 做调控偏差选择;off 对照 `--shuffle_regulon`(保度置换)。 **查分**(8/20 次):X3 on λ=3 = 48.64,**off 乱网对照 = 49.73 ≥ on**,PLAN 判据判负(调控结构无信号,位移=噪声);无 mask 的稠密小位移使 variogram skill 崩到 0.30(44.57);单输入"代表性选择"把 proxy10 从 52.97 拉到 46.07。故提交版默认 λ=0(机制关闭,两视图 ≈ copy_last:proxy10 均匀版实测 52.97),机制代码完整保留、环境变量可开,METHOD.md 如实记录负结果。seed 确定性与 vec-check 均通过。 **下一步最值得试**:该族按当前形态(全网络线性解码)应放弃;建议把算力投向 composition_trend(node 7/16,rank3 56.41)与 graph_fate(node 10,X3 54.13)的组合——X3 权重 2 且 node 10 在 X3 上最强,二者机制正交(组成趋势 vs 细胞级后继抽样)。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/engineer.jsonl 205 KB /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 1 分 |
| token 数 | 输入 13,909 · 输出 1,432 · 思考 2,060 |
| 任务(第一行) | 为节点 n18(草稿,父节点 nNone)写改进计划 PLAN.json,思路 regulatory_program |
| 最后的回答(摘录) | gene matrix if >500 TFs × >20k genes.", "family_id": "regulatory_program", "mechanism": "Compute per-cell TF activities via CollecTRI+ULM; estimate activity transitions between stages (or per-type deviations in single-stage); decode activity changes back to expression via signed regulon weights, so expression shifts are coordinated by regulatory structure rather than gene-independent.", "vs_constant_shift": "Displacement is cell-type-specific AND gene-regulon-specific: each gene's change is determined by which TFs regulate it and by how much those TFs' activities changed. A constant per-type shift moves all genes equally regardless of regulatory membership. Here, only regulon-covered genes change, and their direction/magnitude is determined by TF activity × regulatory sign. Must demonstrate: (a) modified genes are enriched for regulon targets, (b) per-type displacement vectors are NOT proportional to a single scalar (show variance in Δexpr across genes within a type).", "mechanism_evidence": "Engineer should report: (1) number of genes modified per cell (should be >>0 and <<total genes, confirming sparsity); (2) correlation between per-gene Δexpr and regulon coverage (should be positive); (3) for top-5 most-changed cell types, show that Δexpr is NOT uniform across genes (std of Δexpr within type > 0.1); (4) four-group score breakdown comparing on vs off; (5) fraction of genes with ≥3 regulators in filtered network. If all genes shift by same amount within a type, mechanism collapsed to constant shift.", "mechanism_off_control": "Same program with --shuffle_regulon flag: randomly reassign target genes among TFs preserving each TF's out-degree and each gene's in-degree (configuration model shuffle). All other steps identical. Expected: shuffled version produces uncoordinated noise → de_score, de_direction, covariation should all be near copy_last baseline or worse; if shuffled ≈ unshuffled, the regulon structure is not driving any signal.", "sources": [] } |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/researcher.jsonl 6 KB /home/spark-longxinyang/vec/runs/formal/20261003-093415-search-t1-r2-D-s1/nodes/18/researcher.stderr |