iFLYTEK2024电力需求预测挑战赛暨LightGBM模型

一、赛题描述

赛题:电力需求预测挑战赛
主办方:科大讯飞xDatawhale
主页:https://challenge.xfyun.cn/topic/info?type=electricity-demand&option=ssgy

背景

随着全球经济的快速发展和城市化进程的加速,电力系统面临着越来越大的挑战。电力需求的准确预测对于电网的稳定运行、能源的有效管理以及可再生能源的整合至关重要。

然而,电力需求受到多种因素的影响,为了提高电力需求预测的准确性和可靠性,推动智能电网和可持续能源系统的发展,本场以“电力需求预测”为赛题的数据算法挑战赛。选手需要根据历史数据构建有效的模型,能够准确的预测未来电力需求。

任务

给定多个房屋对应电力消耗历史N天的相关序列数据等信息,预测房屋对应电力的消耗。

二、数据集说明

赛题数据由训练集、测试集、事件数据组成。总设备id超过2w,包含设备信息、APP信息和事件信息,其中device_id为用户的唯一标识符,gender为用户性别,age为用户年龄。

为了保证比赛的公平性,将会从中抽取2w条设备id为训练集,3千多个设备id作为测试集,同时会对部分字段信息进行脱敏。

特征字段字段描述
device_id用户对应设备号,唯一表示,无重复
gender用户性别,0为男性,1为女性
age用户年龄
phone_brand手机品牌
device_model手机型号
event_id事件id
app_id应用程序id
is_installed是否安装
is_active是否激活
tag_list应用程序的标签列表
date事件发生日期

数据集版权许可协议

BY-NC-SA 4.0
https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans

三、解决方案样例

导入相关系统库

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import gc
import seaborn as sns
from sklearn.model_selection import KFold
from sklearn.metrics import mean_absolute_error
import lightgbm as lgbm

【本样例运行环境的关键版本信息】

python 3.12.3

lightgbm 3.3.0

seaborn 0.13.2

读入数据集

data_path = './data/'
df_tr            = pd.read_csv(data_path + 'train.csv')
df_tr_app_events = pd.read_csv(data_path + 'train_app_events.csv')
df_te            = pd.read_csv(data_path + 'test.csv')
df_te_app_events = pd.read_csv(data_path + 'test_app_events.csv')

分析数据

df_tr_te_app_events.head()

df_tr['gender'].value_counts().plot(kind = 'bar')

特征工程

df_tr_te_app_events['tag_list_len'] = df_tr_te_app_events['tag_list'].apply(lambda x: x.count(',') + 1)

agg_dic = {
    "event_id": ['count', 'nunique'],
    "app_id": ['nunique'], 
    "is_installed": ['mean', 'sum'],
    "is_active": ['mean', 'sum'],
    "date": ['max', 'nunique'],
    "tag_list_len": ['mean', 'std'] 
}

df_device_features = df_tr_te_app_events.groupby('device_id').agg(agg_dic).reset_index()
fea_names = ['_'.join(c) for c in df_device_features.columns]
df_device_features.columns = fea_names
df_device_features.rename(columns = {'device_id_':'device_id'}, inplace = True)

LighGBM 模型训练和预测

# gender 模型
lgb_params = {
    "objective": "binary",  # 定义学习任务和相应的学习目标。"binary" 表示这是一个二分类任务
    "metric": "auc",  # 评估模型性能的指标。"auc": 曲线下面积,衡量模型的区分能力
    "boosting_type": "gbdt",  # 定义提升类型。"gbdt" 是梯度提升决策树的默认类型,适用于大多数情况
    "early_stopping_rounds": 50,  # 在验证集上监控模型的性能,如果在指定的轮数内性能没有提升,则提前停止训练,防止过拟合
    "learning_rate": 0.05,  # 控制每一步的步长,较小的学习率需要更多的迭代次数
    "colsample_bytree": 0.8,  # 每棵树随机采样的列数比例。0.8 表示每棵树使用 80% 的特征
    "max_depth": 7,  # 控制每棵树的最大深度,防止过拟合
    "num_leaves": 63,  # 调整为 2^max_depth - 1 或其他合适的值
    "lambda_l1": 0.1,  # L1 正则化参数,用于控制模型的稀疏性,促使部分特征的权重降为零
    "lambda_l2": 0.1,  # L2 正则化参数,用于防止模型权重过大,减少过拟合
    "force_col_wise": True  # 强制使用按列(特征)的多线程方式,提升并行计算的效率
}

X_tr_val = df_tr[tr_features + [label_gender]]
X_te     = df_te[tr_features]

kf = KFold(n_splits=5)
lgb_gender_models = []
y_pred = 0

for f, (tr_ind,val_ind) in enumerate(kf.split(X_tr_val)):
    X_train, X_valid = X_tr_val.iloc[tr_ind][tr_features], X_tr_val.iloc[val_ind][tr_features]
    y_train, y_valid = X_tr_val.iloc[tr_ind][label_gender], X_tr_val.iloc[val_ind][label_gender]

    lgbm_train = lgbm.Dataset(X_train, y_train)
    lgbm_valid = lgbm.Dataset(X_valid, y_valid)

    model_binary = lgbm.train(params = lgb_params,
                              train_set = lgbm_train,
                              valid_sets = [lgbm_train, lgbm_valid],
                              num_boost_round = 100000)
    y_pred += model_binary.predict(X_te[tr_features]) / 5.0
    lgb_gender_models.append(model_binary)
# age 模型
def feval_lgb_Age(preds, lgbm_train):
    labels = lgbm_train.get_label()
    return 'Age Error', round(1.0 / (1.0 + mean_absolute_error(y_true = labels, y_pred = preds)), 7), True

lgb_params = {
    "objective": "mae",  # 指定回归任务的目标函数为平均绝对误差 (Mean Absolute Error, MAE)
    "metric": ["mae", "mse"],  #  在训练过程中监控多个评估指标。MAE 作为主要指标,MSE 作为辅助指标
    "boosting_type": "gbdt",  # 使用梯度提升决策树 (Gradient Boosting Decision Tree, GBDT) 作为提升类型
    "learning_rate": 0.05,  # 控制每一步的步长,较小的学习率需要更多的树
    "max_depth": 7,  # 控制每棵树的最大深度,防止过拟合
    "num_leaves": 63,  # 调整为 2^max_depth - 1 或其他合适的值
    "subsample": 0.8,  # 每棵树使用的样本比例,防止过拟合
    "colsample_bytree": 0.9,  # 每棵树使用的特征比例,防止过拟合
    "min_child_samples": 20,  # 每个叶子节点最少需要的样本数,控制树的复杂度
    "reg_alpha": 0.1,  #  L1 正则化参数,促使部分特征权重为零,实现特征选择
    "reg_lambda": 0.1,  # L2 正则化参数,防止特征权重过大,减少过拟合
    "early_stopping_rounds": 50,  # 在验证集上监控性能,若在连续 50 轮内性能未提升,则提前停止训练
    "force_col_wise": True,  # 强制使用按列(特征)的多线程方式,提升并行计算效率
    "random_state": 42,  # 设置随机种子以确保可重复性
}

X_tr_val = df_tr[tr_features + [label_age]]
X_te     = df_te[tr_features]

kf = KFold(n_splits=5)
lgb_age_models = []
y_pred = 0

for f, (tr_ind, val_ind) in enumerate(kf.split(X_tr_val)):
    X_train, X_valid = X_tr_val.iloc[tr_ind][tr_features], X_tr_val.iloc[val_ind][tr_features]
    y_train, y_valid = X_tr_val.iloc[tr_ind][label_age], X_tr_val.iloc[val_ind][label_age]

    lgbm_train = lgbm.Dataset(X_train, y_train)
    lgbm_valid = lgbm.Dataset(X_valid, y_valid)

    model_mae = lgbm.train(params = lgb_params,
                           train_set = lgbm_train,
                           valid_sets = [lgbm_train, lgbm_valid],
                           num_boost_round = 100000,
                           feval = feval_lgb_Age)
    y_pred += model_mae.predict(X_te[tr_features]) / 5.0
    lgb_age_models.append(model_mae)

提交预测数据

df_submit.to_csv('Fold5_LightGBM_Prediction.csv', index = None)

源码开源协议

GPL-v3
https://zhuanlan.zhihu.com/p/608456168

四、获取案例套件

需要登录后才允许下载文件包。登录

发表评论