首页
/ RuView 学习型多人计数器 Cog:基于 Candle 的 WiFi CSI 人数估计设计与落地(ADR-103 深度解读)

RuView 学习型多人计数器 Cog:基于 Candle 的 WiFi CSI 人数估计设计与落地(ADR-103 深度解读)

2026-09-07 12:37:00作者:翟萌耘Ralph

本篇文章以 RuView 仓库中的架构决策记录 ADR-103(Learned Multi-Person Counter) 为骨架,结合其在 v2/crates/cog-person-count 中的真实 Rust/Candle 实现、sensing-server 中现存的启发式计数函数以及 docs/benchmarks/person-count-cog.md 基准日志,系统讲解:为什么用 WiFi CSI 做人数估计要从"启发式规则"走向"学习型网络",ADR-103 设计了怎样的编码器-计数头-置信度头架构、如何做多节点融合,以及它在仓库中目前真实落地到什么程度(含诚实的精度数据与局限)。读完你可以在仓库中直接定位到 Cog 的完整源码、配置 Schema、测试用例与训练脚本,并理解把它接入现有传感服务时的回退路径。

1. 问题起点:#499 幽灵骨架与 PR #491 的启发式止血

ADR-103 的动机来自两个历史问题:

  • Issue #499:3 节点 ESP32-S3 部署中出现"双重骨架"(double skeletons)——真实只有 1 人时 UI 却渲染出 2 个以上的人影。
  • PR #491:用 RollingP95 流式自校准估计器替换掉硬编码的分母(variance/300motion_band_power/250spectral_power/500),并把多节点 dedup_factor 暴露成运行时旋钮,从而缓解了#499。

在源码中能看到这段历史在传感服务器中的残留:score_to_person_count(smoothed_score, prev_count) 目前仍位于 v2/crates/wifi-densepose-sensing-server/src/csi.rs#L983,它根据 prev_count 分成三档(0|12、其它),再对 smoothed_score 做阈值切分,输出 1~3 之间的整数:

pub fn score_to_person_count(smoothed_score: f64, prev_count: usize) -> usize {
    match prev_count {
        0 | 1 => {
            if smoothed_score > 0.85 { 3 }
            else if smoothed_score > 0.70 { 2 }
            else { 1 }
        }
        2 => {
            if smoothed_score > 0.92 { 3 }
            else if smoothed_score < 0.55 { 1 }
            else { 2 }
        }
        _ => {
            if smoothed_score < 0.55 { 1 }
            else if smoothed_score < 0.78 { 2 }
            else { 3 }
        }
    }
}

field_bridge.rs 还能看到另一个佐证:单条 ESP32 链路能可靠解析的人数上限被定为 MAX_SINGLE_LINK_OCCUPANCY = 3,超出即视为噪声。也就是说,ADR-103 之前的"槽位启发式"本质是手工标定阈值 + 运动状态平滑 + 单链路硬上限的组合。

ADR-103 的判断是:这能给我们一个"能自适应房间的稳定启发式",但到不了已发表的 WiFi CSI 计数论文的水平。下表对比了学术界与 RuView 当时的差距(表格内容直接来自 ADR-103,注意硬件条件差异是核心变量):

系统 设置 报告精度 方法
WiCount(CMU, 2017) Intel 5300 3×3 MIMO 89%(±1 内) CSI 幅度上的 LSTM
DeepCount(2018) Atheros 3×3 92%(±1 内),5 房间 CNN + 跨环境迁移
CrossCount(2019) Atheros,6 房间 84% 跨房间(±1 内) 域对抗 CNN
HeadCount(2021) Intel 5300 MAE < 1 人,5 环境 多流 CSI + 注意力
RuView today(PR #491) ESP32-S3 1×1 SISO 已校准启发式;未对 ground truth 测量 RollingP95 + dedup_factor

文献用的是 3×3 MIMO 科研网卡,RuView 用的是 1×1 SISO ESP32-S3 节点,因此论文数字不能直接照搬;但 ADR-103 认为两者之间的架构性差距足够大——在本仓库硬件上做学习型计数,应能明显优于槽位启发式,而且训练所需的基础设施已经具备(Candle + RTX 5080 曾在 2.1 秒内训出 pose_v1.safetensors,参见 docs/benchmarks/pose-estimation-cog.md)。

2. 五大已有但尚未组合成计数器的原语

ADR-103 的核心论证之一是:做学习型计数器不需要从零造轮子,仓库里已经有五块积木,缺的只是把它们"组合成一个计数器"的编排层:

  1. 成对的 CSI + 相机标签数据集 —— 采集脚本 scripts/collect-ground-truth.py 与对齐脚本 scripts/align-ground-truth.js。从采集源码看,collect-ground-truth.pyL308-L332n_persons = len(result.pose_landmarks) 从 MediaPipe 结果取人数并写入每帧 JSON——也就是说计数标签在既有姿态数据管线里是免费附带的,无需重新开展数据采集。
  2. Stoer-Wagner min-cut,用于划分"人可分离的子载波分组" —— ruvector-mincut 已是 workspace 依赖,Candle 训练器曾报告 Min-cut value: 0.1538 — partition: [55, 1] subcarriers
  3. 对比预训练的 CSI 编码器 —— ruvnet/wifi-densepose-pretrained(HF),12.2M 训练步、60K 帧、128 维 embedding、在 M4 Pro 上约 165k emb/s。
  4. Candle 训练管线 —— 一天前刚验证:RTX 5080 上 400 epochs 只用 2.1 秒,ONNX 导出逐位一致,签名 Cog 二进制已上 GCS。
  5. 多节点融合级 —— multistatic_bridge.rs 已用可调 dedup_factor 聚合各节点特征向量,新模型的输出可以做成现有 dedup 除数的即插即用替代品。

3. 决策:把人数估计做成一个 Cog(cog-person-count

ADR-103 的决策是:训练并交付一个小型学习型多人计数器,作为新的 Cognitum Cog(cog-person-count),打包路径复刻 cog-pose-estimationADR-101),并接入 sensing-server 现存的计数调用点 csi.rs::score_to_person_count,作为槽位启发式的即插即用替代。模型未安装时按 ADR-100 的 stub-fallback 模式回退到启发式。

在仓库中该 crate 已经真实落地,路径为 v2/crates/cog-person-count,模块划分与 ADR-103 的仓库布局一节基本一致:

  • src/main.rs —— Cog 入口,实现 ADR-100 的四动词运行时契约:version | manifest | health | run
  • src/inference.rs —— Candle 前向推理(编码器 + 计数头 + 置信度头);
  • src/fusion.rs —— 置信度加权 log-sum 融合 +(v0.2.0 预留的)Stoer-Wagner min-cut 上限裁剪;
  • src/publisher.rs —— 输出 {count, confidence, count_p95_low, count_p95_high} 结构化 JSON 事件;
  • src/manifest.rssrc/runtime.rs —— 内嵌签名清单与长驻轮询循环;
  • cog/manifest.template.jsoncog/config.schema.jsoncog/README.md
  • tests/smoke.rs + fusion.rs 内嵌单元测试、benches/infer_bench.rs

Cargo.toml(见 v2/crates/cog-person-count/Cargo.toml)确认其依赖栈与 pose cog 同源:candle-core/candle-nn 0.9(默认 CPU,cuda feature 可选开启)、safetensors 0.4、ureq(轮询用)、clapserde_json;dev 依赖含 criterion(ADR-163 稳态推理时延基准)。发布描述词也写明了诚实边界:"8-class count head 随包发布,但超出训练范围的人数会被标记 low_confidence"

3.1 架构(v0.1.0,ASCII 原图)

                              ┌──────────────────────────────┐
       per-node CSI window    │  Encoder (frozen first 50 ep) │
       [56 sub × 20 frames]  ─►  init from ruvnet/wifi-       │
                              │  densepose-pretrained         │
                              │  → 128-dim embedding          │
                              └──────────────┬───────────────┘
                                             │
                            ┌────────────────┴────────────────┐
                            ▼                                 ▼
                   ┌────────────────────┐       ┌────────────────────────┐
                   │  Count head        │       │  Confidence head       │
                   │  Linear(128→64)    │       │  Linear(128→32)        │
                   │  ReLU              │       │  ReLU                  │
                   │  Linear(64→8)      │       │  Linear(32→1) + sigmoid│
                   │  → softmax over    │       │  → calibrated p(correct)│
                   │     {0..7} persons │       └────────────────────────┘
                   └────────┬───────────┘
                            │                    (per-node prediction)
                            │
       N nodes' per-node    │
       counts + confidences ▼
                   ┌─────────────────────────────────────┐
                   │  Multi-node fusion (Stoer-Wagner)   │
                   │  • build graph: nodes × subcarrier  │
                   │    feature similarity               │
                   │  • min-cut → distinct-person bound  │
                   │  • combine with per-node count head │
                   │    via confidence-weighted vote     │
                   └──────────────────┬──────────────────┘
                                      ▼
                          { count: int,
                            confidence: float [0,1],
                            count_p95_low: int,
                            count_p95_high: int,
                            per_node_breakdown: [...] }

3.2 源码中的真实网络结构

inference.rs 的模块注释给出了与 ADR-103 架构一一对应的、已实现的网络形状:

Conv1d(56 -> 64,   k=3, dilation=1, padding=1)
Conv1d(64 -> 128,  k=3, dilation=2, padding=2)
Conv1d(128 -> 128, k=3, dilation=4, padding=4)
mean over time -> [128]              ← 共享编码器
├── Linear(128->64) -> ReLU -> Linear(64->8)  → softmax over {0..7}(计数头)
└── Linear(128->32) -> ReLU -> Linear(32->1)  → sigmoid → confidence(置信度头)

常量定义同样可定位:INPUT_SUBCARRIERS = 56INPUT_TIMESTEPS = 20COUNT_CLASSES = 8,即输入是 [56, 20] 的 CSI 窗口——与 pose cog 完全一致的张量形状。CountNet::newvb.pp("enc") / vb.pp("count_head") / vb.pp("conf_head") 三个命名空间构建参数,保证与 PyTorch 训练端(scripts/train-count.py)导出的 safetensors 布局逐位兼容;infer() 先校验输入长度必须等于 56×20,再 reshape 为 (1, 56, 20) 做一次前向,得到 probs(softmax 后、8 类分布)与 conf(sigmoid 后的置信度标量)。

ADR-103 特别强调的五个设计点,在源码中都能验证:

  1. 前 50 epochs 冻结编码器:沿用 HF 存在模型已有的 128 维 embedding,只训上层头部,属于标准迁移学习套路,避免重学对比几何。
  2. {0..7} 做分类而非回归:人数是整数,分类输出天然给出每个计数的校准概率,置信度头因此才有意义。
  3. Stoer-Wagner 只在融合期使用:用 min-cut 对单节点计数做上界约束(一个节点能看到的不同人数不会超过子载波图的 min-cut 数),再做置信度加权投票。
  4. 输出四元组而非单个整数{count, confidence, count_p95_low, count_p95_high},下游 Cog/仪表盘/告警可按自己的置信度阈值决策——这正是闭环 #499 体验的关键:模型不确定时,仪表盘渲染一个带 "?" 徽标的火柴人,而不是两个"幽灵"。
  5. 不换硬件:仍是现有 ESP32-S3 1×1 SISO,增益来自学习特征 + 多节点融合,而非更大的天线阵列。

4. 训练路径:与 pose cog 同一管线,标签白拿

ADR-103 给出的训练对照表直接复用"昨天刚验证"的 pose 管线,差异只在输入初始化、输出头与损失函数:

Pose cog(当时) Count cog(本文档)
输入 [56, 20] CSI 窗口 [56, 20] CSI 窗口(完全一致)
编码器初始化 随机(HF 架构不匹配) 从 HF 存在模型初始化(架构兼容——同一编码器 Φ)
输出头 Linear(128→256→34) 关键点 Linear(128→64→8) 计数类 + Linear(128→32→1) 置信度
损失 置信度加权 SmoothL1 分类交叉熵 + Brier 分数不确定性校准
标签 MediaPipe 关键点 相机人数(MediaPipe pose_landmarks 长度)
数据 1,077 对(P7) 同一来源、同一脚本——collect-ground-truth.py 每帧已记录 n_persons

关键推论是:计数标签是免费的——collect-ground-truth.py 已经在每帧写入 "n_persons"(源码 L332),align-ground-truth.js 在滑窗时保留该字段,因此无需新的数据采集战役即可用产出 pose_v1 的同一批 1,077 个样本开训。ADR-103 指出大规模数据路径由 Issue #645 追踪(~30K 样本),训练的重现命令(来自 docs/benchmarks/person-count-cog.md):

python3 scripts/train-count.py --paired data/paired/wiflow-p7-1779210883.paired.jsonl \
  --k-fold 5 --epochs 100 --out-results kfold_results.json

python3 scripts/train-count.py --paired data/paired/wiflow-p7-1779210883.paired.jsonl \
  --v2 --epochs 400 \
  --out-safetensors count_v1.safetensors --out-onnx count_v1.onnx \
  --out-results count_train_results.json

其中 --paired 指向 P7 会话的成对数据(1,077 样本,标签分布 {0: 533, 1: 544});训练端按每子载波 Z-score 归一化。v0.0.1 的损失公式为 cross_entropy(count) + 0.3·BCE(conf) + 0.1·Brier(conf),优化器 AdamW(lr 1e-3,余弦热重启 T_0=50),RTX 5080 上 400 epochs 仅 5.6 秒。

5. 多节点融合:置信度加权 log-sum 与 min-cut 上界

单节点计数头+置信度头给出 {0..7} 上的分类分布;有 N 个节点就有 N 个分布 + N 个置信度标量。ADR-103 给出两条融合路径:

  • 置信度加权 log-sum(贝叶斯乘积)log p_fused(k) = Σ_n c_n · log p_n(k)。无额外参数,来自最优专家组合文献,v0.1.0 交付这条。
  • Stoer-Wagner 上界:以节点间两两子载波特征相似度为边建图,min-cut 大小 = 节点 mesh 能分辨的不同人数硬上界;把融合分布裁剪到 {0..min-cut} 支撑集后重归一化。这正是 ruvector-mincut 加入 workspace 的原因,v0.2.0 增加该裁剪。

fusion.rs 提供了两条路径的完整实现:

  • fuse_confidence_weighted(preds):空输入返回"1 人 + 0 置信度"的 stub 默认(与全局 stub 一致);单输入原样透传;置信度统一取 max(EPS_CONF=1e-3) 下界防止 log(0),概率统一取 max(1e-9) 下界;log-sum 后做"减最大值再指数化重归一化"的数值稳定处理;融合后的 confidence 取各节点最大值而非平均值——"至少有一个高置信度观测"比"一堆低置信度平均"更有价值。
  • fuse_with_mincut_clip(preds, max_distinct):v0.2.0 钩子已就位(ruvector_mincut 实装留待后续 PR,函数签名先固定以免运行时 API 断裂)。裁剪 {max+1..7} 的质量并重归一化;若全部质量都在上界之上(退化情形),则把质量放到上界类上而非输出零分布。

融合的数值/退化边界都有单元测试守护(fusion.rs 内嵌 tests),包括:空输入默认、单输入透传、双节点一致投票锐化峰、高置信度节点压过低置信度分歧、归一化保持、min-cut 裁剪不破归一化、P95 区间覆盖 ≥95% 质量。

5.1 v0.0.1 运行期融合的现状

需要诚实指出:当前 runtime.rs 的注释明确说明——v0.0.1 只交付单节点模式:设备上的 /api/v1/sensing/latest 端点已在返回前跨节点聚合,因此每个 Cog 内部的多节点融合推迟到各节点单独上送原始帧的 v0.2.0。运行循环每 poll_ms(默认 40ms,见 config.schema.json)用 ureq 轮询 sensing 端点,滑窗维护最近 56×20 个幅度值,engine.infer 成功后调用 publisher::person_count(tick, &pred, 1)(N=1 时融合为 no-op)。

6. 为什么学习型计数器优于槽位启发式

ADR-103 对"为何该换"给出的失败模式对照表,是理解整篇 ADR 论证价值的核心,全文继承如下:

槽位启发式的失败模式 学习型计数器的规避方式
#499 —— 固定分母钳位导致 1 人渲染成 2+ 组 编码器产出固定维度 embedding;计数头对特征形状而非幅值不变
dedup_factor 按房间手工调优是可见的运维负担 计数头的 softmax 天生就是"学出来的房间归一化器"
节点变多时槽位启发式的计数反而更噪 多节点融合在置信度上可加:每个节点要么降低不确定性、要么保持中立,绝不放大它
每帧没有不确定性信号 每次 emit 都带 confidencecount_p95_low/high
新环境灾难性失败 按房间 LoRA 适配器(ADR-079 P9 计划)可热切换、无需重训

7. 验收门(Acceptance Gates)

v0.1.0(初版) v0.2.0(数据扩展后)
Day-0 部署(免校准) 同房间测试集 ±1 内 ≥ 80% ±1 内 ≥ 90%
跨房间(held-out 环境) ±1 内 ≥ 60% ±1 内 ≥ 75%
平均绝对误差(MAE) ≤ 0.6 人 ≤ 0.4 人
每帧置信度反映精度 confidence(predicted==true) 的 Spearman r ≥ 0.5 r ≥ 0.7
Pi 5(Cog)推理时延 冷启动 < 5 ms/帧 < 5 ms/帧
GCS 二进制体积 ≤ 4 MB(对齐 cog-pose-estimation ≤ 4 MB

v0.1.0 刻意保持谦逊——它受限于数据采集规模(#645)。"框架本身就是交付物,精度随数据增长而到来"。

8. 仓库布局与传感服务器接线

ADR-103 规划的落地形态:

v2/crates/cog-person-count/                   # NEW(本 ADR)
├── Cargo.toml
├── src/
│   ├── main.rs                # cog runtime: version | manifest | health | run
│   ├── lib.rs
│   ├── inference.rs           # Candle 对每节点 CSI 的前向
│   ├── fusion.rs              # Stoer-Wagner 上界 + 置信度加权 log-sum
│   └── publisher.rs           # 发射 {count, confidence, count_p95_low, count_p95_high}
├── cog/
│   ├── manifest.template.json
│   ├── config.schema.json
│   ├── README.md
│   └── artifacts/             # 由发布管线填充
│       ├── count_v1.safetensors
│       ├── count_v1.onnx
│       └── train_results.json
└── tests/
    ├── smoke.rs               # 5+ 测试
    └── fusion_test.rs         # 多节点融合数学

外加一个小的服务器端接线改动:

  • v2/crates/wifi-densepose-sensing-server/src/csi.rs::score_to_person_count —— 通过 /api/v1/edge/registry 发现运行时后调用 Cog(与 cog-pose-estimation 相同),Cog 未安装时按 ADR-100 的 stub-fallback 模式回退到 PR #491 的启发式。

需要注意:仓库中的实际实现对此做了一次务实调整——cog/README.md 描述为 out-of-process 并行运行:sensing-server 继续发射自己的槽位启发式计数(回退路径,未安装本 Cog 的用户仍能得到一个数字,只是校准较差),而 cog-person-count 二进制轮询同一 /api/v1/sensing/latest 端点、对每窗口跑 count_v1、向 stdout 发射 person.count 事件,由设备的 cognitum-cog-gateway 经标准 cog 事件通道路由到仪表盘。操作者通过"装或不装"这个 Cog 来选择路径,无需重新编译 sensing-server;下游消费者订阅任一路事件流即可。

9. 事件输出格式与运行契约

9.1 每帧输出

config.schema.json 定义了运行配置的三字段:sensing_url(默认 http://127.0.0.1:3000/api/v1/sensing/latest)、model_path(必填,指向 count_v1.safetensors,相对路径基于 /var/lib/cognitum/apps/person-count/ 解析)、poll_ms(整数,10~1000,默认 40)。main.rsCmd 枚举实现了 ADR-100 的四动词契约:versionmanifesthealthrun --config <path>

publisher.rs 定义 person.count 事件(每行一个 JSON,走 stdout):

{
  "ts": 1779210883.444,
  "level": "info",
  "event": "person.count",
  "fields": {
    "tick": 12345,
    "count": 2,
    "confidence": 0.81,
    "count_p95_low": 1,
    "count_p95_high": 3,
    "n_nodes": 3,
    "probs": [0.01, 0.03, 0.81, 0.13, 0.01, 0.005, 0.003, 0.002]
  }
}

health.ok 事件则上报 backendcandle-cpu / candle-cuda / stub)、synthetic_countsynthetic_confidencesynthetic_p95_range

9.2 诚实裁剪(honest-clip)机制

源码 inference.rs 定义了 MAX_TRAINED_CLASS = 1:计数头有 8 个 logit,但已发布的 count_v1 权重只在类 0/1(空/有人)上受过监督——argmax 落到 2..7 属于分布外。为此:

  • CountPrediction::is_low_confidence() 返回 argmax() > MAX_TRAINED_CLASS
  • clamped_count() 把上报计数钳到最高受训类(宁可少报也不编造多人头数),原始分布仍留在 probs 供诊断;
  • publisher.rscount 用钳制值、raw_count 保留原始 argmax、分布外时事件 level 升为 warn

下游消费端可以做三种渲染策略:高置信度时直接渲染最可能计数;不确定时渲染 [count_p95_low, count_p95_high] 区间加 "?" 徽标;OOD 时只看 clamped_count。这就是 ADR-103 所说"关闭 #499 概念循环"的落地形态:人数变成学出来的任务,而不是带运行时旋钮的启发式

10. 安全设计:极小的攻击面

cog/README.md 的安全性一节强调:本 Cog 是纯 CSI 数据消费者而非服务器,零网络监听端口、零额外文件写入(仅 pid/output.log/error.log 由 cog-gateway 外部管理)。威胁与缓解措施包括:

威胁 缓解
不可信模型文件 mmap count_v1.safetensorsVarBuilder::from_mmaped_safetensors 加载(文档化 unsafe 块);发布管线按 ADR-100 用 COGNITUM_OWNER_SIGNING_KEY 签名,cog-gateway 校验 Ed25519 签名与 weights_sha256 后才放置文件
损坏模型产生非有限输出 CountPrediction::is_finite()cmd_health 与 run 循环发射 person.count 前检查,非有限输出 fail-closed
sensing-server 拉取失败 发射 WARN 事件并跳过该帧——与 pose cog 相同的"fail-open-as-log"模式,不崩溃、不泄漏 fd、不卡死 pid 文件
融合除零 / log(0) fuse_confidence_weighted 将置信度下限设为 1e-3、概率下限设为 1e-9;空输入返回 stub 默认而非传播 NaN
min-cut 裁剪后质量全在 cap 之上 fuse_with_mincut_clip 重归一化存活前缀;退化情形把质量放在 cap 类而非输出零分布
经 stdout 伪造输出 事件严格按 ADR-100 契约一行一个 JSON;无交互提示、无 shell 转义、无 ANSI 控制序列

11. 性能与实测数据

cog/README.mddocs/benchmarks/person-count-cog.md 记录了真实测量:

  • 二进制体积:Release 构建(workspace 已开启 opt-level=3lto="fat"codegen-units=1strip=true)在 x86_64 上为 2.36 MB,小于 pose cog 的 4.5 MB(不传递依赖 wifi-densepose-train)。
  • 冷启动(Windows x86_64、candle-cpu,30 次连续 health):pose cog 76.2 ms,person-count cog 53.3 ms
  • Pi 5 真机冷启动:9.2 ms/次调用(30 次共 0.276 s),略慢于 pose cog 的 8.4 ms,因为共享编码器后双头推理(计数 softmax + 置信度 sigmoid)约 2× 工作量;仍在 ADR-103 < 5 ms 热路径预算内(一旦长驻 run 循环落地、safetensors 保持 mmap 常驻)。
  • 热路径:stub 后端亚毫秒/帧(8 类单次 softmax 几乎零成本);带真实权重时受三个 Conv1d 层约束,Pi 5 上预计 ≤ 2 ms。
  • v0.0.1 实测精度(单一 30 分钟单人会话数据):整体 65.1%,类 1(有人)精度 0%——模型在 epoch 100 左右过拟合,"最佳"检查点实际是预测了 eval 窗口的类分布(大多数类 0)。v0.0.2(5-fold 随机 CV + 标签平滑 0.1 + 类别平衡采样 + patience 20 早停 + 温度缩放 T=0.9262):整体 62.3%、类 1 精度提升到 34.3%、MAE 0.377;5-fold CV 参考值显示架构在公平划分下类 1 能力约 57.1%。
  • 诚实结论:confidence 校准是当前真实短板——v0.0.1 Spearman 0.023、v0.0.2 仅 0.013,温度缩放无法修复"对着噪声 argmax==truth 指示符训练的置信度头";根本瓶颈与 pose_v1 相同,都是数据稀缺(#645),修复路径同样是多房间成对录制,而非更多训练技巧。

发布制品(v0.0.2)已在 cognitum-v0 上实装:count_v1.safetensors 392,088 B(sha256 32996433516891a37c63c600db8b95e42192a53bd538c088c82cd6a85e55513c),arm/x86_64 二进制均以 COGNITUM_OWNER_SIGNING_KEY(Ed25519)签名,清单在 cog/artifacts/manifests/{arm,x86_64}/manifest.json

12. 后果与风险(ADR 原文结论)

积极面

  • 关闭 #499 开启的概念闭环——多人计数成为学习任务而非带运行时旋钮的启发式。
  • 复用了当周已交付的全部原语:Candle GPU 训练(ADR-101)、HF 编码器、Cog 打包(ADR-100)、edge 模块注册表(ADR-102)、Stoer-Wagner mincut、成对数据管线(PR #641)。
  • Day-2 跨房间校准沿用 ADR-079 P9 为 pose 规划的同一 LoRA 路径,两个 cog 共享同一套微调机制。
  • 显式的 confidence + count_p95_low/high 输出让 UI 渲染不确定性而非凭空制造幽灵。

消极面

  • 精度受限于与 pose_v1 相同的成对数据稀缺(#645);无更多多房间数据时,v0.1.0 只能带有限的绝对精度发布。
  • GCS 目录中多一个需要维护的 Cog 二进制(每架构 4 MB)。
  • 融合段 min-cut 在 Pi 5 上约增加 0.3 ms/N 节点帧(ruvector-mincut 微基准),在 ≤5 ms 预算内可接受但值得追踪。

风险与缓解

  • 标签噪声:P7 会话 MediaPipe 检出率仅 47%——一半帧即使房间里明显有人,n_persons 也是 0。缓解:训练前按 MediaPipe confidence ≥ 0.7 过滤,并用置信度加权损失(pose_v1 用过同一技巧)。
  • 冻结过度:若 50 epochs 冻结编码器训练不收敛,提前解冻;train_results.json 的遥测可支撑经验决策。
  • min-cut 在单人场景过度约束:N=1 时子载波图 trivially 有 min-cut=1,融合降级为"信任单节点计数头"——可接受,但需要回归测试(tests/fusion_test.rs::single_node_degrades_gracefully)。

13. 迁移路线

  1. 落地本 ADR + 新 crate 脚手架(一个 PR,暂不含模型——与 ADR-101 首个 PR 发布 stub cog 相同)。
  2. 用既有 1,077 个成对样本 + n_persons 标签训练 count_v1.safetensors(与产出 pose_v1 相同的 Candle 管线)。
  3. 按 ADR-100 交叉编译 + 签名 + GCS 上传;按 ADR-101 的模式实装到 cognitum-v0
  4. 接线 csi.rs::score_to_person_count:安装 Cog 时调用它,保留 PR #491 启发式作为回退。
  5. v0.2.0:用 #645 推动的多房间数据重训,按 ADR-079 P9 增加 LoRA 按房间适配器。

14. 相关文档导航(仓库内相对路径)

登录后查看全文
热门项目推荐
相关项目推荐