打卡Day1

赛题介绍

2023“SEED”第四届江苏大数据开发与应用大赛--新能源赛道

https://www.marsbigdata.com/competition/details?id=40144958741

给出数据集中有电动汽车充电站的场站编号、位置信息、历史电量等基本信息,我们需要根据这些数据预测出每个站点未来一周每天的充电量。提交结果为三列(场站编号+日期+充电量)。

Baseline分析

首先准备相关库

#import 相关库
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')

numpy,pandas:进行数据导入及处理。

LightGBM :是一个梯度 boosting 框架, 使用基于学习算法的决策树.它是个快速的,分布式的,高性能的基于决策树算法的梯度提升框架。可用于排序,分类,回归以及很多其他的机器学习任务中。

StratifiedKFold, KFold, GroupKFold:交叉验证迭代器。

mean_squared_error, mean_absolute_error:回归问题的评估指标。

 matplotlib.pyplot:绘制数据相关图。

数据导入

# 读取数据
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')

使用pandas的导入功能即可。导入后可使用df.head()查看dataframe前五列。

train_power_forecast_history.head()

第一张表核心是收费,第二张表核心为充电时间,第三张表为各场站物理参数 。

数据整合

# 聚合数据
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')

train_df['flag'] = train_df['flag'].map({'A':0,'B':1})
test_df['flag'] = test_df['flag'].map({'A':0,'B':1})

三表合一,为后续提取特征做准备。

由于需要预测的是每天的充电量之和,而原数据给出的是每小时充电量,故依据日期对每小时充电量求和。

绘制数据分布图像进行初步观察

# 定义要绘制的列
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))

绘制场站编号为0-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']]

提取ds列中的时间特征

模型训练与验证

# 模型训练与验证

# 使用K折交叉验证训练和验证模型
def cv_model(clf, train_x, train_y, test_x, seed=2020):
    # 定义折数并初始化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

# 调用上面的函数进行模型训练和预测
lgb_oof, lgb_test = cv_model(lgb, train_df[cols], train_df['power'], test_df[cols])

重要参数

boosting_type:用于指定弱学习器的类型,默认值为 ‘gbdt’,表示使用基于树的模型进行计算。还可以选择为 ‘gblinear’ 表示使用线性模型作为弱学习器。‘gbdt’,使用梯度提升树。

objective:用于指定学习任务及相应的学习目标,“regression”,使用L2正则项的回归模型(默认值)。

metric:用于指定评估指标,可以传递各种评估方法组成的list。赛题评判标准为rmse 。

min_child_weight:指定孩子节点中最小的样本权重和,如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束,默认值为1。推荐的候选值为:[1, 3, 5, 7]。

num_leaves:指定叶子的个数,默认值为31

lambda_l2:L2正则化权重项,增加此值将使模型更加保守。

feature_fraction:构建弱学习器时,对特征随机采样的比例。

bagging_fraction:指定采样出 subsample * n_samples 个样本用于训练弱学习器。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。 取值在(0, 1)之间,设置为1表示使用所有数据训练弱学习器。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。
bagging_freq:表示禁用样本采样。如果设置为整数 z ,则每迭代 k 次执行一次采样。

learning_rate:LightGBM 不完全信任每个弱学习器学到的残差值,为此需要给每个弱学习器拟合的残差值都乘上取值范围在(0, 1] 的 eta,设置较小的 eta 就可以多学习几个弱学习器来弥补不足的残差。

seed:指定随机数种子。

提分策略

1.修改baseline参数

尝试修改seed,有一定作用,但是比较有限。



 
 

2.提取新特征进行训练

3.更换模型

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值