【深度学习项目实战·30】PM2.5短期预测:用LSTM构造没有未来信息的滑动窗口

文章目录

01 本篇要解决什么问题

给定最近24小时的污染与气象观测,能否预测下一小时PM2.5?这和把一张图片分成某一类不同,样本的先后顺序本身就是任务条件。

本篇使用LSTM进行多变量单步预测,重点讲清时间划分、缺失值处理、滑动窗口、训练集标准化,以及与持续性基线的比较。

  • 本篇关键词:时间切分、因果填补、滑动窗口、滚动预测、持续性基线、MAE/RMSE。
  • 完成标志:仅用预测时刻之前的观测建立输入,在原始浓度单位下评价下一小时误差。
  • 任务边界:单站历史数据的逐小时滚动实验,不是一次预测未来全年,也不能代表全城所有位置。

02 背景:按目标时刻划分集合

UCI Beijing PM2.5包含2010---2014年43824条小时记录,来自北京美国使馆的PM2.5与首都机场气象数据,原始CSV约1.9 MB,缺失值记为NA。

本篇按目标小时划分:2010---2012训练、2013验证、2014测试。先保留完整小时时间轴,不因为缺失污染值就直接删掉整行。

验证的第一个目标可以使用上一年末的历史观测,测试也可使用2013年末历史。它们在预测时已经发生,作为上下文是合理的;但不能把目标小时或之后的观测放入输入。

03 实操:先把窗口与缺失处理做对

(1)下载并核对连续时间轴

powershell 复制代码
python examples/download_data.py --dataset pm

文件保存为data/pm/pm25.csv。读取后按年、月、日、小时排序,检查时间戳唯一且逐小时连续;如果缺一整小时,应先明确补时规则,而不能把相隔两小时当成相邻一步。

(2)缺失输入只向过去寻找数值

对历史数值特征使用前向填补,尚无历史观测时固定用0,同时附加缺失标记。没有使用会读取未来点的双向插值或backfill。

python 复制代码
import numpy as np

def causal_fill(values):
    values=np.asarray(values,dtype=np.float64)
    missing=~np.isfinite(values);out=values.copy();last=np.zeros(values.shape[1],dtype=np.float64)
    for i,row in enumerate(values):
        valid=np.isfinite(row);last[valid]=row[valid];out[i]=last
    return out,missing.astype(np.float32)

填补用于模型输入,真实目标仍以原始PM2.5为准:目标缺失时不训练、不评价该目标。这样不会把我们自己填出的标签当成真值。

保留时间轴也很关键。如果先dropna(),所谓24步输入可能跨过远超过24小时的实际时间,模型任务就悄悄变了。

(3)历史窗口和目标只差一个明确索引

默认lookback=24,对目标行t:

python 复制代码
history = features[t - lookback:t]  # 含t-1,不含t
target = original_pm[t]             # 下一小时真实观测

输入为[24,22]:7个历史数值量、对应7个缺失标记、4个风向one-hot,以及小时/月周期的sin/cos各两项。没有加入目标小时的真实气象观测。

历史数值包含PM2.5、露点、温度、气压、累计风速、累计降雪与降雨记录;固定风向类别为NE、NW、SE、cv。特征顺序写入检查点,推理不靠CSV列顺序猜测。

(4)标准化器只拟合选中的训练数据

输入均值/标准差从实际训练窗口涉及的唯一历史行计算,目标均值/标准差从实际训练目标计算。常量特征的标准差按1处理,避免除零。

验证与测试只应用这些参数。不能对五年数据整体标准化后再切分,那会把未来分布信息带进预处理。

小规模limit按每个时间段最早的有效目标小时截取,并不是全年随机抽样。这便于快速检查,但不能把几天的结果当成全年误差。

(5)用固定长度窗口训练LSTM

python 复制代码
from torch import nn

class ForecastLSTM(nn.Module):
    def __init__(self,features=22,hidden=32):
        super().__init__();self.lstm=nn.LSTM(features,hidden,batch_first=True);self.head=nn.Linear(hidden,1)

    def forward(self,x):
        _,(hidden,_)=self.lstm(x)
        return self.head(hidden[-1])

布局为[N,24,22],LSTM默认hidden=32,最终隐藏状态经线性层输出[N,1]。所有输入都是同长度历史窗口,因此无需沿用第27篇的变长打包。

训练使用标准化目标MSE,按验证同一损失最低保存权重。划好时间集合后,训练batch可以打乱顺序;问题是不能在原始时间行上随意打乱后再构造历史窗口。

(6)原始单位指标与持续性基线

输出反标准化后,MAE、RMSE按µg/m³报告,R²为无量纲指标。不能拿标准化空间里的误差数值冒充实际浓度误差。

持续性基线直接使用最近一个历史时刻的因果填补PM2.5作为预测。小时级数据往往具有较强连续性,神经网络应该和这个简单方法比较,而不是只证明loss能够下降。

本篇不裁剪负预测,原始数值如实进入评价。R²为负表示比测试真值均值这个参考更差;常量目标或样本不足时R²记null。

图:原创示意。预测t时只使用t之前的信息,填补不能反向读取未来。

04 一个具体例子:从最近24小时预测下一小时

小规模流程检查:

powershell 复制代码
python examples/train_pm.py --epochs 2 --hidden 8 --limit-train 128 --limit-val 32 --limit-test 32 --batch-size 16
python examples/visualize_run.py --run artifacts/30_pm

完整时间段的训练起点:

powershell 复制代码
python examples/train_pm.py --epochs 20 --output artifacts/30_pm_full

入口如下,因果特征、窗口选择与训练代码见公共附录。

python 复制代码
"""Chapter30: next-hour PM prediction from historical observations only."""
from project_train import parser_for,train_project

if __name__=='__main__':train_project('pm',parser_for('pm','artifacts/30_pm').parse_args())

准备包含同样字段的连续历史CSV,至少24小时:

powershell 复制代码
python examples/predict.py --checkpoint artifacts/30_pm/best.pt --input data/my_history.csv --output artifacts/30_predict

脚本以最后一个观测小时之后一小时为预测时刻。可以提供更长的已发生历史,帮助窗口起点之前的前向填补;不需要提供未来目标小时的真实天气或PM2.5。

测试采用滚动单步方式:时间推进后,新的已观测污染值可以进入后续窗口。这与从年初一次性生成全年轨迹是两种任务,结果不应混称为长期预测能力。

05 常见问题与自测

问题1:为什么不能随机划分全部小时行?

可能把未来数据分布和高度重叠的窗口混进训练与测试,应按预测时刻先后建立集合。

问题2:输入缺失可以用后一个小时补吗?

本篇不可以,那是预测时尚未发生的信息,采用过去方向填补。

问题3:目标缺失时也能填补后评价吗?

不能把自填标签当成真值。本工程跳过缺失目标,但保留其所在时间行作为历史轴。

问题4:验证窗口使用上一年末数据算泄漏吗?

过去已观测的上下文可以使用,关键是目标及未来观测不进入输入,标准化参数仍来自训练。

问题5:LSTM没有超过上一小时基线,结果要删掉吗?

应该保留并分析。它可能揭示训练不足、时间差异或模型尚未带来增益。

06 本篇回顾与下一步

时序预测首先是信息可用性的约定。时间切分、因果填补和窗口索引正确之后,再讨论模型容量与训练轮次才有意义。

中文 常见英文或写法
历史窗口 Lookback Window
前向填补 Forward Fill
持续性基线 Persistence Baseline
滚动单步预测 Rolling One-step Forecast

下一篇进入多通道传感器,把一段固定长度人体运动窗口分类为活动类别。

相关推荐
汤姆宝库17 分钟前
LoRA的低秩数学与QLoRA实现
人工智能·深度学习·机器学习
学编程就要猛8 小时前
RAG(Retrieval Augmented Generation)
人工智能·spring ai
冬奇Lab9 小时前
一天一个开源项目(第259篇):Modern Web Guidance —— Chrome 团队给 AI 编码 Agent 的「现代 Web 最佳实践」外挂
人工智能·开源
飞哥数智坊10 小时前
打造自己的 Personal Agent,从抄大肥鱼作业开始
人工智能·deepseek
对你无可奈何11 小时前
Magpie 实战:把 WorkBuddy、Qoder 的订阅模型接进一个本地池子
人工智能
Csvn11 小时前
每请求到底多少钱?把 Token 成本算成可观测指标(C01)
人工智能·aigc·agent
吴名氏.11 小时前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
老金带你玩AI12 小时前
惊人的一致性!Seedream 5.5实测!
人工智能