2024Datawhale AI夏令营--Task 02任务有感

一、题目背景与概述

       随着全球经济的快速发展和城市化进程的加速,电力系统面临着越来越大的挑战。电力需求的准确预测对于电网的稳定运行、能源的有效管理以及可再生能源的整合至关重要。然而,电力需求受到多种因素的影响,为了提高电力需求预测的准确性和可靠性,推动智能电网和可持续能源系统的发展,本场以“电力需求预测”为赛题的数据算法挑战赛。选手需要根据历史数据构建有效的模型,能够准确的预测未来电力需求。

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

二、数据集格式分析

赛题数据由训练集和测试集组成,为了保证比赛的公平性,将每日日期进行脱敏,用1-N进行标识,即1为数据集最近一天,其中1-10为测试集数据。数据集由字段id(房屋id)、 dt(日标识)、type(房屋类型)、target(实际电力消耗)组成。

特征字段字段描述
id房屋id
dt日标记
type房屋类型
target实际电力消耗,预测目标

三、预测方法

①首先要对时间序列数据进行预处理,包括将训练数据合并排序,以及数据特征的提取。这个步骤通常在机器学习或深度学习项目中用于预测任务,提取对模型预测有利的特征。

根据参考文档我提取了两个数据特征,历史平移以及窗口统计:

历史平移:历史平移特征是通过将时间序列中的值向后或向前平移一个或多个时间步长(lags)来创建的。例如,如果last5_target是历史平移特征之一,那么它代表了在时间点t处的值y(t)是由y(t-5)的值决定的。

窗口统计:窗口统计特征是通过对时间序列数据的一个固定长度的窗口内的数据进行统计运算得到的,如平均值、标准差、最大值或最小值等。

# 合并训练数据和测试数据,并进行排序
data = pd.concat([test, train], axis=0, ignore_index=True)
data = data.sort_values(['id','dt'], ascending=False).reset_index(drop=True)

# 历史平移
for i in range(10,30):
    data[f'last{i}_target'] = data.groupby(['id'])['target'].shift(i)
    
# 窗口统计
data[f'win3_mean_target'] = (data['last10_target'] + data['last11_target'] + data['last12_target']) / 3
#窗口统计优化代码示例:
#rolling_windows = [3, 7, 14]  # 不同的滚动窗口大小
#for window in rolling_windows:
#    data[f'win{window}_mean_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).mean())
#    data[f'win{window}_std_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).std())
#    data[f'win{window}_max_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).max())
#    data[f'win{window}_min_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).min())
# 进行数据切分
train = data[data.target.notnull()].reset_index(drop=True)
test = data[data.target.isnull()].reset_index(drop=True)

# 确定输入特征
train_cols = [f for f in data.columns if f not in ['id','target']]

 ②根据提取的数据特征使用LightGBM库构建了一个回归模型来预测目标变量。函数time_model首先切分训练数据为训练集和验证集,然后使用LightGBM库构建和训练一个回归模型。参数设置、数据集构建、模型训练、预测和评估都在此函数中完成。

def time_model(lgb, train_df, test_df, cols):
    # 训练集和验证集切分
    trn_x, trn_y = train_df[train_df.dt>=31][cols], train_df[train_df.dt>=31]['target']
    val_x, val_y = train_df[train_df.dt<=30][cols], train_df[train_df.dt<=30]['target']
    # 构建模型输入数据
    train_matrix = lgb.Dataset(trn_x, label=trn_y)
    valid_matrix = lgb.Dataset(val_x, label=val_y)
    # lightgbm参数
    lgb_params = {
        'boosting_type': 'gbdt',
        'objective': 'regression',
        'metric': 'mse',
        'min_child_weight': 5,
        'num_leaves': 2 ** 7,#叶子结点
        'lambda_l2': 15,#正则强度参数
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 4,
        'learning_rate': 0.01,#学习率
        'seed': 2024,
        'nthread' : 16,
        'verbose' : -1,
    }
    # 训练模型
    model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix], 
                      categorical_feature=[], verbose_eval=500, early_stopping_rounds=1500)
    # 验证集和测试集结果预测
    val_pred = model.predict(val_x, num_iteration=model.best_iteration)
    test_pred = model.predict(test_df[cols], num_iteration=model.best_iteration)
    # 离线分数评估
    score = mean_squared_error(val_pred, val_y)
    print(score)
       
    return val_pred, test_pred
    
lgb_oof, lgb_test = time_model(lgb, train, test, train_cols)

# 保存结果文件到本地
test['target'] = lgb_test
test[['id','dt','target']].to_csv('submit1.csv', index=None)

四、模型优化

 根据我的理解,模型优化可以从两个方面入手:

①修改模型参数:比如num_leaves、learning_rate、lambda_12和早停轮数等等,增加叶子节点数量,增加学习率,这两者可能会使模型在训练数据上表现得更好,但在未见过的数据(如验证集或测试集)上泛化能力下降。这是过拟合的表现,具体应该怎么调整数据这需要在实际中得到答案,不过为了弱化泛化能力的下降所可能带来的影响,我们可以增加lambda_12的值,从而增强正则化强度来帮助模型泛化,其次,如果早停条件太严格,可以适当放宽,也就是增加early_stopping_rounds,给模型更多时间去收敛。

②数据特征提取模式的探索:在历史平移特征的基础上,我们可以尝试不同的平移步长,比如更短或更长的时间跨度,看是否能捕捉到更复杂的模式;对于窗口统计特征,除了平均值,我们还可以尝试计算最大值、最小值、标准差等统计量,这些可能捕捉到数据的不同方面,或者对于平均值而言,我们可以增加平均值计算的列范围,看能否捕捉到新模式等等。

五、心得感悟

       通过Task02的学习,我了解了如何指导和优化模型预测,对各因素在模型预测过程中的作用有了一个清晰的认知,机器学习不再是一个脑中的抽象概念,而是有了一个总体的认知,我觉得这是我收获最大的地方,让我产生了了解更多模型的兴趣,比如别的决策树模型或者神经网络模型等等,拓宽了我的见识。

总体模型代码:

# 合并训练数据和测试数据,并进行排序
data = pd.concat([test, train], axis=0, ignore_index=True)
data = data.sort_values(['id','dt'], ascending=False).reset_index(drop=True)

# 历史平移
for i in range(10,30):
    data[f'last{i}_target'] = data.groupby(['id'])['target'].shift(i)
    
# 窗口统计
data[f'win3_mean_target'] = (data['last10_target'] + data['last11_target'] + data['last12_target']) / 3
#窗口统计优化代码示例:
#rolling_windows = [3, 7, 14]  # 不同的滚动窗口大小
#for window in rolling_windows:
#    data[f'win{window}_mean_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).mean())
#    data[f'win{window}_std_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).std())
#    data[f'win{window}_max_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).max())
#    data[f'win{window}_min_target'] = data.groupby('id')['target'].transform(lambda x: #x.shift(10).rolling(window).min())
# 进行数据切分
train = data[data.target.notnull()].reset_index(drop=True)
test = data[data.target.isnull()].reset_index(drop=True)

# 确定输入特征
train_cols = [f for f in data.columns if f not in ['id','target']]
def time_model(lgb, train_df, test_df, cols):
    # 训练集和验证集切分
    trn_x, trn_y = train_df[train_df.dt>=31][cols], train_df[train_df.dt>=31]['target']
    val_x, val_y = train_df[train_df.dt<=30][cols], train_df[train_df.dt<=30]['target']
    # 构建模型输入数据
    train_matrix = lgb.Dataset(trn_x, label=trn_y)
    valid_matrix = lgb.Dataset(val_x, label=val_y)
    # lightgbm参数
    lgb_params = {
        'boosting_type': 'gbdt',
        'objective': 'regression',
        'metric': 'mse',
        'min_child_weight': 5,
        'num_leaves': 2 ** 6,
        'lambda_l2': 15,
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 4,
        'learning_rate': 0.03,
        'seed': 2024,
        'nthread' : 16,
        'verbose' : -1,
    }
    # 训练模型
    model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix], 
                      categorical_feature=[], verbose_eval=500, early_stopping_rounds=1000)
    # 验证集和测试集结果预测
    val_pred = model.predict(val_x, num_iteration=model.best_iteration)
    test_pred = model.predict(test_df[cols], num_iteration=model.best_iteration)
    # 离线分数评估
    score = mean_squared_error(val_pred, val_y)
    print(score)
       
    return val_pred, test_pred
    
lgb_oof, lgb_test = time_model(lgb, train, test, train_cols)

# 保存结果文件到本地
test['target'] = lgb_test
test[['id','dt','target']].to_csv('submit1.csv', index=None)

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值