☰
电力AI数据挖掘管道实战:从扬中大赛数据集到可复现建模流水线
2026/9/26 20:10:32 网站建设 项目流程

简介:本资源面向计算机、人工智能、自动化等专业学生与开发者,提供基于大航杯“智造扬中”电力AI大赛的数据挖掘管道搭建完整示例,适合作为毕业设计、课程设计、竞赛复现或项目立项参考。压缩包共32个文件,约3.72MB,以22个ipynb交互式笔记为核心,配合4个py脚本、3个csv数据表、2个txt说明及1个md文档,覆盖数据清洗、特征提取、模型训练与结果预测等环节。已有44人学习下载。资源内含详细文档与全部源码,可帮助读者理解从原始数据到预测输出的完整流程,掌握特征工程、样本划分与规则提取等关键思路,并支持在此基础上修改扩展,实现其他功能或直接用于毕设、课设与作业。

1. 电力AI数据挖掘管道:从扬中大赛数据集到可复现的建模流水线

手上这份electricAI-master压缩包,是我近期拆过比较完整的一个电力赛题工程。它来自大航杯“智造扬中”电力AI大赛,核心不是某个炫技模型,而是一条从原始 CSV 到预测结果的数据挖掘管道。很多人做电力负荷预测,卡点从来不在算法本身,而在数据怎么清洗、特征怎么拼、节假日和天气怎么对齐——这套源码恰好把这几件事串成了可跑的流程。它适合计算机、人工智能、自动化方向的学生做课设毕设,也适合刚接触电力AI的工程师拿来当管道模板。下面我按“资源是什么、怎么跑、坑在哪”的顺序,把这份dataset加code的工程拆开讲清楚。

2. 数据集与代码结构:先看清 yangzhong.csv 和 train.csv 的关系

2.1 数据文件到底装了什么

压缩包里的dataset目录是整条管道的起点,几个 CSV 各有分工,不能混着读。yangzhong.csv是扬中地区的原始电力负荷记录,通常带时间戳和负荷值;train.csv是切分后用于建模的训练样本;holiday.csv存的是节假日标记,用来给时间特征打标签。这三者构成了“原始数据 → 训练样本 → 外部特征”的基本三角。

我一般会先跑一遍字段探查,确认时间列格式和缺失情况,再决定后续清洗策略。常见做法是用 pandas 快速看结构:

import pandas as pd # 先摸清每个文件的字段和规模,别急着建模 for name in ["yangzhong", "train", "holiday"]: df = pd.read_csv(f"dataset/{name}.csv") print(name, df.shape) print(df.dtypes) print(df.head(3)) print("-" * 40)

这段代码的逻辑是先看形状、再看类型、最后看前几行,目的是判断时间列是字符串还是已解析的 datetime、负荷列有没有异常值。参数上没什么可调的,重点是dtypes输出——如果时间列显示为object,后面所有基于时间的特征都会翻车,必须先pd.to_datetime转换。

2.2 代码目录的模块划分

code目录里文件不少,但按职责能分成四类。清洗类:clean_data.py、clean_data.ipynb;特征类:combine_fetures.ipynb、extract_fetures.py、extract_fetures.ipynb、trick_extract.py、trick_extract.ipynb;采集类:weather_crawl.py、holiday_crawl.py;建模与输出类:split_samples.ipynb、train_model.ipynb、predict_result.ipynb、run.ipynb、rules.ipynb、visualize.ipynb。注意文件名里fetures是拼写笔误,但工程里就是这么命名的,引用时别自作主张改成features,否则 import 直接报错。

run.ipynb是总入口,result.txt是预测输出,README.md给的是运行说明。我的习惯是先读README.md再动代码,因为这类赛题工程的依赖顺序往往写在里面,跳过它容易在combine_fetures阶段就因为缺列而崩。

2.3 环境依赖与运行顺序

这套代码是 Python 技术栈,依赖 pandas、numpy、scikit-learn,采集脚本还会用到 requests 和解析库。建议单独建虚拟环境,避免和系统里的包版本打架:

python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install pandas numpy scikit-learn requests beautifulsoup4 jupyter

装完后按clean_data → extract_fetures → combine_fetures → split_samples → train_model → predict_result的顺序执行。run.ipynb可以一次性串起来,但我更建议先逐个跑通,因为中间任何一步的列名对不上,整条管道都会断,逐个跑能快速定位是哪一环出的问题。

3. 数据清洗与特征工程:clean_data 到 combine_fetures 的落地细节

3.1 清洗脚本在做什么

clean_data.py承担的是去重、缺失填充和异常值处理。电力负荷数据常见的脏点是:某段时间采集器掉线导致整段缺失、节假日负荷骤降被误判为异常、时间戳重复。清洗的核心不是把数据洗得“好看”,而是保证时间序列连续且负荷值在合理区间。

我一般会这样处理缺失和异常:

import pandas as pd import numpy as np df = pd.read_csv("dataset/yangzhong.csv") df["time"] = pd.to_datetime(df["time"]) df = df.sort_values("time").drop_duplicates("time") # 负荷列做前后向填充,再对极端值做截断 df["load"] = df["load"].interpolate(method="linear") q1, q3 = df["load"].quantile([0.25, 0.75]) iqr = q3 - q1 low, high = q1 - 3 * iqr, q3 + 3 * iqr df["load"] = df["load"].clip(low, high)

逻辑说明:先转时间类型并排序去重,保证时序单调;interpolate用线性插值补缺失,比直接填均值更贴合负荷的连续变化;IQR 截断把极端离群值压回合理范围。参数上3 * iqr是放宽后的阈值,电力数据波动大,用 1.5 倍容易把真实高峰误杀,这点和普通统计清洗不一样。

3.2 特征提取的几类构造

extract_fetures.py和trick_extract.py负责把时间戳拆成可建模的特征。电力负荷预测里,时间特征是最强的一类:小时、星期、是否周末、是否节假日。trick_extract里通常还会加滑窗统计,比如前 1 天同一时刻的负荷、前 7 天均值,这些滞后特征对预测精度影响很大。

构造时间特征的常见写法:

df["hour"] = df["time"].dt.hour df["weekday"] = df["time"].dt.weekday df["is_weekend"] = (df["weekday"] >= 5).astype(int) # 合并节假日标记 holiday = pd.read_csv("dataset/holiday.csv") holiday["date"] = pd.to_datetime(holiday["date"]).dt.date df["date"] = df["time"].dt.date df = df.merge(holiday[["date", "is_holiday"]], on="date", how="left") df["is_holiday"] = df["is_holiday"].fillna(0).astype(int)

这里的关键是 merge 的键要对齐到“日期”粒度,因为节假日是按天标记的,而负荷是按小时或更细粒度记录的。how="left"保证不丢负荷记录,fillna(0)把非节假日补成 0。如果 holiday.csv 的日期格式和主表不一致,merge 后is_holiday会全是 NaN,这是最常见的翻车点之一。

3.3 combine_fetures 的拼接逻辑

combine_fetures.ipynb把清洗后的负荷、时间特征、节假日、天气拼成一张宽表。天气数据来自weather_crawl.py采集,通常包含温度、湿度。拼接时最容易出问题的是时间对齐——天气是按天或按小时,负荷可能是 15 分钟粒度,直接 merge 会产生大量重复行。

我的做法是先把所有外部特征统一到同一时间粒度,再横向拼接:

# 统一到小时粒度后再合并,避免行数膨胀 df["hour_key"] = df["time"].dt.floor("h") weather["hour_key"] = pd.to_datetime(weather["time"]).dt.floor("h") merged = df.merge(weather[["hour_key", "temp", "humidity"]], on="hour_key", how="left") merged = merged.drop(columns=["hour_key"])

dt.floor("h")把时间向下取整到小时,作为对齐键。这样即使原始粒度不同,也能在小时级别对齐。参数上how="left"保留全部负荷记录,天气缺失的地方留 NaN,后续建模时再决定填充还是丢弃。这一步做完,combine_fetures输出的宽表就是split_samples的输入。

4. 样本切分与模型训练:split_samples 和 train_model 怎么配合

4.1 训练测试集的切分原则

split_samples.ipynb做的是把宽表切成训练集和测试集。时间序列不能随机切分,否则会用未来数据预测过去,造成精度虚高。正确做法是按时间顺序切,比如前 80% 做训练、后 20% 做测试。

merged = merged.sort_values("time").reset_index(drop=True) split_idx = int(len(merged) * 0.8) train = merged.iloc[:split_idx] test = merged.iloc[split_idx:] # 特征列和标签列分开 feature_cols = [c for c in train.columns if c not in ["time", "load"]] X_train, y_train = train[feature_cols], train["load"] X_test, y_test = test[feature_cols], test["load"]

逻辑上先排序再按位置切,保证训练集时间早于测试集。feature_cols用排除法挑,把时间列和标签列剔掉。参数0.8是经验比例,数据量小可以调到 0.7,给测试集留够样本。如果这里用了train_test_split的默认随机切分,测试集精度会明显偏高,上线就露馅。

4.2 train_model 的模型选择

train_model.ipynb里通常会用树模型或线性回归做基线。电力负荷预测里,梯度提升树(如 LightGBM、XGBoost)对表格特征表现稳定,训练快、调参少。如果工程里用的是 sklearn 的GradientBoostingRegressor或RandomForestRegressor,也够用。

from sklearn.ensemble import GradientBoostingRegressor from sklearn.metrics import mean_absolute_error model = GradientBoostingRegressor( n_estimators=300, learning_rate=0.05, max_depth=4, random_state=42 ) model.fit(X_train, y_train) pred = model.predict(X_test) print("MAE:", mean_absolute_error(y_test, pred))

参数说明:n_estimators=300是树的数量,太少欠拟合、太多过拟合;learning_rate=0.05配合 300 棵树是比较稳的组合;max_depth=4控制单棵树复杂度,电力特征维度不高,深度太大会记住噪声。random_state固定后结果可复现,方便对比不同特征组合的效果。

4.3 预测结果输出与 result.txt

predict_result.ipynb把模型输出写成result.txt,格式一般是一行一个预测值,或者带时间戳的键值对。这个文件是提交或验收的产物,格式必须和赛题要求一致。我见过有人模型跑得不错,但result.txt多了一列索引或表头,直接判格式错误。

result = pd.DataFrame({"time": test["time"].values, "predict": pred}) result.to_csv("result.txt", index=False, header=False)

index=False去掉 pandas 自动加的行号,header=False去掉列名,这两点取决于赛题格式要求。如果要求带表头,就把header改成True。输出前一定用head看一眼,别让一个格式问题毁掉整条管道。

5. 避坑与排查:这套管道最容易翻车的五个地方

5.1 时间列没解析导致特征全错

现象:df["time"].dt.hour报错AttributeError: Can only use .dt accessor with datetimelike values。原因是 CSV 读进来时间列是字符串。解决:读文件后立刻pd.to_datetime,并加errors="coerce"检查有没有解析失败的脏时间戳,失败的行要单独看。

5.2 节假日 merge 后全是 NaN

现象:合并 holiday.csv 后is_holiday整列缺失。原因是两边日期格式不一致,一边是2023-01-01,另一边是2023/01/01。解决:merge 前统一用pd.to_datetime(...).dt.date转成同一种日期对象,再对齐键。

5.3 天气数据粒度不一致导致行数膨胀

现象:合并天气后数据行数翻了好几倍。原因是天气按天、负荷按小时,直接 merge 变成笛卡尔积。解决:先把两边都dt.floor到同一粒度再合并,合并后检查shape是否和原表接近。

5.4 随机切分造成精度虚高

现象:测试集 MAE 很低,但换一段新数据预测就很差。原因是用了随机切分,训练集里混入了未来信息。解决:按时间排序后顺序切分,训练集时间必须早于测试集,这是时间序列建模的铁律。

5.5 文件名拼写 fetures 导致 import 失败

现象:from extract_fetures import ...报ModuleNotFoundError。原因是工程里文件名就是fetures而非features。解决:引用时严格照抄工程里的文件名,别按正确拼写去改,改了就找不到模块。

6. 进阶技巧:用 rules.ipynb 做后处理校正与结果验证

rules.ipynb是这套工程里容易被忽略但很实用的一环。模型预测出来的负荷曲线有时会在节假日或极端天气下偏离常识,比如凌晨负荷预测成白天高峰。规则后处理就是拿业务常识去兜底:节假日整体下调、夜间负荷设上限、连续突变做平滑。

我一般会写一层简单的规则校正:

# 对预测结果做业务规则校正 pred = pd.Series(pred, index=test.index) # 节假日预测值整体下调 10% holiday_mask = test["is_holiday"] == 1 pred[holiday_mask] = pred[holiday_mask] * 0.9 # 夜间负荷不超过当日均值的 1.2 倍 night_mask = test["hour"].isin([0, 1, 2, 3, 4, 5]) daily_mean = pred.mean() pred[night_mask] = np.minimum(pred[night_mask], daily_mean * 1.2)

逻辑说明:第一层按节假日标记做比例下调,因为节假日负荷普遍低于工作日;第二层给夜间负荷设上限,防止模型在缺失特征时给出离谱高值。参数0.9和1.2不是拍脑袋,要结合visualize.ipynb画出的历史曲线来定——先看真实节假日相对工作日的降幅,再决定系数。

验证方法上,我习惯把校正前后的预测和真实值画在同一张图上对比:

import matplotlib.pyplot as plt plt.plot(test["time"], y_test.values, label="real") plt.plot(test["time"], pred.values, label="corrected") plt.legend() plt.savefig("check.png")

看图比看 MAE 更直观,能发现指标掩盖掉的系统性偏差。如果校正后曲线在某个时段整体偏高或偏低,说明规则系数需要再调,或者特征里缺了关键变量。

这套管道我跑下来最大的体会是:电力AI项目的成败八成在数据对齐和特征构造,模型只是最后一步。从那以后我每次拿到新的负荷数据集,都强制先走一遍“时间解析 → 粒度统一 → 顺序切分”这三步检查,再谈建模。希望这份拆解帮到你,需要完整源码和数据集的话,按工程里的README.md说明拉下来跑一遍,比只看文档收获大得多。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询