想象你站在厨房里观察一锅正在煮沸的汤。要判断汤的味道如何,你不会只看某一瞬间——你会舀起一勺,看看这“一小段”汤的颜色、浓稠度、香气,然后根据这一勺的特征来判断整锅汤的状态。过一会儿,再舀一勺,锅里的汤又有了新的变化。这“一勺”就是一个滑动窗口,而你从每一勺中提取的“颜色、浓稠度、香气”就是窗口特征。 时间序列数据就像这锅不断翻滚的汤:每一秒都在变化,但单独看某一秒的数据几乎没有意义。真正有价值的信息藏在“一小段时间内数据的变化模式”里——是上升还是下降?波动大还是平稳?跟上一次相比变了多少?滑动窗口特征工程,就是用一把“会移动的勺子”从时间序列中舀出一段段数据,计算出各种统计量,把这些原始数据变成机器学习模型真正能“品尝”出规律的特征。 在时间序列预测、异常检测、信号处理等任务中,滑动窗口特征是最基础也最有效的特征工程手段之一。从股票价格预测到设备故障预警,从心率监测到网站流量分析,几乎所有时序建模任务的第一步,都是构建滑动窗口特征。这篇文章将从生活直觉出发,带你完整掌握窗口大小选择、滚动统计量计算和滞后特征构建,并配有可视化演示和可运行的代码,让你真正理解并上手这套时序建模的基本功。
对 AI 从业者而言,滑动窗口特征是将原始时序数据转化为机器学习模型可理解特征的核心技能,是数据科学面试和实际工程中最高频的时序问题之一,掌握它等于拿到了时序特征工程的通行证。
可视化演示
动态演示滑动窗口特征的核心机制,通过输入/处理/存储/输出四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
滑动窗口特征:滑动窗口 滑动窗口特征工程基本概念 窗口大小选择策略与周期对齐 核心机制可视化 滑动窗口特征整体架构与关键组件
窗口基础概念
你端着一锅汤走向餐桌,客人问:“这汤味道怎么样?”你绝不会把整锅汤一饮而尽——你会舀一小勺,吹一吹,尝一口,然后给出判断。这一小勺,就是对我们理解“整锅汤的状态”有代表性的“窗口”。时间序列分析也是同样的道理:面对几十、几百甚至上万个时间点的数据,我们不可能一次性“喝掉”整条序列,而是用一把固定大小的“勺子”——滑动窗口——从序列的起点开始,每次取固定长度的一段数据,然后让窗口沿着时间轴一步一步向前滑动。
滑动窗口(Sliding Window),就是时间序列中一个固定长度的连续子序列。窗口有两个关键参数:窗口大小(width),也就是“勺子”能盛多少数据点;滑动步长(stride),也就是窗口每次向前移动几个时间点。在实际工程中,最常见的做法是步长为 1——窗口每向前滑动一个时间点,就生成一条新的样本。
为什么不能用全局统计代替窗口?假设你要判断“此刻汤的味道趋势”,如果只用整锅汤从下锅到现在的所有状态来计算平均味道,那等于把刚下锅的清水和煮了半小时的浓汤混在一起——你得到的是一个毫无意义的“平均味觉”。滑动窗口的意义正在于此:它只关注“最近这段距离”的变化,让模型能够捕捉到数据的局部动态模式,而不是被遥远的过去所稀释。窗口大小决定了你观察的“时间尺度”:窗口越小,越关注短期波动;窗口越大,越体现长期趋势。
滑动窗口特征的本质,是把“一小段时间内的数据”压缩成“一组统计量”。这个过程看似简单,却是时序建模中最常用、最有效的特征工程手段。从基础的均值、标准差,到复杂的滞后值组合,窗口就是那把在时间轴上不断移动的“勺子”,帮我们从翻滚的数据之汤中,舀出真正有信息量的“味道”。
窗口大小选择
选多大的勺子,取决于你想品出什么。如果你想知道汤有没有烧焦,你需要一小勺——太少了尝不出焦味,太多了反而被其他味道掩盖。如果你想知道这锅汤的总体咸淡,你可能需要稍大的一勺,让它包含多种食材的味道。滑动窗口的大小选择,正是这样一个“看细节还是看趋势”的权衡。
短窗口(如 3-5 个时间点)对数据的即时变化非常敏感,适合捕捉快速波动。比如监测心跳异常,你需要极短的窗口才能捕捉到一次心悸的瞬间特征;再比如股票的日内高频交易,短窗口能抓住几分钟内的价格突变。但短窗口的缺点是噪声大——单个异常点就会让窗口内的统计量剧烈波动,就像勺子太小,一粒胡椒就能让整勺汤“辣味爆炸”。
长窗口(如 30-50 个时间点甚至更长)则平滑了噪声,更擅长体现周期性规律。比如分析网站每小时的访问量,你用 24 小时的窗口能看出“每天的访问高峰”这一周期模式,但 1 小时的窗口只能看到一片混乱的波动。长窗口的代价是反应迟钝:它需要积累足够多的新数据才能“察觉”到趋势变化,就像大勺子很难尝出汤里刚加的一小撮盐。
实用策略是多窗口组合:不要只选一个窗口大小,而是同时计算多个窗口的特征。这就好比品汤时先小口尝鲜、再大口感受整体——短窗口特征捕捉短期波动,长窗口特征捕捉长期趋势,把它们拼接在一起作为模型的输入。在工程实践中,常见做法是同时使用 3 个不同尺度的窗口(比如“过去 1 小时”“过去 1 天”“过去 1 周”),让模型自己学习哪个尺度对预测目标更重要。
选择窗口大小的核心原则是:窗口要覆盖数据中一个完整的有意义模式。如果数据有日周期,窗口至少应该包含 24 个点;如果任务是预测下一个时刻的值,窗口至少要包含足够描述“当前状态”的信息量。这需要通过实验调参——就像厨师反复试勺,最终找到最能“品出问题”的那个尺寸。
滚动统计量
你舀起一勺汤,不会只说“嗯,是汤”。你会评价它的咸度(均值)、油腻程度(波动)、有没有大块的料(极值)、口感是否顺滑(分布形态)。滚动统计量就是对窗口内的数据做同样的“品味”——用数学语言把一勺数据的特征描述出来。
滚动均值(Rolling Mean) 是最基础的窗口统计量,它计算窗口内所有数据点的平均值。公式为:
滚动均值能平滑噪声,突出数据的整体趋势,但它丢失了波动信息——两锅汤可能平均咸度一样,但一锅稳定、一锅时咸时淡。这时需要滚动标准差(Rolling Standard Deviation):
除了均值和标准差,滚动最大值/最小值可以捕捉窗口内的极值事件(比如传感器尖峰、价格最高点);滚动偏度描述窗口内数据分布是否对称(偏度为正说明右尾更长,像汤里偶尔冒出一大块肉);滚动峰度描述分布的“尖锐”程度(峰度高说明数据集中在均值附近,像味道高度统一的浓汤)。这些统计量共同构成了一勺汤的完整“味觉画像”。
在实际工程中,滚动统计量通常组合使用。比如构建一个“波动爆发”特征:滚动标准差突然变大,往往意味着异常事件发生——工厂设备的振动传感器标准差骤增,可能是轴承要坏了。这正是滑动窗口特征在异常检测中的核心应用。
- 计算偏差每个数据点减去窗口均值 x̄_t,得到它偏离“平均味道”多少,偏差有正有负
- 平方求和把偏差平方后加起来,消除正负抵消,让大的偏差贡献更大的数值——就像把“偏咸”和“偏淡”都视为偏离,但幅度越大越突出
- 除以 w-1 再开方取平均(用 w-1 而非 w 是为了无偏估计)后开平方根,把平方量纲还原回原始数据的量纲
滞后特征
你判断汤的味道,不只是尝当前这一口,还会回想“上一口是什么味道”“跟上一次喝到的相比是变咸了还是变淡了”。滞后特征(Lag Features)做的事情完全一样:把过去某个时刻的值直接作为当前时刻的特征,让模型“记得”之前发生了什么。
滞后特征就是时间序列在 t-k 时刻的值,记为 $x_{t-k}$。最简单的滞后特征是一阶滞后 $x_{t-1}$——上一时刻的值。它的公式非常直观:
为什么要滞后特征? 因为时间序列本质上是“有记忆的”——今天的天气影响明天的天气,昨天的股价影响今天的股价。但如果只给模型当前值 x_t,模型就像一个没有记忆的品汤师,尝完一口就忘光,完全无法判断“变化趋势”。滞后特征把时间维度的“记忆”变成了特征的维度。
滞后多步组合则是构造多个不同步长的滞后特征。比如对于日度销量数据,你可能需要 $x_{t-1}$(昨天销量)、$x_{t-7}$(上周同期销量)、$x_{t-30}$(上月同期销量)。这就像品汤时不仅回忆上一口,还会想起“昨天这个时间喝的汤是什么味道”——周期性信息往往是预测的关键。
差分特征(Differencing) 是基于滞后特征的衍生特征,计算当前值与滞后值之差:
差分特征在金融领域尤其重要——股票价格本身很难预测,但价格的“变化率”(收益率)有一定规律可循。这就好比判断汤的好坏,比起“这勺汤咸度是 7”,“比上一勺咸了 2”更有决策价值。
滞后特征的构造有一个关键细节:滞后窗口内可用的历史数据越多,你能构造的滞后阶数就越高。但滞后阶数不是越多越好——过高的滞后阶数会引入过多噪声,还会导致特征维度爆炸。工程师需要结合业务知识选择有意义的滞后点,比如“预测明天销量,昨天的销量和去年同天的销量最有价值”。
- 当前值减上一时刻值计算相邻两个时间点的变化量,正值说明上升,负值说明下降
- 变化量作为特征模型用“变化了多少”而不是“是多少”来做预测,这对于平稳性差的数据尤其重要
特征矩阵构建
你收集了每一勺汤的“味觉画像”,但你不可能把这些画像写成一堆零散的笔记——你需要一张表格,每一行是一勺汤的记录,每一列是一种味道指标,这样你才能比较、分析、找规律。特征矩阵就是机器学习中这张“表格”。
构建滑动窗口特征矩阵,核心工作是把一条时间序列“摊开”成“样本-特征”的二维结构。假设原始序列为 $x_1, x_2, \ldots, x_T$,窗口大小为 w,你需要为每个时刻 t(从 w 开始)生成一行特征,包含窗口内的统计量:
构建特征矩阵时有三个关键环节。时间对齐是最容易出错的一步:特征矩阵中第 t 行的所有特征,必须只使用 t 时刻及之前的信息。如果你不小心把 t+1 时刻的数据混入了第 t 行的特征,就造成了“信息泄漏”——模型在训练时偷看了未来的答案,测试时表现会断崖式下跌。这就像品汤时不小心把还没煮好的食材也算进了当前的味道里。
缺失值处理也很关键。时间序列的开头 w-1 个点没有足够的“历史”来构建窗口特征,这些位置的样本需要特殊处理:可以选择删除,也可以用前面可用数据的均值/中位数填充。在实际代码中,通常用 min_periods 参数控制“窗口内至少有几天数据才能计算统计量”。
训练测试划分必须按时间顺序切分,不能随机打乱。时间序列数据本质上是有序的——用未来的数据训练模型去预测过去,就像先看了菜谱的最后一页再回头说“我早就知道这汤会煮成什么样”。标准的做法是:前 70%-80% 的数据作为训练集,最后 20%-30% 作为测试集,保证测试集的时间点全部晚于训练集。
构建好的特征矩阵有明确的形状:(T-w)×(特征数)。一个 1000 个时间点的序列,窗口大小为 10,可以生成约 990 个样本,每个样本有 10+ 个特征。这张“表格”随后可以直接输入到线性回归、随机森林、XGBoost 或神经网络中——滑动窗口特征工程的质量,往往比模型选择本身更影响最终预测效果。
- 特征向量拼接把滚动统计量(均值、标准差、极值)和滞后特征拼接成一个向量,所有信息来自 t 时刻及之前的数据
- 滞后序列窗口内每个历史时刻的值本身也是特征,模型可以直接“看到”最近的原始数据
- 标签如果需要做预测,目标变量通常是未来某个时刻的值 y_t = x_{t+h},与特征 X_t 组成监督学习的训练样本
实战案例流程
想象你是一家面包店的老板,想预测明天要烤多少面包。你记录了每天打烊后的销售数据。现在,你决定用滑动窗口特征来做一个预测模型——这就进入了完整的实战流程。
第一步:数据预处理。你手头可能有 300 天的日销量数据,但里面有一些异常值(比如某天停电只卖了 10 个面包)。你需要先清洗数据(处理缺失值和异常值),再检查序列是否平稳。原始数据是一维序列 [d1, d2, ..., d300],你的目标是预测第 301 天的销量。就像做汤前先要把食材洗干净、切好,数据预处理决定了后续所有步骤的质量。
第二步:特征生成与筛选。设定窗口大小 w=7(一周七天,因为面包销量有明显的一周周期),为每一天生成一组特征:
这些特征包括:过去 7 天平均销量(掌握整体水平)、过去 7 天销量波动(判断稳定性)、过去 7 天最高/最低销量(捕捉极端情况)、昨天销量(最直接的近期信息)、上周同一天销量(消除周期性)。特征生成后,可以通过特征重要性分析筛选掉无用的特征——就像品尝后调整配方,去掉多余的调料。
第三步:模型训练与评估。把前 240 天的数据作为训练集,后 60 天作为测试集(为什么不能随机划分?因为时间顺序不能乱)。训练一个随机森林或 XGBoost 模型,用均方误差评估预测效果。评价指标选择方面,时间序列预测常用 MAE、RMSE,回归任务默认是 MSE。一个典型的实验结果是:用滑动窗口特征训练的模型,预测误差可能比直接用原始序列的“朴素预测”(用昨天销量预测明天销量)低 20%-30%。
这套流程在不同场景下的差异主要在于窗口大小的选择。面包店用的是“7 天窗口捕捉周周期”,股票预测可能用“20 天窗口捕捉月趋势”,心率异常检测可能用“5 秒窗口捕捉瞬时异常”。但整体的“预处理→特征生成→模型训练评估”框架是通用的。滑动窗口特征工程的精妙之处在于:它把核心建模问题从“选模型”前置到了“选窗口和统计量”——握好你手中的“勺子”,比选一口好“锅”往往更重要。
# 假设 sales 是日销量序列,窗口为 7X_t = [mean_7, std_7, max_7, min_7, sales_{t-1}, sales_{t-7}]
常见问题避坑
你终于建好了模型,效果不错,但过了两周,模型突然失灵了——预测值像醉汉一样乱跳。你检查代码,发现问题出在一个你从未注意过的细节上。滑动窗口特征工程有几个常见的“坑”,它们不像算法原理那样引人注目,却往往决定模型成败。
坑一:信息泄漏。最常见的错误是在构造特征时使用了“未来”信息。比如你想预测 t 时刻的值,却在特征里包含了 t 时刻的均值——这个均值的计算使用了 x_t 本身,模型等于“知道了答案再做题”。更隐蔽的是:用全量数据的均值/标准差做标准化后再切分训练测试集,测试集的信息已经悄悄混入了训练集。这就像你把整锅汤都尝了一遍,再让客人猜“第一口汤是什么味道”——你当然能猜到,但这不是本事,是作弊。
坑二:窗口大小不匹配新数据。模型上线后,你发现它的表现远不如训练时——因为你的模型是用窗口大小为 7 的特征训练的,但实际预测时,新数据每天只来一条,你要等 7 天才够攒出一个窗口特征。这就像训练时用的勺子能盛 7 天数据,部署时却发现勺子小了。解决方案是设计特征时就要考虑“线上延迟”——确保每个特征在任意时间点都是可计算的,比如不等满 7 天,用“可用数据的前 N 天均值”代替。
坑三:naive 的差分处理。有些初学者对非平稳序列直接做一阶差分,然后构造窗口特征——这本身没错,但预测完要把差分还原成原始尺度时,容易弄错对齐关系。差分的还原是一个累加过程,错一步,后面全错。
坑四:忽视计算效率。窗口统计量的朴素实现是每个时间点都重新计算窗口内所有数据——复杂度 O(T×w)(T 是序列长度,w 是窗口大小)。当数据量达到百万级、窗口又大时,速度慢得令人绝望。优化方法是用增量更新:滑动窗口时,新均值 = 旧均值 + (新进点 - 滑出点)/w,复杂度降为 O(T)。这就像品汤时不需要把整锅汤重新尝一遍,只需要比较“新加的一勺”和“倒掉的一勺”的差别。
这些坑的共同根源是:没有时刻牢记“时间顺序”这个核心约束。时间序列分析的所有操作——特征构造、标准化、交叉验证——都必须尊重“过去的数据只能看到过去”这一铁律。守住这条底线,你就避开了滑动窗口特征工程中 80% 的坑。
AI 应用场景
场景一:电商销量预测
阶段:特征工程
解决的问题:电商平台需要预测未来几天的商品销量来指导备货。传统做法是仓库管理员凭经验预估,准确率低且无法规模化。采用滑动窗口特征后,系统自动从历史销量序列中提取滚动均值(捕捉整体趋势)、滚动标准差(判断波动风险)和滞后 7 天特征(消除周周期性),大幅提升预测精度。
具体案例:某生鲜电商平台对 5000 个 SKU 做日销量预测。工程师为每个 SKU 构建 14 天滑动窗口的均值、标准差、最大值、最小值以及滞后 1/7/14 天特征,输入 LightGBM 模型。结果显示,相比简单“用昨天销量预测明天”的基线,加入窗口特征后预测误差降低 32%,缺货率下降 18%,同时减少了 15% 的库存损耗。
场景二:工业设备异常检测
阶段:特征提取与监控
解决的问题:工厂设备传感器每秒产生大量振动、温度数据。设备正常运行时数据平稳波动,异常时会出现趋势突变或方差骤增。直接用原始序列做检测误报率太高。用滑动窗口特征(窗口内标准差、偏度等)将原始信号转化为“波动状态指标”,配合阈值或异常检测模型,能精准捕捉故障前兆。
具体案例:某风电场为每台风机采集每秒的振动数据。工程师计算 10 秒窗口的滚动标准差和峰度,当标准差连续 3 个窗口超过正常范围 2 倍时触发预警。这套“窗口特征+规则”方案提前 4 小时发现了一台风机轴承的早期故障,避免了价值 200 万元的设备损坏。相比直接用原始信号阈值检测,误报率降低了 70%。
场景三:金融风险指标计算
阶段:量化特征构建
解决的问题:金融市场中的移动平均线(MA)、布林带(标准差)等技术指标,本质就是滑动窗口特征的经典应用。它们是量化交易模型最常用的输入特征。手动计算大量技术指标耗时且易错,用滚动统计量统一构建特征矩阵,可高效接入机器学习交易策略。
具体案例:某量化团队构建日频交易策略,用 5/10/20/60 日四个窗口的均值、标准差和收益率差分作为特征,训练梯度提升模型预测次日涨跌方向。样本外测试中,包含滑动窗口特征的策略年化收益率比仅用原始价格序列的策略高出 8.2 个百分点,回撤降低了 12%。团队还发现,短窗口特征(5 日)捕捉短期动量,长窗口特征(60 日)捕捉长期趋势,两者组合效果最佳。
Python 演示
import numpy as npimport pandas as pdfrom sklearn.ensemble import RandomForestRegressorfrom sklearn.metrics import mean_absolute_error np.random.seed(42) # 生成模拟的日销量数据: 趋势 + 周周期 + 噪声T = 365t = np.arange(T)daily = 50 + 0.05 * t + 10 * np.sin(2 * np.pi * t / 7) + np.random.normal(0, 3, T)sales = pd.Series(daily, name='sales') # 构造滑动窗口特征def build_window_features(series, window=7): df = pd.DataFrame({'sales': series}) df['roll_mean'] = series.rolling(window).mean() df['roll_std'] = series.rolling(window).std() df['roll_max'] = series.rolling(window).max() df['roll_min'] = series.rolling(window).min() df['lag_1'] = series.shift(1) df['lag_7'] = series.shift(7) df['diff_1'] = series.diff(1) df['target'] = series.shift(-1) return df df = build_window_features(sales, window=7) # 丢弃窗口起始处含 NaN 的行df = df.dropna() # 按时间顺序切分: 前 80% 训练, 后 20% 测试split = int(len(df) * 0.8)train = df.iloc[:split]test = df.iloc[split:] feature_cols = ['roll_mean', 'roll_std', 'roll_max', 'roll_min', 'lag_1', 'lag_7', 'diff_1']X_train, y_train = train[feature_cols], train['target']X_test, y_test = test[feature_cols], test['target'] # 训练随机森林并评估model = RandomForestRegressor(n_estimators=200, random_state=42)model.fit(X_train, y_train) pred = model.predict(X_test)mae = mean_absolute_error(y_test, pred)baseline_mae = mean_absolute_error(y_test, test['lag_1']) print(f"滑动窗口特征模型 MAE: {mae:.2f}")print(f"朴素基线(昨日值) MAE: {baseline_mae:.2f}")print(f"提升幅度: {(baseline_mae - mae) / baseline_mae * 100:.1f}%")
series.rolling(window).mean()计算滚动均值,等价于对每个时刻取最近 7 天的平均销量series.rolling(window).std()计算滚动标准差,捕捉销量波动大小series.shift(1)生成滞后 1 天的特征,即“昨天的销量”series.diff(1)计算一阶差分,即“今天比昨天多卖了多少”series.shift(-1)构造预测目标:把未来一天的销量作为当前时刻的标签df.dropna()删除窗口起始处因历史不足产生的空值行df.iloc[:split]按时间顺序切分训练集,保证不随机打乱时序mean_absolute_error(y_test, test['lag_1'])用“昨天销量预测今天”作为朴素基线对比
常见误区
误区“窗口越大,包含的历史信息越多,模型效果一定越好。我把窗口从 7 改成 30,预测应该更准吧?”
正解窗口并非越大越好。大窗口虽然包含更多历史信息,但也混入了大量与当前预测无关的过时信息,相当于品汤时用一个大缸把所有食材从下锅到现在的味道全部混在一起——你尝不出“此刻”的味道。窗口越大,特征对近期变化的敏感度越低,还会引入更多噪声。最佳窗口大小应当与数据中的“有效模式长度”匹配:日销量数据用 7 天窗口捕捉周周期,心率数据用几秒窗口捕捉瞬时异常。选择窗口大小应当通过实验对比,而非直觉认为“越大越好”。
为何常见:直观上,“更多信息 = 更好预测”符合直觉。初学者容易忽略时间序列的“局部性”——过时的信息不但没有帮助,反而会稀释近期信息的权重。
误区“我先把所有样本随机打乱,再按 80/20 切分训练集和测试集,这样训练集和测试集的分布更均匀,模型评估更可靠。”
正解这是时间序列建模中最危险的错误。时间序列的每个样本都蕴含时间顺序,随机打乱会让训练集中混入时间上“未来”的样本——模型在训练时偷看了未来的数据,测试时的好成绩是虚假的。这就好比你先尝了汤的最终味道,再回过头来“预测”第一口是什么味。正确做法是:按时间顺序切分,训练集的时间必须全部早于测试集;如果要更严格的评估,应使用时间序列交叉验证(如 TimeSeriesSplit),每次都只用过去的数据训练、未来的数据验证。
为何常见:在普通表格数据中,随机打乱是正确的标准做法,很多初学者把这个惯例直接搬到了时间序列上,忽略了时序数据最本质的“顺序属性”。
误区“既然滞后 1 天有用,那滞后 2 天、3 天、一直到 30 天都应该有用。我把所有滞后阶数都加上,让模型自己选。”
正解滞后特征的数量并非越多越好。首先,滞后阶数增加会线性增加特征维度,但很多高阶滞后特征与目标变量几乎无关,纯属噪声。其次,滞后阶数过多会导致严重的特征共线性——相邻的滞后值高度相关,让树模型的特征重要性失真,让线性模型的系数不稳定。更实际的问题是:滞后 30 天的特征意味着模型上线后,必须积累 30 天数据才能做出第一次预测。正确的做法是结合业务知识选择有意义的滞后点——比如预测日销量选 lag 1 和 lag 7(周周期)、预测月销量选 lag 1 和 lag 12(年周期),而不是盲目堆砌。
为何常见:“多多益善”的直觉让初学者倾向于添加所有可用特征。他们没有意识到,特征工程的目标是用最少、最有信息量的特征表达数据规律,而非穷举所有可能性。
误区“滑动窗口特征就是算个平均值,窗口内数据的平均水平就是最有价值的特征。”
正解均值只是窗口特征的第一步。两段数据的均值可能完全相同,但一段平稳如镜、另一段剧烈振荡——它们对预测的含义截然不同。标准差、最大值、最小值、偏度、峰度分别捕捉了波动的不同侧面。在异常检测中,滚动标准差和偏度往往比均值更关键:设备故障前,振动数据的方差会突然增大,但均值可能几乎没有变化。模型的预测能力来自多个统计量的互补,就像品汤不能只说“咸淡适中”,还要体会鲜度、厚度和余味。
为何常见:均值是大家最早接触的统计量,思维惯性让人默认“平均水平”是最有代表性的特征。事实上,对于时序建模,波动性(标准差)、极端值(最大/最小)和分布形态(偏度/峰度)往往携带更丰富的信息。
面试题
Q1. 滑动窗口特征工程的核心思想是什么?
- A.对全量数据计算一个全局统计量
- B.用固定长度的窗口在时间轴上滑动并提取局部统计量← 正确答案
- C.对数据进行随机采样后计算均值
- D.将时间序列转换为频域信号
答案:B。滑动窗口特征的核心是“局部性”——用固定长度的窗口逐段提取统计量,而非全局统计。选项 B 准确描述了这一过程。A 是“全局统计”,丢失了局部动态模式;C 是随机采样,与时间顺序无关;D 是频域转换,属于另一种特征工程方法。
Q2. 滞后特征 x_{t-1} 表示什么?
- A.t 时刻的预测值
- B.t-1 时刻的观测值,作为 t 时刻模型的特征← 正确答案
- C.窗口内的平均值的差分
- D.未来 t+1 时刻的值
答案:B。x_{t-1} 是“上一时刻的观测值”,它被用作当前时刻的特征,让模型“记住”近期状态。选项 A 是模型输出而非特征;C 是差分特征的概念;D 是目标变量而非特征,涉及未来信息导致泄漏。
Q3. 窗口大小从 7 天调整为 3 天,以下哪种影响是正确的?
- A.特征对近期变化更敏感,但噪声更大← 正确答案
- B.特征更平滑,但反应更迟钝
- C.模型的训练速度一定变快
- D.特征数量一定减少
答案:A。短窗口关注近期,敏感但噪声大(A 正确)。B 描述的是长窗口的特征。C 和 D 与窗口大小没有必然联系——窗口大小影响特征的值,但不改变特征数量。
Q4. 为什么时间序列的训练集和测试集不能随机打乱划分?
- A.随机打乱计算开销太大
- B.因为时间顺序蕴含信息,打乱会导致数据泄漏← 正确答案
- C.因为测试集必须包含更多样本
- D.因为随机打乱会让模型过拟合
答案:B。时间序列的“时间顺序”本身就是信息的一部分。随机打乱会让训练集中混入“未来”数据,模型在训练时偷看到了测试阶段才应该出现的信息,导致评估结果虚高。这就像先看了汤的成品再回头猜原料。
Q5. 以下哪些属于滚动统计量的范畴?
- A.滚动均值← 正确答案
- B.滚动标准差← 正确答案
- C.滞后一阶差分
- D.滚动最大值← 正确答案
答案:ABD。滚动统计量是对窗口内数据计算的统计指标:均值、标准差、最大值、最小值、偏度、峰度等都属于此范畴。滞后差分(C)是滞后特征的衍生特征,不属于统计量。
Q6. 以下关于信息泄漏的说法正确的有哪些?
- A.特征中使用了未来时刻的数据属于泄漏← 正确答案
- B.用全量数据的均值做标准化后再划分训练测试集不会泄漏
- C.用全量数据的均值做标准化属于泄漏← 正确答案
- D.泄漏会让模型的测试评估结果虚高← 正确答案
答案:ACD。任何特征或预处理步骤使用了“未来”信息都属于泄漏。用全量数据计算均值做标准化,让标准化参数“看到了”测试集,属于间接泄漏(B 错,C 对)。泄漏会让模型在训练时的表现虚高,但真实部署时性能会暴跌(D 对)。
Q7. 差分特征 Δx_t = x_t - x_{t-1} 的主要作用是什么?
- A.消除时间序列的趋势和季节性,使序列更平稳← 正确答案
- B.增大序列的方差
- C.将序列转换为概率分布
- D.减少特征矩阵的行数
答案:A。差分通过计算相邻时间点的变化量,消除了数据的绝对水平影响,让模型关注“变化”而非“值本身”。ARIMA 等经典模型常通过差分处理非平稳序列。B 是反向效果;C 与差分无关;D 差分不改变样本数。
Q8. 一个 1000 个时间点的序列,窗口大小为 5,步长为 1,以下哪些描述是正确的?
- A.可以生成约 996 个有效样本← 正确答案
- B.可以生成约 199 个有效样本
- C.每个样本的滞后特征可直接使用 x_{t-5}
- D.窗口起始处有 4 个时间点无法构建完整窗口特征← 正确答案
答案:AD。窗口大小为 5 时,前 4 个时间点没有足够的历史来填充窗口,从第 5 个点开始才能生成完整特征,因此有效样本数约 1000-4=996(A 对,B 错)。滞后特征在窗口内可用的最高阶数为 4(即 x_{t-4}),x_{t-5} 超出窗口范围(C 错)。D 正确:前 4 个点因历史不足被丢弃。
Q9. 模型上线后性能远低于训练时的表现,最可能的原因是什么?
- A.训练时存在信息泄漏,模型依赖了实际预测时不可用的信息← 正确答案
- B.模型选择了错误的损失函数
- C.训练数据量太大
- D.特征数量太少
答案:A。训练-测试差距巨大的一个典型原因就是泄漏:训练时特征包含“未来”信息或标准化用了全量数据统计量,模型在训练时“作弊”,上线后作弊条件消失,性能自然崩盘。B 和 D 可能导致性能不佳,但不会造成如此大的训练-测试差距;C 不是原因。
Q10. 关于构建滑动窗口特征矩阵,正确的做法包括哪些?
- A.特征严格使用当前时刻及之前的数据计算← 正确答案
- B.窗口起始处的缺失值直接删除或用已有数据填充← 正确答案
- C.训练测试划分可采用时间顺序切分← 正确答案
- D.特征矩阵的每一行对应一个时间窗口的样本← 正确答案
答案:ABCD。滑动窗口特征矩阵构建的四条基本原则:特征只用过去和现在信息(A);开头因历史不足产生的 NaN 需要处理(B);按时间顺序划分数据(C);每行是一个窗口的样本(D)。四者全部正确,违背任何一条都可能导致模型失效。