Datawhale AI春训营:第三届世界科学智力竞赛新能源赛道baseline深度解读

LightGBM模型与数据处理策略

关键要点

  • 竞赛目标是预测10个新能源电站的功率输出,基于气象和历史数据,研究表明这对能源管理至关重要。
  • 数据包括气象变量(如风速、辐射)和功率输出,证据显示这些数据需处理以提高预测准确性。
  • baseline使用LightGBM模型,数据处理涉及空间平均和时间序列整合,研究表明其效率高但有优化空间。
  • 评估指标为RMSE和相关性系数(C_r),似乎是衡量预测性能的标准方法。

竞赛简介

第三届世界科学智力竞赛的新能源赛道聚焦于预测5个风电场和5个光伏电站的功率输出。这对构建现代电力系统、提升能源安全和促进可持续性有重要意义。竞赛从2025年2月持续到7月,分为初赛、半决赛和决赛,鼓励全球人才创新。

数据概述

竞赛提供气象数据(NWP_1、NWP_2、NWP_3),包括8个变量如风速(u100、v100)、温度(t2m)、辐射(ghi、poai)等,以NetCDF格式存储,每小时一次。功率数据为10个电站的实际输出,每15分钟一次,可能含缺失值需处理。

baseline解读

baseline是一个Python脚本,使用LightGBM进行回归预测,涉及:

  • 数据提取:从NetCDF文件计算空间平均值。
  • 数据预处理:整合气象和功率数据,按小时采样。
  • 模型训练:5折交叉验证,参数如学习率0.1、特征比例0.9。
  • 输出:生成10个CSV文件,匹配15分钟粒度。

LightGBM因其高效性和处理大规模数据的优势被选用,支持自动特征选择和缺失值处理。

评估与优化

评估指标为RMSE(均方根误差)和(C_r)(相关性系数),baseline通过(1/(1+\text{RMSE}))转换分数。优化方向包括特征工程(如风速幅值)、时间序列模型和模型融合。


详细报告

竞赛背景与目标

第三届世界科学智力竞赛由上海科学智力研究院和复旦大学主办,旨在通过科学和技术手段解决实际问题。新能源赛道特别聚焦于新能源发电功率预测,目标是预测10个新能源电站(5个风电场和5个光伏电站)的功率输出,基于气象数据和历史功率数据。竞赛从2025年2月持续到7月,分为注册、初赛、半决赛和决赛,团队可由1-3人组成,需通过上海智研院平台注册,强调公平性,禁止代码共享和使用外部数据。竞赛与南方电网调度控制中心合作,旨在提升预测准确性,构建灵活开放的新能源预测生态系统,对能源安全、经济效益和环境可持续性至关重要。

数据描述与处理

竞赛提供两种主要数据类型:

  • 气象数据:包括三个来源(NWP_1、NWP_2、NWP_3),包含8个变量:u100、v100(100米高度风速分量)、t2m(2米温度)、tcc(总云量)、tp(总降水量)、sp(地表压力)、ghi(全球水平辐射)、poai(阵面辐射)。数据以NetCDF格式存储,每小时一次,覆盖24小时,适合处理多维科学数据。
  • 功率数据:为10个电站的实际功率输出,每15分钟一次,数据已归一化,可能包含缺失值、异常值或负值,需参赛者处理。

baseline的处理步骤包括:

  • 数据提取:从NetCDF文件中提取气象数据,计算每个特征的11x11网格空间平均值,使用np.mean简化维度。
  • 数据预处理:将气象数据(每小时)和功率数据(每15分钟)整合,功率数据按小时采样,只保留每小时第一个数据点(“00:00”),确保时间序列一致。
  • 特征工程:baseline通过空间平均处理数据,但可进一步优化,如计算风速幅值( u 10 0 2 + v 10 0 2 \sqrt{u100^2 + v100^2} u1002+v1002 )、辐射比值(如ghi/poai),或加入时间特征(如小时、日期)。
baseline模型与实现

baseline是一个Python脚本,使用LightGBM进行回归预测,采用5折交叉验证。LightGBM参数设置如下:

参数名
boosting_type‘gbdt’
objective‘regression’
metric‘rmse’
num_leaves256
learning_rate0.1
feature_fraction0.9
bagging_fraction0.8
bagging_freq5
verbose100
num_threads8

LightGBM因其高效性被选用,训练速度快、内存占用低,适合处理大规模数据,支持自动特征选择和缺失值处理。模型训练后,预测结果重复四次以匹配15分钟粒度,生成10个CSV文件(output1.csv到output10.csv),对应10个电站。

评估指标与性能

竞赛评估指标包括:

  • RMSE:均方根误差,公式为 1 n ∑ i = 1 n ( P M , i − P P , i ) 2 \sqrt{\frac{1}{n} \sum_{i=1}^n (P_{M,i} - P_{P,i})^2} n1i=1n(PM,iPP,i)2 ,衡量预测值与实际值的差异。
  • (C_r):相关性系数,公式为 ( 1 − 1 n ∑ i = 1 n ( P M , i − P P , i ) 2 max ⁡ ( P M , i , 0.2 ) ) × 100 % \left(1 - \sqrt{\frac{1}{n} \sum_{i=1}^n \frac{(P_{M,i} - P_{P,i})^2}{\max(P_{M,i}, 0.2)}}\right) \times 100\% (1n1i=1nmax(PM,i,0.2)(PM,iPP,i)2 )×100%,评估预测与实际值的相关性。

baseline的RMSE得分通过公式 1 / ( 1 + RMSE ) 1/(1+\text{RMSE}) 1/(1+RMSE)转换,确保分数越高表示性能越好。

深入分析与优化方向

baseline提供了一个高效起点,但有优化空间:

  1. 特征工程:可提取更多特征,如风速幅值、辐射比值,或分析气象变量间的关系(如ghi与poai的正比性)。
  2. 时间序列处理:数据具有时间序列特性,可考虑ARIMA、LSTM等模型,或加入时间窗口特征。
  3. 模型融合:结合LightGBM、XGBoost、CatBoost的预测结果,可能提高性能。
  4. 异常值处理:baseline仅删除含缺失值的行,可进一步使用插值或异常值检测提升数据质量。
总结与展望

通过对baseline的解读,我们了解了竞赛数据的结构、baseline的实现方式及其潜在优化方向。baseline为参赛者提供了一个高效且易于理解的起点,但要取得更好成绩,需对数据进行更深入分析和处理。希望本文能为参赛者提供有价值的insights,帮助大家在竞赛中取得佳绩。

第二部分:代码详细解读

关键要点

  • 以下是baseline代码的逐段详细解读,涵盖数据解压、库安装、数据处理、模型训练和结果保存。
  • 解读基于提供的baseline代码,重点解释每段代码的功能和逻辑。
  • 研究表明,baseline使用LightGBM模型,数据处理涉及空间平均和时间序列整合,适合新能源功率预测任务。

解压缩和准备

baseline代码首先通过 unzip 命令解压比赛数据集,包括测试集、训练集和输出示例文件,解压到 data 目录,确保数据文件准备就绪。

库安装和导入

然后,安装必要的Python库(如numpy、pandas、netCDF4、lightgbm、scikit-learn),并导入这些库,用于后续数据处理和模型训练。

数据读取和预处理

代码读取NetCDF格式的气象数据,提取通道信息和气象数据,计算每个气象要素的空间平均值,并转换为DataFrame格式。训练和测试数据分别按日期范围生成,功率数据处理只保留整点数据。

模型训练和预测

使用LightGBM模型进行5折交叉验证训练,设置参数如学习率0.1、特征抽样比例0.8等。预测结果重复4次以匹配15分钟粒度,最终生成10个CSV文件。

结果保存和打包

预测结果保存为CSV文件,生成10个输出文件,并打包为zip格式,方便提交。



详细报告

引言

本文详细解读第三届世界科学智力竞赛新能源赛道baseline代码,代码基于Python实现,涵盖数据解压、预处理、模型训练和结果生成。baseline使用LightGBM模型,数据处理涉及空间平均和时间序列整合,适合新能源发电功率预测任务。以下按代码段逐一分析,帮助参赛者理解其逻辑和优化方向。

代码逐段解读
1. 解压缩比赛数据集文件
# 解压缩比赛数据集文件
!unzip -d data data/初赛测试集.zip  # 解压测试集数据到data目录
!unzip -d data data/初赛训练集.zip  # 解压训练集数据到data目录
!unzip -d data data/output.zip     # 解压输出示例文件到data目录
  • 功能: 使用 unzip 命令解压比赛提供的三个zip文件,包括测试集、训练集和输出示例文件,解压到 data 目录。
  • 解释: 这一步确保所有数据文件(如NetCDF格式的气象数据和CSV格式的功率数据)都已准备好,方便后续读取和处理。
2. 安装必要的Python库
# 安装必要的Python库
%pip install numpy==2.2.4 pandas==2.2.3 netCDF4==1.7.2 lightgbm==4.6.0 scikit-learn==1.6.1
  • 功能: 安装特定版本的Python库,包括 numpypandasnetCDF4lightgbmscikit-learn
  • 解释: 这些库分别用于数值计算、数据操作、读取NetCDF文件、机器学习建模和评估。版本固定确保环境一致性。
3. 导入所需的库
# 导入所需的库
from netCDF4 import Dataset  # 用于读取NC格式的气象数据
import numpy as np
import pandas as pd
  • 功能: 导入 netCDF4Dataset 类用于读取NetCDF文件,numpypandas 用于数据处理。
  • 解释: 这些库是后续数据读取和处理的基石,netCDF4 特别适合处理气象数据。
4. 读取示例NC文件,了解数据结构
# 读取示例NC文件,了解数据结构
nc_path = "data/初赛训练集/nwp_data_train/1/NWP_1/20240101.nc"  # 指定NC文件路径
dataset = Dataset(nc_path, mode='r')  # 以只读模式打开NC文件
dataset.variables.keys()  # 查看NC文件中的变量名
  • 功能: 打开一个示例NetCDF文件,查看其变量名。
  • 解释: 这一步帮助理解数据结构,通常包含 “channel”(气象要素)和 “data”(气象数据)等变量。
5. 获取通道信息(气象要素)
# 获取通道信息(气象要素)
channel = dataset.variables["channel"][:]  # 提取通道变量
channel  # 显示通道信息
  • 功能: 提取 “channel” 变量,通常包含8个气象要素的名称。
  • 解释: 这些要素如风速、温度、辐射等,是后续特征工程的基础。
6. 获取气象数据
# 获取气象数据
data = dataset.variables["data"][:]  # 提取数据变量
data.shape  # 显示数据形状,了解数据维度
  • 功能: 提取 “data” 变量,查看其形状。
  • 解释: 数据维度可能包括时间、高度、纬度、经度和通道,形状信息帮助理解数据结构。
7. 计算每个通道的平均值
# 计算每个通道的平均值
# 对每个气象要素(8个通道),计算其在空间维度上的平均值
mean_values = np.array([np.mean(data[:, :, i, :, :][0], axis=(1, 2)) for i in range(8)]).T
mean_values.shape  # 显示处理后的数据形状
  • 功能: 计算8个气象要素的空间平均值。
  • 解释: 使用 np.mean 对空间维度(纬度、经度)求平均,简化数据为每个要素的单值,.T 转置数组以便后续处理。
8. 将平均值数据转换为DataFrame格式
# 将平均值数据转换为DataFrame格式
df_day = pd.DataFrame(mean_values, columns=channel)
df_day  # 显示DataFrame,每列对应一个气象要素
  • 功能: 将numpy数组转换为pandas DataFrame。
  • 解释: 每列对应一个气象要素,方便后续数据合并和分析。
9. 生成日期范围,用于读取训练数据
# 生成日期范围,用于读取训练数据
date_range = pd.date_range(start='2024-01-01', end='2024-12-30')  # 创建从2024-01-01到2024-12-30的日期范围
date = [date.strftime('%Y%m%d') for date in date_range]  # 将日期格式化为'YYYYMMDD'格式
date[:5]  # 显示前5个日期,检查格式
  • 功能: 生成训练数据的日期范围。
  • 解释: 从2024年1月1日到12月30日,格式化为 ‘YYYYMMDD’,如 ‘20240101’,用于后续文件路径。
10. 定义函数,用于从NC文件中提取数据并计算平均值
# 定义函数,用于从NC文件中提取数据并计算平均值
def get_data(path_template, date):
    dataset = Dataset(path_template.format(date), mode='r')  # 打开指定日期的NC文件
    channel = dataset.variables["channel"][:]  # 获取通道信息
    data = dataset.variables["data"][:]  # 获取数据
    mean_values = np.array([np.mean(data[:, :, i, :, :][0], axis=(1, 2)) for i in range(8)]).T  # 计算平均值
    return pd.DataFrame(mean_values, columns=channel)  # 返回DataFrame格式的数据
  • 功能: 定义函数 get_data,读取指定日期的NetCDF文件,计算平均值。
  • 解释: 这一函数封装了数据读取和预处理的逻辑,方便批量处理多个日期。
11. 读取所有训练日期的数据
# 读取所有训练日期的数据
train_path_template = "data/初赛训练集/nwp_data_train/1/NWP_1/{}.nc"  # 训练数据路径模板
data = [get_data(train_path_template, i) for i in date]  # 对每个日期应用get_data函数
train = pd.concat(data, axis=0).reset_index(drop=True)  # 将所有日期的数据合并为一个DataFrame
train.shape  # 显示训练数据的形状
  • 功能: 读取所有训练数据,合并为一个DataFrame。
  • 解释: 使用列表推导式批量处理,pd.concat 纵向合并,reset_index 重置索引,shape 查看维度。
12. 读取目标变量(功率数据)
# 读取目标变量(功率数据)
target = pd.read_csv("data/初赛训练集/fact_data/1_normalization_train.csv")
target = target[96:]  # 跳过前96行数据
# 功率数据中每四条数据取一条(只保留整点数据)
target = target[target['时间'].str.endswith('00:00')]
target = target.reset_index(drop=True)  # 重置索引
target.head()  # 显示前几行数据
  • 功能: 读取功率数据,处理时间序列。
  • 解释: 跳过前96行,筛选整点数据(‘00:00’),确保与气象数据的时间粒度一致。
13. 读取测试数据
# 读取测试数据
test_path_template = "data/初赛测试集/nwp_data_test/1/NWP_1/{}.nc"  # 测试数据路径模板

# 生成测试日期范围
date_range = pd.date_range(start='2024-12-31', end='2025-02-27')
date = [date.strftime('%Y%m%d') for date in date_range]
date[:5]  # 显示前5个测试日期
  • 功能: 生成测试数据的日期范围。
  • 解释: 测试数据从2024年12月31日到2025年2月27日,格式化为 ‘YYYYMMDD’。
14. 读取所有测试日期的数据
# 读取所有测试日期的数据
data = [get_data(test_path_template, i) for i in date]  # 对每个测试日期应用get_data函数
test = pd.concat(data, axis=0).reset_index(drop=True)  # 将所有测试日期的数据合并
test.shape  # 显示测试数据的形状
  • 功能: 读取所有测试数据,合并为DataFrame。
  • 解释: 与训练数据处理类似,确保测试数据格式一致。
15. 导入模型训练和评估所需的库
# 导入模型训练和评估所需的库
from sklearn.model_selection import KFold  # 用于交叉验证
from sklearn.metrics import mean_squared_error  # 用于计算均方误差
import lightgbm as lgb  # 使用LightGBM模型
  • 功能: 导入交叉验证、评估和建模所需的库。
  • 解释: KFold 用于5折交叉验证,mean_squared_error 计算RMSE,lightgbm 是核心模型。
16. 定义交叉验证模型训练函数
# 定义交叉验证模型训练函数
def cv_model(clf, train_x, train_y, test_x, seed):
    # 5折交叉验证
    folds = 5
    kf = KFold(n_splits=folds, shuffle=True, random_state=seed)  # 创建K折交叉验证对象
    oof = np.zeros(train_x.shape[0])  # 存储训练集上的预测结果
    test_predict = np.zeros(test_x.shape[0])  # 存储测试集上的预测结果
    cv_scores = []  # 存储每折的评分
    
    # 进行K折交叉验证
    for i, (train_index, valid_index) in enumerate(kf.split(train_x, train_y)):
        print('************************************ {} ************************************'.format(str(i+1)))
        # 划分训练集和验证集
        trn_x, trn_y, val_x, val_y = train_x.iloc[train_index], train_y[train_index], train_x.iloc[valid_index], train_y[valid_index]
        
        # 创建LightGBM数据集
        train_matrix = clf.Dataset(trn_x, label=trn_y)
        valid_matrix = clf.Dataset(val_x, label=val_y)
        
        # 设置LightGBM模型参数
        params = {
            'boosting_type': 'gbdt',  # 使用梯度提升决策树
            'objective': 'regression',  # 回归任务
            'metric': 'rmse',  # 使用均方根误差作为评估指标
            'min_child_weight': 5,  # 最小叶子节点样本权重和
            'num_leaves': 256,  # 叶子节点数量
            'lambda_l2': 10,  # L2正则化系数
            'feature_fraction': 0.8,  # 特征抽样比例
            'bagging_fraction': 0.8,  # 样本抽样比例
            'bagging_freq': 4,  # 抽样频率
            'learning_rate': 0.1,  # 学习率
            'nthread' : 16,  # 使用的线程数
            'verbose' : -1,  # 不显示训练信息
        }
        
        # 训练模型
        model = clf.train(params, train_matrix, 3000, valid_sets=[train_matrix, valid_matrix])
        
        # 预测验证集和测试集
        val_pred = model.predict(val_x, num_iteration=model.best_iteration)
        test_pred = model.predict(test_x, num_iteration=model.best_iteration)
        
        # 存储预测结果
        oof[valid_index] = val_pred
        # 将每个模型结果加权并相加
        test_predict += test_pred / kf.n_splits
        
        # 计算评分(1/(1+RMSE))
        score = 1/(1+np.sqrt(mean_squared_error(val_pred, val_y)))
        cv_scores.append(score)
        print(cv_scores)
            
    return oof, test_predict
  • 功能: 定义 cv_model 函数,使用5折交叉验证训练LightGBM模型。
  • 解释: 参数包括学习率0.1、特征抽样比例0.8等,评估指标为1/(1+RMSE),适合竞赛的评分规则。
17. 训练模型并生成预测结果
# 设置随机种子并训练模型
seed = np.random.randint(0, 10000)  # 随机生成种子
lgb_oof, lgb_test = cv_model(lgb, train, target['功率(MW)'], test, seed)  # 训练模型并获取预测结果

# 将测试集预测结果重复4次(恢复到原始时间粒度)
lgb_test = [item for item in lgb_test for _ in range(4)]
  • 功能: 训练模型,生成预测结果,并调整时间粒度。
  • 解释: 预测结果重复4次以匹配15分钟粒度,符合功率数据的原始格式。
18. 保存预测结果
# 保存预测结果
import os
if not os.path.exists("output"):  # 如果output目录不存在,则创建
    os.makedirs("output")
    
# 读取输出模板文件
output = pd.read_csv("data/output/output1.csv").reset_index(drop=True)
output["power"] = lgb_test  # 将预测结果填入power列
output.rename(columns={'Unnamed: 0': ''}, inplace=True)  # 重命名列
output.set_index(output.iloc[:, 0], inplace=True)  # 设置索引
output = output.drop(columns=["0", ""])  # 删除不需要的列

# 生成10个输出文件(比赛要求)
for i in range(1, 11):
    output.to_csv('output/output'+ str(i) + '.csv')
  • 功能: 保存预测结果为CSV文件,生成10个输出文件。
  • 解释: 符合比赛要求,每个文件对应一个电站的预测结果。
19. 将输出文件打包为zip格式
# 将输出文件打包为zip格式,用于提交
!zip -r output.zip output
  • 功能: 将输出文件打包为zip格式。
  • 解释: 方便参赛者提交结果,符合比赛提交规范。
总结与优化建议

baseline代码实现了从数据读取到结果生成的完整流程,核心使用LightGBM模型,数据处理包括空间平均和时间序列整合。优化方向包括:

  • 特征工程:提取风速幅值、辐射比值等。
  • 时间序列模型:尝试ARIMA、LSTM等。
    有关深度学习,baseline创建者建议“深度学习问题 :因训练集数据量少(单个场站 8760 条,深度学习小模型最好需 10 万条以上数据),使用深度学习可能过拟合,做好数据工程机器学习表现不次于深度学习。
  • 模型融合:结合XGBoost、CatBoost提升性能。
关键参数表

以下是LightGBM模型的部分关键参数:

参数名说明
boosting_type‘gbdt’使用梯度提升决策树
objective‘regression’回归任务
metric‘rmse’均方根误差
learning_rate0.1学习率
feature_fraction0.8特征抽样比例
结论

通过对baseline代码的详细解读,参赛者可以理解其实现逻辑,并在此基础上进行优化。希望本文能为参赛者提供有价值的参考。


关键引用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值