ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LSTM时间序列预测实战:空气污染数据源码全流程解析

LSTM时间序列预测实战:空气污染数据源码全流程解析 简介这份资源面向计算机、人工智能相关专业学生及需要完成时间序列预测任务的开发者提供一套基于LSTM的完整项目源码与配套数据可直接用于课程设计或期末大作业。压缩包共129个文件约5.42MB其中78个py文件承载模型搭建、训练与预测逻辑26个csv文件提供空气质量等时间序列原始数据另有txt说明、checkpoint权重、h5模型及TensorFlow数据分片等便于复现与二次训练。代码含详细注释新手也能看懂部署简单下载后即可运行。项目围绕LSTM时间序列数据预测展开涵盖数据预处理、模型构建、训练评估与结果可视化等环节功能完善、结构清晰具有较高的实际应用参考价值。目前已有169人学习下载适合作为期末大作业、课程设计的高分参考也能帮助读者快速掌握LSTM预测流程与排错思路。1. 从一份空气污染数据说起这套 LSTM 时间序列预测源码到底能跑出什么很多同学做时间序列预测的期末大作业卡点从来不是 LSTM 本身而是数据从哪来、格式怎么对齐、预测结果怎么画出来。这份资源给的是一个完整闭环一份空气污染的多变量时间序列 CSV加上一套基于 LSTM 的 Python 预测源码从数据读取、归一化、滑窗切分、模型搭建、训练到预测可视化全流程都能跑通。它适合两类人一类是刚接触 Python 和深度学习、需要一份能直接部署交作业的课程设计另一类是想快速验证 LSTM 在自己数据上效果的从业者拿它当模板改数据源就行。资源里带了代码注释和全部数据文件不用自己再去爬数据、补缺失值省掉最耗时的数据准备环节。2. 数据与目录先摸清pollution.csv 到 air_pollution_new.csv 的对应关系拿到压缩包别急着跑代码先把数据文件和脚本的对应关系理清楚。这份资源里出现了多个 CSV 文件名包括pollution.csv、air_pollution.csv、air_pollution_new.csv还有checkpoint目录。它们不是随便堆的而是对应了数据处理的不同阶段。搞混了文件名后面训练报错都找不到原因。2.1 原始数据与清洗后数据的区分pollution.csv通常是原始空气污染数据字段一般包含 PM2.5、PM10、SO2、NO2、CO、O3 等污染物浓度外加时间戳、风向、风速等气象列。原始数据常见的问题是缺失值用NA表示、时间列不是标准 datetime、部分列全是空值。air_pollution.csv和air_pollution_new.csv一般是清洗后的版本前者可能做了缺失值填充和列筛选后者可能进一步做了重采样或特征工程。我一般会先跑一段探查代码把每个 CSV 的形状、列名、缺失情况打出来确认哪个文件才是训练入口。import pandas as pd for f in [pollution.csv, air_pollution.csv, air_pollution_new.csv]: df pd.read_csv(f) print(f, df.shape) print(df.columns.tolist()) print(df.isnull().sum().sum(), missing values) print(---)这段代码的作用是快速对比三个文件的维度差异。shape告诉你行数和列数columns.tolist()让你看清字段名是否一致isnull().sum().sum()统计总缺失数。如果某个文件缺失值特别多说明它还是原始状态如果缺失为 0 且列数变少说明已经清洗过。参数上不需要额外配置直接改文件名列表即可。2.2 checkpoint 目录的作用checkpoint目录一般存放训练过程中的模型权重文件常见格式是.h5、.pth或.ckpt。它的价值在于训练中断后可以接着跑不用从头再来也可以直接加载已训练好的权重做预测跳过训练阶段。如果你只是想把预测结果跑出来交作业优先看 checkpoint 里有没有现成权重有的话直接加载能省几十分钟甚至几小时的训练时间。提示加载 checkpoint 前先确认它对应的模型结构和当前代码里的网络层是否一致层数或隐藏单元数对不上会直接报维度错误。2.3 环境依赖与版本确认这份源码基于 Python核心依赖一般是numpy、pandas、matplotlib、scikit-learn深度学习框架可能是tensorflow/keras或pytorch。先看代码顶部的 import 语句再决定装哪个框架。常见做法是建一个虚拟环境避免和系统里已有版本冲突。python -m venv lstm_env source lstm_env/bin/activate # Windows 用 lstm_env\Scripts\activate pip install numpy pandas matplotlib scikit-learn pip install tensorflow # 如果代码用的是 keras # 或者 pip install torch # 如果代码用的是 pytorch虚拟环境的作用是隔离依赖source那行在 Linux/Mac 下激活Windows 用括号里的路径。框架二选一看源码 import 的是tensorflow.keras还是torch。装完后跑一次python -c import tensorflow或import torch确认没报错再往下走。3. 把 LSTM 时间序列预测跑通滑窗、归一化与模型搭建数据摸清之后核心工作就是把时间序列切成 LSTM 能吃的监督学习格式然后搭网络、训练、预测。这一步是整份源码的技术重心也是新手最容易翻车的地方。下面按数据预处理、滑窗构造、模型定义、训练与预测四块拆开讲。3.1 缺失值处理与归一化空气污染数据几乎不可能没有缺失值。常见做法是先做时间索引对齐再用前向填充或插值补缺失。归一化用 MinMaxScaler 把数值压到 0 到 1 之间这一步对 LSTM 收敛速度影响很大不做归一化经常出现 loss 不下降的情况。import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler df pd.read_csv(air_pollution_new.csv) df[datetime] pd.to_datetime(df[datetime]) df df.set_index(datetime).sort_index() # 前向填充 后向填充兜底 df df.fillna(methodffill).fillna(methodbfill) values df.values scaler MinMaxScaler(feature_range(0, 1)) scaled scaler.fit_transform(values) print(scaled.shape)pd.to_datetime把时间列转成标准格式set_index加sort_index保证时间顺序不乱。ffill是前向填充用上一个有效值补当前空值bfill是后向填充防止开头就是空值。MinMaxScaler的feature_range默认就是 (0,1)fit_transform同时完成拟合和转换。注意 scaler 要保存下来预测完做反归一化时还要用。3.2 滑窗构造监督学习样本LSTM 需要的是「用前 N 个时间步预测下一个时间步」这样的样本对。滑窗函数就是把一维或多维序列切成(样本数, 时间步长, 特征数)的三维张量。def create_dataset(data, look_back24): X, y [], [] for i in range(len(data) - look_back): X.append(data[i:i look_back, :]) y.append(data[i look_back, 0]) # 假设第0列是预测目标 return np.array(X), np.array(y) look_back 24 X, y create_dataset(scaled, look_back) print(X.shape, y.shape)look_back24表示用过去 24 个时间步预测下一步如果数据是逐小时的就是拿过去一天预测下一小时。data[i:ilook_back, :]取一个窗口的所有特征y只取目标列这里假设第 0 列是 PM2.5 之类的预测目标。返回的X形状是(样本数, 24, 特征数)正好是 LSTM 输入要求的三维格式。look_back这个参数可以调太小捕捉不到周期规律太大训练慢且容易过拟合一般从 12 到 48 之间试。3.3 LSTM 网络结构定义模型部分通常是一到两层 LSTM 加一个全连接输出层。Keras 写法最简洁PyTorch 写法更灵活看源码用的是哪个。from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout model Sequential() model.add(LSTM(64, return_sequencesTrue, input_shape(look_back, X.shape[2]))) model.add(Dropout(0.2)) model.add(LSTM(32)) model.add(Dropout(0.2)) model.add(Dense(1)) model.compile(lossmse, optimizeradam) model.summary()第一层LSTM(64)有 64 个隐藏单元return_sequencesTrue表示输出整个序列供下一层 LSTM 继续处理。input_shape是(时间步长, 特征数)必须和滑窗输出对上。Dropout(0.2)随机丢弃 20% 神经元抑制过拟合。第二层LSTM(32)不加return_sequences默认只输出最后一个时间步。Dense(1)输出单个预测值。compile用mse做损失、adam做优化器这是时间序列回归的常规组合。3.4 训练、预测与反归一化训练时用fit指定轮数和 batch size预测后用 scaler 反归一化回原始量纲再画图对比。model.fit(X, y, epochs50, batch_size32, validation_split0.1, verbose1) pred model.predict(X) # 反归一化把预测值放回原始尺度 pred_inv scaler.inverse_transform( np.concatenate([pred, np.zeros((len(pred), scaled.shape[1] - 1))], axis1) )[:, 0] y_inv scaler.inverse_transform( np.concatenate([y.reshape(-1, 1), np.zeros((len(y), scaled.shape[1] - 1))], axis1) )[:, 0]epochs50是训练轮数batch_size32是每批样本数validation_split0.1留 10% 做验证。反归一化这里有个细节inverse_transform要求列数和当初fit_transform一致所以先用np.concatenate补零凑齐列数再取第 0 列。这是很多人第一次做反归一化时踩的坑直接传一维数组会报维度错误。4. 避坑与排查LSTM 时间序列预测最常见的五个翻车点这套源码能跑通不代表你改完还能跑通。下面五个问题是我在类似项目里反复遇到的按「现象 → 原因 → 解决」列出来对照排查能省不少时间。4.1 损失不下降或变成 nan现象训练几个 epoch 后 loss 一直是常数或者直接变成 nan。原因通常是学习率太大、数据没归一化、或者序列里有极端异常值。解决先确认归一化做了没有再把adam的默认学习率 0.001 调小到 0.0001 试试同时检查数据里有没有超大值用df.describe()看最大值是否离谱。4.2 预测结果是一条直线现象画出来的预测曲线几乎水平完全不跟随真实波动。原因多半是模型只学到了均值常见于look_back太小、训练轮数不够、或者目标列本身波动被归一化压平。解决把look_back从 24 加到 48 或 72增加 LSTM 隐藏单元数检查归一化前目标列的方差是否过小。4.3 维度不匹配报错现象ValueError: Input 0 is incompatible with layer lstm。原因一般是input_shape里的时间步长和实际X.shape[1]不一致或者特征数列数对不上。解决在model.add之前打印X.shape确保input_shape(X.shape[1], X.shape[2])不要手写死数字。4.4 反归一化后数值离谱现象预测值反归一化后变成几万甚至负数和真实值差几个量级。原因是用错了 scaler或者反归一化时列顺序和目标列不一致。解决确认训练和预测用的是同一个 scaler 对象反归一化时目标列的位置要和当初fit_transform时一致别把第 0 列和第 3 列搞混。4.5 checkpoint 加载失败现象load_model报未知层或维度错误。原因是保存模型时的代码版本和当前版本不一致或者自定义层没注册。解决优先用源码自带的 checkpoint别混用其他项目的权重如果必须加载确认 Keras 版本一致自定义层要用custom_objects参数传进去。5. 从能跑到好用多步预测与结果可视化的进阶技巧把单步预测跑通只是及格线真正让这份作业出彩的是多步预测和像样的可视化。多步预测有两种常见做法递归预测和直接多输出。递归预测是用预测出的下一步当作输入继续预测下下步实现简单但误差会累积直接多输出是把Dense(1)改成Dense(n)一次输出未来 n 步训练难度大一些但误差不累积。# 递归多步预测示例 def recursive_forecast(model, last_window, steps, scaler): preds [] window last_window.copy() for _ in range(steps): p model.predict(window.reshape(1, look_back, -1), verbose0) preds.append(p[0, 0]) window np.append(window[1:], p.reshape(1, 1, -1), axis0) preds np.array(preds).reshape(-1, 1) preds_inv scaler.inverse_transform( np.concatenate([preds, np.zeros((len(preds), scaled.shape[1] - 1))], axis1) )[:, 0] return preds_invlast_window是最近一个滑窗的输入steps是预测未来多少步。每次预测完把新值拼到窗口末尾去掉最老的一个时间步保持窗口长度不变。verbose0关掉每次预测的输出不然循环里会刷屏。这个函数返回的是反归一化后的真实量纲预测值可以直接和真实未来值画在一起对比。可视化部分我一般会把训练集真实值、测试集真实值、预测值三条线画在同一张图上再单独画一张局部放大图看细节。matplotlib的plot加legend就够用重点是时间轴要对齐别把训练段和测试段的索引搞混。另外可以加一个误差指标表把 MAE、RMSE、MAPE 算出来放在图旁边答辩时比单纯一张曲线图有说服力。指标含义适用场景MAE平均绝对误差误差量纲和原数据一致直观RMSE均方根误差对大误差更敏感惩罚离群预测MAPE平均绝对百分比误差跨量纲比较但真实值接近 0 时会爆炸最后说个习惯每次改完look_back、隐藏单元数或学习率我都会把这次实验的配置和对应 RMSE 记在一个小本子上跑上十几组之后就能看出哪组参数最稳。LSTM 调参这事没有银弹靠的就是一次次对比。从那以后我每次交作业前都强制走一遍「归一化检查 → 维度打印 → 反归一化验证」这三步翻车次数少了一大半。希望帮到你。本文还有配套的精品资源点击获取
返回列表