简介:这是一套面向计算机相关专业学生与项目实战学习者的机器学习天气预测完整项目包,适用于期末大作业、毕业设计及课程实践场景,难度适中,可帮助读者快速理解从数据获取到模型训练与可视化展示的全流程。压缩包共38个文件,约12.17MB,包含10个py脚本、4个ipynb笔记本、10张png结果图,以及pkl、h5、joblib等模型文件,另有csv、json数据与docx说明文档,覆盖数据爬取、模型训练、界面交互与结果展示等环节。项目围绕气温预测展开,涉及线性回归、决策树、随机森林、MLP与LSTM等多种算法,并配有GUI最简版与正式版界面,便于对比不同模型的预测效果。已有115人学习下载,适合需要完整项目结构、可运行源码与配套说明的读者参考使用。
1. 从一份 98 分气温预测作业说起:这套 Python 机器学习源码到底能跑出什么
期末大作业选题里,天气预测几乎是每年都被抢的方向,但真正能跑通、能讲清楚、还能拿高分的没几个。我手上这份 Python 机器学习天气预测与可视化源码,评审分 98,导师认可通过,核心不是它用了多前沿的模型,而是它把「数据爬取 → 数据探索 → 多模型训练 → 可视化 → GUI 演示」这条链路完整地串了起来,而且每个环节都有可运行的脚本和落地产物。它解决的是学生和初学者最头疼的问题:模型代码网上到处都是,但数据从哪来、特征怎么选、模型怎么对比、结果怎么展示,没人给你一套能直接跑的东西。这套资源适合正在做机器学习期末大作业、毕业设计的学生,也适合想拿一个完整项目练手的 Python 入门者。下面我按实际拆包和复现的顺序,把这份资源讲透。
2. 拆开压缩包先看什么:目录结构与技术栈选型
2.1 文件清单背后的模块划分
拿到压缩包,别急着跑代码,先把目录结构过一遍。这份资源的文件组织其实很清晰,按功能可以分成五块:
| 模块 | 代表文件 | 作用 |
|---|---|---|
| 数据爬取 | 全国天气信息爬取.py、临沧历史天气爬取.py | 从天气网站抓取原始数据 |
| 数据集 | WeatherData.csv、Lingcang202001-202312.csv | 训练和测试用的结构化数据 |
| 模型训练 | LSTM气温预测.py、3层MLP气温预测.py、机器学习气温预测模型.py | 不同算法的训练脚本 |
| Notebook | LSTM气温预测.ipynb、气温可视化.ipynb、3层MLP气温预测.ipynb | 交互式探索与可视化 |
| 模型产物 | models/ 目录下的 .h5、.pkl、.joblib | 训练好的模型文件,可直接加载 |
| GUI | GUI最简版.py、GUI正式版.py | 图形界面演示预测效果 |
| 辅助 | all_county_dict.json、city_dict_1.json、requirements.txt | 城市字典、依赖清单 |
这个划分的好处是,你不需要从头跑爬虫也能直接用 dataset 里的 CSV 开始训练,模型产物也已经保存在 models 目录里,想快速看效果可以直接加载。requirements.txt 里列了依赖,常见做法是先建虚拟环境再装,避免和系统里的包打架。
2.2 为什么选 LSTM + MLP + 传统模型做对比
这份资源没有只用一个模型交差,而是同时给了 LSTM、3 层 MLP,以及随机森林、决策树、线性回归这几个传统模型。这个选型思路值得说一下。
气温数据本质是时间序列,LSTM 能捕捉时序依赖,适合做滑动窗口预测;3 层 MLP 是纯前馈网络,把历史气温当成特征输入,结构简单、训练快,适合做 baseline;随机森林和决策树属于传统机器学习,不需要 GPU,在小数据集上反而稳。把这几类放一起对比,论文或报告里就有东西写:不同模型在同一份数据上的表现差异、训练时间对比、过拟合情况,这些都是评分点。
我一般会先跑 MLP 和随机森林,确认数据管道没问题,再上 LSTM。因为 LSTM 对数据缩放、序列长度、batch size 都敏感,一旦前面数据有问题,LSTM 的 loss 曲线会直接给你脸色看,排查起来反而慢。
2.3 环境准备与依赖安装
在动手之前,先把环境弄干净。这份资源的依赖不算复杂,但版本要对上,尤其是 TensorFlow/Keras 和 scikit-learn。
# 创建虚拟环境,Python 版本建议 3.8 - 3.10 python -m venv weather_env # 激活环境 # Windows: weather_env\Scripts\activate # macOS/Linux: source weather_env/bin/activate # 安装依赖,requirements.txt 在项目根目录 pip install -r requirements.txt # 如果 requirements.txt 里没有锁版本,手动补几个关键包 pip install tensorflow==2.12.0 scikit-learn==1.2.2 pandas==1.5.3 matplotlib==3.7.1 joblib==1.2.0这里有几个参数要注意:TensorFlow 2.12 是最后一个支持原生 Windows GPU 的版本之一,如果你在 Windows 上想用 GPU 训练 LSTM,这个版本比较省心;scikit-learn 1.2.x 和 joblib 的兼容性好,加载 .pkl 模型不容易报 warning。装完之后用pip list确认一下,重点看 tensorflow、sklearn、pandas 三个包的版本。
提示:如果安装 TensorFlow 时卡在下载,可以换国内镜像源,比如
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple,但要注意镜像同步可能有延迟,关键包还是以官方源为准。
3. 数据管道怎么搭:从爬虫到 CSV 再到特征工程
3.1 爬虫脚本的运行逻辑与数据落盘
资源里有两个爬虫脚本:全国天气信息爬取.py 和临沧历史天气爬取.py。前者抓全国范围的城市天气信息,后者专门抓临沧地区 2020 到 2023 年的历史数据,对应 Lingcang202001-202312.csv 这个文件。
爬虫脚本的核心逻辑一般是:读取城市字典(city_dict_1.json 或 all_county_dict.json)→ 拼接请求 URL → 解析返回的 HTML 或 JSON → 提取日期、气温、天气状况等字段 → 写入 CSV。运行之前先确认城市字典的格式,打开 json 文件看一眼,通常是{"城市名": "城市代码"}这种键值对。
# 全国天气信息爬取.py 的核心结构示意(根据资源文件推断) import json import requests import pandas as pd from bs4 import BeautifulSoup # 加载城市字典 with open('city_dict_1.json', 'r', encoding='utf-8') as f: city_dict = json.load(f) records = [] for city_name, city_code in city_dict.items(): # 拼接目标 URL,具体地址以脚本内为准 url = f"http://www.weather.com.cn/weather/{city_code}.shtml" resp = requests.get(url, timeout=10) resp.encoding = 'utf-8' soup = BeautifulSoup(resp.text, 'html.parser') # 解析七天气温、天气状况等字段 # ... 解析逻辑 ... records.append({'city': city_name, 'date': ..., 'temp': ...}) # 落盘为 CSV df = pd.DataFrame(records) df.to_csv('WeatherData.csv', index=False, encoding='utf-8-sig')这段代码的关键参数是timeout=10,爬虫一定要设超时,不然某个城市卡住整个脚本就挂在那里。encoding='utf-8-sig'是为了 Excel 打开 CSV 不乱码,这个细节很多新手会忽略。另外,爬虫频率别太高,加个time.sleep(1)是基本礼貌,也能降低被封的风险。
3.2 数据探索:先看分布再决定怎么洗
拿到 CSV 之后,别直接丢进模型。资源里的数据探索.py 和 气温可视化.ipynb 就是干这个的。我一般会先跑一遍基础统计,看缺失值、异常值、时间范围。
import pandas as pd import matplotlib.pyplot as plt # 加载数据 df = pd.read_csv('dataset/Lingcang202001-202312.csv') # 基础信息 print(df.info()) print(df.describe()) # 检查缺失值 print(df.isnull().sum()) # 气温随时间变化 df['date'] = pd.to_datetime(df['date']) df = df.sort_values('date') plt.figure(figsize=(14, 5)) plt.plot(df['date'], df['temp_max'], label='最高气温') plt.plot(df['date'], df['temp_min'], label='最低气温') plt.legend() plt.title('临沧 2020-2023 气温走势') plt.show()这一步的重点是确认时间列能不能正确解析、气温列有没有超出合理范围的异常值(比如 60 度这种明显错误)。如果发现缺失,常见做法是线性插值或者用前后值填充,但要在报告里写清楚处理方式,不然评审老师会问。
3.3 特征工程与滑动窗口构造
气温预测的特征工程,核心是把时间序列转成监督学习能吃的格式。LSTM 需要三维输入(样本数, 时间步长, 特征数),MLP 和传统模型需要二维表格。资源里的脚本应该都做了这个转换,我按常见做法补一下逻辑。
import numpy as np from sklearn.preprocessing import MinMaxScaler # 假设用历史 7 天气温预测第 8 天 def create_sequences(data, seq_length): X, y = [], [] for i in range(len(data) - seq_length): X.append(data[i:i+seq_length]) y.append(data[i+seq_length]) return np.array(X), np.array(y) # 归一化,LSTM 对尺度敏感 scaler = MinMaxScaler() temp_scaled = scaler.fit_transform(df[['temp_avg']].values) SEQ_LEN = 7 X, y = create_sequences(temp_scaled, SEQ_LEN) # 划分训练集和测试集,时间序列不能随机打乱 split = int(len(X) * 0.8) X_train, X_test = X[:split], X[split:] y_train, y_test = y[:split], y[split:] print(X_train.shape) # (样本数, 7, 1)参数说明:SEQ_LEN=7表示用一周的历史数据预测下一天,这个值可以调,但别太大,否则样本数会急剧减少。归一化用 MinMaxScaler 把气温缩到 0-1,LSTM 训练更稳。注意时间序列划分不能 shuffle,否则测试集里混入未来数据,评估结果会虚高,这是血泪经验。
注意:models 目录里的 lstm_scaler.joblib 和 mlp_scaler.joblib 就是保存好的 scaler,加载模型预测时一定要用同一个 scaler 做逆变换,不然预测出来的气温数值会完全不对。
4. 模型训练与对比:LSTM、MLP 和传统模型怎么跑
4.1 LSTM 气温预测脚本的关键参数
LSTM气温预测.py 和对应的 ipynb 是这份资源的核心。LSTM 的结构一般是Embedding → LSTM层 → Dropout → Dense,但气温预测不需要 Embedding,直接LSTM → Dropout → Dense就行。
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.callbacks import EarlyStopping model = Sequential([ LSTM(64, return_sequences=True, input_shape=(SEQ_LEN, 1)), Dropout(0.2), LSTM(32), Dropout(0.2), Dense(1) ]) model.compile(optimizer='adam', loss='mse', metrics=['mae']) # 早停,防止过拟合 early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) history = model.fit( X_train, y_train, epochs=100, batch_size=32, validation_split=0.1, callbacks=[early_stop], verbose=1 ) # 保存模型 model.save('models/LSTM_temperature_prediction_model.h5')参数说明:第一层 LSTM 用 64 个单元,return_sequences=True是为了接第二层 LSTM;第二层 32 个单元,输出二维。Dropout 设 0.2 是常规操作,数据量小的时候可以调到 0.3。patience=10表示验证集 loss 连续 10 轮不下降就停,restore_best_weights=True会恢复到最优轮次的权重,这个参数很关键,不然保存的是最后一轮的模型,可能已经过拟合了。batch_size 32 是默认值,如果显存不够可以降到 16。
4.2 3 层 MLP 的快速 baseline
3层MLP气温预测.py 适合快速验证数据管道。MLP 的输入是展平后的历史气温,比如 7 天就是 7 个特征。
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout model = Sequential([ Dense(128, activation='relu', input_shape=(SEQ_LEN,)), Dropout(0.2), Dense(64, activation='relu'), Dropout(0.2), Dense(32, activation='relu'), Dense(1) ]) model.compile(optimizer='adam', loss='mse', metrics=['mae']) model.fit(X_train_flat, y_train, epochs=100, batch_size=32, validation_split=0.1) model.save('models/MPL_temperature_prediction_model.h5')注意资源里保存的文件名是MPL_temperature_prediction_model.h5,不是 MLP,加载的时候别写错。MLP 训练快,几分钟就能跑完,适合先确认数据没问题。如果 MLP 的 loss 都不下降,那 LSTM 也不用试了,先回去查数据。
4.3 传统模型:随机森林、决策树、线性回归
资源里还有 random_forest_model.pkl、decision_tree_model.pkl、linear_regression_model.pkl 三个传统模型。这些模型用 scikit-learn 训练,不需要 GPU,适合做对比实验。
from sklearn.ensemble import RandomForestRegressor from sklearn.tree import DecisionTreeRegressor from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_absolute_error, mean_squared_error import joblib # 传统模型用二维特征 X_train_2d = X_train.reshape(X_train.shape[0], -1) X_test_2d = X_test.reshape(X_test.shape[0], -1) models = { 'random_forest': RandomForestRegressor(n_estimators=100, random_state=42), 'decision_tree': DecisionTreeRegressor(random_state=42), 'linear_regression': LinearRegression() } for name, model in models.items(): model.fit(X_train_2d, y_train.ravel()) pred = model.predict(X_test_2d) mae = mean_absolute_error(y_test, pred) rmse = mean_squared_error(y_test, pred, squared=False) print(f"{name}: MAE={mae:.4f}, RMSE={rmse:.4f}") joblib.dump(model, f'models/{name}_model.pkl')随机森林的n_estimators=100是常用值,数据量小的话 50 也够。random_state=42保证结果可复现,报告里写实验设置的时候要提。传统模型的评估指标用 MAE 和 RMSE,和 LSTM 的 mae、mse 对应,方便做对比表格。
4.4 模型对比与结果解读
跑完所有模型,把结果整理成表格,这是报告里的核心内容。
| 模型 | MAE | RMSE | 训练时间 | 备注 |
|---|---|---|---|---|
| LSTM | 待填 | 待填 | 较长 | 需要 GPU 更佳 |
| 3层 MLP | 待填 | 待填 | 短 | 快速 baseline |
| 随机森林 | 待填 | 待填 | 短 | 无需缩放 |
| 决策树 | 待填 | 待填 | 极短 | 容易过拟合 |
| 线性回归 | 待填 | 待填 | 极短 | 欠拟合参考 |
解读的时候注意:LSTM 不一定在所有数据集上都最好,如果数据量小、噪声大,随机森林可能更稳。线性回归如果 MAE 特别高,说明气温和滞后特征之间不是纯线性关系,这本身就是个可以写进报告的结论。
5. 避坑与排查:跑这套源码时最容易翻车的五个地方
5.1 现象:加载 .h5 模型报错「Unknown layer」或「No model found」
原因:Keras 版本不匹配。资源里的 .h5 模型可能是用 TensorFlow 2.x 某个版本保存的,你本地装了 2.15 或更高版本,API 变了。另外,如果模型里用了自定义层,加载时需要custom_objects参数。
解决:先确认 requirements.txt 里的 TensorFlow 版本,严格按那个版本装。如果找不到,试 2.12 或 2.13。加载时用tf.keras.models.load_model('models/LSTM_temperature_prediction_model.h5', compile=False),先不编译,加载完再手动 compile。
5.2 现象:预测出来的气温是 0.2、0.3 这种小数,不是真实温度
原因:忘了做逆变换。模型是在归一化后的数据上训练的,输出也是 0-1 范围,必须用保存的 scaler 做inverse_transform才能还原成摄氏度。
解决:加载对应的 scaler 文件,LSTM 用 lstm_scaler.joblib,MLP 用 mlp_scaler.joblib。
import joblib scaler = joblib.load('models/lstm_scaler.joblib') pred_real = scaler.inverse_transform(pred.reshape(-1, 1))注意 scaler 的 fit 对象要和训练时一致,如果重新 fit 了,逆变换的结果也是错的。
5.3 现象:GUI 运行后界面空白或按钮没反应
原因:GUI最简版.py 和 GUI正式版.py 可能用了 tkinter 或 PyQt,如果依赖没装全,或者图片路径写的是绝对路径,换台机器就找不到资源。
解决:先确认 GUI 用的库,tkinter 一般 Python 自带,PyQt 需要pip install PyQt5。然后检查代码里的图片路径,改成相对路径,比如img/image-20240522210616667.png这种。如果界面能打开但按钮没反应,看控制台有没有报错,通常是模型加载失败或者回调函数没绑定。
5.4 现象:爬虫跑一半报「ConnectionError」或返回空数据
原因:目标网站反爬、网络波动、或者城市代码失效。资源里的 city_dict_1.json 和 all_county_dict.json 可能包含已经变更的代码。
解决:加 try-except 捕获异常,跳过失败的城市继续跑;加time.sleep(1)降低频率;如果某个城市一直失败,手动检查 URL 是否还能访问。另外,爬虫脚本里的 User-Agent 最好设一下,默认的 python-requests 很容易被识别。
5.5 现象:LSTM 训练 loss 不下降,或者 val_loss 一直震荡
原因:学习率太大、序列长度不合适、数据没归一化、或者 batch_size 太小导致梯度不稳定。
解决:先把学习率从默认的 0.001 降到 0.0005 试试;检查 SEQ_LEN 是不是太长,7 到 14 之间比较合理;确认归一化做了;batch_size 可以调到 64 看看。如果还是不行,把 LSTM 单元数从 64 降到 32,减少模型复杂度。玄学的时候,换个随机种子也可能有惊喜。
6. 进阶用法:把模型接进 GUI 并做实时预测验证
6.1 GUI 正式版的集成逻辑
GUI正式版.py 是这份资源的演示门面。它的逻辑一般是:加载模型和 scaler → 提供输入框让用户输入历史气温或选择日期 → 调用模型预测 → 在界面上显示结果和可视化图表。我一般会先跑 GUI最简版.py,确认模型能加载、界面能弹出,再跑正式版。
集成的时候注意一点:GUI 里加载模型最好用相对路径,并且把模型加载放在界面初始化之前,避免用户点击按钮时才加载导致卡顿。如果 GUI 用了 matplotlib 嵌入,记得用FigureCanvasTkAgg或者对应的 Qt 后端,不然图表显示不出来。
6.2 用 key_predictions.py 做预测结果验证
资源里的 key_predictions.py 应该是用来做关键预测点验证的。我的习惯是,训练完模型后,不只看 MAE,还要把预测值和真实值画在同一张图上,看趋势对不对。
import matplotlib.pyplot as plt # 假设 y_test 和 pred 都是归一化后的值 y_test_real = scaler.inverse_transform(y_test.reshape(-1, 1)) pred_real = scaler.inverse_transform(pred.reshape(-1, 1)) plt.figure(figsize=(14, 5)) plt.plot(y_test_real, label='真实气温') plt.plot(pred_real, label='预测气温') plt.legend() plt.title('LSTM 气温预测对比') plt.xlabel('时间步') plt.ylabel('气温 (℃)') plt.show()如果预测曲线整体滞后于真实曲线,说明模型在追趋势但反应慢,可以尝试减小 SEQ_LEN 或增加 LSTM 层数。如果预测曲线太平,说明模型没学到变化,检查归一化范围是不是太窄。
6.3 一个具体技巧:用滑动窗口做多步预测
单步预测只能预测下一天,实际场景里可能需要预测未来一周。做法是每次预测完,把预测值追加到输入序列末尾,滚动预测。
def multi_step_predict(model, last_sequence, n_steps, scaler): predictions = [] current_seq = last_sequence.copy() for _ in range(n_steps): pred = model.predict(current_seq.reshape(1, SEQ_LEN, 1), verbose=0) predictions.append(pred[0, 0]) # 滚动:去掉最早的值,追加预测值 current_seq = np.append(current_seq[1:], pred) return scaler.inverse_transform(np.array(predictions).reshape(-1, 1)) # 用测试集最后一段做起点 last_seq = X_test[-1] future_temps = multi_step_predict(model, last_seq, 7, scaler) print(future_temps)这个技巧的坑在于误差会累积,预测步数越多越不准。我一般只做 3 到 7 步,并且会在报告里说明多步预测的误差会随步数增加。从那以后我每次做时间序列项目,都会把单步和多步的结果分开评估,不混在一起写。希望帮到你。
本文还有配套的精品资源,点击获取