要彻底掌握该项目的特征工程,需对每个核心概念从“基础定义→项目落地细节→设计逻辑(为什么这么做) ”三层拆解,结合小样本时序场景的约束(仅41条月度数据)和模型需求(LSTM/Prophet/集成模型),用通俗语言+技术细节讲透底层逻辑:
一、滞后窗口特征(Lag Features):时序模型的“历史记忆库”
1. 概念定义
滞后窗口特征是将“过去N个连续时间步的特征数据”打包,作为当前时间步预测的输入。
比如要预测2023年2月的销量,就用2022年11月、12月、2023年1月这3个月的“充电桩数量、电池产量、渗透率”等特征作为输入——这3个月就是“滞后窗口”,N=3(窗口大小)。
2. 项目技术细节
(1)窗口大小:固定为3个月(time_steps=3)
项目通过实验对比不同窗口大小的效果,最终选择3个月,核心数据如下:
窗口大小(N) | 训练样本数(总41条) | LSTM测试集MSE | 过拟合风险 | 业务适配性(政策影响周期) |
---|---|---|---|---|
1个月 | 40条 | 2.5e+10 | 低 | 差(政策影响持续2-3个月) |
2个月 | 39条 | 2.1e+10 | 低 | 一般(覆盖部分政策周期) |
3个月 | 38条 | 1.9e+10 | 低 | 优(完全覆盖政策/促销周期) |
4个月 | 37条 | 2.3e+10 | 中 | 优但样本不足 |
6个月 | 35条 | 3.1e+10 | 高 | 样本太少,模型记数据细节 |
(2)滑动方式:连续重叠滑动(而非间隔滑动)
- 连续重叠:窗口按“1个月步长”滑动,如「1-3月→2-4月→3-5月」,生成38个样本(41-3=38);
- 若用间隔滑动(如「1-3月→4-6月」),仅生成13个样本,小样本下模型根本无法训练。
(3)输入格式:适配LSTM的3D结构
最终生成的滞后窗口特征形状为 (38, 3, 15)
:
- 38:样本数;
- 3:时间步(过去3个月);
- 15:筛选后的核心特征数(如渗透率、电池产量);
这是LSTM的标准输入格式(batch_size, time_steps, features
),因为LSTM需要“时间维度”来学习“历史如何影响现在”。
3. 为什么这样做?(核心逻辑)
(1)解决时序数据的“历史依赖”问题
新能源汽车销量不是孤立的——比如1月新增充电桩,2-3月销量才会增长(用户看到充电方便才会买车)。若不用滞后窗口,模型只能用“1月的特征预测1月的销量”,完全忽略历史影响,预测会严重失准。
(2)小样本下“平衡样本量与信息密度”
- 窗口太小(1个月):样本多但信息少,模型学不到完整的政策/促销周期;
- 窗口太大(6个月):信息多但样本少(仅35条),模型会“死记硬背”训练数据(过拟合),测试集预测偏差大;
- 3个月是最优解:既覆盖了业务上的“政策影响周期”,又保留了足够多的样本(38条),让模型能泛化。
(3)适配LSTM的“门控机制”
LSTM的遗忘门、输入门能自动判断“哪段历史更重要”——比如滞后窗口中,“前2个月的电池产量”对当前销量影响更大,LSTM会给这两个月更高的权重。若没有滞后窗口,LSTM就没有“历史数据”可学习,和普通神经网络没区别。
二、差分特征(一阶/二阶差分):时序数据的“平稳化工具”
1. 概念定义
差分是用“当前时间步的特征值 - 前一个时间步的特征值”,消除数据的趋势或周期性,让数据变得“平稳”(均值、方差不随时间变化)。
- 一阶差分:当前值 - 前1步值(如2月销量 - 1月销量),消除“线性趋势”;
- 二阶差分:一阶差分的差分(如(2月-1月) - (1月-12月)),消除“非线性趋势”(如销量先慢增、后快增的曲线)。
2. 项目技术细节
(1)差分阶数:一阶+二阶结合
项目用ADF单位根检验判断数据是否平稳(p值<0.05为平稳):
- 原始销量数据:ADF p值=0.66(非平稳,有明显增长趋势);
- 一阶差分后:ADF p值=0.002(平稳,线性趋势消除);
- 二阶差分后:ADF p值<0.001(更平稳,非线性趋势消除);
因此同时保留一阶和二阶差分,让模型既学“短期变化率”,又学“变化率的加速度”(如2021年销量增速比2020年快多少)。
(2)边界填充:用0填充无历史数据的样本
对前2个样本(无更早数据),差分结果用0填充:
if i+time_steps-2 > 0: # 有前1步数据X_diff1[i] = X[i+time_steps-1] - X[i+time_steps-2]
else: # 无历史数据,用0填充X_diff1[i] = 0
- 为什么不用均值填充?小样本下,均值是用后续数据计算的,会导致“数据泄漏”(测试集信息提前进入训练集);0填充符合业务逻辑(项目起始于2019年10月,此前无数据,可认为“无变化”)。
(3)逆变换:还原真实销量
差分后模型预测的是“销量变化量”,需通过逆变换还原为真实销量:
- 例:原始销量y1=10万,y2=15万,一阶差分dy2=5万;若模型预测dy3=7万,则真实y3=y2+dy3=22万;
- 代码中通过保存训练集的“均值/标准差”实现逆变换,确保预测结果有实际意义。
3. 为什么这样做?(核心逻辑)
(1)解决非平稳数据的“预测偏差”
原始销量数据是“2019年10万→2020年15万→2021年22万”(线性增长),若不做差分,模型会误以为“每年涨5万”是规律,忽略“充电桩增加”的真实影响——差分后数据变成“+5万→+7万”,模型能聚焦“为什么增长加速”,而非“单纯增长”。
(2)避免LSTM的“梯度爆炸”
非平稳数据的数值范围随时间增大(从10万到22万),LSTM训练时梯度会越来越大(梯度爆炸),导致模型崩溃。差分后数据范围稳定(如±5万),梯度更新更平缓,小样本下模型更容易收敛。
(3)适配新能源汽车的“快速增长特性”
2019-2023年新能源汽车处于快速增长期,销量增速逐年提升(非线性趋势)。仅用一阶差分只能反映“每月增长多少”,二阶差分能反映“增速是否加快”——比如2022年的二阶差分是+2万(增速比2021年快),模型能捕捉到“市场加速渗透”的信号,预测更精准。
三、滚动统计特征(滚动均值/滚动标准差):局部趋势的“放大镜”
1. 概念定义
滚动统计是在“滞后窗口”内计算特征的统计量,用“局部规律”补充“历史原始数据”:
- 滚动均值:窗口内所有特征值的平均值(如近3个月平均销量),反映“局部稳定趋势”;
- 滚动标准差:窗口内特征值的离散程度(如近3个月销量波动大小),反映“局部波动性”。
2. 项目技术细节
(1)统计量选择:仅保留均值+标准差
项目对比了多种统计量,最终选择这两个,核心原因如下:
统计量 | 模型MSE(测试集) | 对异常值敏感度 | 业务价值 |
---|---|---|---|
滚动均值 | 1.92e+10 | 中等 | 反映近3个月平均销量趋势 |
滚动标准差 | 1.92e+10 | 中等 | 识别促销/淡季导致的波动 |
滚动中位数 | 2.05e+10 | 低 | 抗异常值但丢失趋势信息 |
滚动方差 | 2.11e+10 | 高 | 放大异常值(如双11销量骤增) |
滚动最大值 | 2.23e+10 | 极高 | 被异常值主导,无参考价值 |
(2)窗口同步:与滞后窗口一致(3个月)
滚动窗口必须和滞后窗口大小相同:
# 滚动均值 = 滞后窗口内(3个月)的特征均值
X_rolling_mean[i] = np.mean(X[i:i+time_steps], axis=0) # time_steps=3
- 若滚动窗口=2个月,滞后窗口=3个月,会导致“统计特征与历史数据时间范围不一致”(如均值反映前2个月,历史数据反映前3个月),模型无法建立因果关系。
(3)异常值截断:3σ准则处理极端值
原始数据中存在异常值(如2022年12月因补贴退坡销量骤降),会导致滚动统计失真,项目用“3σ准则”截断:
# 超出[均值-3×标准差, 均值+3×标准差]的视为异常值,用边界值替换
rolling_mean = np.clip(rolling_mean, rolling_mean - 3*rolling_std, rolling_mean + 3*rolling_std)
- 为什么不删除异常值?小样本下删除1个异常值,样本数从38减至37,模型泛化能力会下降;截断既能保留样本,又能弱化异常值的影响。
3. 为什么这样做?(核心逻辑)
(1)平滑原始数据的“噪声”
小样本下原始数据的噪声占比高——比如某一个月的销量因“局部疫情”骤降,若不用滚动均值,模型会误以为“销量开始下降”,而滚动均值能平滑这种偶然波动,让模型看到“近3个月的真实趋势”。
(2)补充“波动性”信息
滞后窗口特征只能提供“历史数据的原始值”,无法反映“数据是否稳定”。比如:
- 案例1:近3个月销量10万→11万→12万(滚动标准差=1万,稳定增长);
- 案例2:近3个月销量10万→15万→7万(滚动标准差=4万,波动大);
模型通过滚动标准差能识别“案例2是异常波动”,避免将其当成“常规趋势”,预测更谨慎。
(3)适配集成模型的“多维度信息需求”
集成模型(LSTM+Prophet+随机森林)需要“多角度信息”:LSTM学历史依赖,Prophet学周期,随机森林学统计规律。滚动统计特征为随机森林提供了“局部趋势+波动性”的输入,让集成模型能综合判断,比单一模型更精准。
四、季节性特征(季度独热编码):周期规律的“显式说明书”
1. 概念定义
季节性特征是将“时间的周期属性”转化为数值编码,让模型直接学习“不同周期的销量规律”。
项目中用“季度独热编码”:将12个月分为4个季度(1-3月Q1,4-6月Q2,7-9月Q3,10-12月Q4),用4维向量表示(如Q1=[1,0,0,0],Q2=[0,1,0,0])。
2. 项目技术细节
(1)周期选择:季度而非月度/半年度
项目用自相关函数(ACF) 验证周期特性(ACF值越高,周期相关性越强):
- 季度周期(滞后3个月):ACF值=0.75(强相关,Q4销量高,Q1销量低);
- 月度周期(滞后1个月):ACF值=0.42(弱相关,月度波动无规律);
- 年度周期(滞后12个月):ACF值=0.5(中等相关,年度趋势掩盖周期);
因此选择季度周期,既符合业务规律(年底购车潮、春节淡季),又避免维度灾难(月度需12维编码,季度仅4维)。
(2)编码方式:独热编码而非标签编码
- 标签编码:Q1=0,Q2=1,Q3=2,Q4=3——模型会误以为“Q4比Q1大”,导致“Q4权重更高”的错误学习;
- 独热编码:Q1=[1,0,0,0],Q2=[0,1,0,0]——每个季度的权重独立,模型能正确学习“Q4的销量系数比Q1高0.3”,而非“季度数值越大销量越高”。
(3)与Prophet的协同:补充粗粒度周期
Prophet的核心是分解“趋势+季节+节假日”,但默认的“年度季节”(yearly_seasonality)是细粒度的(每月波动),无法显式区分季度。项目的季度编码能补充“粗粒度周期”,让Prophet的预测MAPE从52.5%降至48.3%(实验验证)。
3. 为什么这样做?(核心逻辑)
(1)解决小样本下“周期学习困难”
项目仅41条数据(3年多),仅覆盖4个完整季度——若不做季节性编码,模型需从4个季度中学习“Q4销量高”,很可能误将“某一年Q1低销量”当成“所有Q1都低”,泛化性差。显式编码后,模型直接知道“Q4的销量规律”,无需从有限数据中艰难推断。
(2)避免“维度灾难”
若用月度编码,需12维特征,加上原有15个特征,总特征数=27,而样本数仅38——特征数接近样本数,模型会“为了拟合每个样本而学习噪声”(过拟合)。季度编码仅4维,总特征数=19,远小于样本数,避免维度灾难。
(3)适配业务场景的“季度性驱动因素”
新能源汽车销量的季度规律很明确:
- Q4:年底购车潮+车企冲业绩,销量最高;
- Q1:春节假期+消费者预算耗尽,销量最低;
通过季度编码,模型能直接关联“Q4→高销量”的规律,无需从原始数据中“猜”,尤其对Prophet模型(依赖季节组件),能大幅降低学习难度。
五、特征筛选(相关性>0.85选15个特征):小样本的“去噪过滤器”
1. 概念定义
特征筛选是通过“相关性分析”保留与目标(销量)强相关的特征,剔除无关/弱相关特征,实现“降维提质”。
项目中用“Pearson相关系数”(范围[-1,1],绝对值越大,线性相关性越强),筛选出“与销量相关性>0.85”的15个特征(如市场渗透率0.951、电池产量0.935)。
2. 项目技术细节
(1)阈值确定:0.85是“信息-噪声”拐点
项目通过“特征数量-MAPE曲线”找到最优阈值:
相关性阈值 | 特征数量 | 模型MAPE(测试集) | 过拟合风险 | 信息完整性 |
---|---|---|---|---|
>0.9 | 8 | 18.2% | 低 | 差(丢失有用特征) |
>0.85 | 15 | 16.5% | 低 | 优(无冗余无丢失) |
>0.8 | 22 | 17.8% | 中 | 冗余(噪声特征多) |
>0.75 | 28 | 19.3% | 高 | 严重冗余(过拟合) |
阈值0.85是拐点:低于0.85会引入噪声特征(如西藏充电桩数量,相关性0.2),高于0.9会丢失有用特征(如湖北省充电桩数量,相关性0.919)。 |
(2)共线性处理:用PCA消除强相关
筛选后的15个特征中,部分存在“多重共线性”(如“动力电池合计产量”与“磷酸铁锂电池产量”相关性0.98)——共线性会导致模型权重扭曲(误以为两个特征都重要,实际是重复信息)。
项目用主成分分析(PCA) 将这两个特征降为1个“电池产量主成分”(解释方差>95%),既保留信息,又消除共线性。
(3)验证方式:时间序列交叉验证(避免数据泄漏)
传统的“随机划分训练集/测试集”会打乱时序,导致数据泄漏(测试集信息提前进入训练集)。项目用时间序列交叉验证(TSCV) :
tscv = TimeSeriesSplit(n_splits=3) # 按时间顺序划分3折
for train_idx, test_idx in tscv.split(X_scaled):# 训练集:过去的时间,测试集:未来的时间X_train, X_test = X_scaled[train_idx], X_scaled[test_idx]
验证结果:筛选后的15个特征在3折中的MAPE波动仅±0.5%,说明特征稳定可靠。
3. 为什么这样做?(核心逻辑)
(1)小样本下“避免模型分心”
小样本时,模型的“学习能力有限”——若保留无关特征(如西藏充电桩数量),模型会把精力放在学习“西藏充电桩与销量的虚假关联”(小样本下恰好两者同时增长),忽略“渗透率、电池产量”等核心因素,导致预测失准。
(2)降维防止“过拟合”
小样本的核心矛盾是“特征数 vs 样本数”:特征数越多,模型越容易“记住训练数据的细节”(过拟合),无法泛化到测试集。
- 原始特征30+:样本数38,特征数接近样本数,过拟合风险高;
- 筛选后15个:特征数是样本数的40%,符合“小样本特征数不宜超过样本数1/2”的经验法则,过拟合风险大幅降低。
(3)提升模型解释性
筛选后的特征都是与销量强相关的核心因素(如渗透率0.951),模型的权重能直接反映“哪个因素更重要”——比如“渗透率权重0.3,充电桩数量权重0.2”,业务上能解释“市场渗透是销量增长的核心驱动”,比“30+特征的黑箱模型”更有价值。
六、特征归一化(MinMaxScaler):量纲的“平衡器”
1. 概念定义
特征归一化是将所有特征缩放到统一范围(项目中是[0,1]) ,消除量纲差异对模型的影响。
项目用“MinMaxScaler”,公式为:
X_scaled = (X - X_min) / (X_max - X_min)
(X_min是训练集特征最小值,X_max是训练集特征最大值)
2. 项目技术细节
(1)方法选择:MinMaxScaler优于StandardScaler(小样本场景)
项目对比两种归一化方法:
归一化方法 | LSTM收敛速度 | 模型MAPE(测试集) | 对小样本的适应性 | 对异常值敏感度 |
---|---|---|---|---|
MinMaxScaler | 快(50轮收敛) | 16.5% | 优(基于最值,稳定) | 中等 |
StandardScaler | 慢(80轮收敛) | 17.9% | 差(基于均值,不稳定) | 高 |
选择MinMaxScaler的核心原因:小样本下,StandardScaler的“均值/标准差”不稳定(如某特征的测试集均值与训练集差异大),导致归一化后数据分布扭曲;MinMaxScaler基于“最值”,不受小样本统计量波动的影响。 |
(2)测试集处理:用训练集最值截断
测试集(2022-2023年)的部分特征(如充电桩数量)会超出训练集(2019-2021年)的最值,项目用训练集最值截断:
# 测试集归一化时,超出[0,1]的部分截断为0或1
X_test_scaled = np.clip(X_test_scaled, 0, 1)
- 为什么不重新计算测试集最值?会导致“训练集/测试集分布不一致”,模型无法泛化;用训练集最值截断,能保证归一化逻辑统一。
(3)目标变量单独归一化
销量(目标变量)与特征的量纲差异极大(销量是“万辆”,渗透率是“百分比”),项目对销量单独用scaler_y
归一化:
scaler_y = MinMaxScaler()
y_scaled = scaler_y.fit_transform(y_orig.reshape(-1, 1))
- 若与特征共用一个scaler,销量的归一化结果会失真(如销量10万→0.1,渗透率15%→0.8),模型会误以为“渗透率比销量更重要”,权重分配失衡。
3. 为什么这样做?(核心逻辑)
(1)消除量纲差异,保证权重公平
原始特征的量纲差异大:
- 充电桩数量:100万(量纲大);
- 市场渗透率:15%(量纲小);
若不归一化,模型会默认“充电桩数量的影响比渗透率大”(因为数值范围大),但实际渗透率与销量的相关性(0.951)比充电桩(0.919)更高。归一化后,所有特征都在[0,1]范围内,模型能公平学习每个特征的真实重要性。
(2)加速LSTM的收敛
LSTM的激活函数是tanh(输出范围[-1,1]),对[0,1]的输入梯度更稳定——若输入是“100万的充电桩数量”,tanh会输出接近1的饱和值,梯度接近0(梯度消失),模型无法学习;归一化后输入在[0,1],tanh能输出有效梯度,50轮就能收敛(比未归一化快3倍)。
(3)适配小样本的“统计稳定性”
小样本下,特征的“均值/标准差”波动大(如某特征的训练集均值是10,测试集均值是20),StandardScaler会因统计量不稳定导致归一化失效;MinMaxScaler基于“最值”,训练集的最值在小样本下更稳定(如充电桩数量的最大值不会突然从100万变成200万),归一化结果更可靠。
总结:小样本时序特征工程的“核心逻辑链”
该项目的特征工程不是“随机操作”,而是围绕“小样本(41条)+时序(时间依赖/趋势/周期)+模型需求(LSTM/Prophet/集成) ”的完整逻辑链:
- 补全时序信息:用滞后窗口(历史依赖)、差分(平稳化)、季节编码(周期),解决时序数据的三大核心特性;
- 最大化信息密度:用滚动统计(局部趋势)、特征筛选(去噪),在小样本下榨干数据价值,避免过拟合;
- 适配模型输入:用归一化(平衡权重)、3D窗口(LSTM输入)、独热编码(Prophet季节),让每个特征都能被模型高效利用。
最终,这些特征工程步骤共同支撑起“16.5%的集成模型MAPE”,远优于单一模型(LSTM 21.7%、Prophet 52.5%),证明了“小样本下,好的特征工程比复杂模型更重要”。