简介这是一套面向计算机相关专业学生与项目实战学习者的机器学习天气预测完整项目包适用于期末大作业、毕业设计及课程实践场景难度适中已通过导师评审并获98分。资源共38个文件压缩包约12.17MB包含10个py脚本、4个ipynb笔记本、10张png图表及jpg截图另有pkl、joblib、h5等模型文件与csv、json数据集配套docx说明手册和txt依赖清单覆盖从数据爬取、模型训练到可视化展示的完整链路。项目围绕气温预测展开提供线性回归、决策树、随机森林、三层MLP及LSTM等多种算法实现并附带GUI正式版与最简版界面方便对比不同模型效果。目前已有115人学习下载源码均经本地编译调试可运行读者可据此快速复现实验、理解特征工程与模型评估流程也可作为二次开发与论文写作的参考模板。1. 从一份天气预测源码说起机器学习到底在预测什么很多同学做期末大作业时第一反应是去搜「Python机器学习天气预测可视化源码全套」拿到压缩包解压一看目录里躺着data.csv、train.py、app.py和一份 Word 文档却不知道从哪一行开始读。我当年也是这样代码能跑通但被老师追问「你的特征为什么选这几个」「模型评估为什么用这个指标」时直接卡壳。这篇笔记就按一线做项目的顺序把这份典型大作业拆开讲清楚数据从哪来、特征怎么造、模型怎么选、可视化怎么画、文档怎么写才经得起答辩。适合正在做机器学习期末大作业、想真正搞懂而不是只交差的人也适合刚入门想找一个完整小项目练手的同学。天气预测这个题目看着简单其实是个标准的监督学习回归问题用历史气象观测数据温度、湿度、气压、风速、风向等作为特征去预测未来的温度或是否降雨。它不像图像分类那样需要 GPU一台普通笔记本就能跑完但麻雀虽小五脏俱全——数据清洗、特征工程、模型对比、超参调优、可视化、结果解释一个都不少。这也是为什么它常年霸占「机器学习期末大作业」选题榜。下面我按「数据 → 特征 → 模型 → 可视化 → 避坑 → 进阶」的顺序把每个环节的可复现细节讲透。2. 数据获取与清洗天气预测源码的第一道坎2.1 数据从哪来以及为什么不能直接用常见的天气数据集来源有三类一是公开气象数据平台导出的 CSV字段通常是日期、最高温、最低温、天气状况、风向、风力二是自己用爬虫抓的逐小时数据三是老师直接发的data.csv。不管哪种拿到手第一件事不是急着read_csv然后fit而是先看数据长什么样。我一般会先跑一段探查代码把行数、列名、缺失值、重复值、各列类型一次性看清楚。import pandas as pd import numpy as np # 读取数据注意编码中文数据常见 gbk df pd.read_csv(weather.csv, encodingutf-8) # 基础探查形状、列名、类型、缺失情况 print(数据形状:, df.shape) print(列名:, df.columns.tolist()) print(各列类型:\n, df.dtypes) print(缺失值统计:\n, df.isnull().sum()) print(重复行数:, df.duplicated().sum()) # 看前几行确认字段含义 print(df.head())这段代码的逻辑是先建立对数据的整体认知再决定清洗策略。shape告诉你样本量够不够几百条和几万条对应的建模思路完全不同isnull().sum()定位缺失集中在哪几列duplicated()排查是否有重复录入。参数上encoding一定要和文件实际编码一致中文 CSV 用utf-8读出来乱码时换成gbk或gb18030这是新手最常翻车的地方。2.2 缺失值、异常值和日期字段的处理天气数据里缺失值很常见尤其是湿度、气压这类传感器字段。处理方式取决于缺失比例缺失低于 5% 可以直接删行5% 到 30% 之间用均值、中位数或前后值填充超过 30% 的列建议直接放弃硬填只会引入噪声。异常值方面温度出现 -100℃ 或 200℃ 这种明显是录入错误用分位数或物理常识范围过滤。# 1. 日期字段转成 datetime并拆出年、月、日、星期 df[date] pd.to_datetime(df[date], errorscoerce) df[month] df[date].dt.month df[day] df[date].dt.day df[weekday] df[date].dt.weekday # 2. 数值列缺失用中位数填充比均值更抗异常值 num_cols [temp_max, temp_min, humidity, pressure, wind] for col in num_cols: if col in df.columns: df[col] df[col].fillna(df[col].median()) # 3. 用物理范围过滤异常温度 df df[(df[temp_max] -50) (df[temp_max] 60)] # 4. 删除日期解析失败的行 df df.dropna(subset[date]).reset_index(dropTrue) print(清洗后形状:, df.shape)逻辑说明日期拆解是天气预测的关键特征工程因为气温有强烈的季节性和周内规律模型拿到「月份」和「星期」比拿到一个原始日期字符串有用得多。errorscoerce让无法解析的日期变成 NaT 而不是直接报错方便后续统一删除。中位数填充比均值稳健遇到极端值不会被带偏。物理范围过滤是最后一道保险把明显不可能的温度剔除。参数上温度上下限按你所在地区调整热带和寒带范围不一样。提示清洗完一定要把处理后的数据另存一份比如weather_clean.csv后续建模都基于它避免每次重复清洗也方便复现。3. 特征工程与模型选型让天气预测真正跑起来3.1 特征怎么造比选什么模型更重要很多人一上来就纠结用线性回归还是随机森林其实在天气预测这种小数据集上特征质量对结果的影响远大于模型选择。除了原始的温度、湿度、气压我一般会补几类衍生特征滞后特征昨天、前天的温度、滑动窗口统计近 7 天平均温度、季节编码月份的正弦余弦变换。滞后特征尤其重要因为今天的气温和昨天强相关。# 按日期排序保证滞后特征方向正确 df df.sort_values(date).reset_index(dropTrue) # 滞后特征前 1 天、前 2 天的最高温 df[temp_max_lag1] df[temp_max].shift(1) df[temp_max_lag2] df[temp_max].shift(2) # 滑动窗口近 7 天最高温均值 df[temp_max_roll7] df[temp_max].rolling(window7).mean() # 月份周期编码避免 12 月和 1 月被当成距离很远 df[month_sin] np.sin(2 * np.pi * df[month] / 12) df[month_cos] np.cos(2 * np.pi * df[month] / 12) # 滞后和滑动会产生 NaN删掉开头几行 df df.dropna().reset_index(dropTrue) print(特征工程后形状:, df.shape)逻辑说明shift(1)把前一天的值挪到当前行构造出「用历史预测未来」的结构这是时间序列类任务的核心。rolling(7).mean()平滑掉单日波动反映趋势。月份的正弦余弦编码解决了一个经典问题——如果直接用 1 到 12 的数字模型会认为 12 月和 1 月相差 11实际上它们相邻周期编码让首尾在特征空间里也接近。参数上滞后阶数和窗口大小要试一般从 1、2、7 开始数据量大可以加到 14、30。3.2 模型对比从线性回归到集成模型天气预测常用的模型有线性回归、决策树、随机森林、梯度提升如 XGBoost、LightGBM。我的建议是至少跑三个做对比这样答辩时能说清楚为什么选最终那个。线性回归作为基线随机森林作为主力梯度提升作为冲刺。评估指标用 MAE平均绝对误差和 RMSE均方根误差MAE 直观RMSE 对大误差更敏感。from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error # 特征列和目标列 feature_cols [temp_min, humidity, pressure, wind, temp_max_lag1, temp_max_lag2, temp_max_roll7, month_sin, month_cos] X df[feature_cols] y df[temp_max] # 时间序列不能随机打乱按顺序切分 split int(len(df) * 0.8) X_train, X_test X[:split], X[split:] y_train, y_test y[:split], y[split:] models { 线性回归: LinearRegression(), 随机森林: RandomForestRegressor(n_estimators200, random_state42) } for name, model in models.items(): model.fit(X_train, y_train) pred model.predict(X_test) mae mean_absolute_error(y_test, pred) rmse np.sqrt(mean_squared_error(y_test, pred)) print(f{name} - MAE: {mae:.2f}, RMSE: {rmse:.2f})逻辑说明这里最关键的一点是不能随机打乱再切分。天气数据有时间顺序随机切分会让「未来」的数据混进训练集造成数据泄漏测试分数虚高答辩时被问到就露馅。按 80/20 顺序切分才符合真实预测场景。随机森林的n_estimators是树的数量200 是常用起点加到 500 通常还能小幅提升但更慢random_state固定后结果可复现写文档时务必固定。跑完对比如果随机森林明显优于线性回归说明特征和目标之间存在非线性关系这个结论本身就是文档里值得写的一段。注意如果 MAE 大得离谱比如十几度先别怀疑模型回头检查特征里有没有把目标列本身混进去这是最常见的泄漏来源。4. 可视化与文档天气预测大作业的加分项4.1 用 Matplotlib 和 Seaborn 画出能讲故事的图可视化不是把数据随便画出来就行而是要服务于「让老师一眼看懂你发现了什么」。我一般会准备四张图温度时间序列折线图、真实值 vs 预测值对比图、特征重要性条形图、相关性热力图。前两张证明模型有效后两张证明你理解数据。import matplotlib.pyplot as plt import seaborn as sns plt.rcParams[font.sans-serif] [SimHei] # 中文显示 plt.rcParams[axes.unicode_minus] False # 图1真实值 vs 预测值 plt.figure(figsize(12, 5)) plt.plot(y_test.values, label真实值, colorsteelblue) plt.plot(pred, label预测值, colororange, alpha0.8) plt.title(天气预测真实值 vs 预测值) plt.xlabel(样本序号) plt.ylabel(最高温 (℃)) plt.legend() plt.tight_layout() plt.savefig(pred_vs_true.png, dpi150) # 图2随机森林特征重要性 rf models[随机森林] importance pd.Series(rf.feature_importances_, indexfeature_cols) importance.sort_values().plot(kindbarh, figsize(8, 5), colorteal) plt.title(特征重要性排序) plt.tight_layout() plt.savefig(feature_importance.png, dpi150)逻辑说明中文显示是 Matplotlib 的老大难font.sans-serif设成SimHei并关掉负号乱码这两行几乎是国内做可视化的标配。dpi150保证导出图片清晰直接放进 Word 文档不糊。特征重要性图能帮你回答「哪个特征最重要」这个高频答辩问题通常滞后特征和最低温会排前面。参数上alpha控制透明度两条线重叠时方便看清figsize按文档排版调整宽图适合时间序列。4.2 文档说明怎么写才经得起追问源码配套的文档说明很多人写成流水账「第一步安装 Python第二步运行脚本」这种文档拿不到高分。好的文档应该包含问题定义、数据来源与字段说明、特征工程理由、模型对比表格、评估结果、结论与不足。尤其是「不足」这一节主动写出模型在极端天气下预测偏差大、数据量有限等局限反而显得你思考深入。文档章节必须写清的内容常见扣分点问题定义预测目标、输入输出只写「预测天气」太笼统数据说明来源、字段含义、样本量不写字段单位特征工程每个新特征的理由只列代码不解释模型对比至少两个模型的指标表只跑一个模型结论与不足发现 局限只报喜不报忧提示文档里的指标数字要和代码跑出来的一致答辩前重新跑一遍截图避免改了代码忘了更新文档。5. 天气预测项目避坑五条血泪经验5.1 数据泄漏测试分数高得反常现象测试集 MAE 只有 0.5℃好到不真实。原因特征里混入了目标列本身或者随机打乱切分让未来数据进了训练集。解决检查feature_cols是否包含目标列时间序列一律按顺序切分切分前先排序。5.2 中文乱码图表和 CSV 双双翻车现象Matplotlib 图里中文变成方框CSV 读出来是乱码。原因字体未设置、文件编码不匹配。解决绘图前设SimHei并关负号读 CSV 时utf-8不行就换gbk写文件时显式指定encodingutf-8-sig让 Excel 也能正常打开。5.3 滞后特征方向错模型学到未来现象模型表现异常好但实际预测一塌糊涂。原因数据没按日期排序就做shift滞后特征取到了错误方向的值。解决做任何shift、rolling之前先sort_values(date)并reset_index。5.4 缺失值填成 0温度凭空多出零度现象填充后数据分布出现异常尖峰。原因对温度、湿度这类连续量用 0 填充0 在物理上无意义。解决连续量用中位数或前后值填充只有计数类字段才考虑填 0。5.5 环境依赖缺失换台电脑就跑不起来现象自己电脑能跑同学或老师电脑报ModuleNotFoundError。原因没记录依赖版本。解决用pip freeze requirements.txt导出文档里写清 Python 版本和关键库版本比如 scikit-learn、pandas、matplotlib。6. 进阶技巧把天气预测做成可展示的小系统如果基础版本已经跑通想让大作业更出彩可以往两个方向走。一是加一个简单的可视化界面用 Streamlit 或 Gradio 把预测功能包成网页输入今天的温湿度就能看到预测结果答辩时现场演示效果拉满。二是做超参调优用GridSearchCV或Optuna自动搜索随机森林的最优参数把调优前后的指标对比写进文档。from sklearn.model_selection import GridSearchCV # 随机森林超参搜索 param_grid { n_estimators: [100, 200, 300], max_depth: [None, 10, 20], min_samples_split: [2, 5] } grid GridSearchCV( RandomForestRegressor(random_state42), param_grid, cv3, scoringneg_mean_absolute_error, n_jobs-1 ) grid.fit(X_train, y_train) print(最优参数:, grid.best_params_) print(最优 MAE:, -grid.best_score_)逻辑说明cv3表示三折交叉验证时间序列严格来说应该用TimeSeriesSplit但作为大作业用普通 K 折也能接受写文档时说明即可。scoring用负 MAE 是因为 sklearn 的评分约定「越大越好」所以取负。n_jobs-1用满所有 CPU 核心加速搜索。参数网格别设太大否则跑一晚上都出不来先粗搜再细搜。验证模型是否真的可用我习惯留出最后 30 天做「盲测」训练时完全不碰这段数据最后预测一次看误差是否和测试集接近。如果盲测误差突然变大说明模型对近期数据不适应可能需要加更多近期特征或缩短训练窗口。这个习惯是我被答辩老师追问「你怎么知道上线后准不准」之后养成的从那以后每次做预测类项目都会留一段盲测数据。希望帮到你。本文还有配套的精品资源点击获取
