
ESPectre 数据集质量评审的检测器无关化改造从 Classic 阈值回放到共享尺度不变特征证据【免费下载链接】espectreWi-Fi CSI motion sensing for ESP32. C SDK, ESPHome, Native, and Matter frontends, browser tools, and a CLI for the full device lifecycle. GPLv3 and commercial licensing.项目地址: https://gitcode.com/GitHub_Trending/es/espectre导读本文围绕 ESPectre 项目中的一份架构决策记录ADR展开详细讲解tools/validate_dataset_quality.py如何从依赖 Classic 检测器回放、启动校准与阈值语言的评审机制演进为**完全检测器无关detector-agnostic**的评审机制。你将理解为什么低 RSSI 采集对会触发检测器告警但数据本身可分的伪劣信号评审指标如何改用 8 个尺度不变的生产特征Cover / Sep / Tail / Exc / Burst / Drift / Score等评审指标的精确含义与阈值以及如何运行验证器、读懂生成在data/auto_generated/DATASET_QUALITY_CHECK.md中的报告。读完本文你可以直接上手校验自己的数据集并能向他人解释数据集评审与检测器性能门禁为什么必须是两套独立的证据面。背景一份文档曾经同时承担两件不同的事在 2026-07-29 这份 ADR 之前tools/validate_dataset_quality.py已经能很好地完成两个任务阻止被污染或不可用的采集进入 ML 训练在data/auto_generated/DATASET_QUALITY_CHECK.md中汇总已准入语料供人工评审。问题出在 2026-07-17 的拆分Classic 已经从数据集准入流程中移除但评审表格仍然依赖ClassicDetector回放、启动校准startup calibration以及阈值相对的语言threshold-relative language。这就让操作面残留了一种循环论证一个校准不良的检测器即使共享的生产特征已经把数据干净地分开也可能让某条采集看起来质量差。这个缺陷在低 RSSI 配对low-RSSI pairs上尤其显眼报告可能因为检测器被激活而告警而数据内在的 idle/motion 分离其实很强——这反映的是检测器的局限而不是数据集损坏。报告因此需要直接描述数据本身而不是描述某一个检测器的阈值落在哪里。ADR 同时强调必须保留单一事实来源one source of truth数据集准入属于验证器检测器晋升promotion属于docs/performance/README.md把报告拆成第二份数据集质量文档会重复策略与指标。决策保留一份报告但评审指标检测器无关ADR 的核心决策一句话即可概括仍然只生成一份数据集质量报告但让其中的评审指标完全脱离任何检测器回放。准入admission逻辑保持不变仍然可能让整次运行失败完整性、连续性与信号质量检查integrity / continuity / signal-qualityempty与static_presence的可用性 / 重叠检查availability / overlapML 就绪检查ML readiness长录制标注与覆盖检查long-recording annotation and coverage被替换的只是仅用于评审的表格。它们现在来源于生产与训练中已经在使用的共享尺度不变特征流水线shared scale-invariant feature pipeline。8 个核心证据特征全部增益不变评审的证据面是当前生产 High Accuracy 特征集按构造全部增益不变gain-invariant。这 8 个特征定义在 tools/lib/csi_features.py 的PHASELESS8_FEATURES即DEFAULT_FEATURES中特征名语义方向FEATURE_EVIDENCE_DIRECTIONSturb_iqr_over_mean_aggr1.0越大越活跃turb_autocorr1.0turb_zcr-1.0过零率越高越安静l1_delta_lag_ratio1.0chan_shape_spread_subband1.0默认方向chan_shape_coherent_innovation_energy1.0默认方向chan_shape_excess_path1.0默认方向chan_shape_subband_kendall_lag_excess1.0默认方向特征方向direction由特征语义固定而不是从检测器回放中推断。在 tools/lib/dataset_quality/severity.py 的FEATURE_EVIDENCE_DIRECTIONS中前 4 个特征显式声明了方向其余特征默认取 1.0tools/lib/dataset_quality/metrics.py 的_feature_evidence_series会把每个窗口的多维特征矩阵按direction * (value - center) / scale归一化并裁剪到 [-8, 8]再沿特征轴取均值折叠成一条共识特征证据序列consensus feature-evidence series。为什么这些特征能在弱链路 / 增益漂移下保持可比代码里有一处非常典型的佐证l1_delta与l1_delta_std两个特征曾在 2026-07-28 被移除——把一条强链路采集加入训练后一条弱链路配对的假阳性从 0% 跳到 100%因为其 idle 位移0.2653高于自身 motion0.1830、也高于新采集的 motion0.0587。这正是绝对能量类特征不可比的实证tools/lib/csi_features.py。配对行用证据覆盖与秩 AUC 替代阈值诊断配对行Pair rows把阈值相对的 Classic 诊断替换为以下指标Covermotion 窗口中有多少比例高于 idle 半段的自身 p95 证据share of motion windows above the idle halfs own p95 evidence。实现见 tools/lib/dataset_quality/pairing.pymotion_coverage ((motion_evidence idle_p95).mean())。Sepidle 与 motion 证据之间的基于秩的 AUCrank-based AUC。实现是 Mann-Whitney 统计量只读两条序列的相对次序因此与阈值位置及任何单调重标度无关tools/lib/dataset_quality/metrics.py。Tailidle 侧 q95 高于该配对自身居中证据基线的量。Score0-100 的指示性排序由分离度、覆盖度与 idle 洁净度合成。配对行的最终Score还会被两个方向的证据共同封顶min(pair_score, reference_cleanliness_score)后再被两端采集的时域占用率occupancy封顶tools/lib/dataset_quality/pairing.py。这样强分离无法掩盖static 捕获整体漂移或持续活跃的问题。Idle 行用自身基线替代自校准 Classic 基线Idle 行覆盖 Presence / Empty / Long-recording 三张表把自校准 Classic 基线项替换为Exc在特征证据轴上超过median 3 MAD的窗口占比excursion share。BASELINE_EXCURSION_MADS 3.0tools/lib/dataset_quality/severity.py。Burst在块级 idle 基线上测得的持续突发长度sustained burst length以 5 秒块为单位BASELINE_BLOCK_SECONDS 5.0。Tailq95 高于该采集自身居中证据基线的量。Drift前半段与后半段的中位证据漂移half-to-half median evidence drift取绝对值tools/lib/dataset_quality/metrics.py。Score0-100 指示性排序由尾部洁净度与突发长度合成agnostic_baseline_score权重 0.7 / 0.3见 tools/lib/dataset_quality/metrics.py。阈值相对的检测器术语从生成报告中整体移除。Lightweight 仍然出现在检测器晋升与性能面中但不再进入数据集质量评审docs/adr/2026-07-29-make-dataset-quality-review-detector-agnostic.md。演进记录日期方向决议2026-07-17将数据集准入与 Classic 诊断分离但保留 Classic 评审表从准入中移除检测器行为2026-07-29让剩余评审指标检测器无关作为唯一数据集质量策略被接受验证器如何运行命令、阶段与报告命令入口入口脚本是 tools/validate_dataset_quality.py常用调用方式脚本自身 help 文本中的示例python tools/validate_dataset_quality.py # 完整校验自动报告 元数据刷新 python tools/validate_dataset_quality.py --chip C6 # 只校验 C6 python tools/validate_dataset_quality.py --data-dir data/untracked/example --preserve-pairs python tools/validate_dataset_quality.py --data-dir data/untracked/example --diagnostic-all-phy python tools/validate_dataset_quality.py --no-cache # 绕过持久化的验证缓存 python tools/validate_dataset_quality.py --no-report # 跳过 Markdown 报告关键参数--chip按芯片类型过滤如 C6、S3、C3、ESP32--data-dir数据集根目录默认data/需包含dataset_info.json与标签目录--report-output报告输出路径默认data-dir/auto_generated/DATASET_QUALITY_CHECK.md--preserve-pairs保留显式配对而非按时间戳刷新--diagnostic-all-phy在仍报告违反受支持的 HT20 / HT-LTF 传感契约的前提下评估所有显式 PHY 行--no-cache单次运行绕过持久化的时间感知 ML 行缓存--check-current仅当报告与当前输入一致时以 0 退出CI 场景很有用。校验阶段编排逻辑在 tools/lib/dataset_quality/runner.py 的run_validation中按阶段执行元数据完整性Phase 1域integrity要求每个新条目声明environment与显式dataset_role缺失角色视为exclude但校验仍会失败直到所有条目显式声明。NPZ 完整性 / 质量Phase 2域integrity对每个文件做完整性、连续性stream loss、信号质量检查low_rssi采集的流缺失失败阈值放宽到 5%普通录制为 3%1% 以上开始告警。配对校验Phase 3域feature_space基于共享特征矩阵评估static_presence ↔ motion配对产出 Pair Scores 行。配对由refresh_pair_metadata自动刷新同芯片、同子载波数、采集时间差在PAIR_MAX_DELTA_SECONDS 30 * 60秒内、按时间差做最近 1:1 贪心配对tools/lib/dataset_quality/pairing.py。Empty / Presence 健全性Phase 4域label_sanity/feature_space产出 Empty Scores 与 Presence Scores 行并把empty_quality/*、presence_quality/*归入特征空间域。Quiet-test 健全性Phase 5域long_recording/feature_space面向long_recording: true的安静长录制产出 Long-recording scores 行。ML 就绪Phase 6域ml。Excluded 诊断dataset_role: exclude的配对与 idle 采集仍会以信息性诊断形式出现在 Excluded 表中不参与校验汇总——这正是 ADR被排除的配对可以保持可见但不重新引入检测器偏差的落地方式。报告最终由 tools/lib/dataset_quality/report.py 的_generate_report原子写入atomic_write_text头部记录数据修订哈希、输入修订哈希、评估视图与策略文档指针。先决条件与适用前提按 docs/ML_DATA_COLLECTION.md 的说明校验前必须完成至少 10 个样本 / 标签建议 30-60 秒 / 样本、每条dataset_info.json条目带environment与显式dataset_role、同一环境使用相同环境名。配对字段不要手工填写验证器会基于时间戳自动刷新均值有效槽占用率低于 85% 告警、低于 70% 准入失败并封顶所有相关评审分数。时间质量与 ML 就绪检查需要可用的录制包速率num_packetsduration_ms时序元数据不足会被判定为校验失败绝不会被解释成 100 pps。完整流程见 docs/ML_DATA_COLLECTION.md 与 tools/README.md。报告中的评审指标含义、阈值与实现依据报告在每个分数表后都附有Reading these tables与Validation rule段落tools/lib/dataset_quality/report.py核心口径如下。通用规则所有分数都由共享尺度不变特征证据与时域占用率封顶共同构成没有任何一个分数依赖检测器阈值或概率面。配对行的Cover/Sep与外部静态洁净度RefExc/RefBurst保持独立最终Score被两者共同封顶因此强分离不能掩盖漂移或持续活跃的静态采集。Presence / Empty / Long-recording 行汇总采集内部稳定性因为使用采集自身的中心能暴露突发与漂移但无法暴露均匀的跨会话整体漂移Excluded Idle Diagnostics 针对已准入的同芯片、同链路等级、同包速率等级参考提供这个缺失的跨会话视角同一环境至少有 3 个独立采集时优先。阈值一览以报告生成逻辑为准指标告警 / 失败规则Stream loss缺失stream_seq_num⚠️ 1%❌ 3%普通❌ 5%low_rssi: trueOcc均值有效槽时域占用⚠️ 85%❌ 70%失败阈值是准入门占用率同时是分数封顶Covermotion 窗口高于 idle p95 占比⚠️ 95%❌ 90%RefExc5 秒块高于外部参考 p95 占比⚠️ 25%❌ 50%RefBurst高于外部参考 p99 的最长连续块⚠️ 30s❌ 120sExc超过自身median 3 MAD的窗口占比⚠️ 8%❌ 13%Tail自身 q95 与自身中位的差距⚠️ 4.0❌ 6.0Sepidle/motion 证据秩 AUC⚠️ 0.990❌ 0.970Burst最长持续突发秒数⚠️ 30s❌ 120sScore0-100 评审排序信号不参与准入准入只取决于完整性、占用、连续性、元数据、重叠与 ML 就绪以上常数定义在 tools/lib/dataset_quality/severity.py 中如MAX_STREAM_SEQ_MISSING_WARN_RATIO、TEMPORAL_OCCUPANCY_WARN_RATIO、MIN_MOTION_COVERAGE_RATIO、REFERENCE_EXCURSION_WARN_RATIO、BASELINE_TAIL_WARN_LOGITS、SEPARATION_WARN_BELOW等并在 tools/lib/dataset_quality/report.py 中被引用进报告文本——报告里看到的数字与判定代码使用的是同一组常量。经验阈值peer-relative机制从源码结构看评审还在部分指标上引入了同芯片经验阈值机制当本次运行中通过采集足够多时Burst/Drift等指标会以通过样本的经验分位数warn 为 90% 分位、fail 为 98% 分位替代固定阈值同芯片参考不足时回退到固定阈值tools/lib/dataset_quality/severity.py。值得注意的是Sep被刻意排除在经验阈值之外AUC 以 1.0 为上界且好配对紧贴天花板用底部分位数标记会把近完美的录制误标为离群因此配对分离度永远使用绝对下限tools/lib/dataset_quality/severity.py。外部参考洁净度Ref 机制配对行与 Excluded Idle 行中的RefExc/RefBurst由 tools/lib/dataset_quality/references.py 实现从准入的empty与static_presence排除长录制中构建 idle 参考块按芯片 环境 链路/速率层stratum选择参考——同环境参考 ≥3 条时优先chipenvstratum否则退到chipstratum。目标采集的 5 秒块特征证据中超过参考 p95 的占比为RefExc超过参考 p99 的最长连续块为RefBurst。这套机制正是 ADR 中弱链路与增益漂移采集保持可比的具体实现。后果收益、代价与取舍收益数据集质量报告现在描述录制本身而不是某个检测器的启动校准弱链路与增益漂移采集保持可比因为核心指标来自尺度不变共享特征被排除的配对可以保留为信息性诊断而不会重新引入检测器偏差检测器特有的问题仍然留在它们该在的地方性能与晋升门禁docs/performance/README.md。代价报告现在拥有一个小的特征证据层及其无阈值评分规则必须与共享特征语义保持对齐idle 采集的突发与漂移评审需要谨慎解读它们概括的是特征空间行为而不是检测器的二元告警。被否决的备选方案保留 Classic 评审、只删掉标记的阈值列否决。即使不标出的回放表也会让操作者锚定在某个检测器的校准路径上把检测器特有的失败模式留在数据集质量叙事中。在现有报告旁边新建第二份 agnostic 报告否决。数据集质量策略属于一份生成文档性能策略属于docs/performance/README.md。直接用原始 RSSI 或绝对能量特征评分否决。这些量在增益变化或弱链路上不稳健会重新引入本次变更要消除的可比性问题。如何在实践中使用这份评审采集按 docs/ML_DATA_COLLECTION.md 的流程用./espectre collect --label empty|static_presence|motion --duration 60 --target ip采集并保持标签同质。标注元数据为data/dataset_info.json中每条新条目添加environment与显式dataset_roletrain/selection/holdout/exclude。校验运行python tools/validate_dataset_quality.py先解决准入 FAIL评审分数仅为诊断用途准入失败会阻断工作流。读报告查看data/auto_generated/DATASET_QUALITY_CHECK.md的 Pair / Presence / Empty / Long-recording / Excluded 各表关注Cover、Sep与RefExc/RefBurst配对表以及Exc、Burst、Tail、Driftidle 表Score只是紧凑的排序信号不是准入依据。CI 化用--check-current让报告与其输入保持同步报告头部同时记录数据修订与输入修订的 sha256。相关文档数据采集与标注见 docs/ML_DATA_COLLECTION.md训练与导出见 docs/ML_TRAINING.md特征定义见 docs/FEATURES.md检测器晋升与性能门禁见 docs/performance/README.md训练/验证加载器使用的 HT20 HT-LTF 64 子载波契约见 docs/CSI.md。【免费下载链接】espectreWi-Fi CSI motion sensing for ESP32. C SDK, ESPHome, Native, and Matter frontends, browser tools, and a CLI for the full device lifecycle. GPLv3 and commercial licensing.项目地址: https://gitcode.com/GitHub_Trending/es/espectre创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考