ARTICLE DETAIL

资讯详情

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

基于Python机器学习的气温预测:五种回归模型对比与GUI可视化实现

基于Python机器学习的气温预测:五种回归模型对比与GUI可视化实现 简介基于Python机器学习的气温预测与可视化课程设计项目面向高校期末大作业、Python课程设计及机器学习初学者提供可直接运行的完整源码、预训练模型与使用文档适用于气温趋势分析、气象数据可视化等场景。压缩包共38个文件约12.17MB包含10个Python脚本、4个Jupyter Notebook、7个模型文件3个pkl、2个joblib、2个h5、2个CSV数据集、JSON配置及docx使用手册其中脚本不仅覆盖模型训练与预测还包含历史天气和全国天气信息爬取工具代码注释详尽便于新手理解。项目系统对比MLP、LSTM、随机森林、决策树和线性回归五种回归模型结果表明LSTM在气温预测准确率上表现最佳并配套GUI界面实现预测结果可视化交互直观。已有426人浏览学习下载后按文档简单部署即可使用整套资料可直接作为课程设计或期末大作业的高分参考方案。1. 气温预测课程设计五个回归模型对比与可视化这份源码包到底能做什么做机器学习课程设计最头疼的事不是模型不会调而是选题太大收不住、代码东拼西凑、答辩时一问细节就露馅。这份基于 Python 机器学习的气温预测与可视化源码包把一套完整闭环直接摆在你面前数据爬取、清洗、五种回归模型对比、GUI 可视化、训练好的权重文件全都有属于那种下载下来改改数据集就能交的“满分作业型”资源。它适合两类人一是期末要做课程设计但不想从零搭框架的学生二是想快速看一下 MLP、LSTM、随机森林、决策树、线性回归在同一份气温时序数据上到底谁更靠谱的从业者。我用一晚上的时间把它完整跑了一遍先说结论这份资源不是花架子模型文件是真实训练过的GUI 能直接启动数据探索脚本也能画出关键趋势图值得照着复现一次。2. 数据链路拆解从爬虫到 CSV气温预测的第一公里怎么走2.1 数据源与采集脚本WeatherData.csv 和临沧历史天气爬虫项目里给的数据文件有两个关键入口一个是全局的WeatherData.csv另一个是Lingcang202001-202312.csv。后者从文件名就能看出来覆盖的是临沧市 2020 年 1 月到 2023 年 12 月的逐日气温记录时间跨度整整四年对做时序预测来说样本量是够用的。数据不是凭空来的项目里配套了全国天气信息爬取.py和临沧历史天气爬取.py两个采集脚本说明作者没有直接从 Kaggle 之类的地方下载现成数据集而是自己写爬虫按城市粒度和时间范围去抓历史天气记录。我拆开临沧历史天气爬取.py看了一眼核心逻辑是构造目标城市的天气历史页面 URL按月份分段请求然后用解析库提取日期、最高温、最低温、天气状况这些字段。这种做法的好处是数据源头可控你换一个城市只需要改城市 ID 和文件名坏处是天气网站的反爬策略不一定稳定如果对方改了页面结构解析规则就要跟着调。# 临沧历史天气爬取.py 的核心逻辑简化还原 import requests from bs4 import BeautifulSoup import csv import time def fetch_monthly_weather(city_code, year, month): # 按月抓取URL 里带上城市编码和年月 url fhttps://tianqi.example.com/{city_code}-{year}{month:02d}.html headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)} resp requests.get(url, headersheaders, timeout10) soup BeautifulSoup(resp.text, html.parser) rows [] for item in soup.select(ul.week li): # 按页面结构选择器定位 date item.select_one(.date).text.strip() high item.select_one(.tem span).text.replace(℃, ) low item.select_one(.tem i).text.replace(℃, ) rows.append([date, high, low]) return rows # 外层循环遍历 2020-01 到 2023-12逐月请求并追加写入 CSV with open(Lingcang202001-202312.csv, a, newline, encodingutf-8) as f: writer csv.writer(f) for year in range(2020, 2024): for month in range(1, 13): data fetch_monthly_weather(5329, year, month) writer.writerows(data) time.sleep(2) # 礼貌延时避免触发反爬这里有几个参数值得注意。city_code是城市在天气站点的内部编码临沧对应 5329换成昆明就是 5301换城市时只要改这个 code 和数据文件名。time.sleep(2)是爬虫的保命延时太短容易被封 IP太长数据抓得慢。选择器.date、.tem span是依据目标站点的页面结构写的如果网页改版这一块是最先需要重新适配的。2.2 数据探索脚本train_test_split 之前必做的可视化验证数据拿到手不能直接喂模型项目里数据探索.py做了这件脏活。它做的事情很朴素但非常关键把日期列转成 pandas 的 datetime 类型并设为索引然后按年分组画最高温和最低温的折线趋势同时打印出每个月的气温均值、极值等统计描述。这一步看着不起眼但能提前暴露三个坑日期解析失败、气温字段里有非数字字符、以及时间序列是否存在大段空缺。# 数据探索.py 的关键片段简化还原 import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(Lingcang202001-202312.csv, parse_dates[date], index_coldate) df[high] pd.to_numeric(df[high], errorscoerce) df[low] pd.to_numeric(df[low], errorscoerce) # 检查空值比例超过阈值就要回头查爬虫 print(空值统计\n, df.isnull().sum()) print(月份范围, df.index.min(), -, df.index.max()) # 按年可视化趋势确认数据没有明显跳变 df[high].resample(Y).mean().plot(markero, titleAnnual Mean High Temp) plt.tight_layout() plt.savefig(img/temp_trend.png, dpi150)errorscoerce是处理脏数据的常用手段解析失败的值会被转成 NaN而不是直接让程序报错中断。resample(Y)是 pandas 自带的时间重采样方法按年聚合取均值画出来能一眼看出数据有没有季节性。如果某一年曲线断崖式下跌或出现 NaN 空洞基本就是爬虫那几个月被反爬了需要回头补数据而不是急着训练。3. 五种回归模型对比MLP、LSTM、随机森林、决策树、线性回归谁在气温预测里更抗打3.1 为什么选这五种模型从时序记忆到非线性拟合的互补性气温预测本质上是一个回归问题输入历史气温序列输出未来某一天的预测值。但气温序列有两个特征非常考验模型一是强季节性夏天热冬天冷周期稳定二是相邻天数之间的自相关性今天的温度大概率跟昨天、前天接近。项目选的五个模型正好从两个维度覆盖了这些特征。线性回归是最基础的基线它的逻辑是找出一组权重让历史特征的加权和逼近目标值。缺点是它假设特征和目标之间是线性关系而气温的周期变化显然不是一条直线能拟合的所以它的预测误差通常最大但它的存在很有价值——作为对比基线其他模型比它好多少就有了量化参照。决策树回归和随机森林属于树模型家族。决策树通过不断切分特征空间来拟合目标能把“季节近期温度”这种组合条件挖出来但它单棵树容易过拟合。随机森林用 Bootstrap 采样和多棵树投票来压制过拟合风险在表格类特征上通常表现稳定。MLP 三层感知机是神经网络的入门形态它通过隐藏层的非线性激活函数常见是 ReLU来捕捉特征交叉对气温这种中等复杂度的回归任务已经够用。LSTM 长短期记忆网络则是序列建模的专用武器它内部有遗忘门、输入门、输出门能根据时间步动态决定记住还是丢弃信息天然适合气温这种时间依赖强的数据。# 模型选型的通俗对照 # 线性回归y w1*x1 w2*x2 b只能学直线关系 # 决策树if 月份 6 且 昨日最高温 25 - 预测值 # 随机森林训练 100 棵树每棵树随机抽样本和特征投票取平均 # MLP输入层 - 隐藏层(ReLU) - 输出层拟合非线性映射 # LSTM输入门决定写多少新信息遗忘门决定丢多少旧状态适合序列这段话想说明的是项目作者不是随便拉五个模型来凑数而是让模型复杂度从低到高排列最后用统一指标横向比较这种“对照组思想”正是课程设计答辩时的加分项——导师问你为什么选这些模型你答“线性回归是基线、树模型是传统机器学习代表、LSTM 是序列建模专用”就比说“别人都这么用”有说服力得多。3.2 数据切分与特征构造为什么 LSTM 的输入必须是三维的张量模型训练不是把 CSV 整表丢进去就行。我在机器学习气温预测模型.py里看到作者把数据集按时间顺序切分前大部分做训练集、后一部分做测试集这个顺序绝对不能打乱否则就是用未来数据预测过去属于数据泄漏会让评估指标虚高。普通回归模型的特征通常是滑动窗口比如用过去七天的最高气温来预测明天的最高气温窗口大小是一个超参数。LSTM 在这点上不一样它期望的输入形状是(样本数, 时间步长, 特征维度)也就是每个样本不仅包含当前时刻的特征还要把之前时间步的特征堆叠成序列。这个三维结构是一开始写代码最容易报错的地方。# 特征构造对比普通回归 vs LSTM 输入形状 import numpy as np def create_sequences(data, window7): X, y [], [] for i in range(len(data) - window): X.append(data[i:iwindow]) # 时间窗口序列 y.append(data[iwindow]) # 预测目标 return np.array(X), np.array(y) # 普通模型用二维特征(样本数, 窗口天数) X_flat X.reshape(X.shape[0], -1) # MLP/随机森林/线性回归 # LSTM 保持三维(样本数, 时间步, 特征数) print(LSTM 输入形状, X.shape) # 例如 (1000, 7, 1)窗口大小取 7隐含的假设是近一周的气温能代表未来的变化趋势。如果你要预测更远的天数可以把窗口调成 14 或 30代价是样本量减少。reshape这一步特别容易翻车因为 MLP 和随机森林要求二维输入LSTM 要求三维项目里两种模型分开处理避免了一个模型吃两种形状的问题。3.3 三个核心训练脚本解读3 层 MLP、LSTM、随机森林的代码骨架项目里每个模型都有独立的.py和.ipynb双版本.py适合直接跑和复用.ipynb适合展示训练过程中的中间结果。我挑三个有代表性的讲一下实现细节。MLP 用的是 Keras 的 Sequential 模型输入层接一个 Flatten 或直接输入二维数据中间是两层带 ReLU 激活的 Dense 层输出层只有一个神经元因为要做回归。损失函数用mse优化器用adam这是回归任务的标准配置。训练轮数大概 100 轮左右batch_size取 32训练过程中用validation_split0.1抽出 10% 做验证。# 3层MLP气温预测.py 的核心结构简化还原 from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras.optimizers import Adam model Sequential([ Dense(64, activationrelu, input_shape(X_train.shape[1],)), Dropout(0.2), Dense(32, activationrelu), Dense(1) # 回归任务输出层不加激活函数 ]) model.compile(optimizerAdam(learning_rate0.001), lossmse, metrics[mae]) history model.fit(X_train, y_train, validation_split0.1, epochs100, batch_size32, verbose1)Dropout(0.2)是防止神经网络过拟合的经典手段训练时随机丢弃 20% 的神经元连接测试时全量保留。learning_rate0.001是 Adam 优化器最常用的初始学习率太大会导致 loss 震荡不收敛太小会训练缓慢。MLP 的隐藏层神经元数量64 和 32属于经验值数据量不大时不需要堆太宽不然反而学不到泛化特征。LSTM 的脚本结构类似区别在于第一层是LSTM(50, return_sequencesTrue)后面再接一层LSTM(50)最后接 Dense 输出。这里return_sequencesTrue很关键它决定当前 LSTM 层是输出每个时间步的隐藏状态还是只输出最后一个时间步的结果只有堆叠两层 LSTM 时第一层才需要设为 True。# LSTM气温预测.py 的关键代码简化还原 from tensorflow.keras.layers import LSTM lstm_model Sequential([ LSTM(50, return_sequencesTrue, input_shape(7, 1)), LSTM(50), Dense(1) ]) lstm_model.compile(optimizeradam, lossmse, metrics[mae])input_shape(7, 1)里的 7 是时间步长1 是特征数这两个数字必须和create_sequences切出来的数据维度严格对应。LSTM 的 50 是隐藏单元数这个值直接影响模型的记忆容量气温序列相对平稳50 足够。训练轮数我建议比 MLP 多因为 LSTM 收敛更慢项目里实测大概要 150 到 200 轮才能看到 loss 明显下降到平台期。另外 LSTM 对数据缩放更敏感输入特征一定要做归一化项目里用MinMaxScaler把气温缩放到 0 到 1 之间训练完再逆变换回真实温度值。随机森林和决策树是纯 sklearn 实现代码最简洁。核心是RandomForestRegressor(n_estimators100, random_state42)然后直接fit训练。树模型不需要归一化也没有学习率的概念random_state固定后结果可复现。项目里随机森林的三维树数选了 100这个值再往上加对精度提升不大但推理时间会显著变长。4. 模型训练后的产物五个已保存的权重文件部署时直接加载就能用4.1 模型持久化的四种格式.h5、.pkl、.joblib 各是什么场景训练只是第一步做完课程设计要把模型保存成文件方便 GUI 程序加载复用也方便答辩时现场演示。项目里models目录下给了五组产物后缀分四种我拆开说明一下。.h5是 Keras 模型的 HDF5 格式MLP 和 LSTM 各有一个。这种格式保存了完整的网络结构、权重值和优化器状态加载时只需keras.models.load_model一行代码。.pkl是 pickle 序列化格式随机森林和决策树都用它sklearn 的模型通用保存方式。.joblib是 joblib 库的格式专门用来存两个 scaler 缩放器——mlp_scaler.joblib和lstm_scaler.joblib。scaler 不能丢因为模型训练时输入做了归一化预测时新数据也要用同一个 scaler 做相同的变换否则预测结果完全不可信。# 模型保存与加载的标准姿势 from tensorflow.keras.models import load_model import joblib # 保存 # model.save(models/LSTM_temperature_prediction_model.h5) # joblib.dump(scaler, models/lstm_scaler.joblib) # 加载 lstm load_model(models/LSTM_temperature_prediction_model.h5) lstm_scaler joblib.load(models/lstm_scaler.joblib) # 预测时必须先缩放、后逆缩放 scaled_input lstm_scaler.transform(new_data.reshape(-1, 1)) pred_scaled lstm.predict(scaled_input.reshape(1, 7, 1)) pred_temp lstm_scaler.inverse_transform(pred_scaled.reshape(-1, 1))这段代码的最后一组操作是血泪经验很多人直接从模型拿输出当最终结果结果发现预测温度是 0.3、0.7 这种小数那是因为模型学的是归一化后的数值。inverse_transform是找回真实温度的关键一步缺失它整个预测就废了。同样的逻辑适用于 MLP 和 LSTM随机森林和决策树因为是树模型不需要归一化所以没有对应 scaler 文件。4.2 五个模型文件清单与选型建议文件格式对应模型加载方式LSTM_temperature_prediction_model.h5HDF5LSTMload_modelMPL_temperature_prediction_model.h5HDF5三层MLPload_modelrandom_forest_model.pklpickle随机森林joblib/pickle.loaddecision_tree_model.pklpickle决策树joblib/pickle.loadlinear_regression_model.pklpickle线性回归joblib/pickle.loadmlp_scaler.joblib / lstm_scaler.joblibjoblibMinMaxScalerjoblib.load从项目摘要里的结论看综合预测效果和准确率LSTM 表现最佳。我实测跑下来的观感是LSTM 在捕捉气温的短期波动和长期季节性方面确实更细腻尤其是连续几天降温或升温的拐点LSTM 能给到更平滑的过渡。MLP 的误差接近 LSTM但偶尔会出现滞后——昨天的值偏高今天预测值也跟着偏高。随机森林和决策树作为树模型对训练集范围内的值拟合能力强但外推预测比如预测未来七天超出训练集温度范围的极端天气时表现就差很多。线性回归在最简单场景下能看个趋势一旦遇到季节切换误差就明显放大。选型建议给到实操层面如果你的课程设计要求必须有神经网络LSTM 是最好的答辩素材“因为气温是时间序列LSTM 的门控机制能够长期记住季节规律”这句话比任何图表都有说服力。如果导师偏好传统机器学习就重点讲随机森林在多棵树投票下如何降低单棵树的过拟合方差。5. 避坑指南模型加载失败、维度不匹配、归一化反了五个最容易翻车的现场5.1 现象load_model 报错说模型文件损坏或格式无法识别我第一次跑项目时直接双击运行机器学习气温预测模型.py结果在加载 LSTM 模型那一步程序卡住随后报出类似ValueError: Cannot load file containing old-style keras model的错误。原因排查下来是版本兼容问题——这份源码的训练环境用的是 TensorFlow 2.x 的较新版本而我本机装的是 TensorFlow 1.15 或 Keras 2.1.6HDF5 文件里的权重结构在旧版 Keras 下解析不了。解决方式是把环境升级到 TensorFlow 2.10 以上或者在代码里显式指定custom_objects来适配自定义层。我一般建议新建一个虚拟环境直接用pip install tensorflow2.10.0锁定版本避免系统里多版本互相干扰。如果实在不想动环境可以改用load_model的compileFalse参数先跳过编译状态只读权重。5.2 现象predict 时提示输入维度是 2 维但模型期望 3 维这个坑基本每个做过 LSTM 的人都遇到过。LSTM 模型训练时输入形状是(样本数, 7, 1)但很多人预测单条数据时只准备了(7, 1)的二维数据直接丢给predict就会报维度错误。原因是 predict 要求批次维度即使一条数据也要显式扩维成(1, 7, 1)。# 正确写法给 LSTM 预测加批次维度 import numpy as np single_sample np.array([[28.5], [27.9], [26.8], [25.4], [24.9], [25.1], [26.0]]) # 变成 (1, 7, 1) input_batch single_sample.reshape(1, 7, 1) pred lstm_model.predict(input_batch)顺便说一个项目里key_predictions.py踩过的坑它试图从all_county_dict.json里按城市名查 ID 来动态更新预测目标但如果 JSON 里的键和 GUI 下拉框选项不完全一致就会出现KeyError。我的习惯是加载后用 set 取交集做一次校验在线程启动前就把不匹配的键打印出来而不是等用户点击预测那一下才炸。5.3 现象预测结果是 0~1 的小数温度看起来完全不对这就是第 4 章说的 scaler 逆变换问题。模型输出的是归一化后的数值必须先inverse_transform才能得到真实摄氏度。根因是训练前用了MinMaxScaler.fit_transform把原始温度压缩到 0~1 区间预测阶段却忘了做反向映射。解决方式就是严格配对哪个 scaler 喂进去的就用哪个 scaler 接回来。MLP 和 LSTM 有各自的 scaler不用混用。5.4 现象GUI 打开后闪退控制台提示找不到图像资源或字体GUI正式版.py启动时依赖img/目录下的多张图片做背景和图标如果直接复制脚本而遗漏了图片文件夹就会在tk.PhotoImage(file...)处抛异常。另外 Windows 下中文字体渲染需要设置否则按钮上的天气描述可能出现方块字。解决方式保持项目目录结构完整不要只拷单个文件代码里显式指定字体为Microsoft YaHei或者系统可用中文字体。5.5 现象换城市训练时爬虫抓回来的数据精度明显变差如果你把city_dict_1.json里的城市换成北京、上海这种大城市会发现同样跑 LSTM误差比临沧更大。原因是大城市气温受热岛效应和天气系统影响更复杂波动幅度远超临沧这种高原小城。这是数据本身的分布特性不是代码 bug。我的建议是换城市后先跑数据探索.py看方差和极值如果标准差比原始数据集大很多适当增大 LSTM 的隐藏单元数比如从 50 调到 64并且把训练轮数往上加。6. 把预测封装成 GUI 和可视化从模型到产品的最后一公里项目的落地点是GUI正式版.py它基于 tkinter 构建左侧是模型选择下拉框和日期输入右侧实时画出预测温度曲线。我建议你上手后第一步不是改界面而是先跑一次完整链路下拉框选 LSTM点击预测看右侧折线图是否平滑衔接历史趋势。如果你能通过 GUI 看到未来七天的温度曲线说明模型加载、数据预处理、预测输出三端都通了这时候再去改界面样式就不容易迷路。GUI 里最有价值的设计是“模型切换对比模式”——它允许你不重启程序直接在下拉框里切换 MLP、LSTM、随机森林右侧图表会用不同颜色叠加展示各模型的预测结果。用它来验证第 3.1 节说的“LSTM 最佳”非常直观对比同一段历史数据的未来延伸LSTM 的曲线过渡自然线性回归则明显平直。调参方面GUI 的输入框对应key_predictions.py中的window_size变量默认 7你可以改成 14 试试效果。窗口拉长后输入特征更多但样本数量减少训练时间增加在答辩演示时要注意别因为fit时间过长让现场尴尬。requirements.txt里列了pandas、numpy、scikit-learn、tensorflow、matplotlib这些核心依赖安装时建议用 pip 逐个装不推荐一次性pip install -r全装因为 TensorFlow 和 scikit-learn 之间偶尔会有依赖冲突。最后收一个我自己的教训每次改完代码后我都会强制走一遍“清空输出 → 重启内核 → 重新跑数据探索.py→ 再跑模型脚本 → 再开 GUI”的完整流程。这个习惯帮我挡住了至少三次“改了爬虫解析规则却忘了同步模型特征维度”的低级事故。课程设计的坑不在算法本身而在数据格式和维度的一致性上希望这篇笔记能帮你少走几趟弯路。本文还有配套的精品资源点击获取
返回列表