CSI 长空档的频谱代价:用真实采样时间轴做一次对照实验
作者 Wu Jun · 更新于 2026-10-30 · Wi-Fi CSI, 时间戳, 缺失数据, 频谱, Lomb-Scargle, 可复现实验 · 约 6 分钟
先看结论:这份 10 分钟抓包的平均测量率约为 12.68 组/秒,但它不是一个整齐的 12.68 Hz 时钟。把数据强行插值到 10 Hz 后,6,000 个网格点中有 1,823 个(30.383%) 落在超过 0.5 秒的原始空档内部。对一个已知的 0.25 Hz 正弦控制信号,线性插值的 RMS 误差为 0.099658,相当于信号 RMS 的 14.094%;直接使用原始时间戳的 最小二乘周期图仍返回 0.250 Hz。这不是人体或呼吸实验,但它足以否决“任意插值后再 把峰值当生理结论”的做法。
四个面板依次展示:原始组间隔、最大 2.37 秒空档附近的已知 0.25 Hz 控制信号、控制信号的 频谱,以及真实 CSI 幅度特征上两种估计器的差异。图由公开脚本从同一份数据生成。
1. 为什么“平均 12.68 Hz”仍然会有时间问题
先把测量组与链记录分开。公开抓包有 57,293 条外层链记录,按 chain_info bit15 闭合后得到
7,609 个组;剔除一个 64 子载波过渡组后,留下 7,608 个可用的 256 子载波组
[1]。平均组率是:
7608 / 599.924 s = 12.6817 组/秒
但平均值不等于采样时钟。实际组间隔中位数约 41.02 ms,p95 约 321.84 ms, p99 约 945.69 ms,最大间隔 2.373 s。其中超过 0.5 秒的间隔有 224 个, 超过 1 秒的有 57 个。采集器在运行,不等于每个预定时刻都真的留下了一个 CSI 快照。
如果算法只读取“12.68 Hz”这个摘要,就会把一个有长空档的时间轴当成等间隔序列;后面的 FFT、STFT、带通滤波和呼吸峰值检测都会继承这个错误。数据格式与原始包的下载方式见 数据集页,完整的时间审计见 [2]。
2. 这次实验到底比较了什么
实验只使用一条每组的代表链:优先 tx0/rx0;若不可用,则取该组中平均幅度最大的有效链。
把选中链的 256 个子载波幅度取平均,得到一维幅度特征。所有 7,608 组都选中了
tx0/rx0,因此本实验不会把多个接收链误当成多个时间样本。
比较三条路径:
- 均匀网格 + 插值 Welch:用
np.interp把原始时间戳映射到 10 Hz 网格,再用 1024 点 Hann 窗 Welch; - 原始时间戳直接拟合:在 0.05–0.60 Hz、步长 0.001 Hz 上,对原始非均匀时间戳 做正弦/余弦最小二乘拟合,属于 Lomb–Scargle 方法族 [3] [4];
- 已知信号控制:不生成随机数据,而是在同一批真实时间戳上放置振幅为 1 的 0.10–0.50 Hz 正弦波,再比较插值后的值和真实值。
第三条是本次实验的关键。真实 CSI 没有呼吸或动作真值;但已知正弦波有真值,所以能区分 “数据本身包含什么”和“预处理方法制造或扭曲了什么”。
3. 10 Hz 网格里有多少点是插值出来的
10 Hz 网格在 599.924 秒内有 6,000 个点,适合观察 0.05–4 Hz 的低频成分(Nyquist 为 5 Hz), 但其中 1,823 个点落在原始超过 0.5 秒的间隔内部,比例为 30.383%。这不是说原始数据 少了 30%,而是说部分均匀网格值没有对应的同一时刻的原始快照,必须由相邻点合成。
同一份时间轴在更严格的分段规则下也不宽裕:
| 分段阈值 | 至少 20 秒的连续段 | 可保留时长 |
|---|---|---|
| 不允许超过 0.5 秒的间隔 | 2 段 | 231.90 s |
| 不允许超过 1.0 秒的间隔 | 6 段 | 391.45 s |
因此“只在连续窗口做 Welch”并不天然没有代价:阈值越严格,被丢掉的时间越多。正确做法不是 偷偷插值,而是把空档、可用窗口、丢失比例和最终适用的频段一起报告。
4. 已知 0.25 Hz 信号的对照结果
0.25 Hz 落在常见呼吸相关频带附近,但这里它只是一个可控的数学信号,不是呼吸录音。
| 指标 | 结果 |
|---|---|
| 真实频率 | 0.250 Hz |
| 均匀 10 Hz 参考 Welch 峰 | 0.253906 Hz(受 0.009766 Hz 频率栅格限制) |
| 插值 Welch 峰 | 0.253906 Hz |
| 原始时间戳最小二乘峰 | 0.250 Hz |
| 插值误差 RMS | 0.099658 |
| 插值误差最大值 | 1.09835 |
| 相对信号 RMS 误差 | 14.094% |
| 0.10–0.50 Hz 频带功率保留比例 | 88.64% |
这个控制实验说明:插值不一定会把峰“搬”到另一个频率;它也可能保留峰的位置,却改变波形、 幅度和时间局部结构。对于只报告“有一个峰”的演示,这种误差可能被忽略;对于比较呼吸深度、 估计心率谐波或做事件检测,误差会影响结论。插值后的频带功率比真实值低约 11.36%,也说明 谱峰位置正确不等于幅度可比较。
5. 频率越高,空档的相对代价越大
在同一时间轴上改变已知正弦频率,得到如下敏感性表:
| 真实频率 | 插值相对 RMS 误差 | 插值/Welch 主峰 | 原始时间戳主峰 |
|---|---|---|---|
| 0.10 Hz | 2.31% | 0.097656 Hz | 0.100 Hz |
| 0.15 Hz | 4.72% | 0.146484 Hz | 0.150 Hz |
| 0.20 Hz | 9.80% | 0.195312 Hz | 0.200 Hz |
| 0.25 Hz | 14.09% | 0.253906 Hz | 0.250 Hz |
| 0.30 Hz | 18.40% | 0.302734 Hz | 0.300 Hz |
| 0.40 Hz | 27.85% | 0.400391 Hz | 0.400 Hz |
| 0.50 Hz | 38.16% | 0.498047 Hz | 0.500 Hz |
频率并非唯一变量,空档相对周期长度、空档位置和信号相位都会影响结果;但表中清楚地显示,
不能把 0.25 Hz 的结论简单外推到所有频段。完整数据在同目录的 frequency_sweep.csv。
6. 真实 CSI 上两种估计器会不会给出同一个答案
不会。对同一份真实幅度特征,插值 Welch 在 0.05–0.60 Hz 搜索到的最高点是 0.068359 Hz; 直接在原始时间戳上做最小二乘拟合得到 0.145 Hz,两者相差 0.076641 Hz。
这不能证明 0.145 Hz 是真实人体信号,也不能证明 0.068 Hz 是假峰。它只证明一个更基础的事实: 在没有时间真值、动作标签或参考设备时,预处理方法本身就能改变“主频”结论。若页面上一句 “检测到 0.145 Hz 呼吸”来自这样的数据,并把插值细节隐藏起来,读者无法复现,也无法判断 差异来自人还是算法。
7. 实际工程上怎么处理
7.1 保留时间轴
原始外层时间戳、payload 内时间戳、组边界和链选择规则都要保留。不要只保存一个“平均采样率”; 平均值既不能重建空档,也不能恢复不规则采样。
7.2 在 FFT 之前报告质量
至少输出:
- 组间隔中位数、p95、p99 和最大值;
- 超过 0.5、1、2 秒的间隔数量;
- 均匀网格点数,以及落在长空档内的比例;
- 插值所用的边界规则和是否外推;
- 最终频谱使用的连续窗口长度。
7.3 低频用不规则方法或显式掩码
呼吸、慢动作和长事件的频率较低,可以优先使用原始时间戳的 Lomb–Scargle 类方法,或在 短连续片段上做 Welch 并报告片段覆盖率。无论选哪一种,都要做“频率/空档/估计器”敏感性 检查;不要把一个算法的峰直接写成人体结论。
7.4 跌倒和快事件更不能靠插值补
跌倒检测需要事件前后的时间结构,不能只看一个低频峰值。插值会平滑事件边界,并可能改变 短时能量、恢复期和上下文特征。这个项目现有 12.64 Hz 组率也不支持完整步行微多普勒, 见 跌倒检测 与 CSI 雷达边界。
8. 复现实验
下载公开 10 分钟抓包与本目录脚本后执行:
python3 analyze_csi_gap_spectrum.py csi-10m.anon.bin \
--summary summary.json \
--csv frequency_sweep.csv \
--img csi-gap-spectrum.svg
本脚本只依赖 Python 3.9+ 与 NumPy,不需要 Matplotlib 或 SciPy。公开文件:
输入公开派生抓包的 SHA-256 为
527466ceb8b5f835e55ff348f02808736b947db39e7baac1f34e375de146a440。
9. 证据边界
本实验属于 E 级一手复现 [5],采样方法参考 B 级文献 [3] [4] [6]。它不包含:
- 呼吸带真值、人体位置、动作标签或跌倒标签;
- 多房间、多客户端、多固件版本的泛化实验;
- 对 Lomb–Scargle 显著性的完整噪声模型验证;
- 任何“可以用 10 Hz 插值恢复所有 CSI 信息”的结论。
10. 验收清单
- 记录总数、组数、组间隔分布与最大空档;
- 明确选择的链和是否按 bit15 分组;
- 明确均匀网格频率和插值方法;
- 报告落在长空档内的网格比例;
- 至少与一种不规则时间方法或连续片段方法对照;
- 用已知正弦控制信号检查插值误差;
- 在文章结论中把“观察到的主峰”与“人体真值”分开;
- 发布脚本、摘要、CSV、图和 SHA-256。
参考与数据来源
本文的每条外部结论都标注来源与证据等级(分级标准);标注 E 级的是本项目可复现的实测数据。
- E 级 · 本项目实测
本项目 10 分钟实测抓包(57,293 条 / 600.0 s,SHA-256 00373f83…95e2)
Router CSI Lab · 2026
okwujun.pw/zh/datasets/ · 核实: 分片重组逐字节校验通过(2026-10-11) · 本地原始母片 SHA-256 为 00373f83…95e2;公开下载的是去标识派生文件,SHA-256 为 527466ce…a440,两者不可混用。 - E 级 · 本项目实测
Router CSI Lab — GL-MT6000 (MT7986) Wi-Fi CSI dataset, 10 s sample + 10 min capture
Router CSI Lab · 2026
doi:10.5281/zenodo.23434789 · 核实: CC BY 4.0;SHA-256 已发布;Zenodo DOI 10.5281/zenodo.23434789 · 数据集已获 Zenodo DOI(10.5281/zenodo.23434789),可直接引用。 - B 级 · 同行评审
Least-squares frequency analysis of unequally spaced data
N. R. Lomb · Astrophysics and Space Science · 1976
doi:10.1007/BF00648343 · 被引 5106 · 核实: CrossRef API, 2026-10-30 · 不均匀采样时间序列的经典最小二乘频率分析方法;本文只在方法层引用,不假定 CSI 一定满足其噪声模型。 - B 级 · 同行评审
Studies in astronomical time series analysis. II. Statistical aspects of spectral analysis of unevenly spaced data
J. D. Scargle · The Astrophysical Journal · 1982
doi:10.1086/160554 · 被引 6463 · 核实: CrossRef API, 2026-10-30 · Lomb–Scargle 周期图的统计基础;说明为什么要直接处理原始采样时刻,而不是先伪造均匀网格。 - E 级 · 本项目实测
CSI timestamp-gap spectral sensitivity analysis (script, summary, frequency sweep)
Router CSI Lab · 2026
okwujun.pw/zh/csi-timestamp-gaps-spectrum/ · 核实: 从公开 10 分钟抓包重跑,输入 SHA-256 527466ce…a440;脚本、JSON、CSV 与图同时发布(2026-10-30) · 只证明该采样时间轴上的方法敏感性,不提供呼吸、跌倒或人体真值。 - B 级 · 同行评审
Understanding the Lomb–Scargle Periodogram
J. T. VanderPlas · The Astrophysical Journal Supplement Series · 2018
doi:10.3847/1538-4365/aab766 · 被引 1182 · 核实: CrossRef API, 2026-10-30 · 面向实践的 Lomb–Scargle 方法综述,强调采样、窗口、噪声和显著性假设;本文据此限制结论范围。