
简介这是一份基于Python的机器学习天气预测与数据可视化完整项目面向毕业设计、期末大作业及课程设计场景也可作为机器学习入门实践参考。项目覆盖天气数据采集、清洗、特征处理、模型训练与预测、可视化展示的完整流程代码注释清晰新手也能读懂。压缩包共24个文件体积仅1.42MB包含4个Python源文件分别负责数据获取、数据处理、模型训练和主程序、4个CSV格式的天气数据集、1个已训练好的pkl模型文件、1个HTML前端展示页面以及12张jpg格式的可视化结果图还有readme说明文档便于对照学习与二次开发。目前已有403人学习下载。该项目为个人手打98分高分作品获导师认可部署简单能帮助读者快速理清天气预测类项目的实现思路是完成毕业设计或课程设计的高质量参考。1. 天气预测项目为什么值得拆开看这套基于Python的机器学习天气预测与数据可视化项目是一个典型的教学型完整工程。源码加数据共24个文件覆盖了数据采集、预处理、模型训练、结果可视化的完整链路。对于正在做期末大作业、课程设计或毕业设计的同学来说它的价值不在于某个算法多前沿而在于把一个真实问题从数据到部署讲清楚了。项目里最有信息量的部分我个人认为是ProcessData.py到Model.pkl这条线。天气数据本身带有明显的时间序列特征和周期性波动加上csv里包含的训练集测试集划分刚好能把回归类模型的训练、评估、调参讲完整。而可视化部分又绑定了HTML页面不是单纯用matplotlib画两张折线图糊弄过去。下面按数据流顺序把每个模块拆开讲标注了哪些地方值得照抄、哪些地方容易踩坑。2. 数据流水线与天气数据的预处理策略2.1 csv文件结构与字段含义解压后你会看到date_train.csv、date_test.csv、date_valid.csv三个数据集文件。这三个文件就是整个项目的燃料。训练集和测试集已经按照时间顺序切好验证集用于模型训练过程中的泛化能力检查这是标准的监督学习数据划分。import pandas as pd train_df pd.read_csv(date_train.csv) test_df pd.read_csv(date_test.csv) valid_df pd.read_csv(date_valid.csv) print(train_df.shape, test_df.shape, valid_df.shape) print(train_df.columns.tolist()) print(train_df.head())这段代码用于确认三份数据的基本规模。read_csv是pandas读取csv文件的标准入口shape返回的是行列数元组通过它可以直接判断样本量比例是否合理。columns.tolist会把列名转为列表用来快速核对字段名拼写避免后续写特征工程时手误。head则查看前五行第一时间发现数据错位或空值。2.2 缺失值处理的常见做法天气数据经常存在连续缺失这来源于观测站设备故障或传输中断。ProcessData.py里的处理思路通常是先统计缺失率再决定填充方式而不是一股脑全部fillna。missing_ratio train_df.isnull().mean().sort_values(ascendingFalse) print(missing_ratio[missing_ratio 0])isnull()把每个单元格转成布尔值mean()按列计算缺失比例sort_values把缺失最严重的列排到前面。这一步的意义在于区分少量缺失和大面积缺失缺失率超过30%的列直接删除或做标记缺失率低于5%的列用前后时间点的均值或中位数填充。常见的填充手段是train_df[温度] train_df[温度].ffill()ffill是向前填充适合温度这类缓慢变化的物理量。2.3 时间戳转换与特征衍生原始csv里时间字段大多是字符串格式必须转成datetime类型才能做时间窗口的特征提取。train_df[日期] pd.to_datetime(train_df[日期]) train_df[月] train_df[日期].dt.month train_df[星期] train_df[日期].dt.dayofweek train_df[是否为周末] (train_df[星期] 5).astype(int)to_datetime把字符串解析为标准时间对象dt.month取出月份dayofweek返回星期几的数字表示周一为0周日为6。天气预测任务里节假日效应和季节性周期是最强的两个信号来源。把月份转成数值特征把星期转成是否为周末的0/1标志模型就能学到此类的周期性规律。另外气压、湿度、风速这类气象要素存在明显的早晚差异原始数据里如果包含小时粒度建议再加一列时段划分。2.4 训练集与测试集的分布一致性检查这是很多人在课程设计里忽略的步骤。训练集和测试集如果分布偏差过大模型在线上的表现会断崖式下跌。检查方式是分别统计关键特征的均值、方差和分位数。for col in [最高温度, 最低温度, 湿度]: print(col) print(train:, train_df[col].mean(), train_df[col].std()) print(test:, test_df[col].mean(), test_df[col].std())mean是均值std是标准差。两组数据在同一特征上的均值差如果超过一个标准差就要考虑是不是切分时混入了不同季节的数据。天气数据切分时必须在时间轴上顺序切不能随机打乱。随机切分会导致训练集里出现未来数据测试集里出现过去数据在时间序列场景下属于数据泄露会高估模型表现。3. 从ProcessData.py到Model.pkl的训练链路3.1 特征矩阵构建与目标变量选择train.csv里的weather天气现象如晴/多云/小雨和气温类字段是预测目标的主要候选。如果是回归任务预测最高温度最常用如果是分类任务预测天气现象类别更贴近真实需求。特征矩阵的构建要把原始字段做数值化处理。import joblib import numpy as np from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import cross_val_score feature_cols [月, 星期, 是否为周末, 湿度, 气压, 风速] X_train train_df[feature_cols].fillna(train_df[feature_cols].median()) y_train train_df[最高温度] model RandomForestRegressor(n_estimators300, max_depth12, random_state42) scores cross_val_score(model, X_train, y_train, cv5, scoringneg_mean_absolute_error) print(MAE:, -scores.mean())fillna用中位数填充是为了兼容缺失行median比mean更抗离群值干扰。RandomForestRegressor的n_estimators是树的数量300棵是一个平衡训练时间和精度的数值max_depth限制单棵树深度防止过拟合random_state固定随机种子保证结果可复现。cross_val_score做五折交叉验证scoringneg_mean_absolute_error表示用平均绝对误差作为评估指标负号是sklearn的统一约定数值越小越好。这里不用R2作为唯一指标是因为天气预测场景中绝对误差更能反映实际可用性。3.2 为什么选择随机森林和梯度提升的组合单棵决策树容易过拟合线性回归对非线性交互捕捉不足。项目里用随机森林作为基线模型如果精度不够一般再叠加梯度提升决策树。from sklearn.ensemble import GradientBoostingRegressor gbr GradientBoostingRegressor( n_estimators200, learning_rate0.05, max_depth4, subsample0.8, random_state42 ) gbr.fit(X_train, y_train) print(训练完成, 特征重要性:, gbr.feature_importances_)GradientBoostingRegressor的learning_rate是每棵树贡献的缩放系数0.05是偏保守的设置配合200棵树既能控制过拟合又不会让训练时间失控。subsample是每轮迭代随机抽样的样本比例0.8让每棵树看到的样本略有不同增加模型多样性。feature_importances_输出每个特征的贡献度如果发现月份和气压排在前两位说明季节性和气压场变化主导气温预测这是符合气象常识的。3.3 模型保存与加载的坑项目里提供了Model.pkl文件这就是训练完成后序列化保存的产物。使用joblib或pickle保存模型时有一个常见坑环境依赖版本不一致会导致加载报错。import joblib joblib.dump(gbr, Model.pkl) loaded_model joblib.load(Model.pkl)joblib.dump把模型对象序列化到磁盘joblib.load从磁盘恢复模型对象。注意加载模型时所在的Python环境和训练时保持一致尤其是sklearn版本。如果版本不一致常见的报错是ModuleNotFoundError或ValueError: Unknown label type。解决方法是在项目说明里记录依赖版本或者用joblib.dump时同时保存模型对应的特征列名列表。项目里readme.md应该做了相关说明实际复现时建议先pip install scikit-learn版本号再加载。3.4 交叉验证与滑动窗口验证时间序列预测不能直接用普通K折交叉验证因为随机划分会打乱时间顺序导致模型在未来数据上训练、在过去数据上验证产生时间穿越问题。from sklearn.model_selection import TimeSeriesSplit tscv TimeSeriesSplit(n_splits5) for train_index, test_index in tscv.split(X_train): X_tr, X_te X_train.iloc[train_index], X_train.iloc[test_index] y_tr, y_te y_train.iloc[train_index], y_train.iloc[test_index] gbr.fit(X_tr, y_tr) score gbr.score(X_te, y_te) print(fold score:, score)TimeSeriesSplit是sklearn提供的专门用于时间序列的交叉验证器它保证测试集的索引永远大于训练集索引。n_splits5表示切出5组训练验证对每一组都逐步往后滚。这样做出来的评估结果才能真实反映模型对未来天气的预测能力。4. 天气图表可视化与HTML前端的联动4.1 matplotlib绘图的参数细节项目包含12张jpg图像文件这些是模型评估和EDA阶段产出的图表。常见的可视化内容包括气温时序折线图、湿度分布直方图、预测值与真实值散点图。这里给出一个高频使用的绘图模板。import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei] matplotlib.rcParams[axes.unicode_minus] False plt.figure(figsize(12, 5)) plt.plot(test_df[日期], y_test, label真实温度, color#333333) plt.plot(test_df[日期], y_pred, label预测温度, color#d62728, linestyle--) plt.xlabel(日期) plt.ylabel(温度 (℃)) plt.title(最高温度预测对比) plt.legend() plt.xticks(rotation45) plt.tight_layout() plt.savefig(预测对比图.jpg, dpi150) plt.show()font.sans-serif设置为SimHei是为了让中文标签正常显示axes.unicode_minus设为False是为了让负号正常显示。figure里的figsize控制画布宽高dpi150控制保存分辨率。plot中linestyle--把预测线设为虚线与真实值实线区分。xticks(rotation45)旋转日期刻度标签防止重叠。tight_layout自动调整子图间距避免标签被裁切。4.2 用HTML组织图表的零依赖方案项目里weather网.html把图片整合到页面中这是最轻量的前端展示方式。不需要启动Flask或Django双击HTML就能在浏览器里查看效果。原理是通过img标签引用本地jpg文件。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title天气预测可视化/title style body { background: #f5f7fa; font-family: Microsoft YaHei; } .chart-container { max-width: 1000px; margin: 20px auto; background: #fff; padding: 20px; } h1 { text-align: center; color: #2c3e50; } img { width: 100%; border-radius: 8px; } /style /head body h1天气预测与数据可视化/h1 div classchart-container img src预测对比图.jpg alt预测对比 /div /body /html这个页面的核心价值在于展示成果不需要后端参与就能跑。CSS里max-width限制内容宽度保证大屏下不拉伸变形margin: 20px auto让容器水平居中border-radius给图片圆角提升观感。如果想把多张图放进来复制chart-container这个div追加即可。4.3 预测误差分布图的三种画法误差分析是评估模型上限的关键。预测值和真实值的差值分布能直观暴露系统偏差。error y_pred - y_test plt.hist(error, bins30, edgecolorwhite, alpha0.8) plt.axvline(x0, colorred, linestyle--, linewidth1) plt.xlabel(预测误差 (℃)) plt.ylabel(频数) plt.title(预测误差分布) plt.savefig(误差分布图.jpg, dpi150)hist是直方图函数bins30把误差范围切为30个区间alpha0.8控制柱子透明度edgecolor给柱子描边便于区分相邻柱体。axvline在x0处画一条红色虚线作为零误差参考线观察误差分布相对这条线的偏移就能判断模型系统性偏高还是偏低。5. GetData.py与实时天气数据采集5.1 静态数据与动态采集的取舍date_train.csv和date_test.csv是打包自带的静态数据适合复现项目流程。但如果要部署成每日更新的预报系统就需要用GetData.py从公开天气接口拉取新数据。项目采用requests模块发送HTTP请求解析JSON响应。5.2 天气接口调用的最小实现import requests import pandas as pd from datetime import datetime def fetch_weather(city_code): url https://restapi.amap.com/v3/weather/weatherInfo params { key: 你的API_KEY, city: city_code, extensions: all } resp requests.get(url, paramsparams, timeout10) data resp.json() forecasts data.get(forecasts, []) return forecasts result fetch_weather(110000) print(result)requests.get中的timeout10是请求超时阈值防止接口无响应时程序卡死。resp.json()把响应体解析为Python字典get方法从嵌套字典里安全取值避免KeyError。extensions参数传all时返回多日预报数据传base只返回实时天气。项目里如果没有真实的API_KEY建议把获取到的数据转为csv格式保持和原有训练数据结构一致。5.3 新采集数据如何喂给Model.pkl采集到新数据后要走和训练时一致的特征工程流程。def preprocess_new(df): df[日期] pd.to_datetime(df[日期]) df[月] df[日期].dt.month df[星期] df[日期].dt.dayofweek df[是否为周末] (df[星期] 5).astype(int) features df[feature_cols].fillna(df[feature_cols].median()) return featuresmonth和dayofweek保证新增数据具备模型在训练时见过的特征。fillna用中位数是为了处理新采集数据可能存在的空值。特征列的顺序必须与原训练时feature_cols完全一致否则输入模型时列位置错位会得到错误预测结果。5.4 爬虫脚本的完善点如果没有现成的API_KEY用requests直接抓网页时需要处理编码和反爬。headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } resp requests.get(url, headersheaders, timeout10) resp.encoding utf-8headers模拟浏览器标识避免部分站点返回403状态码。resp.encoding手动指定解析编码防止中文乱码。这类方式适合作为演示补充不建议在生产环境长期使用因为页面结构一变脚本就要跟着改。GetData.py在这个项目里的最佳定位是数据补充而不是核心模块。6. 模型部署到本地运行时的几个关键检查6.1 readme.md里最容易遗漏的依赖清单把项目下载下来后自己动手跑一遍时最容易卡住的是环境依赖。天气预测的可复现要求每行代码都能在当前环境执行。readme.md里建议标注完整的依赖清单。pip install pandas numpy scikit-learn matplotlib requests python main.pypython main.py是项目入口它会读取训练好的Model.pkl并对test数据集做预测最终生成对比图和HTML页面。无论从哪个环节跑保证pandas版本不低于1.2、scikit-learn版本不低于0.24是一个安全边界。6.2 预测结果的验证方法模型能不能用最后要看预测值和真实值之间的偏差是否收敛。from sklearn.metrics import mean_absolute_error, r2_score mae mean_absolute_error(y_test, y_pred) r2 r2_score(y_test, y_pred) print(fMAE: {mae:.2f} ℃, R2: {r2:.3f})mean_absolute_error计算平均绝对误差单位仍是摄氏度用于直观描述平均偏差点数r2_score反映模型对真实值方差的解释比例越接近1越好。在天气预测场景下MAE低于2℃、R2高于0.85可以认为项目达到了课程设计比较优秀的水平。6.3 把jpg图表嵌入HTML展示的最终技巧最后收尾阶段要把六张以上的图整合到一份HTML中建议先统一输出尺寸。在遍历生成图表时固定figsize和dpi这样HTML里所有img元素可以共用一套CSS宽度设置页面效果更整洁。for idx, (col, dataseries) in enumerate(data_dict.items()): plt.figure(figsize(12, 5), dpi120) plt.plot(dataseries[date], dataseries[value]) plt.title(col) plt.savefig(fchart_{idx}.jpg) plt.close()enumerate同时拿到序号和内容f-string拼出文件名。plt.close每画一张图就关闭画布是为了释放内存否则循环画几十张图内存占用会持续累积。生成的chart_0.jpg、chart_1.jpg这类命名可以直接写进HTML模板用Python字符串替换批量生成页面代码不用手动一条条粘贴。本文还有配套的精品资源点击获取