ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于CNN-LSTM混合网络的小时级天气预测实战

基于CNN-LSTM混合网络的小时级天气预测实战 简介一套针对小时级精细化天气预测的Python源码基于CNN-LSTM混合网络实现功能完善、注释清晰面向课程设计、期末大作业及毕业设计场景新手也能快速上手。项目融合CNN特征提取与LSTM时序建模能力共包含26个文件压缩包仅1.82MB其中8个Python源文件覆盖模型构建、训练、对比与数据展示另有CSV气象数据集、多张loss曲线、预测效果图和使用手册文档等。整体目录结构清晰部署后即可运行适合快速验证。资源同时提供RNN、LSTM、GRU、Bi-LSTM等模型实现通过可视化对比图直观展示各模型在小时级天气预测上的性能差异方便用于实验分析、论文写作和模型调优。压缩包内的使用手册文档还能帮助快速理解代码结构便于二次开发与答辩展示已有163人学习/下载具有较高实用价值。1. 小时级天气预测为什么值得用CNN-LSTM混合网络天气预报App只给到24小时级粒度时做光伏功率预测、教学楼能耗调度这类任务的工程师会明显感觉到数据不够用——你真正需要的是下个小时的温度、气压和湿度趋势。把时间序列预测换到小时粒度后单靠LSTM或RNN容易出现相位滞后预测曲线比真实曲线慢一两个时间步峰值总是被削平。这个基于CNN-LSTM混合网络的工程实践项目正好把卷积特征提取和循环时序建模拼在一起配合RNN、LSTM、GRU、BiLSTM四个消融对照组完整呈现出这个问题的解决路径。源码包里包含8个Python文件、Houston.csv逐小时气象数据、一组loss和预测对比图以及一本docx格式手册覆盖了从数据构造到模型对比的全流程适合作为期末大作业或Python课程设计代码新手也能按注释跑通。2. 数据预处理与小时级序列样本构造拿到源码包先别急着训练。整个项目的数据基础是Houston.csv里面是按小时采样的气象记录包含温度、湿度、气压等连续特征。小时级预测的第一步是把原始的时间顺序数据转换成监督学习的X/y样本对用过去若干个时刻的特征去预测下一个时刻的目标值。2.1 从Houston.csv到监督学习样本滑动窗口的构造逻辑在util.py里create_dataset函数承担了窗口切分的功能。我一般会直接把这段代码抽出来单独测试因为它决定了LSTM能看到多长的历史依赖。import numpy as np import pandas as pd def create_dataset(data, lookback24, pred_step1): 把多变量时间序列切成监督学习样本 data: DataFrame列为特征 lookback: 用过去多少个小时作为输入窗口 pred_step: 预测未来多少个时刻小时级任务一般取 1 X, y [], [] for i in range(len(data) - lookback - pred_step 1): # 取 [i, ilookback) 这一段作为输入 X.append(data.iloc[i:i lookback].values) # 取 ilookback 时刻的目标值作为标签 y.append(data.iloc[i lookback pred_step - 1].values) return np.array(X), np.array(y)这段代码的核心参数有两个。lookback24表示用过去24小时的数据预测下一小时这个值直接决定模型能捕获多长的日周期模式pred_step1对应单步预测如果想做多步递推预测把它调大即可——但注意多步预测的误差会逐小时累积。处理完窗口切分后还有一个容易踩坑的点时间序列不能像图像分类那样随机打乱。源码里通常的做法是先按8:1:1切出训练集、验证集和测试集再各自做窗口化。如果先打乱再切分等于把未来的信息泄漏给训练集验证曲线会异常好看但部署到真实预测时效果垮掉。切分的具体逻辑在util.py里有体现新手在这里最容易出错。2.2 data_show.py用可视化确认数据质量与周期特性训练之前先用data_show.py探一遍数据是值得养成的习惯。这个脚本的做法很直接把温度、气压、湿度逐列画成时间序列折线图看是否有明显的日周期、是否有停采数据段。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(Houston.csv, parse_dates[datetime]) df.set_index(datetime, inplaceTrue) # 检查缺失值和基本统计量 print(df.isnull().sum()) print(df.describe()) # 抽取连续7天的温度曲线观察小时级周期 df[temperature].iloc[:168].plot(figsize(12, 4), titleTemperature in 7 days) plt.tight_layout() plt.savefig(data_check.png, dpi150)缺失值处理上气象数据用前向填充比均值填充更合理因为气压和温度变化是连续的前向填充不会破坏短时趋势。运行这个脚本后正常情况下能看到温度曲线呈现明显的昼夜波动这就是小时级预测模型要学习的主要周期模式。如果看到长段直线或跳变说明CSV里有坏点需要先清洗再训练。窗口长度方面建议至少覆盖24小时让LSTM有足够的上下文感知日周期。如果数据量不够大lookback可以压缩到12但代价是夜间温度上升这类跨时段特征会丢失。3. CNN-LSTM混合网络模型设计与参数细节这个项目的核心文件是cnn_A_lstm.py它把一维卷积网络和LSTM串接起来。要理解这个混合网络的价值先得明确一个问题纯LSTM直接吃原始多变量序列时每个时刻的特征向量会原封不动地进入遗忘门和输入门计算当特征维度高且噪声大时模型的一部分容量被浪费在无关波动上。CNN在这里扮演的角色是先用卷积核对局部时间窗口做特征抽取把“每小时的原始读数”提炼成更高层的模式表达再交给LSTM做跨时刻的依赖建模。3.1 为什么用Conv1D而不是全连接层做特征提取一维卷积天然适合时间序列卷积核在时间维度上滑动每个输出位置都由相邻若干个时刻的局部片段加权求和得出。相比全连接层Conv1D有两个明显优势一是参数共享卷积核参数在所有时间步复用需要的参数量小得多二是局部平移不变性温度骤降这类模式不管出现在凌晨还是傍晚都能被同一个卷积核识别。在CNN-LSTM混合网络里输入张量的shape是(batch_size, lookback, feature_dim)。Conv1D沿着时间维度卷积输出的(batch_size, conv_steps, filters)序列再送入LSTM。这样LSTM接收到的就不是原始读数而是经过卷积抽象后的特征序列。3.2 cnn_A_lstm.py核心结构拆解import tensorflow as tf from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense, Dropout from tensorflow.keras.models import Sequential def build_cnn_lstm(input_shape, filters64, kernel_size3, lstm_units32): input_shape: (lookback, feature_dim) filters: 卷积核数量决定特征提取的宽度 kernel_size: 卷积窗口大小控制每个特征覆盖的时间跨度 lstm_units: LSTM隐层维度 model Sequential([ # 第一层卷积沿时间轴提取局部模式 Conv1D(filtersfilters, kernel_sizekernel_size, activationrelu, paddingsame, input_shapeinput_shape), # 池化层降采样压缩序列长度减少LSTM计算负担 MaxPooling1D(pool_size2), # 第二层卷积继续抽象filters加倍以补偿池化损失的信息量 Conv1D(filtersfilters * 2, kernel_sizekernel_size, activationrelu, paddingsame), # LSTM对卷积后的特征序列建模时间依赖 LSTM(unitslstm_units, return_sequencesFalse), Dropout(0.2), # 输出层预测目标特征数量 Dense(1, activationlinear) ]) model.compile(optimizeradam, lossmse, metrics[mae]) return model关键参数参考参数默认值调整方向filters64数据量大可加到128小数据集用32防止过拟合kernel_size3调大到5会覆盖更长时间跨度但可能模糊短时突变lstm_units32序列规律复杂时可加至64注意训练时间翻倍pool_size2对小时级数据2是安全选择过大会丢细节Dropout0.2过拟合明显时提升到0.3需要同时增加epoch训练时模型的输入形状会自动匹配input_shapeDense(1)代表预测一个目标变量。如果做多变量预测输出层维度改为目标特征数量即可。注意paddingsame保证了卷积前后序列长度不变这很重要否则LSTM接收到的时间步数量会逐步缩减。3.3 训练配置与收敛判断Hourly预测任务的训练回合不用太大因为气象数据本身模式比较规整。源码里常见配置是epochs30、batch_size32、validation_split0.1小数据集上几分钟就能跑完一轮。loss曲线看两个点训练loss持续下降且验证loss没有在后期掉头向上说明模型在正常拟合验证loss先降后升说明过拟合此时应该增大Dropout或提前终止。训练完成后cnn_lstm_loss.jpg和cnn_A_lstm_loss.jpg这两张图就是用来对比不同配置下模型收敛速度的。理想情况下CNN-LSTM的训练loss下降速度比纯LSTM平稳因为卷积层提前做了一层“降噪”LSTM部分需要拟合的复杂度降低了。4. 消融对比实验RNN、LSTM、GRU、BiLSTM与CNN-LSTM的差距只看模型结构不看对比很难说明CNN-LSTM混合网络到底好在哪。这个源码包里同时给出了rnn.py、lstm.py、gru.py、Bi_lstm.py和cnn_lstm.py五个模型文件配图里也有rnn_loss.png、lstm_loss.png、gru_loss.jpg、bi_lstm对应图以及各自的真实值vs预测值对比图。这就是一组完整的消融实验设计用来验证“卷积前置处理是否真的带来了收益”。4.1 五个模型文件的分工与结构差异文件网络结构特点适用判断rnn.py单层SimpleRNN结构最简单训练最快基线对比验证循环网络是否有效lstm.py单层LSTM引入门控机制解决长期依赖判断门控是否带来增益gru.py单层GRU参数量比LSTM少约1/3训练更快的替代方案Bi_lstm.py双向LSTM同时看历史和未来信息适合离线预测不适合在线递推cnn_lstm.py / cnn_A_lstm.pyCNNLSTM卷积提取局部特征再进LSTM面对高维噪声特征时效果最好需要特别说明的是BiLSTM。双向结构会同时使用t时刻前后的信息做预测这在实验对比中效果往往不错但部署到真实的小时级滚动预测时未来数据并不可得实际使用价值有限。源码中包含它主要为了学术对比完整性。4.2 从loss图和预测对照图判断模型优劣训练完五个模型后源码里的评价方式是同时输出loss曲线和预测对照图。对照图的x轴是小时序号y轴是归一化后的温度或气压值真实曲线和预测曲线会叠在同一张图上。import numpy as np from sklearn.metrics import mean_squared_error, mean_absolute_error def evaluate_model(model, X_test, y_test, scaler_y): 反归一化并计算误差指标 model: 训练好的模型 X_test/y_test: 测试集窗口样本 scaler_y: 目标变量的MinMaxScaler实例 pred model.predict(X_test) # 反归一化回到原始量纲 pred_inv scaler_y.inverse_transform(pred) y_inv scaler_y.inverse_transform(y_test) rmse np.sqrt(mean_squared_error(y_inv, pred_inv)) mae mean_absolute_error(y_inv, pred_inv) return rmse, mae对于小时级天气预测RMSE的单位就是温度或气压的实际单位。温度预测RMSE在1到2摄氏度之间属于合理范围超过3度说明模型欠拟合或窗口长度设置不合适。MAE比RMSE更能反映平均偏差水平两者的差越大说明存在明显的离群误差——这种情况常见于极端天气突变时段卷积核的感受野不够大没有捕获到突变的前兆信号。解读对照图时重点看预测曲线是否滞后于真实曲线。如果预测曲线整体向右偏移一个时间步基本可以断定是滑动窗口过短或者序列本身的自相关性太强需要增大lookback。如果预测曲线几乎是一条平滑直线说明LSTM输出被压到了均值附近此时需要减少卷积的层数或调小pool_size。5. 验证技巧用相位滞后检测量化CNN-LSTM的预测质量最后分享一个很实用的验证技巧。光看loss曲线和预测叠图很难量化“滞后”程度到底是多少。小时级天气预测里最常见的问题不是预测错而是预测得“太晚”——曲线形状完全对但在时间轴上偏了一位。这时可以用相位滞后检测来诊断。def find_best_shift(y_true, y_pred, max_shift6): 检测预测序列相对真实序列的时间滞后量 返回最佳平移步数和对应MAE最佳平移为0说明无滞后 best_mae float(inf) best_shift 0 y_true np.array(y_true).flatten() y_pred np.array(y_pred).flatten() for shift in range(0, max_shift 1): if shift 0: mae np.mean(np.abs(y_true - y_pred)) else: aligned_pred y_pred[:-shift] aligned_true y_true[shift:] mae np.mean(np.abs(aligned_true - aligned_pred)) if mae best_mae: best_mae mae best_shift shift return best_shift, best_mae把测试集的预测结果喂进去如果最佳平移步数大于等于2说明模型系统性滞后了两个小时。这时调大lookback通常比增加LSTM单元更有效。如果最佳平移步数是0但整体MAE偏高问题就不在滞后而在卷积特征提取能力不足可以尝试增加一个卷积层或调大kernel_size。另一个与运维相关的细节源码包里的手册.1.docx建议把模型保存为HDF5格式部署时用keras.models.load_model直接加载。实测中我一般会多存一个scaler_y的副本反归一化必须匹配训练时的scaler实例否则预测结果会出现整体偏移。如果部署环境换了一台机器确保通过pip freeze requirements.txt导出依赖版本tensorflow与keras的版本不匹配是复现失败的第一大原因。这些验证手段做完CNN-LSTM混合网络在小时级天气预测场景下的优势、局限和调优方向就完全清楚了。直接打开code目录下的cnn_A_lstm.py开始跑或者从data_show.py一步一步看数据都是可行的路径。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进