想象你是一名气象观测员,住在山脚下的小气象站里。你的日常工作很简单:走到院子里看一眼温度计,在笔记本上写下一行记录。但真实的记录过程远没有想象中干净——自动气象站每 5 分钟吐一条数据,哗哗地像打字机;你的手动笔记本呢,有时半小时记一条,有时因为接电话漏掉一整个下午;同事老李送来的观测记录,用的还是另一套时间刻度。月底一到,气象局要的是一张“每小时一条、时间整整齐齐”的温度报表。 要交出这样一张报表,你必须做三件事:把 5 分钟一条的高频记录“压粗”成 1 小时一条(降采样);把漏掉的时刻根据前后数据“脑补”出来(升采样);把 9:12、9:47 这种参差不齐的时间戳“摆正”到 9:00、9:30 的标准网格上(时间对齐)。这一整套在时间维度上“换记录节奏”的加工手艺,就是时序数据的重采样与对齐技术。

岗位关联

重采样与对齐是时序数据工程的“基础设施”:掌握它,你才能把监控、金融、IoT 等真实世界里的杂乱时间序列,变成模型吃得下的规整数据。这是每一位数据分析师和 AI 建模工程师的基本功。

目录
  1. 可视化演示
  2. 概念与本质
  3. 时间对齐基础
  4. 降采样聚合
  5. 升采样插值
  6. 不规则处理
  7. 工程实现
  8. 应用与误区
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示降采样聚合降频、升采样插值补缺与不规则采样均匀化对齐,交互理解时序重采样的三种核心操作。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+modeData.downsample.caption+'

概念与本质

你是一名气象观测员,住在山脚下的小气象站里。每天的工作听起来简单:去院子里看一眼温度计,在笔记本上写一行记录。但“记录节奏”从来由不得你——自动气象站每 5 分钟吐一条数据,哗哗地像打字机;你手动记录呢,有时半小时一条,有时一忙就是一小时一条。等月底把记录交给气象局时,对方只认一种格式:每小时一条。于是你不得不把数据从一种“记录节奏”硬生生换成另一种。

这种“换节奏”的操作,在时序数据处理里叫作重采样(Resampling)。它的本质是调整时间轴的刻度:把散落在旧刻度上的观测值,映射到一组新的、统一的时间刻度上。如果新刻度比旧刻度更稀疏,也就是从高频走向低频,叫降采样;如果新刻度比旧刻度更密集,从低频走向高频,叫升采样。而在动手重采样之前,还有一个绕不开的前置动作——时间对齐,也就是先把时间戳摆到目标网格上,否则后面的聚合与插值都无从谈起。

衡量记录节奏有两个基本参数:采样间隔 ΔT 与采样频率 f。采样间隔是相邻两条记录的时间差,采样频率是单位时间内记录的次数。高频数据细节丰富,但存储与计算开销都大;低频数据简洁,却对瞬时突变不敏感。重采样的核心,就是在这两者之间做一次可控制的转换。转换前你总要回答三个问题:新刻度定多密、时间窗怎么切、窗内的值如何汇总——这三个问题串起来,就是整篇重采样技术的骨架。

回到气象站:自动站的高频记录像打字机一样哗哗出纸,手动笔记本则稀稀拉拉。重采样就是你手中的“抄表规范”,决定最终用哪种节奏把温度写进报表。概念清楚了,下一步得先把时间戳本身摆正。

f=1ΔT\displaystyle f = \frac{1}{\Delta T}
采样频率与采样间隔互为倒数。比如每 5 分钟一条记录,频率就是每小时 12 条;重采样做的事情,本质上就是改写这个“倒数”关系里的分母。
  1. f(采样频率)f 表示单位时间内的记录条数,比如每小时记录 1 条,则 f 等于 1 条每小时。
    f\displaystyle f
  2. ΔT(采样间隔)ΔT 表示相邻两条记录之间的时间差,比如每 5 分钟一条,则 ΔT 等于 5 分钟。
    ΔT\displaystyle \Delta T
  3. 倒数关系频率与间隔互为倒数,间隔越小频率越高;重采样就是调整间隔从而改变频率。
    f=1ΔT\displaystyle f = \frac{1}{\Delta T}

时间对齐基础

月底,你要和同事老李合并数据画一条温度曲线。翻开你的笔记本:9:12、9:47、10:03……再看老李的自动站输出:9:00、9:15、9:30……两本记录的时间戳根本对不上,硬画在同一张图上,点与点全错位,曲线变成一团乱麻。

时间对齐(Time Alignment)要解决的就是这个问题:让来自不同来源、不同时刻的记录,落在同一套标准时间网格上。它是所有重采样的前置步骤——时间戳都不齐,谈何聚合与插值?对齐的第一步是时间戳规整:选定目标间隔 Δ 后,把每个原始时间戳向下取整,归入它所在的网格区间。第二步是选择对齐方向:左对齐让窗口标签取区间起点,右对齐让标签取区间终点,这会影响聚合结果挂在哪个时刻上。第三步是索引对齐:以目标网格为索引,把原始数据一一映射上去,落在同一格内的观测自然归为一组。如果数据来自不同时区,还得先统一到时区再做规整,否则“9 点”到底是哪里的 9 点都说不清。

对齐就像把两本笔记本的时间列都统一改成“整点、半点”的刻度。时间轴摆正之后,才轮到真正的重采样——先看把高频数据变稀疏的降采样。

τi=⌊tiΔ⌋×Δ\displaystyle \tau_i = \left\lfloor \frac{t_i}{\Delta} \right\rfloor \times \Delta
把 9:12 按 30 分钟网格规整:9:12 除以 30 分钟得 18.4,向下取整得 18,再乘回 30 分钟,得到 9:00。于是 9:12 这条记录就被“摆”到了 9:00 这个格子上。
  1. t_i(原始时间戳)这是某条记录原本的时刻,比如笔记本上的 9:12。
    ti\displaystyle t_i
  2. Δ(目标间隔)目标时间网格的间隔,比如气象局要求的 30 分钟。
    Δ\displaystyle \Delta
  3. 向下取整把 t_i 除以 Δ 后向下取整,得到它落在第几个网格区间。
    ⌊tiΔ⌋\displaystyle \left\lfloor \frac{t_i}{\Delta} \right\rfloor
  4. 乘回间隔把网格编号乘回 Δ,得到该区间的起点时刻,完成时间戳规整。
    ⌊tiΔ⌋×Δ\displaystyle \left\lfloor \frac{t_i}{\Delta} \right\rfloor \times \Delta

降采样聚合

自动站每 5 分钟吐一条数据,一个月下来积了三万多条,而气象局只要每小时一条。你不能随手删掉中间的数据——9:00 到 9:55 之间那 12 条记录,每一条都带着真实信息,你得想个办法把它们“浓缩”成一条。

把高频数据转换成低频数据的操作叫降采样(Downsampling)。它的核心思想是:以目标时间窗为单位,把窗内所有观测值通过一个聚合函数压缩成一个代表值。聚合函数怎么选,决定了你保留哪种信息。最常见的聚合是均值,它表达窗口内的“平均水平”,适合温度这类平稳变量。但如果业务关心窗口内的极值——比如服务器流量峰值、降雨瞬时强度——就该用最大值或最小值。金融行情里还有一种经典的 OHLC 聚合:同时保留窗口的开盘价、最高价、最低价和收盘价四个值。

值得注意的是,降采样必然损失信息。窗口内部的细节一旦被压成一个数,就再也找不回来。所以选择聚合函数,本质是一次信息取舍的决策:报表要回答什么问题,就选能保留那个答案的聚合方式。选错了口径,后面的分析就像拿着错版的摘要读整本书。

这就像把每分钟一行的流水总账浓缩成每小时一行的摘要,摘要用什么口径,取决于这份报表要回答什么问题。浓缩完毕,再看反方向——把稀疏记录“补密”的升采样。

Yˉi=1ni∑j=1niXj,Yimax⁡=max⁡1≤j≤niXj\displaystyle \bar{Y}_i = \frac{1}{n_i} \sum_{j=1}^{n_i} X_j, \qquad Y_i^{\max} = \max_{1 \le j \le n_i} X_j
第一个式子把窗口内所有观测值相加后取平均,得到“平均水平”;第二个式子逐条比较窗口内所有观测值,挑出最大的那个,代表“峰值水平”。
  1. X_j(第 j 条观测)窗口内任意一条原始记录,比如 9:00 到 9:55 之间的第 j 个温度读数。
    Xj\displaystyle X_j
  2. n_i(窗口容量)第 i 个时间窗内一共有几条观测,比如 5 分钟数据聚到 1 小时,n_i 通常等于 12。
    ni\displaystyle n_i
  3. 均值聚合把窗口内 n_i 条观测全部相加,再除以 n_i,得到窗口的平均水平。
    Yˉi=1ni∑j=1niXj\displaystyle \bar{Y}_i = \frac{1}{n_i} \sum_{j=1}^{n_i} X_j
  4. 最大值聚合在窗口内逐条比较,保留最大者,适合流量峰值、瞬时极值类业务。
    Yimax⁡=max⁡1≤j≤niXj\displaystyle Y_i^{\max} = \max_{1 \le j \le n_i} X_j

升采样插值

翻看笔记本时你发现,9:30 之后直接跳到了 10:30——10 点整你接了个电话,忘了记录。气象局规定整点必须有值,你不能空着。于是你盯着 9:30 的 18 度和 10:30 的 21 度,心里盘算:10:00 大概介于两者之间,估个 19.5 度吧。

把低频数据转换成高频数据的操作叫升采样(Upsampling)。与降采样的“浓缩”不同,升采样做的是“补全”:目标时刻本来没有观测,只能从相邻的已知点推算一个估计值。这个推算过程就是插值(Interpolation)。最常用的线性插值假设两个已知点之间的变化是均匀的,把前后两点连成一条直线,目标时刻在直线上取对应的值。样条插值则用分段低次多项式穿过多个已知点,保证曲线处处连续平滑,适合温度、压力这类变化平缓的物理量。还有一种更偷懒的前向填充,不画线,直接把上一个有效观测值复制到缺失时刻,实现最简单,只适合变化非常缓慢的变量。

但请记住一个关键认知:插值是估计,不是实测。无论哪种方法,都不会增加真实信息量。如果真实曲线在缺失区间里剧烈波动,线性插值会把它平滑成一条直线,反而掩盖了关键的转折。升采样之后数据点变多了,模型却没有“看到”更多的真实世界。

你盯着 9:30 和 10:30 两个点,在它们之间连一条线,取中点——这就是插值的手工版。但补空之前还有一道坎:如果你的记录时间本身就不是整点,插值同样无从下手,必须先规整。这正是下一节的内容。

X^(t)=X(t0)+X(t1)−X(t0)t1−t0×(t−t0)\displaystyle \hat{X}(t) = X(t_0) + \frac{X(t_1) - X(t_0)}{t_1 - t_0} \times (t - t_0)
缺失点 t 的值,等于左端点 X(t₀) 加上“单位时间变化速度乘以离左端点的时间距离”。18 度出发,按每小时 6 度的速度爬升 0.5 小时,得到 21 度——19.5 度就是这么“补”出来的。
  1. X(t₀) 与 X(t₁)缺失点前后两个已知观测值,分别对应左端点和右端点的实测温度。
    X(t0),X(t1)\displaystyle X(t_0), \quad X(t_1)
  2. t − t₀(时间距离)目标时刻距离左端点的时长,决定估计值在直线上前进多远。
    t−t0\displaystyle t - t_0
  3. 变化速度前后温度差除以时间差,得到单位时间内的平均变化速度。
    X(t1)−X(t0)t1−t0\displaystyle \frac{X(t_1) - X(t_0)}{t_1 - t_0}
  4. 线性外推取值从 X(t₀) 出发,按速度推进 t − t₀,得到目标时刻的插值估计。
    X^(t)=X(t0)+X(t1)−X(t0)t1−t0×(t−t0)\displaystyle \hat{X}(t) = X(t_0) + \frac{X(t_1) - X(t_0)}{t_1 - t_0} \times (t - t_0)

不规则处理

有一次你忙昏了头,记录时间变得七零八落:9:12、9:47、10:03、10:38……每个时刻都不在气象局的整点网格上。你辩解:“我量得挺勤的啊!”但报表需要的是标准网格,没人关心你的生活节奏。

现实世界中的绝大多数数据都是不规则采样(Irregular Sampling):传感器偶发掉线、日志写入抖动、人工记录随性发挥,相邻时间间隔忽长忽短。要分析这类数据,第一步不是插值,而是均匀化——把观测点对齐到固定频率的网格上。均匀化的标准做法是重索引(Reindex):先构造目标网格,再为每个网格时刻找值。网格时刻恰好有观测,直接采用;网格时刻没有观测,就按规则从邻近观测推导。

最常见的推导规则是前向填充(Forward Fill,简称 ffill):用最近一个过去时刻的有效值填充当前缺失。它适合“系统状态会持续一段时间”的变量,比如设备的运行模式、液位高度。如果想要更平滑的结果,可以再叠加插值。多源数据的对齐也是同一套思路:不同设备、不同日志的时间戳先各自规整到公共网格,才能在同一个坐标系下做联合分析。否则一台设备说 9:12,另一台说 9:13,你以为是在同一时刻,其实差了一分钟。

不规则数据就像随手记的备忘录,必须先誊写到标准表格里才能统计。到这里,概念层面的招式都讲完了——接下来看看这些操作在代码里如何落地。

X^(ti)=X(tlast),tlast=max⁡{tj∣tj≤ti}\displaystyle \hat{X}(t_i) = X(t_{\text{last}}), \quad t_{\text{last}} = \max\{t_j \mid t_j \le t_i\}
目标时刻 t_i 缺失时,前向填充在所有不晚于 t_i 的观测中找出最近的那一条,把它的值复制过来。比如 9:12 有观测,9:47 也有观测,那么 9:30 这个网格就用 9:12 的值填充。
  1. t_i(目标时刻)网格上需要填值的缺失时刻,比如 9:30。
    ti\displaystyle t_i
  2. 候选集合所有不晚于 t_i 的观测时刻组成的集合。
    {tj∣tj≤ti}\displaystyle \{t_j \mid t_j \le t_i\}
  3. 取最近前值从候选中选出最大的 t_j,也就是离 t_i 最近的过去观测。
    tlast=max⁡{tj∣tj≤ti}\displaystyle t_{\text{last}} = \max\{t_j \mid t_j \le t_i\}
  4. 前向填充把该观测值直接复制给目标时刻,完成填充。
    X^(ti)=X(tlast)\displaystyle \hat{X}(t_i) = X(t_{\text{last}})

工程实现

手工誊了一个月的数据后,你痛定思痛,决定把整套流程写成气象站的“自动誊写程序”。在 Python 生态里,pandas 的 resample 就是这把趁手的工具,几乎所有的时序预处理都从它开始。

resample 的核心三件套是:频率规则、聚合函数、插值方式。第一步用 resample('1H') 把数据按小时分组;第二步接 agg 指定聚合函数,比如均值和最大值;第三步如果要从低频回到高频,再对结果 resample 后调用 interpolate 补点。这三个动作,正好对应前面讲的降采样、升采样与对齐。如果你拿到的是不规则数据,则用 reindex 先构造标准网格,再用 ffill 或 nearest 填充缺失。

频率规则字符串有固定语法:T 表示分钟,H 表示小时,D 表示天,前面加数字表示倍数,比如 15T 就是 15 分钟。对齐网格时,label 与 closed 参数控制窗口标签取左端点还是右端点,对应前面说的左对齐与右对齐。工程上还要心里有数:降采样会让索引变稀疏,升采样会产生大量 NaN 需要填充,聚合结果的列名会变成多层索引——这些都是新手最容易懵的地方。

誊写程序运行顺畅,但你交报表时突然意识到一个哲学问题:报表上的数字,哪些是真的、哪些是补的?于是最后一节,我们来聊聊应用场景和那些容易踩的坑。

X^(tg)=X ⁣(arg⁡min⁡ti∣ti−tg∣)\displaystyle \hat{X}(t_g) = X\!\left(\arg\min_{t_i} |t_i - t_g|\right)
对目标网格时刻 t_g,在原始观测中找出与它时间距离最近的时刻 t_i,把 t_i 的观测值赋给 t_g。等价于一句大白话:“谁离整点最近,就用谁的值。”
  1. t_g(目标网格时间)规整后标准网格上的某个时刻,比如 9:30。
    tg\displaystyle t_g
  2. 绝对距离每个原始观测时刻与目标时刻的时间差取绝对值。
    ∣ti−tg∣\displaystyle |t_i - t_g|
  3. arg min(找最近)在所有候选 t_i 中找出使绝对距离最小的那一个。
    arg⁡min⁡ti∣ti−tg∣\displaystyle \arg\min_{t_i} |t_i - t_g|
  4. 取值映射把最近观测时刻对应的观测值赋给目标网格时刻。
    X^(tg)=X ⁣(arg⁡min⁡ti∣ti−tg∣)\displaystyle \hat{X}(t_g) = X\!\left(\arg\min_{t_i} |t_i - t_g|\right)

应用与误区

报表交上去没两天,气象局打来电话:“9:45 那条记录,你是怎么知道的?”你支支吾吾——当时为了凑齐整点,你偷偷用了 10:30 的实际观测值去填 9:45。这就是典型的用未来数据填过去。

重采样与对齐在真实业务里无处不在:监控平台把秒级指标降采样成分钟级,用于流量峰值告警;智能工厂把不同传感器的数据对齐到同一时间轴,才能做多模态故障诊断;量化系统把逐笔成交数据重采样成 1 分钟 K 线,再喂给因子模型。但工程实践中藏着两个高频陷阱。第一个是信息丢失:降采样把窗口压成一个值,峰值、长尾细节全部消失,如果聚合口径和实际关注点不一致,后续模型会“看不见”关键信号。比如你想监控服务器 5 分钟内的最大延迟,却用了均值聚合——高峰期的毛刺被平均掉了,告警自然失灵。

第二个陷阱更隐蔽,叫未来数据泄漏。用缺失点之后的观测值(反向填充,bfill)填补训练数据,模型在训练时等于“偷看”了未来的答案,指标漂亮得惊人;可一旦上线做实时预测,未来还没发生,拿不到那个值,指标瞬间崩塌。因此,任何进入模型的数据,一律只能用过去信息(前向填充或插值)来补,反向填充只允许在纯离线分析的场景出现。

你默默修正了 9:45 那条记录。最后在报表扉页写下四行心得:降采样用聚合,浓缩不编造;升采样用插值,补全靠估计;不规则先对齐,建模才可靠;未来值不能碰,泄漏是大忌。

X^(ti)=X(tnext),tnext=min⁡{tj∣tj≥ti}\displaystyle \hat{X}(t_i) = X(t_{\text{next}}), \quad t_{\text{next}} = \min\{t_j \mid t_j \ge t_i\}
这是反向填充(bfill)的数学写法:取 t_i 之后最近的观测值来填 t_i。离线整理历史图表可以这么干,但一旦用于训练模型,就等于提前把未来的答案告诉了模型。
  1. t_next(未来最近时刻)在目标时刻 t_i 之后的最近一个观测时刻。
    tnext\displaystyle t_{\text{next}}
  2. 约束条件t_j ≥ t_i 保证候选全部来自“未来”,这正是泄漏的根源。
    tj≥ti\displaystyle t_j \ge t_i
  3. 取最小值从未来候选中选出时间上最近的一个观测时刻。
    tnext=min⁡{tj∣tj≥ti}\displaystyle t_{\text{next}} = \min\{t_j \mid t_j \ge t_i\}
  4. 反向填充把未来时刻的观测值复制到当前缺失处,完成 bfill 操作。
    X^(ti)=X(tnext)\displaystyle \hat{X}(t_i) = X(t_{\text{next}})

AI 应用场景

服务器监控指标的降采样聚合

阶段:数据预处理与特征工程

解决的问题:监控系统每秒采集数千条指标,直接存储成本高、告警容易漏掉瞬时尖峰。传统做法是随机抽样,可能恰好丢失峰值;用降采样聚合则能按业务关注点保留关键信号。

具体案例:某云厂商的 SRE 团队把每 5 秒一条的 CPU 和延迟指标,用 resample('1M').agg('max') 聚合成分钟级指标。延迟告警只看最大值,一旦分钟最大延迟超过阈值就触发报警,既降低了存储成本,又不再漏掉瞬时抖动。

智能工厂多传感器时间对齐

阶段:多源数据融合

解决的问题:振动、温度、电流三个传感器频率各不相同,时间戳错位,直接拼接会导致特征对不上真实物理时刻。传统人工对齐效率低且容易出错;用重索引把三路数据对齐到同一时间网格后,模型才能学到“同一时刻的多维状态”。

具体案例:某电机故障诊断项目中,振动传感器 1kHz、温度每 10 秒一条、电流 50Hz。团队先统一时区,再用 reindex 对齐到 10ms 网格并前向填充,构造出时序特征矩阵输入 LSTM,故障识别准确率从 78% 提升到 93%。

金融高频数据重采样成 K 线

阶段:特征构造

解决的问题:逐笔成交数据量巨大且时间间隔不均匀,无法直接输入模型;传统做法是手工挑特征,容易遗漏量价关系。用重采样把逐笔数据聚合成固定周期的 OHLC 四项,再衍生出收益率、振幅等因子,特征工程更规范、可复现。

具体案例:某量化团队把股票逐笔成交数据 resample('1T').agg({'price': 'ohlc', 'volume': 'sum'}) 生成 1 分钟 K 线,再基于 K 线计算 30 分钟动量因子,输入 LightGBM 预测次日涨跌,回测夏普比率显著优于直接使用成交明细的方案。

Python 演示

python28 行
import pandas as pdimport numpy as np np.random.seed(42)base = pd.Timestamp('2024-01-01 08:00:00') # 生成 60 个不规则时间戳,间隔随机为 5-24 分钟offsets = np.cumsum(np.random.randint(5, 25, 60))times = base + pd.to_timedelta(offsets, unit='m') # 模拟温度读数:趋势正弦波动加噪声temps = 20 + 10 * np.sin(np.arange(60) / 6) + np.random.normal(0, 0.8, 60)df = pd.DataFrame({'temp': temps}, index=pd.DatetimeIndex(times, name='time'))print('irregular records:', len(df)) # 1) 降采样:每 1 小时聚合一次,同时算均值和最大值down = df.resample('1H').agg({'temp': ['mean', 'max']})print('downsampled rows:', len(down)) # 2) 升采样:从 1 小时插值回每 15 分钟up = down['temp']['mean'].resample('15T').interpolate(method='linear')print('upsampled rows:', len(up), 'first:', round(float(up.iloc[0]), 2)) # 3) 不规则数据对齐:重索引到 30 分钟标准网格,前向填充grid = pd.date_range('2024-01-01 08:00', '2024-01-01 14:00', freq='30T')aligned = df['temp'].reindex(grid).ffill()print('aligned grid points:', len(aligned))print(aligned.head(4).to_string())
目的:完整演示时序数据三大操作——用 resample 做降采样聚合、用 interpolate 做升采样插值、用 reindex + ffill 做不规则数据对齐。
  1. offsets = np.cumsum(np.random.randint(5, 25, 60))生成 60 个不相等的间隔,模拟“随性记录”导致的不规则采样。
  2. df = pd.DataFrame({'temp': temps}, index=pd.DatetimeIndex(times, name='time'))以不规则时间戳为索引建表,对应笔记本上记的原始温度。
  3. down = df.resample('1H').agg({'temp': ['mean', 'max']})按 1 小时分组,同时计算均值和最大值,一步完成降采样。
  4. up = down['temp']['mean'].resample('15T').interpolate(method='linear')从 1 小时升采样到 15 分钟,用线性插值补出中间时刻的估计值。
  5. aligned = df['temp'].reindex(grid).ffill()先重索引到 30 分钟标准网格,再用前向填充补缺,完成时间对齐。

常见误区

误区降采样就是把窗口内所有数据求个平均,均值最通用,反正数据都差不多,用哪个都一样。

正解均值只代表“平均水平”,会抹平峰值、谷值和分布形态。业务关注流量峰值时该用 max,关注总量时该用 sum,关注报价时该用 OHLC 四值。选错聚合函数,后续模型看到的信号就是错的——像报表摘要口径写错,整份报告都会误导人。

为何常见:均值概念最简单,多数入门教程只演示 mean,很容易让人形成“唯一答案”的错觉。

误区数据太少了就升采样,插值后数据点变多,模型训练效果一定会更好。

正解插值是估计而非实测,信息量并没有增加。线性插值假设均匀变化,若真实曲线在缺失区间剧烈波动,插值会平滑掉关键转折。更危险的是,插值点会放大模型的自信,让人误以为模型看到了更密的数据。想要更多真实数据,只能靠加强采集,而不是靠插值。

为何常见:视觉上数据点确实变多了,指标也可能因样本量上升而改善,容易产生“数据变好”的错觉。

误区LSTM 不是能处理序列吗?时间戳不规则也没关系,直接把原始数据按时间顺序输入就行。

正解绝大多数序列模型假设输入是等间隔的,时间信息蕴含在“位置”里,而不是时间戳的数值里。不规则间隔会让模型错误理解节奏——把 1 分钟间隔和 1 小时间隔当成同样的一步。必须先重采样或对齐到固定频率;如果确实想保留间隔信息,需要额外设计时间间隔特征,但预处理仍然不可省。

为何常见:序列模型的输入输出格式看起来统一,容易忽略它背后“等间隔”的强假设。

误区缺了 10:00 的记录,用 10:30 的实际观测值补上,总比插值估计的准吧?

正解用未来值(bfill)填补训练数据属于未来数据泄漏:模型在训练时通过“偷看”学会了依赖未来信号,而线上预测那一刻未来还没发生,指标会瞬间崩塌。离线画图可以这样补,但任何进入模型的数据,一律只能用过去信息(前向填充或插值)。

为何常见:离线数据都是“已经发生”的,后一个值就在手边,看起来更真实,容易忽略时间因果顺序。

面试题

Q1. 降采样的本质是什么?

单选题 · easy

  • A.把数据频率提高
  • B.高频数据聚合为低频← 正确答案
  • C.直接删除全部数据
  • D.随机抽样部分数据

答案:B。降采样是从高频往低频转换,把窗口内多个观测值通过聚合函数压缩成一个代表值,故选 B。A 是升采样,C 和 D 都不属于有信息保留的规整操作。

Q2. 以下哪个是升采样的常用手段?

单选题 · easy

  • A.对窗口取平均值
  • B.线性插值补中间← 正确答案
  • C.对窗口取最大值
  • D.直接丢弃缺失值

答案:B。升采样是从低频往高频补点,线性插值是补出中间时刻估计值的经典方法,故选 B。取均值和取最大值是降采样的聚合手段,丢弃缺失值不产生新数据。

Q3. 5 分钟数据降采样到 1 小时,想保留“每小时峰值”,应选哪种聚合?

单选题 · mid

  • A.窗口内求平均值
  • B.窗口内求最大值← 正确答案
  • C.取窗口首个观测
  • D.窗口内求和汇总

答案:B。峰值对应窗口内的最大观测值,用 max 聚合才能保留瞬时极值。均值抹平峰值,首值只看开头,求和代表总量,都不适合峰值告警类场景。

Q4. 时间对齐中“前向填充”的含义是什么?

单选题 · mid

  • A.用前一个有效值填充← 正确答案
  • B.用后一个有效值填充
  • C.用窗口均值填充
  • D.直接删除缺失行

答案:A。前向填充(ffill)用最近一个过去时刻的有效值填充当前缺失,故选 A。用后一个值填充是反向填充 bfill,可能引入未来数据泄漏。

Q5. 关于升采样插值,下列说法正确的有?

多选题 · mid

  • A.插值并不增加真实信息← 正确答案
  • B.线性插值假设均匀变化← 正确答案
  • C.样条插值曲线更平滑← 正确答案
  • D.插值结果一定准确无误

答案:ABC。插值是估计而非实测,不增加真实信息,A 正确;线性插值确实假设两点间均匀变化,B 正确;样条插值用分段多项式拟合,曲线更平滑,C 正确;插值在剧烈波动区间可能严重失真,D 错误。

Q6. 为什么建模前必须把不规则采样数据对齐到固定频率?

单选题 · hard

  • A.让图表看起来更整齐美观
  • B.多数模型要求等间隔输入← 正确答案
  • C.减少数据存储的开销
  • D.方便用未来值填补缺失

答案:B。序列模型(如 LSTM)假设输入等间隔,时间信息藏在位置里,不规则间隔会让模型误解节奏,故选 B。对齐主要服务模型假设,而非美观或存储;对齐更不能成为用未来值的理由。

Q7. 下列哪个业务最适合用“最大值”聚合做降采样?

单选题 · mid

  • A.天气平均气温周报
  • B.服务器流量峰值告警← 正确答案
  • C.股票每日收盘价格
  • D.用户每日步数统计

答案:B。峰值告警关心窗口内是否出现极端值,必须用 max 保留瞬时尖峰,故选 B。平均气温适合均值,收盘价适合末值,步数通常用总和。

Q8. 关于用未来值填补缺失(反向填充),说法正确的有?

多选题 · hard

  • A.会造成未来数据泄漏← 正确答案
  • B.训练好但线上预测失真← 正确答案
  • C.只适合事后离线分析← 正确答案
  • D.可用于实时在线预测

答案:ABC。反向填充把未来观测复制到过去,会泄漏未来信息,A 正确;训练时偷看未来导致评估虚高,上线时拿不到未来值,B 正确;它只适合整理历史图表等离线场景,C 正确;实时预测禁止使用,D 错误。

Q9. 线性插值估计 t 时刻的值,主要依赖哪些观测?

单选题 · mid

  • A.只依赖前一个观测点
  • B.只依赖后一个观测点
  • C.依赖前后两个相邻点← 正确答案
  • D.依赖所有历史观测点

答案:C。线性插值公式用缺失点前后两个相邻观测连直线,在目标时刻取线上的值,故选 C。它不依赖全部历史,也不只用单侧数据。

Q10. 一段时间间隔杂乱的时间序列要输入 LSTM,正确的第一步预处理是?

单选题 · hard

  • A.直接输入原始时间戳
  • B.重采样并固定频率对齐← 正确答案
  • C.删除所有非整点记录
  • D.只按时间排序即可用

答案:B。LSTM 假设等间隔输入,杂乱间隔必须先重采样到固定频率并做时间对齐,故选 B。直接输入时间戳或仅排序都无法满足等间隔假设,删数据则会造成大量信息浪费。