【Datawhale手把手带打一场时间序列赛事】任务一学习笔记

一、赛题任务解读

电动汽车充电站充电量预测:赛事链接

1.1任务要求

初赛任务:根据赛题提供的电动汽车充电站多维度脱敏数据,构造合理特征及算法模型,预估站点未来一周每日的充电量。(以为单位)

1.2数据集介绍

初赛为参赛选手准备的数据字典,具体含义见下图:

其中,power.csv文件为训练集的标签。最终任务即在验证集的数据基础上得到验证集的power.csv文件。再上传至比赛官方得到评分。验证集的数据类别与训练集一致。

注:

(1)h3编码是一种用于分层地理编码的系统,可以将地球划分为不同的六边形网格。选手可以尝试使用 h3 编码来构造与地理位置相关的额外特征。

(2)、脱敏字段,不提供字段业务描述,供选手自由探索。

1.3评估指标

评估指标:RMSE 具体含义见下图:

式中y为第个数据的真实值,y星为第个数据的预测值,n为样本总数。

RMSE作为评估指标的优势:RMSE对预测误差的敏感性很高,它会惩罚大误差,因此能够清晰地显示模型预测与实际观测之间的差异;此外,RMSE的值以与目标变量相同的单位表示,因此易于理解,这有助于解释模型误差的实际影响;最后,MSE是在数学上稳健的评估指标,它涉及误差的平方,有利于数学分析和优化。

 二、时间序列赛事的通用流程及baseline讲解

2.1时间序列赛事的通用流程:

2.1.1数据收集和理解:
  • 获取竞赛数据集,了解数据的结构和特征。
  • 探索数据,包括查看时间序列的趋势、季节性和周期性,识别异常值和缺失数据。
2.1.2特征工程:
  • 对数据进行预处理,包括平滑处理、填补缺失值、处理异常值等。
  • 创建相关的特征,例如滞后特征、移动平均特征、时间特征等,以帮助模型更好地捕捉时间序列的模式。
2.1.3拆分数据:

       将数据集分为训练集和验证集,通常使用时间滑窗或交叉验证来确保模型的泛化性能。

2.1.4模型构造:
  • 根据问题的性质和数据的特点,选择适当的时间序列模型,如ARIMA、Prophet、LSTM、GRU、XGBoost等。
  • 使用训练集训练所选的模型,调整超参数以优化性能。
  • 调整模型的超参数,如学习率、滞后阶数、层次数等,以提高模型的性能。
  • 可以尝试将多个模型进行集成,如堆叠、投票、加权平均等,以进一步提高性能。
  • 在验证后,将模型部署到测试集上,评估模型在未知数据上的性能。
  • 根据测试结果进行模型优化,可以反复迭代上述步骤,直到获得满意的结果。
2.1.5结果提交

      将模型的预测结果提交到竞赛平台,以便进行排名和评估。

2.2baseline讲解

2.2.1导入相关库
#导入相关库
import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import StratifiedKFold, KFold, GroupKFold
from sklearn.metrics import mean_squared_error, mean_absolute_error
import matplotlib.pyplot as plt
import tqdm
import sys
import os
import gc
import argparse
import warnings
warnings.filterwarnings('ignore')

warnings.filterwarnings('ignore'),这段代码是用来抑制警告信息。使用 warnings 模块来在脚本中忽略警告。这样可以防止警告消息在输出中混杂,但警告中也有可能含有代码的漏洞,所以需要慎重使用。

2.2.2数据读取与数据的简单处理
train_power_forecast_history = pd.read_csv('./data1/train/power_forecast_history.csv')
train_power = pd.read_csv('./data1/train/power.csv')
train_stub_info = pd.read_csv('./data1/train/stub_info.csv')

test_power_forecast_history = pd.read_csv('./data1/test/power_forecast_history.csv')
test_stub_info = pd.read_csv('./data1/test/stub_info.csv')

train_df = train_power_forecast_history.groupby(['id_encode','ds']).head(1)
del train_df['hour']

test_df = test_power_forecast_history.groupby(['id_encode','ds']).head(1)
del test_df['hour']

tmp_df = train_power.groupby(['id_encode','ds'])['power'].sum()
tmp_df.columns = ['id_encode','ds','power']

# 合并充电量数据
train_df = train_df.merge(tmp_df, on=['id_encode','ds'], how='left')

### 合并数据
train_df = train_df.merge(train_stub_info, on='id_encode', how='left')
test_df = test_df.merge(test_stub_info, on='id_encode', how='left')

    .表示与当前数据集与项目文件处于同一文件夹内。groupy函数是以传入的参数作为对数据进行再次分类的标签。

2.2.3数据可视化
# 定义要绘制的列
cols = ['power']

# 遍历id_encode的五个值
for ie in [0,1,2,3,4]:

    # 获取train_df中id_encode为当前值ie的所有行,并重置索引
    tmp_df = train_df[train_df['id_encode']==ie].reset_index(drop=True)

    # 再次重置索引,并为新索引添加一个名为'index'的列
    tmp_df = tmp_df.reset_index(drop=True).reset_index()

    # 遍历要绘制的列
    for num, col in enumerate(cols):

        # 设置图的大小
        plt.figure(figsize=(20,10))

        # 创建子图,总共有4行1列,当前为第num+1个子图
        plt.subplot(4,1,num+1)

        # 绘制图形:x轴为'index',y轴为当前列的值
        plt.plot(tmp_df['index'],tmp_df[col])

        # 为当前子图设置标题,标题为当前列的名称
        plt.title(col)

# 显示图形
plt.show()

# 创建一个新的图,大小为20x5
plt.figure(figsize=(20,5))

将不同编码的场站的的用电量能量进行可视化。

2.2.4对数据的进一步挖掘
def get_time_feature(df, col):
    
    df_copy = df.copy()
    prefix = col + "_"
    df_copy['new_'+col] = df_copy[col].astype(str)
    
    col = 'new_'+col
    df_copy[col] = pd.to_datetime(df_copy[col], format='%Y%m%d')
    df_copy[prefix + 'year'] = df_copy[col].dt.year
    df_copy[prefix + 'month'] = df_copy[col].dt.month
    df_copy[prefix + 'day'] = df_copy[col].dt.day
    # df_copy[prefix + 'weekofyear'] = df_copy[col].dt.weekofyear
    df_copy[prefix + 'dayofweek'] = df_copy[col].dt.dayofweek
    df_copy[prefix + 'is_wknd'] = df_copy[col].dt.dayofweek // 6
    df_copy[prefix + 'quarter'] = df_copy[col].dt.quarter
    df_copy[prefix + 'is_month_start'] = df_copy[col].dt.is_month_start.astype(int)
    df_copy[prefix + 'is_month_end'] = df_copy[col].dt.is_month_end.astype(int)
    del df_copy[col]
    
    return df_copy   
    
train_df = get_time_feature(train_df, 'ds')
test_df = get_time_feature(test_df, 'ds')

cols = [f for f in test_df.columns if f not in ['ds','power','h3']]

时间特征对新能源网约车的用电量有一定影响,在特定日子,例如春节,大家都在过年,网约车出行量大大减少,用电量也会减少。将官方给出的时间进一步细化就是这段代码的功能。

2.2.5模型调用
# 模型训练与验证

# 使用K折交叉验证训练和验证模型
def cv_model(clf, train_x, train_y, test_x, seed=2023):
    # 定义折数并初始化KFold
    folds = 5
    kf = KFold(n_splits=folds, shuffle=True, random_state=seed)
    
    # 初始化oof预测和测试集预测
    oof = np.zeros(train_x.shape[0])
    test_predict = np.zeros(test_x.shape[0])
    cv_scores = []

    # KFold交叉验证
    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': 2 ** 7,
            'lambda_l2': 10,
            'feature_fraction': 0.8,
            'bagging_fraction': 0.8,
            'bagging_freq': 4,
            'learning_rate': 0.1,
            'seed': 2023,
            'nthread' : 16,
            'verbose' : -1,
            # 'device':'gpu'
        }

        # 训练模型
        model = clf.train(params, train_matrix, 3000, valid_sets=[train_matrix, valid_matrix], categorical_feature=[])
        
        # 获取验证和测试集的预测值
        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
        
        # 计算并打印当前折的分数
        score = np.sqrt(mean_squared_error(val_pred, val_y))
        cv_scores.append(score)
        print(cv_scores)
        
    return oof, test_predict

参考文章:https://aistudio.baidu.com/projectdetail/6882171?sUid=2554132&shared=1&ts=1697254726362

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值