资讯详情

Python机器学习天气预测实战:从数据到可视化完整源码

📅 2026/10/11 12:18:41 | 华诺云谱 👁 阅读
Python机器学习天气预测实战:从数据到可视化完整源码
简介这份资源是面向高校学生与Python初学者的一套机器学习天气预测与数据可视化完整项目源码可直接用于课程设计、期末大作业或毕业设计场景。项目以Python语言实现涵盖数据获取、数据清洗、模型训练与预测、可视化展示等完整流程并配有详细代码注释新手也能快速理解与部署。压缩包共24个文件约1.42MB包含4个py源码文件、4个csv数据集、1个pkl模型文件、1个html页面、1个md说明文档及12张jpg运行截图结构清晰便于按模块查阅。目前已有410人学习下载具备一定参考热度。读者可获得一套可直接运行的天气预测方案包括训练与测试数据、已训练模型、数据预处理脚本及可视化页面既能作为作业提交模板也能帮助理解机器学习项目从数据到模型再到展示的完整链路具有较高的实际应用与学习价值。1. 从一份「满分项目」源码说起机器学习天气预测到底在做什么很多人搜「基于Python的机器学习天气预测与数据可视化完整源码」心里想的其实是两件事一是能不能直接跑起来看到效果二是这套东西到底能不能用来做真实预测。我先把结论摆在这这类项目本质是一个监督学习回归任务——用历史气象观测数据温度、湿度、气压、风速、风向等作为特征去拟合未来某个时刻的气温或天气状态再用可视化把预测结果和真实值摆在一起对比。它解决的不是「明天会不会下雨」这种精确到分钟的预报而是让你完整走一遍「数据获取 → 特征工程 → 模型训练 → 评估 → 可视化」的机器学习应用流程。适合谁适合刚学完机器学习西瓜书、想找一个能写进简历或课程设计的完整案例的人也适合想用 Python 把气象数据玩起来的开发者。下面我按自己搭这套流程的顺序把每个环节拆开讲。2. 数据从哪来、怎么选气象数据源与特征工程2.1 常见气象数据源与字段含义做天气预测第一步不是写模型而是搞清楚数据长什么样。公开气象数据通常来自气象站逐小时或逐日观测记录常见字段包括气温temp、体感温度、湿度humidity、气压pressure、风速wind_speed、风向wind_deg、云量clouds、降水量rain。如果是做单站点的气温预测一般用历史逐小时数据把过去 N 小时的观测作为输入特征预测未来 1 小时或未来 24 小时的气温。我一般会先确认三件事时间粒度是小时还是天、缺失值比例有多少、目标变量是连续值还是分类标签。如果是预测「晴/雨/阴」这种离散状态那就是分类任务如果是预测具体温度数值就是回归任务。这两条路后面的模型选型和评估指标完全不同别混着做。2.2 用 pandas 做时间序列特征构造原始数据往往只有一列时间戳和一列气温直接丢给模型效果很差。需要手动构造滞后特征lag features和滑动窗口统计量。下面这段代码是我常用的特征构造模板import pandas as pd import numpy as np # 假设 df 有 datetime 和 temp 两列已按时间排序 df pd.read_csv(weather_history.csv, parse_dates[datetime]) df df.sort_values(datetime).reset_index(dropTrue) # 构造滞后特征过去1、2、3、6、12、24小时的气温 for lag in [1, 2, 3, 6, 12, 24]: df[ftemp_lag_{lag}] df[temp].shift(lag) # 滑动窗口统计过去6小时和24小时的均值、标准差 df[temp_roll_mean_6] df[temp].rolling(window6).mean() df[temp_roll_std_6] df[temp].rolling(window6).std() df[temp_roll_mean_24] df[temp].rolling(window24).mean() # 时间特征小时、月份帮助模型捕捉日周期和季节周期 df[hour] df[datetime].dt.hour df[month] df[datetime].dt.month # 丢弃因 shift/rolling 产生的空值 df df.dropna().reset_index(dropTrue) # 目标变量预测下一小时气温 df[target] df[temp].shift(-1) df df.dropna().reset_index(dropTrue)这段代码的逻辑是把「过去的信息」显式变成列让模型能直接看到历史规律。shift(lag)表示把数据向下移动 lag 行这样当前行就能拿到 lag 小时前的值。rolling(window6).mean()计算过去 6 行的均值用来平滑短期波动。hour和month是周期特征因为气温有明显的日变化和季节变化。参数上滞后阶数不是越多越好一般选 1、2、3、6、12、24 这几个能覆盖短、中、长周期的点窗口大小根据数据粒度调整小时数据用 6 和 24日数据用 7 和 30。提示如果数据里有明显缺失段不要直接dropna把整段删掉先用插值补上再构造特征否则会丢掉大量样本。2.3 训练集/测试集怎么切才不泄露未来信息时间序列不能随机打乱切分否则模型会「偷看」未来数据评估结果虚高。正确做法是按时间顺序切前 80% 做训练后 20% 做测试。如果要做交叉验证用TimeSeriesSplit不要用普通的 KFold。这一点是很多课程设计翻车的地方——随机切分后 R² 能到 0.99一上线就废。3. 模型选型与训练从线性回归到梯度提升3.1 为什么我优先用树模型而不是 LSTM标题里写的是「机器学习天气预测」没有限定必须用深度学习。实际做下来对于中小规模结构化气象数据梯度提升树如 XGBoost、LightGBM在精度和训练速度上都比 LSTM 更稳。原因有三第一树模型对特征尺度不敏感不需要额外做归一化第二训练快调参成本低第三可解释性好能输出特征重要性方便你写报告。LSTM 适合数据量很大、且你愿意花时间调网络结构和超参的场景否则很容易欠拟合或过拟合。我一般会先跑一个线性回归作为基线再上 LightGBM对比 RMSE 和 MAE。如果树模型比线性回归提升不到 10%说明特征工程没做到位回去补滞后和周期特征。3.2 用 LightGBM 训练气温预测模型import lightgbm as lgb from sklearn.metrics import mean_squared_error, mean_absolute_error from sklearn.linear_model import LinearRegression import numpy as np # 特征列排除 datetime 和 target feature_cols [c for c in df.columns if c not in [datetime, target]] X df[feature_cols] y df[target] # 按时间顺序切分 split_idx int(len(df) * 0.8) X_train, X_test X.iloc[:split_idx], X.iloc[split_idx:] y_train, y_test y.iloc[:split_idx], y.iloc[split_idx:] # 基线线性回归 lr LinearRegression() lr.fit(X_train, y_train) lr_pred lr.predict(X_test) print(Linear RMSE:, np.sqrt(mean_squared_error(y_test, lr_pred))) # LightGBM model lgb.LGBMRegressor( n_estimators500, learning_rate0.05, max_depth6, num_leaves31, subsample0.8, colsample_bytree0.8, random_state42 ) model.fit(X_train, y_train, eval_set[(X_test, y_test)], eval_metricrmse, callbacks[lgb.early_stopping(50)]) pred model.predict(X_test) print(LGBM RMSE:, np.sqrt(mean_squared_error(y_test, pred))) print(LGBM MAE:, mean_absolute_error(y_test, pred))参数说明n_estimators500是树的数量配合early_stopping(50)表示如果验证集 50 轮没提升就提前停防止过拟合。learning_rate0.05是学习率越小越稳但需要更多树。max_depth6和num_leaves31控制单棵树复杂度气象数据特征维度不高不需要太深。subsample和colsample_bytree是行采样和列采样比例增加随机性提升泛化。跑完记得看特征重要性如果temp_lag_1和temp_lag_2占绝对主导说明短期自相关很强模型逻辑是对的。3.3 评估指标怎么读才不被误导RMSE 和 MAE 的单位和气温一样比如 RMSE1.8 表示平均预测偏差约 1.8 摄氏度。但要注意如果测试集包含极端天气寒潮、热浪RMSE 会被拉高这时候要看 MAE 和分位数误差。另外R² 在时间序列里容易虚高因为相邻时刻气温高度相关不要只拿 R² 说事。我一般会画预测值和真实值的时间序列对比图肉眼看一下相位有没有滞后——如果预测曲线总是比真实曲线慢一拍说明滞后特征窗口没设对。4. 数据可视化把预测结果讲成一张能看懂的图4.1 用 Matplotlib 画预测对比曲线可视化不是装饰是验证模型有没有学到东西的手段。最核心的一张图是「真实值 vs 预测值」随时间变化的曲线import matplotlib.pyplot as plt import matplotlib.dates as mdates plt.figure(figsize(14, 5)) plt.plot(df[datetime].iloc[split_idx:], y_test.values, labelActual, color#2c7fb8, linewidth1.2) plt.plot(df[datetime].iloc[split_idx:], pred, labelPredicted, color#e6550d, linewidth1.2, alpha0.8) plt.xlabel(Time) plt.ylabel(Temperature) plt.title(Temperature Prediction: Actual vs Predicted) plt.legend() plt.gca().xaxis.set_major_formatter(mdates.DateFormatter(%m-%d %H)) plt.gca().xaxis.set_major_locator(mdates.HourLocator(interval24)) plt.xticks(rotation45) plt.tight_layout() plt.savefig(prediction_vs_actual.png, dpi150) plt.show()这段代码的关键在mdates.HourLocator(interval24)它控制横坐标每 24 小时显示一个刻度。很多人搜「python画图横坐标太密集」就是因为没设 locator几百个时间点全挤在一起。dpi150保证保存的图清晰度够用。如果曲线整体贴合但峰值处偏低说明模型对极端值欠拟合可以尝试加temp_roll_max和temp_roll_min特征。4.2 特征重要性与误差分布图除了对比曲线我还会画两张辅助图一张是 LightGBM 的特征重要性条形图用来确认模型有没有依赖合理的特征另一张是预测误差的直方图看误差是不是近似正态分布。如果误差分布严重偏斜说明模型在某些区间系统性偏高或偏低需要分段建模或加特征。# 特征重要性 lgb.plot_importance(model, max_num_features15, figsize(8, 6)) plt.title(Feature Importance) plt.tight_layout() plt.savefig(feature_importance.png, dpi150) # 误差分布 errors y_test.values - pred plt.figure(figsize(8, 4)) plt.hist(errors, bins50, color#31a354, edgecolorwhite) plt.xlabel(Prediction Error) plt.ylabel(Count) plt.title(Error Distribution) plt.tight_layout() plt.savefig(error_distribution.png, dpi150)如果要做 Web 端展示常见做法是用 Flask 把预测结果以 JSON 返回前端用 ECharts 渲染交互式折线图。这一步不是必须的但如果你想让项目看起来更完整加一个简单的 Flask 接口和 ECharts 页面会加分不少。5. 避坑与排查这套流程里最容易翻车的 5 个地方5.1 现象模型在测试集上 R² 接近 1实际预测完全不能用原因随机切分了时间序列导致训练集里混入了未来信息。模型记住了「未来」不是学会了规律。解决严格按时间顺序切分用TimeSeriesSplit做交叉验证。切分前先按datetime排序切分后不要 shuffle。5.2 现象预测曲线整体比真实曲线滞后一两个小时原因滞后特征窗口设置不合理或者目标变量对齐错了。比如用shift(-1)做目标时如果数据本身有缺失行对齐会错位。解决检查shift的方向和步数确认target确实是当前行之后的下一个时刻。可以手动打印几行对比temp和target验证。5.3 现象训练 loss 一直降验证 loss 很早就开始升原因树太深或树太多模型把训练集的噪声也学进去了。解决加early_stopping降低max_depth增大subsample和colsample_bytree的随机性。如果还不行减少滞后特征数量只保留最重要的几个。5.4 现象特征重要性里hour和month排在最前面气温滞后特征反而很低原因数据里可能有时间泄露比如hour和target之间存在某种固定映射关系或者数据本身是合成数据规律太简单。解决检查数据生成逻辑确认hour不是从目标变量反推出来的。如果是真实数据这种情况通常说明滞后特征没构造对回去检查shift是否在排序后执行。5.5 现象可视化图横坐标时间挤成一团完全看不清原因没有设置mdates的 locator 和 formatterMatplotlib 默认按数据点索引显示。解决用mdates.DateFormatter和mdates.HourLocator或DayLocator控制刻度和格式再配合rotation45旋转标签。6. 进阶技巧用残差修正和滚动预测把误差再压一压基础流程跑通之后如果想把 RMSE 再降一点我一般会试两个方向。第一个是残差修正先用 LightGBM 跑一版预测然后把「真实值减预测值」作为新的目标变量用同样的特征再训练一个模型去拟合残差最终预测等于两个模型输出相加。这个方法对系统性偏差比较有效代码改动很小# 第一层预测 pred_stage1 model.predict(X_test) residual y_test.values - pred_stage1 # 第二层用同样特征拟合残差 residual_model lgb.LGBMRegressor( n_estimators200, learning_rate0.03, max_depth4, random_state42 ) residual_model.fit(X_train, y_train - model.predict(X_train)) pred_final pred_stage1 residual_model.predict(X_test) print(Stage2 RMSE:, np.sqrt(mean_squared_error(y_test, pred_final)))第二个是滚动预测不要一次性预测未来 24 小时而是每次只预测下一小时然后把预测值填回输入特征再预测下下小时。这样做的好处是每一步都利用了最新信息缺点是误差会累积。我一般会对比两种方式的 RMSE如果滚动预测在 6 小时以内明显更好就采用滚动方式做短期预报。还有一个容易被忽略的点保存模型和特征列顺序。训练时特征列的顺序和预测时必须完全一致否则 LightGBM 会报错或给出错误结果。我习惯把feature_cols一起存成 JSON加载模型时先读特征列表再对齐数据。这个习惯帮我省过好几次「后悔药」——有一次换了个环境跑推理列顺序变了预测结果全乱排查了半天才发现是这个问题。最后说一个验证方法拿最近一周的真实数据做一次「盲测」不要参与任何训练和调参直接跑推理看误差。如果盲测 RMSE 和测试集 RMSE 差距在 20% 以内说明模型没有过拟合到特定时间段可以放心用。如果差距很大回去检查数据分布有没有漂移。这套流程我从头跑过好几遍每次翻车的地方都不一样但归根结底都是数据对齐和切分的问题。模型本身反而不是最难的。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑