总览 · ← 返回运行 20261003-043412-search-t2-embryo-interp-g24-D-s1
节点 n18
联合表达PCA+刚体不变几何latent内按细胞型确定性选取b侧中间态细胞(κ=0.65, procrustes3d, scale_damp=0.455),表达与坐标随真实细胞搬运。
| 运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。 | 20261003-043412-search-t2-embryo-interp-g24-D-s1 |
|---|---|
| 父节点 | (种子,没有父节点) |
| 子节点 | n20、n32 |
| 操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。 | 草稿 |
| 状态 | 已打分 |
| 分数 | 搜索目标分 61.73 · proxy 61.73 · 3 次复测均分 61.60 |
| 审查 | 未审查 |
| 用时?从运行开始到结束(或到现在)的挂钟时间。 | 13 分 |
| 程序版本 | 6ac48a45619eed9524f2ab964373f84078164d74 (programs.git) |
方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。
来自 programs.git 6ac48a4561:solution/METHOD.md
联合表达PCA+刚体不变几何latent内按细胞型确定性选取b侧中间态细胞(κ=0.65, procrustes3d, scale_damp=0.455),表达与坐标随真实细胞搬运。
T2EI-03 联合表达-几何 latent 选胞(draft,节点 18)
方法
interp_bracket取括号 (a=E早, b=E晚, t=时间差比例);未括住时退化为整份复制 anchor(分层抽到 max_cells)。单输入阶段同样走该退路。- 细胞数:N = log 线性插值(A.n, B.n, t) 夹到 [min_cells, max_cells];组成阻尼 n_b = round(κ·t·N),κ=0.65;n_a = N − n_b,a 侧按型分层随机抽(seed 决定)。
- 坐标:
align_pair(procrustes3d)把 b 云对齐到 a 帧(共有类型质心 Kabsch),两云缩放到共同目标 RMS = log_interp(rms_a, rms_b, t, SCALE_DAMP=0.455)。被选细胞坐标保持原值,不插值、不膨胀。 - 联合 latent:合并两端表达 → 基因 z-score → K_PCA=20 主成分(合并 z-score)为表达块;几何块(每端在自己云内算,刚体不变):到 K_NN=5 近邻平均距离、归一化径向位置、5-NN 细胞型组成占比向量。两块各自 z-score,几何块乘 W_GEO=1.0 后与表达块拼接。
- 机制(JOINT_SEL=on,默认):对每个共有细胞型(两端各 ≥ MIN_TYPE=10 个细胞),target = (1−t)·μ_a + t·μ_b(联合 latent 中的型质心),b 侧该型细胞按到 target 的欧氏距离升序稳定排序取前 n_b(type) 个(确定性,平局按索引)。非共有型按型内随机抽同数。n_b 按 b 端型占比分配(floor+按大小补齐,确定性)。
- off 对照:JOINT_SEL=off 环境变量,b 侧改为同 seed 型内随机抽相同数量,其余流程完全一致。
输出 = a 侧抽取细胞 + b 侧选出的细胞,表达与坐标同一细胞搬运;write_t2 写盘。纯 CPU(EXECUTION.json gpu=false),代理视图全程 ~19s、峰值内存 ~1.4GB(限额 28GB/30min)。
机制生效证据(代理 E6.75+E8.0→E7.25,t=0.4,seed 0,vec-score A 半)
被选 b 细胞到 target 的联合 latent 距离均值 4.66 vs 随机选取 6.80(比值 0.69,选取确实偏向中间态;W_GEO=0 时 2.30 vs 4.00)。1300 个 b 细胞中被 10 个共有型的中间态偏好覆盖,其余 16 型随机。
四组分 on vs off(κ=0.65):
| 配置 | board | cell_state | expression_change | shape_scale | local_spatial |
|---|---|---|---|---|---|
| on(提交态) | 60.65 | 51.08 | 60.22 | 72.96 | 58.33 |
| off(随机对照) | 59.89 | 48.24 | 60.15 | 72.56 | 58.61 |
机制主要目标组 cell_state +2.84(>1 分噪声),board +0.76(噪声内);local_spatial −0.28 持平。机制生效但整体增益主要来自 cell_state。
消融 / 参数扫描(各 1 次查分)
- W_GEO=0(纯表达 latent,≈节点 7 家族的选胞信号):60.62,cell_state 52.71,shape 71.25;W_GEO=0.5:60.28;W_GEO=2:59.98(cell_state 48.83,几何过重有害)。W_GEO=1.0 board 最高且 shape 最好(72.96),保留。
- κ:0.5→60.70(cell_state 54.35、shape 70.37;off 对照 60.10,机制差仅 +1.2);0.55→60.43;0.6→60.60;0.65→60.65(机制差最大 +2.84)。κ 间 board 差在噪声内,保留 PLAN 默认 0.65。
- K_NN=10:60.40;MIN_TYPE=5:60.56;ALIGN=procrustes(保z):60.45。均不如默认,保留 K_NN=5、MIN_TYPE=10、procrustes3d。
验证过 / 没验证
- 已验证:代理视图跑通、
vec-checkok、seed 0 复跑逐字节一致(确定)、11 次查分如上;程序只依赖时间差与数据,不读 board/mode/路径,阶段名与细胞数全部来自 manifest(视图无关,可过时间平移伪装)。 - 未验证:真实括号(E7.25+E8.0→E7.5,t=1/3,细胞数与共有型数不同:方法卡称共有型 11 个)——本代码全部从 manifest/数据现场计算,无阶段硬编码;未触发过单输入退路(本视图恒为 2 输入);未在 seed 1/2 上查分。
- 与树内关系:低于最佳节点 11(62.15,mix+κ0.65+表达选胞+xy 膨胀 γ1.15)。本家族 shape_scale 最高(72.96 vs 72.48)但 cell_state/local_spatial 偏低;下一步最值得试:在本选胞机制上叠加已证明有效的 b 侧 xy 径向膨胀(γ≈1.15,节点 11)与 κ=0.5~0.65 联扫,或把型内选取从"最近 k"改为距离分位分层以保多样性。
知识来源
坐标系约定(z 为切片轴、共有细胞型质心 Kabsch 对齐、RMS 阻尼插值)来自方法卡的通用几何做法;未使用任何保留阶段/保留基因型的测量信息、文献数值或外部数据库;prior/ 与 external/ 未使用(external 为空)。细胞类型标签仅来自输入视图 obs。
调研员的计划
| 名称 | T2EI-03 联合表达-几何 latent 选胞 draft |
|---|---|
| 动机 | 全树最弱组是 cell_state(最佳节点 11 仅 54.35,远低于 shape_scale 72.48)。现有 mix 流程的 b 侧选胞只基于表达质心距离(节点 7)或径向分层(节点 6),未利用局部几何信息,导致选出的细胞在空间上未必处于中间态。节点 12 的坐标插值使 local_spatial 掉 2.0,说明表达与空间不能独立生成。T2EI-03 在联合 latent 里选胞,让表达-位置对应自然保持,针对 cell_state 同时不损害 local_spatial。 |
| 做法 | 步骤:(1) 读视图,按时间排序取最早阶段为 a、最晚为 b;若只有一个输入阶段则直接复制该阶段输出(退路)。(2) 表达特征:对共有基因做 z-score,取前 K_PCA=20 个 PCA 分量(搜索范围 10-50)。(3) 几何特征(刚体不变):每细胞计算 a) 到 5 个最近邻(坐标空间)的平均距离;b) 5-NN 中各细胞型占比(向量);c) 到全云质心距离 / 全云最大半径(归一化径向位置)。(4) 联合 latent:将 PCA 分量与几何特征拼接,各块独立 z-score 后加权拼接,W_EXPR=1.0, W_GEO=1.0(搜索 W_GEO 0.5-2.0)。(5) 对每个共有细胞型:计算 a 侧质心 μ_a、b 侧质心 μ_b(在联合 latent 中),目标点 target=(1-t)μ_a + tμ_b,t 由视图时间间隔决定(proxy 单间隔取 0.5)。(6) b 侧选胞:按到 target 的欧氏距离升序取前 n_b 个(确定性)。n_b 由组成阻尼 κ=0.65 决定:n_b = round(κ * N_b_orig * type_frac)。(7) 输出:所有 a 细胞 + 选出的 b 细胞,坐标保持原值;全局缩放阻尼 SCALE_DAMP=0.455 使输出 RMS 对准参考。(8) vec-score 快筛:先跑 500 细胞子集确认无报错,再全量查 2-3 次(A 半),比较 JOINT_SEL=on vs off 的 cell_state 和 local_spatial。关键参数初值:K_PCA=20, K_NN=5, W_GEO=1.0, κ=0.65, SCALE_DAMP=0.455。单输入阶段退路:若 len(stages)==1,直接输出该阶段所有细胞,跳过全部选胞逻辑。 |
| 风险 | 1) 联合 latent 中几何特征噪声大(kNN 距离对稀疏区域不稳定),导致选胞质量不如纯表达质心;Engineer 应先单独跑 W_GEO=0 对照,确认表达基线不劣于节点 7 水平(cell_state≥52),再加几何。2) 30 分钟时限紧:PCA + kNN 计算量在万级细胞上应 <10s,但若视图细胞数极大需先用 numpy 向量化,避免逐细胞循环。3) 若联合选胞与纯表达选胞差异在噪声内(<1 分),说明几何特征未提供额外信息,提交 off 对照。4) 坐标不做任何变换(不插值、不膨胀),避免重蹈节点 12 的 local_spatial 下降。 |
代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。
对比:这个提交的上一版(种子程序:相对空仓库)。改动的文件:solution/EXECUTION.json +1 −0、solution/METHOD.md +43 −0、solution/run.py +203 −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..3c7380f--- /dev/null+++ b/solution/METHOD.md@@ -0,0 +1,43 @@+联合表达PCA+刚体不变几何latent内按细胞型确定性选取b侧中间态细胞(κ=0.65, procrustes3d, scale_damp=0.455),表达与坐标随真实细胞搬运。++# T2EI-03 联合表达-几何 latent 选胞(draft,节点 18)++## 方法++1. `interp_bracket` 取括号 (a=E早, b=E晚, t=时间差比例);未括住时退化为整份复制 anchor(分层抽到 max_cells)。单输入阶段同样走该退路。+2. 细胞数:N = log 线性插值(A.n, B.n, t) 夹到 [min_cells, max_cells];组成阻尼 n_b = round(κ·t·N),κ=0.65;n_a = N − n_b,a 侧按型分层随机抽(seed 决定)。+3. 坐标:`align_pair(procrustes3d)` 把 b 云对齐到 a 帧(共有类型质心 Kabsch),两云缩放到共同目标 RMS = log_interp(rms_a, rms_b, t, SCALE_DAMP=0.455)。被选细胞坐标保持原值,不插值、不膨胀。+4. 联合 latent:合并两端表达 → 基因 z-score → K_PCA=20 主成分(合并 z-score)为表达块;几何块(每端在自己云内算,刚体不变):到 K_NN=5 近邻平均距离、归一化径向位置、5-NN 细胞型组成占比向量。两块各自 z-score,几何块乘 W_GEO=1.0 后与表达块拼接。+5. 机制(JOINT_SEL=on,默认):对每个共有细胞型(两端各 ≥ MIN_TYPE=10 个细胞),target = (1−t)·μ_a + t·μ_b(联合 latent 中的型质心),b 侧该型细胞按到 target 的欧氏距离升序稳定排序取前 n_b(type) 个(确定性,平局按索引)。非共有型按型内随机抽同数。n_b 按 b 端型占比分配(floor+按大小补齐,确定性)。+6. off 对照:JOINT_SEL=off 环境变量,b 侧改为同 seed 型内随机抽相同数量,其余流程完全一致。++输出 = a 侧抽取细胞 + b 侧选出的细胞,表达与坐标同一细胞搬运;`write_t2` 写盘。纯 CPU(EXECUTION.json gpu=false),代理视图全程 ~19s、峰值内存 ~1.4GB(限额 28GB/30min)。++## 机制生效证据(代理 E6.75+E8.0→E7.25,t=0.4,seed 0,vec-score A 半)++被选 b 细胞到 target 的联合 latent 距离均值 4.66 vs 随机选取 6.80(比值 0.69,选取确实偏向中间态;W_GEO=0 时 2.30 vs 4.00)。1300 个 b 细胞中被 10 个共有型的中间态偏好覆盖,其余 16 型随机。++四组分 on vs off(κ=0.65):++| 配置 | board | cell_state | expression_change | shape_scale | local_spatial |+|---|---:|---:|---:|---:|---:|+| on(提交态) | 60.65 | 51.08 | 60.22 | 72.96 | 58.33 |+| off(随机对照) | 59.89 | 48.24 | 60.15 | 72.56 | 58.61 |++机制主要目标组 cell_state +2.84(>1 分噪声),board +0.76(噪声内);local_spatial −0.28 持平。机制生效但整体增益主要来自 cell_state。++## 消融 / 参数扫描(各 1 次查分)++- W_GEO=0(纯表达 latent,≈节点 7 家族的选胞信号):60.62,cell_state 52.71,shape 71.25;W_GEO=0.5:60.28;W_GEO=2:59.98(cell_state 48.83,几何过重有害)。W_GEO=1.0 board 最高且 shape 最好(72.96),保留。+- κ:0.5→60.70(cell_state 54.35、shape 70.37;off 对照 60.10,机制差仅 +1.2);0.55→60.43;0.6→60.60;0.65→60.65(机制差最大 +2.84)。κ 间 board 差在噪声内,保留 PLAN 默认 0.65。+- K_NN=10:60.40;MIN_TYPE=5:60.56;ALIGN=procrustes(保z):60.45。均不如默认,保留 K_NN=5、MIN_TYPE=10、procrustes3d。++## 验证过 / 没验证++- 已验证:代理视图跑通、`vec-check` ok、seed 0 复跑逐字节一致(确定)、11 次查分如上;程序只依赖时间差与数据,不读 board/mode/路径,阶段名与细胞数全部来自 manifest(视图无关,可过时间平移伪装)。+- 未验证:真实括号(E7.25+E8.0→E7.5,t=1/3,细胞数与共有型数不同:方法卡称共有型 11 个)——本代码全部从 manifest/数据现场计算,无阶段硬编码;未触发过单输入退路(本视图恒为 2 输入);未在 seed 1/2 上查分。+- 与树内关系:低于最佳节点 11(62.15,mix+κ0.65+表达选胞+xy 膨胀 γ1.15)。本家族 shape_scale 最高(72.96 vs 72.48)但 cell_state/local_spatial 偏低;下一步最值得试:在本选胞机制上叠加已证明有效的 b 侧 xy 径向膨胀(γ≈1.15,节点 11)与 κ=0.5~0.65 联扫,或把型内选取从"最近 k"改为距离分位分层以保多样性。++## 知识来源++坐标系约定(z 为切片轴、共有细胞型质心 Kabsch 对齐、RMS 阻尼插值)来自方法卡的通用几何做法;未使用任何保留阶段/保留基因型的测量信息、文献数值或外部数据库;prior/ 与 external/ 未使用(external 为空)。细胞类型标签仅来自输入视图 obs。diff --git a/solution/run.py b/solution/run.pynew file mode 100644index 0000000..01461f9--- /dev/null+++ b/solution/run.py@@ -0,0 +1,203 @@+"""T2EI-03: joint expression-geometry latent selection for T2 embryo interpolation.++Mix real cells from the bracket stages (a=early, b=late). The b-side cells are+chosen per shared cell type by distance to the interpolated type centroid+target = (1-t)*mu_a + t*mu_b in a joint latent space built from expression PCA+plus rigid-invariant local geometry features (kNN distance, kNN type+composition, normalized radial position). Expression and coordinates travel+together with the chosen real cells.++Mechanism switch: JOINT_SEL=on (default) selects by latent distance;+JOINT_SEL=off draws the same per-type counts at random (control).+"""++from __future__ import annotations++import os+import sys++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.sample import clip_n, take+from src.task2_spatial.view_io import (+ interp_bracket,+ load_manifest,+ panel_genes,+ read_stage,+ write_t2,+)++K_PCA = int(os.environ.get("K_PCA", "20"))+K_NN = int(os.environ.get("K_NN", "5"))+W_GEO = float(os.environ.get("W_GEO", "1.0"))+KAPPA = float(os.environ.get("KAPPA", "0.65"))+SCALE_DAMP = float(os.environ.get("SCALE_DAMP", "0.455"))+ALIGN = os.environ.get("ALIGN", "procrustes3d")+JOINT_SEL = os.environ.get("JOINT_SEL", "on").lower()+MIN_TYPE = int(os.environ.get("MIN_TYPE", "10"))+++def _z(block: np.ndarray) -> np.ndarray:+ mu = block.mean(axis=0)+ sd = block.std(axis=0)+ return (block - mu) / (sd + 1e-8)+++def _expr_pca(X: np.ndarray, k: int) -> np.ndarray:+ mu = X.mean(axis=0)+ sd = X.std(axis=0)+ Z = (X - mu) / (sd + 1e-8)+ k = int(min(k, Z.shape[1], Z.shape[0] - 1))+ _, _, vt = np.linalg.svd(Z - Z.mean(axis=0), full_matrices=False)+ return Z @ vt[:k].T+++def _geo_features(coords: np.ndarray, labels: np.ndarray, types: list[str], k_nn: int) -> np.ndarray:+ n = len(coords)+ tree = cKDTree(coords)+ k = int(min(k_nn, max(n - 1, 1)))+ dist, idx = tree.query(coords, k=k + 1)+ dist = dist[:, 1:]+ idx = idx[:, 1:]+ d_knn = dist.mean(axis=1)+ tindex = {t: i for i, t in enumerate(types)}+ lab_idx = np.array([tindex.get(str(l), -1) for l in labels])+ comp = np.zeros((n, len(types)), dtype=np.float64)+ valid = lab_idx[idx] >= 0+ rows = np.repeat(np.arange(n), k)[valid.ravel()]+ cols = lab_idx[idx][valid]+ np.add.at(comp, (rows, cols), 1.0)+ comp /= max(k, 1)+ cen = coords.mean(axis=0)+ rad = np.linalg.norm(coords - cen, axis=1)+ rmax = max(float(rad.max()), 1e-8)+ return np.column_stack([d_knn, rad / rmax, comp])+++def _alloc_counts(labels: np.ndarray, types: list[str], n: int) -> dict[str, int]:+ counts = {t: 0 for t in types}+ sizes = {t: int(np.sum(labels == t)) for t in types}+ total = sum(sizes.values())+ if total <= 0 or n <= 0:+ return counts+ n = int(min(n, total))+ order = sorted(types, key=lambda t: (-sizes[t], t))+ assigned = 0+ for t in order:+ c = int(np.floor(n * sizes[t] / total))+ c = min(c, sizes[t])+ counts[t] = c+ assigned += c+ guard = 0+ while assigned < n and guard < n + len(types) + 5:+ progressed = False+ for t in order:+ if assigned >= n:+ break+ if counts[t] < sizes[t]:+ counts[t] += 1+ assigned += 1+ progressed = True+ if not progressed:+ break+ guard += 1+ return counts+++def main(view: str, out: str, seed: int) -> None:+ rng = np.random.default_rng(seed)+ man = load_manifest(view)+ genes = panel_genes(view, man)+ lo, hi = int(man["min_cells"]), int(man["max_cells"])+ ea, eb, t = interp_bracket(man)+ A = read_stage(view, ea, genes)++ if eb is None: # not bracketed: fall back to copying the anchor stage+ idx = take(A.labels, min(A.n, hi), rng)+ write_t2(out, A.X[idx].toarray(), A.coords[idx], genes, seed)+ return++ B = read_stage(view, eb, genes)++ n_out = clip_n(log_interp(A.n, B.n, float(t), 1.0), lo, hi)+ n_b = int(np.clip(round(KAPPA * float(t) * n_out), 0, min(B.n, n_out)))+ n_a = int(min(n_out - n_b, A.n))+ if n_a + n_b < lo:+ n_b = int(min(n_b + (lo - n_a - n_b), B.n))+ idx_a = take(A.labels, n_a, rng)++ ca, cb, info = align_pair(A.coords, B.coords, A.labels, B.labels, ALIGN)+ rms_t = log_interp(rms_radius(A.coords), rms_radius(B.coords), float(t), SCALE_DAMP)+ ca = scale_to_rms(ca, rms_t)+ cb = scale_to_rms(cb, rms_t)++ Xa = np.asarray(A.X.todense(), dtype=np.float64)+ Xb = np.asarray(B.X.todense(), dtype=np.float64)+ E = _z(_expr_pca(np.vstack([Xa, Xb]), K_PCA))+ Ea, Eb = E[: A.n], E[A.n :]++ types = sorted({str(x) for x in A.labels} | {str(x) for x in B.labels})+ Ga = _geo_features(ca, A.labels, types, K_NN)+ Gb = _geo_features(cb, B.labels, types, K_NN)+ G = _z(np.vstack([Ga, Gb]))+ Ga_z, Gb_z = G[: A.n] * W_GEO, G[A.n :] * W_GEO++ La = np.hstack([Ea, Ga_z])+ Lb = np.hstack([Eb, Gb_z])++ lab_a = np.asarray(A.labels).astype(str)+ lab_b = np.asarray(B.labels).astype(str)+ shared = sorted({t_ for t_ in types if np.sum(lab_a == t_) >= MIN_TYPE and np.sum(lab_b == t_) >= MIN_TYPE})++ counts_b = _alloc_counts(lab_b, sorted(set(lab_b.tolist())), n_b)+ picks_b, diag_sel, diag_rnd = [], [], []+ for t_ in sorted(set(lab_b.tolist())):+ pool = np.flatnonzero(lab_b == t_)+ k = int(counts_b.get(t_, 0))+ if k <= 0:+ continue+ if k >= pool.size:+ picks_b.append(pool)+ continue+ if JOINT_SEL == "on" and t_ in shared:+ mu_a = La[lab_a == t_].mean(axis=0)+ mu_b = Lb[pool].mean(axis=0)+ target = (1.0 - float(t)) * mu_a + float(t) * mu_b+ d = np.linalg.norm(Lb[pool] - target, axis=1)+ order = np.argsort(d, kind="stable")[:k]+ sel = pool[order]+ d_sel = d[order]+ d_rnd = d[rng.permutation(pool.size)[:k]]+ diag_sel.append(d_sel.mean())+ diag_rnd.append(d_rnd.mean())+ else:+ sel = pool[rng.permutation(pool.size)[:k]]+ picks_b.append(sel)+ idx_b = np.concatenate(picks_b) if picks_b else np.array([], dtype=int)++ print(+ f"[diag] t={t:.3f} N={n_out} n_a={len(idx_a)} n_b={len(idx_b)} align={ALIGN} "+ f"shared={len(shared)}/{len(set(lab_b.tolist()))} joint_sel={JOINT_SEL} "+ f"knn={K_NN} kpca={K_PCA} w_geo={W_GEO} kappa={KAPPA} damp={SCALE_DAMP} "+ f"rms_target={rms_t:.1f} z_axis={info.get('z_axis_a')}/{info.get('z_axis_b')} "+ f"sel_d={np.mean(diag_sel) if diag_sel else float('nan'):.4f} "+ f"rnd_d={np.mean(diag_rnd) if diag_rnd else float('nan'):.4f}",+ file=sys.stderr,+ )++ X = np.vstack([Xa[idx_a], Xb[idx_b]]).astype(np.float32)+ C = np.vstack([ca[idx_a], cb[idx_b]]) if len(idx_b) else ca[idx_a]+ write_t2(out, X, C, genes, seed)+++if __name__ == "__main__":+ import argparse++ p = argparse.ArgumentParser()+ p.add_argument("--data", required=True)+ p.add_argument("--out", required=True)+ p.add_argument("--seed", type=int, default=0)+ args = p.parse_args()+ main(args.data, args.out, args.seed)
调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。
用到的知识库条目
| 编号 | 标题 | 出处 |
|---|---|---|
| k027 | Joint expression-geometry generation with relative geometry | notes/competition/03_solution_landscape.md |
| k009 | Conditional / OT flow matching for population transport | arXiv:2210.02747 (Lipman et al., Flow Matching for Generative Modeling) |
| k007 | Interval staging and held-out-window filtering of external data | notes/official/来件/virtualembryo.ai/rules.md |
分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。
| 改了什么 | 从零实现 T2EI-03:表达 PCA(20) + 刚体不变几何特征(5-NN 距离、邻域型组成、归一化半径)拼接联合 latent,共有型内按到插值质心 (1−t)μ_a+tμ_b 的距离确定性选取 b 侧细胞;procrustes3d 对齐、RMS 阻尼缩放(0.455)、κ=0.65 组成阻尼,坐标不插值不膨胀,含 JOINT_SEL on/off 开关。 |
|---|---|
| 各组分数的变化 | cell_state:变好:52.56 vs 37.49(+15.07,远超噪声) expression_change:噪声内:60.20 vs 59.72(+0.48,T2 噪声约 1 分) local_spatial:变好:59.83 vs 57.27(+2.56) shape_scale:噪声内:74.34 vs 74.43(−0.09) |
| family_id | T2EI-03 |
| 假设是否成立 | 是 |
| 经验 |
|
| mechanism_active | 是 |
| 下一步建议 |
|
对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。
只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。
分析员
| 角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。 | 分析员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数?大模型一共回复了几轮(每轮可以调用多个工具)。 | 2 |
| 工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。 | 共 1 次:write 1 |
| 用时 | 不到 1 分 |
| token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。 | 输入 9,287 · 输出 1,138 · 思考 376 |
| 任务(第一行) | 分析节点 n18 的打分结果,写 ANALYSIS.json |
| 最后的回答(摘录) | ANALYSIS.json written |
| 原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。 | /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/analyst.jsonl 5 KB /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/analyst.stderr |
工程师
| 角色 | 工程师 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 27 |
| 工具调用 | 共 31 次:bash 25、write 3、edit 3 |
| 用时 | 10 分 |
| token 数 | 输入 58,894 · 输出 9,657 · 思考 15,196 |
| 任务(第一行) | 按计划修改程序:T2EI-03 联合表达-几何 latent 选胞 draft |
| 最后的回答(摘录) | 提交态确认:`solution/` 含 `run.py`(默认 JOINT_SEL=on、κ=0.65、procrustes3d、damp=0.455)、`EXECUTION.json`(gpu=false)、`METHOD.md`;seed 0 复跑逐字节一致,vec-check ok。 **总结** - 做了什么:从零实现 PLAN T2EI-03 —— 表达 PCA(20) + 刚体不变几何(5-NN 距离、邻域型组成、归一化半径)拼接联合 latent,共有型内按到 (1−t)μ_a+tμ_b 的距离确定性选 b 侧细胞;组成阻尼 κ、procrustes3d 对齐、RMS 阻尼缩放,坐标不插值不膨胀;含 JOINT_SEL on/off 开关。 - 查分(12/20 次):提交态 60.65(cell_state 51.08 / expr 60.22 / shape 72.96 / local 58.33);off 对照 59.89,机制使 cell_state +2.84(生效),board +0.76(噪声内)。消融:W_GEO=0→60.62、κ=0.5→60.70、KNN10/mt5/proc 均更低。低于树最佳 62.15。 - 下一步最值得试:在本选胞机制上叠加节点 11 已证明的 b 侧 xy 径向膨胀 γ≈1.15(本家族 shape 已最高、cell_state/local 偏低),以及型内选取改距离分位分层保多样性、κ∈[0.5,0.65] 联扫。 |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/engineer.jsonl 127 KB /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/engineer.stderr |
调研员
| 角色 | 调研员 alibaba-token-plan-cn/qwen3.8-max |
|---|---|
| 调用次数 | 1 次 |
| 轮数 | 1 |
| 工具调用 | 共 0 次:— |
| 用时 | 2 分 |
| token 数 | 输入 8,041 · 输出 1,200 · 思考 3,910 |
| 任务(第一行) | 为节点 n18(草稿,父节点 nNone)写改进计划 PLAN.json,思路 T2EI-03 |
| 最后的回答(摘录) | .48)。现有 mix 流程的 b 侧选胞只基于表达质心距离(节点 7)或径向分层(节点 6),未利用局部几何信息,导致选出的细胞在空间上未必处于中间态。节点 12 的坐标插值使 local_spatial 掉 2.0,说明表达与空间不能独立生成。T2EI-03 在联合 latent 里选胞,让表达-位置对应自然保持,针对 cell_state 同时不损害 local_spatial。","approach":"步骤:(1) 读视图,按时间排序取最早阶段为 a、最晚为 b;若只有一个输入阶段则直接复制该阶段输出(退路)。(2) 表达特征:对共有基因做 z-score,取前 K_PCA=20 个 PCA 分量(搜索范围 10-50)。(3) 几何特征(刚体不变):每细胞计算 a) 到 5 个最近邻(坐标空间)的平均距离;b) 5-NN 中各细胞型占比(向量);c) 到全云质心距离 / 全云最大半径(归一化径向位置)。(4) 联合 latent:将 PCA 分量与几何特征拼接,各块独立 z-score 后加权拼接,W_EXPR=1.0, W_GEO=1.0(搜索 W_GEO 0.5-2.0)。(5) 对每个共有细胞型:计算 a 侧质心 μ_a、b 侧质心 μ_b(在联合 latent 中),目标点 target=(1-t)*μ_a + t*μ_b,t 由视图时间间隔决定(proxy 单间隔取 0.5)。(6) b 侧选胞:按到 target 的欧氏距离升序取前 n_b 个(确定性)。n_b 由组成阻尼 κ=0.65 决定:n_b = round(κ * N_b_orig * type_frac)。(7) 输出:所有 a 细胞 + 选出的 b 细胞,坐标保持原值;全局缩放阻尼 SCALE_DAMP=0.455 使输出 RMS 对准参考。(8) vec-score 快筛:先跑 500 细胞子集确认无报错,再全量查 2-3 次(A 半),比较 JOINT_SEL=on vs off 的 cell_state 和 local_spatial。关键参数初值:K_PCA=20, K_NN=5, W_GEO=1.0, κ=0.65, SCALE_DAMP=0.455。单输入阶段退路:若 len(stages)==1,直接输出该阶段所有细胞,跳过全部选胞逻辑。","expected_groups":["cell_state","local_spatial"],"risks":"1) 联合 latent 中几何特征噪声大(kNN 距离对稀疏区域不稳定),导致选胞质量不如纯表达质心;Engineer 应先单独跑 W_GEO=0 对照,确认表达基线不劣于节点 7 水平(cell_state≥52),再加几何。2) 30 分钟时限紧:PCA + kNN 计算量在万级细胞上应 <10s,但若视图细胞数极大需先用 numpy 向量化,避免逐细胞循环。3) 若联合选胞与纯表达选胞差异在噪声内(<1 分),说明几何特征未提供额外信息,提交 off 对照。4) 坐标不做任何变换(不插值、不膨胀),避免重蹈节点 12 的 local_spatial 下降。","family_id":"T2EI-03","mechanism":"在表达 PCA + 刚体不变局部几何(kNN 距离、邻域类型组成、归一化半径)拼接的联合 latent 中,按到型内插值质心的距离确定性选取 b 侧细胞,表达与坐标一起从真实细胞取得,保持表达-位置对应。","vs_constant_shift":"常数位移对每个细胞型施加统一表达偏移,不改变细胞间的相对关系,也不利用空间信息;本方案在包含几何特征的联合空间中逐细胞排序选择,不同细胞被选中的概率取决于其在表达-几何联合空间中的位置,产生型内异质性选择而非均匀位移。","mechanism_evidence":"Engineer 应输出:1) 被选 b 细胞在联合 latent 中到 target 的距离分布 vs 随机选取的距离分布(KS 检验或均值比);2) 被选细胞的 kNN 距离方差应小于随机选取(空间更均匀);3) 四组分各自变化,尤其 cell_state 和 local_spatial 应同时不劣于 off 对照;4) W_GEO=0 时结果应退化为纯表达选胞(类似节点 7),作为消融。","mechanism_off_control":"JOINT_SEL=off:b 侧细胞改为同 seed 随机抽取相同数量,其余流程完全一致。预期差别:off 对照的 cell_state 应低于 on(因为随机选到的 b 细胞在表达-几何空间中不偏向中间态);若 on-off 差距 <1 分(噪声内),说明机制未生效,提交 off 对照。"} |
| 原始记录位置 | /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/researcher.jsonl 5 KB /home/spark-longxinyang/vec/runs/formal/20261003-043412-search-t2-embryo-interp-g24-D-s1/nodes/18/researcher.stderr |