的采纳与落地)
ESPectre Lightweight 检测器决策实录聚合湍流 IQR 特征对turb_autocorr turb_iqr_over_mean_aggr的采纳与落地【免费下载链接】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《use aggregated turbulence IQR for Lightweight》完整还原Lightweight 检测器为何放弃复数频域相干跟踪、改用 5-bin 相邻子载波聚合湍流流的 IQR 特征这一决策的前因后果并结合 lightweight_detector.cpp、lightweight_detector.py 等源码深入讲解特征计算、加权逻辑融合、启动阈值校准与settled-level阈值回落规则的真实实现。读完本文你将掌握 ESPectre 中资源受限检测器Lightweight的两特征流水线的完整原理、关键常量、可调参数及其验证边界并能在 docs/ALGORITHMS.md 与 docs/FEATURES.md 之外获得一份可直接对照源码阅读的决策与实现导读。一、决策背景Lightweight 为什么需要一个新的第二特征在 ESPectre 的检测器体系中LightweightDetector是HighAccuracyDetector的低资源替代方案它的约束是苛刻的必须保持紧凑、确定性的两特征线性检测器two-feature linear detector必须在 ESP32 系列C3/C5/C6/S2/S3 等受限运行时上运行状态量与推理成本都要可控。在 2026-08-13 之前的线上组合中Lightweight 的第二特征来自一个**复数频域相干跟踪器complex frequency-coherence tracker**导出的 temporal spread。问题在于这条路径要求在整个检测器体系旁边再维护一套独立的全频带复数特征族full-band complex feature family而它服务的仅仅是 Lightweight 这一个检测器的次要特征。也就是说为了一个低资源检测器的第二特征生产固件里长期保留着一套复杂且与湍流原语turbulence primitives平行的状态机——两个检测器共用的湍流原语反而没有被充分利用。随后在主机侧host-side展开了一轮系统性对照实验固定湍流自相关turbulence autocorrelation不变分别比较过零率zero-crossing rate, ZCR普通湍流流的 IQRnormal-turbulence IQR专用相邻 bin 聚合湍流流的 IQRIQR from a dedicated adjacent-bin aggregated turbulence stream。实验结论详见 docs/FEATURES.md 与生成的性能报告聚合湍流 IQR 在数据包压力下packet stress提供了更安全的顺序安静尾迹sequential quiet tail——即在流量抖动、丢包场景下检测器回到静默状态的过程更可靠、误报尾部更短同时保持了 Lightweight 的召回底线recall floor。普通 IQR 回退方案虽然更省资源状态更少但其空闲尾迹idle tail明显更差只能作为研究用候选保留。二、决策内容加权逻辑融合的两特征对该 ADR 的最终决策是使用滞后对齐的湍流自相关与聚合湍流流的稳健相对离散度robust relative spread做加权逻辑logistic融合。决策正文给出的核心公式如下x_aggr[t] spatial_turbulence(mean_amplitude_over_adjacent_live_bins(W5)) turb_iqr_over_mean_aggr (Q75(x_aggr) - Q25(x_aggr)) / max(abs(mean(x_aggr)), 1e-6) probability sigmoid(b w_ac * z(turb_autocorr) w_iqr * z(turb_iqr_over_mean_aggr))其中W5表示聚合窗口宽度为 5 个相邻子载波TURB_IQR_AGGREGATION_WIDTH 5U定义见 csi_features.hz(...)表示基于拟合中心center与尺度scale的标准化b、w_ac、w_iqr为拟合产出的截距与权重分母max(abs(mean), 1e-6)保证增益不变性gain invariance——特征只依赖比值不依赖绝对幅度这正是 ESPectre 特征族绝不记录每包 CSI 缩放因子原则的体现见 csi_features.h 文件头注释。2.1 两条流共享一个包级幅度帧决策特别强调普通湍流流与聚合湍流流共享同一个包级幅度帧packet-wide magnitude frame以及同一套可配置的 Hampel 与低通滤波策略。这意味着每个 CSI 包只需计算一次子载波能量两个特征流从同一帧中分别抽取普通幅度与相邻 bin 聚合幅度——这是把内存与算力开销压到最低的关键结构设计详见下文源码解析。2.2 被否决候选仅保留在主机侧决策明确约定offset-coherence、normal-IQR、ZCR 等被否决的候选特征只允许存在于主机侧研究代码中生产 C 与 MicroPython 固件只包含 Lightweight 或 High Accuracy 实际消费的特征。这一约束直接决定了 tools/lib/lightweight_detector.py 与 src/cpp/core/lightweight_detector.cpp 的代码边界。三、决策历史特征对的演进时间线ADR 用一张表记录了这条决策线的全部关键节点日期方向结果2026-07-08 至 2026-07-26使用 L1-primary 与 lag-ratio Classic 变体在非 ML 检测器转向纯湍流特征族后被替换2026-07-30 至 2026-08-12融合湍流自相关与复数频域相干因聚合 IQR 以更简单的共享原语带来更安全的安静尾迹而被替换2026-08-13使用湍流自相关 聚合湍流 IQR被采纳为生产 Lightweight 特征对2026-08-16在 temporal-admission 与 occupancy 变更后重拟合并重新筛查该特征对保留导出特征对并约束了 Lightweight 空房间告警策略可以看到从 7 月初到 8 月中旬该特征对经历了L1 主导 → 复数频域相干 → 聚合湍流 IQR三次方向调整最终在更安全安静尾迹 更简单共享原语两个维度上收敛。相关决策记录见 2026-07-08-promote-classic-detector-and-retire-legacy-baselines.md 与 2026-03-08-use-host-side-validation-gates-for-detector-promotion.md。四、被考虑过的替代方案及其否决理由4.1 保留复数频域相干Keep complex frequency coherence被否决。它需要保留一个独立的复数全频带跟踪器而聚合 IQR 复用了无相位phaseless的湍流原语并通过了晋升门禁promotion gates。用更简单的状态换来同等的安全性是这条决策线的核心取舍。4.2 使用普通湍流 IQRUse normal-turbulence IQR仅保留为主机侧的超低资源回退方案ultra-low-resource fallback。它需要的状态更少但在压力场景下产生的空闲尾迹明显更差因此不进入生产。4.3 使用湍流过零率Use turbulence ZCR被否决。ZCR 的无阈值分离能力在顺序校准前沿sequential calibration frontier无法在不大幅牺牲弱会话召回weak-session recall的前提下存活。4.4 增加非线性融合或第三特征Add nonlinear fusion or a third feature被否决。额外引入的状态或推理成本会收窄与 High Accuracy 之间的资源差距却换不来足够的独立收益——这违背了 Lightweight 作为低资源替代方案的定位。五、后果与验证门禁Consequences采纳该决策后项目层面形成如下确定性约束Lightweight 保持线性、无投票vote-free、增益不变gain-invariant、仅两特征C 与 MicroPython 各自维护第二个过滤湍流环filtered turbulence ring并与普通湍流流共享一个包级幅度帧生产代码中不再包含复数频域相干跟踪器替代特征保持研究属性不扩充受限运行时的体积任何系数或工作点变更都必须重新跑通顺序低 RSSI、空房间、逐录制per-recording、包速率packet-rate、生成报告与跨运行时一致性cross-runtime parity等门禁。最后一条直接呼应了 2026-03-08-use-host-side-validation-gates-for-detector-promotion.md 确立的检测器晋升必须通过主机侧验证门禁的制度特征对被拟合器产物fitter artifacts与性能报告拥有代码中不写死实验数据。六、源码纵深C 实现的两特征流水线6.1 拟合系数常量与类结构C 实现位于 src/cpp/core/lightweight_detector.h头文件顶部直接内联了拟合产出的全部常量constexpr float LIGHTWEIGHT_AUTOCORR_CENTER 0.3919344866784947f; constexpr float LIGHTWEIGHT_AUTOCORR_SCALE 0.3798648330757351f; constexpr float LIGHTWEIGHT_AUTOCORR_WEIGHT 5.083034533668216f; constexpr float LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_CENTER 0.24612139211074338f; constexpr float LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_SCALE 0.20056599613462603f; constexpr float LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_WEIGHT 4.997501915217463f; constexpr float LIGHTWEIGHT_INTERCEPT 1.0776769868761f;这些常量与 Python 参考实现 tools/lib/lightweight_detector.py 中的FEATURE_CENTER / FEATURE_SCALE / FEATURE_WEIGHT / INTERCEPT完全一致该文件注释标明是 Grouped, de-overlapped OOF fit, balanced by class/chip/session 的产物是跨运行时一致性cross-runtime parity门禁的直接体现。MicroPython 门面 src/python/micro_espectre/lightweight_detector.py 则把热路径完全委托给原生espectre_core模块自身只保留BASE_THRESHOLD 0.6621854538596202等镜像常量。类成员中最关键的是两个特征环普通湍流环由BaseDetector基类管理base_detector.h 中的turbulence_buffer_环形缓冲聚合湍流环是独立的FilteredTurbulenceRing aggregated_turbulence_其存储aggregated_turbulence_buffer_在构造函数中按window_size分配并bind见 filtered_turbulence_ring.h 与 lightweight_detector.cpp。LightweightDetector::LightweightDetector(uint16_t window_size, float threshold, uint16_t autocorr_lag) : BaseDetector(window_size), ... { aggregated_turbulence_buffer_(alloc_zeroed_floats(window_size_)) { aggregated_turbulence_.bind(aggregated_turbulence_buffer_.get(), window_size_); ... }注意is_valid()会额外校验aggregated_turbulence_buffer_ ! nullptr保证两个环同时可用lightweight_detector.h。6.2 process_packet一帧两用process_packet()是热路径lightweight_detector.cpp其流程精确实现了共享一个包级幅度帧的决策float packet_amplitudes[HT20_NUM_SUBCARRIERS]{}; const uint8_t packet_count fill_packet_subcarrier_energies(...); detail::required_energies_to_amplitudesTURB_IQR_AGGREGATION_WIDTH( packet_amplitudes, packet_count, resolved_subcarriers, resolved_count, true); float amplitudes[HT20_SELECTED_BAND_SIZE]{}; const uint8_t amplitude_count select_subcarrier_amplitudes(...); process_amplitudes(amplitudes, amplitude_count); // 普通湍流环 float aggregated_amplitudes[HT20_SELECTED_BAND_SIZE]{}; const uint8_t aggregated_count select_adjacent_aggregated_subcarrier_amplitudes( packet_amplitudes, packet_count, resolved_subcarriers, resolved_count, TURB_IQR_AGGREGATION_WIDTH, aggregated_amplitudes, HT20_SELECTED_BAND_SIZE); add_aggregated_turbulence_(calculate_spatial_turbulence_from_amplitudes( aggregated_amplitudes, aggregated_count)); // 聚合湍流环也就是说每个包先统一算出全部子载波幅度再分别抽取选定子载波幅度与相邻 bin 聚合幅度宽度 W5各自计算 spatial turbulence 后推入两个环。rssi_dbm被显式忽略(void) rssi_dbm因为两个特征都对链路增益不变——这与 tools/lib/lightweight_detector.py 中 accepted for interface parity and ignored 的注释完全一致。聚合子载波的选取细节可以参考 Python 参考实现的_build_amplitude_plan()对每个选中子载波取以它为中心的宽度 5 邻域跳过 DC 子载波 32并将邻域钳制到 [4, 60] 范围内预计算好所有偏移量以避免在热路径上做重复索引运算。6.3 特征计算自相关与稳健 IQR湍流自相关calculate_turb_autocorr_在普通湍流环上计算先求窗口内有限样本的均值与方差再调用calc_autocorrelation(ordered, count, mean, variance, autocorr_lag_)定义见 csi_features.h生产默认autocorr_lag 1。构造函数对 lag 做了保护autocorr_lag_(autocorr_lag 0U ? autocorr_lag : 1U)且头文件明确说明非 1 的 lag 仅用于回放实验改动特征偏移必须重新验证拟合系数。聚合湍流 IQR over meancalculate_turb_iqr_over_mean_aggr_在聚合环上计算取出完整窗口的有序视图筛出有限样本计算均值与percentile_in_place的 Q75/Q25 分位差最后除以max(fabs(mean), 1e-6f)const float iqr percentile_in_place(ordered_turbulence_, valid_count, 0.75f) - percentile_in_place(ordered_turbulence_, valid_count, 0.25f); return iqr / std::max(std::fabs(mean), 1e-6f);6.4 逻辑融合、Sigmoid 与判决calculate_logit_完成标准化与加权融合update_state()在评估节拍evaluation cadence上依次计算两特征、logit、sigmoid 概率并对照阈值判决const float normalized_autocorr (turb_autocorr - LIGHTWEIGHT_AUTOCORR_CENTER) / LIGHTWEIGHT_AUTOCORR_SCALE; const float normalized_iqr (turb_iqr_over_mean_aggr - LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_CENTER) / LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_SCALE; return LIGHTWEIGHT_INTERCEPT LIGHTWEIGHT_AUTOCORR_WEIGHT * normalized_autocorr LIGHTWEIGHT_TURB_IQR_OVER_MEAN_AGGR_WEIGHT * normalized_iqr;sigmoid_对 logit 做了 ±20 的饱和截断以节省exp计算state_ current_metric_ threshold_ ? MOTION : IDLE。is_ready()要求普通环与聚合环都填满窗口且有效样本数达标lightweight_detector.cpp。特征与 logit 还通过get_turb_autocorr()、get_turb_iqr_over_mean_aggr()、get_logit()暴露给诊断与遥测lightweight_detector.h运行时诊断可直接读取这三个值参见 runtime_diagnostics.cpp 所在运行时的发布逻辑。6.5 过滤策略两个环共享同一套 Hampel 低通决策要求同一套可配置的 Hampel 和低通策略实现上configure_hampel()与configure_lowpass()会把配置同时转发给基类普通环与聚合环void LightweightDetector::configure_hampel(bool enabled, uint8_t window_size, float threshold) { BaseDetector::configure_hampel(enabled, window_size, threshold); aggregated_turbulence_.configure_hampel(enabled, window_size, threshold); }过滤参数范围定义在 filter_config.h参数默认值范围说明LOWPASS_CUTOFF_DEFAULT11.0 Hz5.0–20.0 Hz一阶 Butterworth IIR 低通截止频率LOWPASS_SAMPLE_RATE100.0 Hz—低通采样率与名义评估节拍匹配HAMPEL_TURBULENCE_WINDOW_DEFAULT73–11Hampel 异常值滤波窗口HAMPEL_TURBULENCE_THRESHOLD_DEFAULT5.0—MAD 倍数阈值MAD_SCALE_FACTOR 1.4826Python 参考实现的构造参数与此一致enable_lowpassFalse, lowpass_cutoff11.0, enable_hampelTrue, hampel_window7, hampel_threshold5.0tools/lib/lightweight_detector.py。FilteredTurbulenceRing::add()内部先过 Hampel 再过低通然后写入环形缓冲filtered_turbulence_ring.cpp。6.6 缺失时隙处理与双环同步advance_missing_slots(count)会把缺失的时序槽同时推进到两个环以quiet_NaN标记缺失样本void LightweightDetector::advance_missing_slots(uint32_t count) { BaseDetector::advance_missing_slots(count); aggregated_turbulence_.advance_missing_slots(count); }FilteredTurbulenceRing通过valid_count_精确跟踪有限样本数filtered_turbulence_ring.cpp特征计算时跳过非有限样本从而保证顺序安静尾迹在丢包压力下依然可靠——这正是聚合 IQR 相对普通 IQR 在实验中胜出的场景。is_ready()的双环校验aggregated_turbulence_.count() window_size_ valid_count minimum_valid_samples_确保窗口未填满前不输出有意义的判决。七、启动阈值校准与 settled-level 回落规则Lightweight 在启动阶段会采集最多 64 个 logit 样本LIGHTWEIGHT_STARTUP_SAMPLE_LIMIT 64校准完成后取其 95 分位LIGHTWEIGHT_STARTUP_QUANTILE 0.95与训练集空闲 Q95 logitLIGHTWEIGHT_TRAIN_IDLE_Q95_LOGIT -2.253902812716911对比按强度LIGHTWEIGHT_STARTUP_STRENGTH 0.5自适应生成阈值on_startup_calibration_complete()lightweight_detector.cpp。更关键的是settled-level 规则当会话开局噪音高于后续时段时启动阈值可能长时间偏高源码注释记录了一个实测案例某次捕获的前缀噪音是其余时段 4.1 倍导致阈值被抬高到会话实际水平的 3.8 倍白白损失 4.7 点召回。该规则让阈值只降不升以 20 次评估为一个块记录块内 logit 最大值收集满 12 个块名义节拍下约 60 秒后取**块最大值的位数median**作为 settled 水平再加上 2.7 logit 的安全余量LIGHTWEIGHT_SETTLE_MARGIN_LOGITS 2.7f若候选阈值更低则下调。因为取的是块最大值的位数单次尖峰无法推动阈值持续真实运动会保持阈值高位从而避免阈值在活动期间向下追逐指标observe_settled_level_()。该规则与 Python 参考实现_observe_settled_level逐字段镜像SETTLE_BLOCKS 12, SETTLE_BLOCK_EVALUATIONS 20, SETTLE_MARGIN_LOGITS 2.7。八、MicroPython 与测试验证8.1 MicroPython 门面src/python/micro_espectre/lightweight_detector.py 是 MicroPython 侧的门面类构造时要求espectre_native_features模块可用并创建原生Detector(lightweight, window_size, threshold, lag, enable_hampel, hampel_window, hampel_threshold, enable_lowpass, lowpass_cutoff, subcarriers)热路径process_packet、update_state全部转发给原生核心update_state()从原生输出数组还原出state / probability / threshold / turb_autocorr / turb_iqr_over_mean_aggr用于诊断get_backend()返回espectre_core。这体现了生产 C 与 MicroPython 只包含被消费的特征的决策落地形态。8.2 测试佐证test/cpp/suites/core/test_lightweight_detector.cpp 中有专门针对聚合环的测试例如test_lightweight_detector_owns_aggregated_turbulence_ring断言aggregated_turbulence_buffer_非空、聚合环容量等于检测器窗口、初始计数为 0另有测试断言两个环的 Hampel 开关状态保持同步configure_hampel后aggregated_turbulence_.hampel_enabled()一致。Python 侧对应的单元测试见 test/python/micro/test_lightweight_detector.py配合 test/python/performance/ 下的低 RSSI、ML 推理、时序质量等回归测试共同构成 ADR 要求的顺序低 RSSI、空房间、逐录制、包速率与跨运行时一致性门禁。九、结论与工程启示从这份 ADR 及其落地代码可以看到 ESPectre 在低资源检测器上的明确方法论两特征、线性、无投票是 Lightweight 不可动摇的契约任何新增状态都必须能证明其独立收益大于资源代价优先复用共享原语聚合湍流 IQR 之所以战胜复数频域相干核心在于它复用了两个检测器都已有的湍流原语与同一个包级幅度帧而不是另起炉灶维护全频带复数跟踪器研究候选与生产特征严格分离ZCR、normal-IQR、offset-coherence 只存在于主机侧 tools/lib/ 研究代码中生产固件保持最小体积一切数字归拟合器与性能报告所有center/scale/weight/intercept 由 OOF 拟合产物导出跨 C / Python / MicroPython 逐常量镜像任何系数或工作点变更都必须重跑完整的验证门禁矩阵。对于需要在自有固件中集成或复现该方案的开发者建议按以下路径阅读仓库先读 docs/FEATURES.md 了解特征证据与基线谱系再对照 src/cpp/core/lightweight_detector.cpp 与 tools/lib/lightweight_detector.py 逐函数比对跨语言一致性最后以 test/cpp/suites/core/test_lightweight_detector.cpp 和 test/python/micro/test_lightweight_detector.py 验证行为契约。若需了解该特征族在 ML 侧High Accuracy的用法与导出路径可继续阅读 docs/ML_TRAINING.md 与 2026-08-11-promote-channel-shape-trajectory-ml-features.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),仅供参考